home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / GRDBDL17.ZIP / ASMOPS.ASM < prev    next >
Encoding:
Assembly Source File  |  1998-10-26  |  32.8 KB  |  1,882 lines

  1. ;                     
  2. ; GRDB
  3. ;
  4. ; Copyright(c) LADsoft
  5. ;
  6. ; David Lindauer, camille@bluegrass.net
  7. ;
  8. ;
  9. ; ASMOPS.ASM
  10. ;
  11. ; Function: Assembler operand parsers
  12. ;
  13.     ;MASM MODE
  14.     .MODEL SMALL
  15.     .386
  16.  
  17. include iasm.inc
  18. include easm.inc
  19. include iopcodes.inc
  20. include eopcodes.inc
  21. include eopcom.inc
  22. include eprints.inc 
  23. include einput.inc 
  24. include emtrap.inc
  25. include    edispatc.inc
  26. include eoperand.inc
  27. include eoptions.inc
  28.  
  29.     PUBLIC    AOP0,  AOP1,  AOP2,  AOP3,  AOP4,  AOP5,  AOP6,  AOP7
  30.     PUBLIC    AOP8,  AOP9,  AOP10, AOP11, AOP12, AOP13, AOP14, AOP15
  31.     PUBLIC    AOP16, AOP17, AOP18, AOP19, AOP20, AOP21, AOP22, AOP23
  32.     PUBLIC    AOP24, AOP25, AOP26, AOP27, AOP28, AOP29, AOP30, AOP31
  33.     PUBLIC    AOP32, AOP33, AOP34, AOP35, AOP36, AOP37, AOP38, AOP39
  34.     PUBLIC    AOP40, AOP41, AOP42, AOP43, AOP44, AOP45, AOP46, AOP47
  35.     PUBLIC    AOP48, AOP49, AOP50, AOP51, aop52, AOP53, AOP54, AOP55
  36.     PUBLIC    AOP56, AOP57, AOP58
  37.  
  38.     .data
  39. base16c    dw    0ff03h,0ff05h,0ff07h,0ff06h,0705h,0605h, 0703h,0603h
  40.     dw    0ffffh,0ffffh,0ffffh,0ffffh,0507h,0506h, 0307h,0306h
  41.  
  42.     .code
  43.  
  44. ;Check if arg1.asize is 4 or less.  If greater, return error to caller's
  45. ;caller by mucking with the stack.
  46.  
  47. intsize PROC
  48.     cmp    [arg1.asize],DWORDSIZE    ;maybe this means the first argument
  49.     ja    rtnDirectlyToDispatcherWithCY    ;can't exceed dword size
  50.     ret
  51. intsize    ENDP
  52.  
  53. ;See if the mode field for this structure references a memory operand
  54. ;and return error to caller's caller if not
  55.  
  56. chkmem    PROC
  57.     cmp    [bx+asmop.mode],AM_MEM        ;this is 3
  58.     jne    rtnDirectlyToDispatcherWithCY    ;bomb if not memory operand
  59.     ret
  60. chkmem    ENDP
  61.  
  62. ;See if the mode field for this structure references an immediate operand
  63. ;and return error to caller's caller if not
  64.  
  65. chkimm    PROC
  66.     cmp    [bx+asmop.mode],AM_IMM        ;check if immediate
  67.     jne    rtnDirectlyToDispatcherWithCY    ;if not, bomb
  68.     ret
  69. chkimm    ENDP
  70.  
  71. ;See if the mode field for this structure references a segment
  72. ;and return error to caller's caller if not
  73.  
  74. chkseg    PROC
  75.     cmp    [bx+asmop.mode],AM_SEG
  76.     jne    rtnDirectlyToDispatcherWithCY
  77.     ret
  78. chkseg    ENDP
  79.  
  80. ;This is a little more complicated. Let's hypothesize that chkregw is 
  81. ;shorthand for checking a 16-bit register type opcode. In this case,maybe the
  82. ;opcode must contain more than a single byte.  So before we check if it
  83. ;is a register-type opcode, we must make sure it has extra byte(s). So
  84. ;we stop here first, and if the length makes us happy, then we check mode
  85. ;  Next guess - if this is a byte argument, we bomb since a word register
  86. ;requires a word operand.
  87.  
  88. chkregw    PROC
  89.     cmp    [bx+asmop.asize],BYTESIZE    ;is this a byte opcode
  90.     je    rtnDirectlyToDispatcherWithCY    ;if so, bomb
  91.     jmp    chkreg            ;else check mode for register type
  92. chkregw    ENDP
  93.  
  94. ;Possibly this is used for in and out, where DX is the only register
  95. ;allowed?
  96.  
  97. chkdx    PROC
  98.     cmp    [bx+asmop.asize],WORDSIZE    ;if not a word register
  99.     jne    rtnDirectlyToDispatcherWithCY    ;then bomb
  100.     cmp    [bx+asmop.areg1],isEDX        ;else see if DX register
  101.     jne    rtnDirectlyToDispatcherWithCY    ;if not, bomb
  102.     jmp    chkreg
  103. chkdx    ENDP
  104.  
  105. ;Not sure about the AX part of this, since all that is being checked is
  106. ;a size of byte
  107.  
  108. chkaxw    PROC
  109.     cmp    [bx+asmop.asize],BYTESIZE    ;if a byte register
  110.     je    rtnDirectlyToDispatcherWithCY    ;then bomb
  111. chkaxw    ENDP
  112.  
  113. ;This IS a check for AX (actually, 0 is EAX)
  114.  
  115. chkax    PROC
  116.     cmp    [bx+asmop.areg1],0            ;if not EAX (maybe AX or AL)
  117.     jne    rtnDirectlyToDispatcherWithCY    ;then bomb
  118. chkax    ENDP
  119.  
  120. ;Check for a register?  As opposed to ??
  121.  
  122. chkreg    PROC
  123.     cmp    [bx+asmop.mode],AM_REG        ;is this flag set?
  124.     jne    rtnDirectlyToDispatcherWithCY    ;if not, bomb
  125.     ret
  126. chkreg    ENDP
  127.  
  128. ;We bomb if arg3.mode isn't none, and if it is, we still bomb if arg2.mode
  129. ;is none.  So arg3 is required to have a 'mode', whatever that is, I guess
  130.  
  131. noarg3    PROC
  132.     cmp    [arg3.mode],AM_NONE
  133.     jne    rtnDirectlyToDispatcherWithCY
  134.     cmp    [arg2.mode],AM_NONE
  135.     je    rtnDirectlyToDispatcherWithCY
  136.     ret
  137. noarg3    ENDP
  138.  
  139. ;Same as above, except it applies to arg2
  140.  
  141. noarg2    PROC
  142.     cmp    [arg2.mode],AM_NONE
  143.     jne    rtnDirectlyToDispatcherWithCY
  144.     cmp    [arg1.mode],AM_NONE
  145.     je    rtnDirectlyToDispatcherWithCY
  146.     ret
  147. noarg2    ENDP
  148.  
  149. ;Whoa, lets see here.  If arg1.mode, whatever that is, is NOT 0, we jnz to
  150. ;rtnDirectlyToDispatcherWithCY. Since this routine was called, the return 
  151. ;address is on the stack. Which means rtnDirectlyToDispatcherWithCY strips 
  152. ;off the return address, and returns to the caller's caller. 
  153.  
  154. noarg1    PROC
  155.     cmp    [arg1.mode],AM_NONE
  156.     jne    rtnDirectlyToDispatcherWithCY
  157.     ret
  158. noarg1    ENDP
  159. ;
  160. ; pops the ret address from the AOP caller
  161. ; and goes directly back to the parser with a mismatch error
  162. ;
  163. rtnDirectlyToDispatcherWithCY    PROC
  164.     pop    ax
  165.     stc
  166.     ret
  167. rtnDirectlyToDispatcherWithCY    ENDP
  168.  
  169.  
  170. ;see if size of this opcode is 1. If not, we are returning NZ and AL=1. I
  171. ;assume that 1 is important, since without the OR line, we would also be
  172. ;returning NZ if the size was not 1. In fact, several callers immediately
  173. ;do a stosb, so at the very least we are ensuring an odd number???
  174. ;  Next guess: AL will eventually be used as part of the stored, assembled
  175. ;byte.  So apparently the purpose of this routine is to set bit 0 of the
  176. ;untimate assembled value if this is NOT a byte operand.
  177.  
  178. sizeb0    PROC
  179.     cmp    [bx+asmop.asize],BYTESIZE
  180.     je    szb0x
  181.     or    al,1
  182. szb0x:
  183.     ret
  184. sizeb0    ENDP
  185.  
  186. ;In which case, the purpose of this routine is to set bit 3 of AL if the
  187. ;operand is NOT a byte operand.
  188.  
  189. sizeb3    PROC
  190.     cmp    [bx+asmop.asize],BYTESIZE
  191.     je    szb3x
  192.     or    al,8
  193. szb3x:
  194.     ret
  195. sizeb3    ENDP
  196. ;
  197. ; main RM handler
  198. ;
  199. ; within this routine, CX = pointer to mod/RM byte and DX = flag for
  200. ; <e>bp based indexing
  201. ;
  202. ; all MOD/RM fields are set up assuming no offset and updated 
  203. ; later...
  204. ;
  205. asmfrm    PROC
  206.     cmp    [bx+asmop.mode],AM_FPREG ; check for register direct mode
  207.     jne    asmrm2
  208.     or    al,0c0h            ; modrm = 0c0+al+regval
  209.     or    al,[bx+asmop.areg1]
  210.     stosb
  211.     ret
  212.     
  213. asmfrm    ENDP
  214.  
  215.  
  216.  
  217. asmrm    PROC
  218.     shl    al,3            ; shift reg val into place
  219. asmrm    ENDP
  220.  
  221.  
  222. asmrm2    PROC
  223. ;
  224. ; registers are the same in both 16 & 32-bit
  225. ;
  226.     cmp    [bx+asmop.mode],AM_REG    ; 1check for register direct mode
  227.     jne    rmnreg
  228.     or    al,0c0h            ; modrm = 0c0+al+regval
  229.     or    al,[bx+asmop.areg1]
  230.     stosb
  231.     ret
  232. rmnreg:
  233.     cmp    [bx+asmop.msize],DWORDMODE    ; see which style of addressing
  234.     je    asmrm32
  235. ;
  236. ; 16-bit MEM handler
  237. ;
  238.     cmp    [bx+asmop.mode],AM_MEM    ; 16 bit, check for mem
  239.     jne    rm16nmem
  240.     or    al,6            ; MODRM = 6+al
  241.     stosb
  242.     jmp    rmwoffs
  243. rm16nmem:
  244.     cmp    [bx+asmop.mode],AM_BASED ; check for 16 bit based
  245.     jne    rtnDirectlyToDispatcherWithCY
  246. ;
  247. ; 16-bit base handler, restricted combos and no scaling
  248. ;
  249.     push    ax            ; yes, get the reg vals
  250.     sub    ax,ax
  251.     mov    al,[bx+asmop.areg1]
  252.     mov    ah,[bx+asmop.areg2]
  253.     mov    dx,ax
  254.     push    di            ; scan for a match and to get index
  255.     mov    di,offset base16c
  256.     mov    cx,16
  257.     repne    scasw
  258.     pop    di
  259.     pop    ax
  260.     jnz    rtnDirectlyToDispatcherWithCY    ; scan failed, exit
  261.     bt    cx,3
  262.     jc    rm16nswap
  263.     xchg    dl,dh
  264. rm16nswap:
  265.     and    cl,7
  266.     or    al,cl
  267.     mov    cx,di            ; cx points at modrm byte
  268.     stosb
  269.     jmp    rmanyoffs        ; check for offs
  270. ;
  271. ; 32-bit modes start here
  272. ;
  273. asmrm32:
  274.     cmp    [bx+asmop.mode],AM_MEM    ; 32 bit, check for mem
  275.     jne    rm32nmem
  276. ;
  277. ; generic mem handler
  278. ;
  279.     or    al,5            ; MODRM = 5+al
  280.     stosb
  281.     jmp    rmwoffs
  282. rm32nmem:
  283.     cmp    [bx+asmop.mode],AM_BASED     ; check for based
  284.     jne    rtnDirectlyToDispatcherWithCY    ; not legal if not
  285.     cmp    [bx+asmop.areg2],0FFh    ; else see if second reg defined
  286.     je    rm32bbonly
  287.     cmp    [bx+asmop.areg1],0FFh    ; else see if first reg defined
  288.     je    rm32bionly
  289. ;
  290. ; both a base AND an index
  291. ;
  292. ; the parser should have checked that ESP is not the scond arg
  293. ; and that we don't have two EBP args
  294. ;
  295.     cmp    [bx+asmop.areg1],isEBP    ; check for BP based
  296.     je    rm32bbsebp
  297.     or    al,4            ; flag MOD for SIB
  298.     mov    cx,di
  299.     stosb
  300.     bsf    ax,[bx+asmop.ascale]    ; calculate SIB byte
  301.     shl    ax,3
  302.     or    al,[bx +asmop.areg2]
  303.     shl    ax,3
  304.     or    al,[bx+asmop.areg1]
  305.     stosb
  306.     sub    dx,dx
  307.     jmp    rmanyoffs
  308. ;
  309. ; base and index, base is ebp
  310. rm32bbsebp:
  311.     or    al,4
  312.     mov    cx,di
  313.     stosb
  314.     bsf    ax,[bx+asmop.ascale]    ; calculate SIB byte
  315.     shl    ax,3
  316.     or    al,[bx+asmop.areg2]
  317.     shl    ax,3
  318.     or    al,5            ; bp based
  319.     stosb
  320.     mov    dx,0ff05h
  321.     jmp    rmanyoffs
  322. ;
  323. ; index only
  324. rm32bionly:
  325.     or    al,4             ; select SIB byte
  326.     stosb
  327.     bsf    ax,word ptr [bx+asmop.ascale] ; calculate scale factor
  328.     shl    ax,3            ; shift over
  329.     or    ax,word ptr [bx+asmop.areg2] ; add in index
  330.     shl    ax,3            ; shift over
  331.     or    ax,5            ; base = 5, that is none since mod = 0
  332.     stosb
  333.     mov    eax,[bx+asmop.addrx]    ; always 32-bit ofs in this mode
  334.     stosd
  335.     ret
  336. ;
  337. ; only a base reg
  338. ;
  339. rm32bbonly:
  340.     ; shouldn't get here if no regs
  341.     cmp    [ebx+asmop.areg1],isESP    ; only one reg, check for ESP
  342.     je    rm32besp
  343.     cmp    [ebx+asmop.areg1],isEBP    ; only one reg, check for EBP
  344.     je    rm32bebp
  345.     or    al,[ebx+asmop.areg1]    ; no, normal MODRM byte with no SIB
  346.     mov    cx,di
  347.     stosb
  348.     mov    dh,0FFh            ; pretend 16 bit
  349.     mov    dl,al
  350.     and    dl,7
  351.     jmp    rmanyoffs
  352. ;
  353. ; based ESP, no index
  354. ;
  355. rm32besp:
  356.     or    al,4            ; select SIB byte (sib needed
  357.     mov    cx,di            ; for indexing off ESP)
  358.     stosb
  359.     mov    al,24h            ; sib byte for [esp] mode
  360.     stosb
  361.     sub    dx,dx
  362.     jmp    rmanyoffs
  363. ;
  364. ; based ebp, no index
  365. ;
  366. rm32bebp:
  367.     or    al,5
  368.     mov    cx,di            ; so we can adjust mod later
  369.     stosb
  370.     mov    dx,0ff05h        ; MUST have offset, this is BP base reg
  371.     jmp    rmanyoffs
  372. ;
  373. ; now the auto offset routine.
  374. ; if (E)BP, we ALWAYS have an offset    
  375. ; otherwise we see if the offset is zero before encoding anything
  376.     
  377. asmrm2    ENDP
  378. rmanyoffs PROC
  379.     mov    eax,[bx+asmop.addrx]    ; get offs
  380.     cmp    dx,0ff05h        ; BP reg ALWAYS has offs
  381.     je    rmaomho
  382.  
  383.     or    eax,eax         ; else no offs if offs = 0
  384.     jz    rmaook
  385. ;
  386. ; if we get here we have an offset, fix the RM field and embed the
  387. ; offset
  388. ;
  389. rmaomho:
  390.     xchg    cx,bx
  391.     add    byte ptr [bx],40h    ; else set MOD field = 1
  392.     xchg    cx,bx
  393.     and    eax,NOT 7FH        ; else see if fits in a byte
  394.     jz    rmboffs
  395.     cmp    eax,NOT 7fh
  396.     je    rmboffs            ; yep, go do it
  397.     xchg    cx,bx
  398.     add    byte ptr [bx],40h    ; else MOD field = 2
  399.     xchg    cx,bx
  400.     jmp    rmwoffs            ; and go do it
  401.  
  402. rmboffs:
  403.     mov    eax,[bx+asmop.addrx]    ; get offs
  404.     stosb                  ; store a byte offs
  405. rmaook:
  406.     clc
  407.     ret
  408. rmanyoffs    ENDP
  409. rmszoffs    PROC
  410.     mov    eax,[bx+asmop.addrx]
  411.     cmp    [bx+asmop.msize],WORDMODE
  412.     jae    rmwoffs
  413.     stosb
  414.     clc
  415.     ret
  416. rmszoffs    ENDP
  417. rmwoffs    PROC
  418.     mov    eax,[bx+asmop.addrx]    ; check size
  419.     cmp     [bx+asmop.msize],WORDMODE
  420.     ja    rmdwoffs
  421.     stosw                ; word offs
  422.     clc
  423.     ret
  424. rmdwoffs:
  425.     test    [Disassemble32Bit],1
  426.     jz    rtnDirectlyToDispatcherWithCY
  427.     stosd                ; dword offs
  428.     clc
  429.     ret
  430. rmwoffs    ENDP
  431. rmszimm    PROC
  432.     mov    eax,[bx+asmop.addrx]    ; check size
  433.     cmp    [bx+asmop.asize],WORDSIZE
  434.     jae    rmszimmw
  435.     stosb
  436.     clc
  437.     ret
  438. rmszimmw:
  439.     jne    rmszimmd
  440.     stosw
  441.     ret
  442. rmszimmd:
  443.     cmp    [bx+asmop.asize],DWORDSIZE
  444.     jne    rtnDirectlyToDispatcherWithCY
  445.     test    [Disassemble32Bit],1
  446.     jz    rtnDirectlyToDispatcherWithCY
  447.     stosd
  448.     ret
  449. rmszimm    ENDP
  450. ;
  451. ; no operands. In this case, the opcode length is 1, so we go through this
  452. ;    weird locution to rep mov a single byte out of the structure and
  453. ;    into [di], wherever that points. Apparently it points into an opcode
  454. ;    buffer somewhere. If the opcode length is greater than one, what
  455. ;    happens?
  456. ;
  457. AOP0    PROC
  458.     call    noarg1            ;see if arg1.mode=0, whatever that means
  459.     push    si            ;only return here if it IS 0
  460.     movzx    cx,[si+opcode.oclength]    ;so get the length of the opcode
  461.     lea    si,[si+opcode.compare]    ;find the opcode in the structure
  462.     rep    movsb            ;copy from structure to buffer
  463.     pop    si            ;restore pointer to structure
  464.     clc                ;say no problem
  465.     ret
  466. AOP0    ENDP
  467. ;
  468. ; word reg, bits 0-2 of opcode = reg num
  469. ;
  470. AOP1    PROC
  471.     call    noarg2
  472.     call    intsize
  473.     mov    bx,offset arg1
  474.     call    chkregw
  475.     mov    al,byte ptr [si+OPCODE.COMPARE]
  476.     or    al,[arg1.areg1]
  477.     stosb
  478.     clc
  479.     ret
  480. AOP1    ENDP
  481. ;
  482. ; word acc,reg... reg = bits 0-2 of opcode
  483. ;
  484. AOP2    PROC
  485.     call    noarg3
  486.     call    intsize
  487.     mov    bx,offset arg1
  488.     call    chkaxw
  489.     mov    bx,offset arg2
  490.     call    chkregw
  491.     mov    al,byte ptr [si+opcode.compare]
  492.     or    al,[arg2.areg1]
  493.     stosb
  494.     ret
  495. AOP2    ENDP
  496. ;
  497. ; one arg, seg goes in b3-4 of opcode
  498. ;
  499. AOP3    PROC
  500.     call    noarg2
  501.     call    intsize
  502.     mov    bx,offset arg1
  503.     call    chkseg
  504.     mov    ah,byte ptr [si+OPCODE.COMPARE]
  505.     mov    al,[arg1.areg1]
  506.     cmp    ah,8
  507.     jae    aop3ext
  508.     cmp    al,4
  509.     jae    aop3errx
  510. aop3c:
  511.     shl    al,3
  512.     or    al,ah
  513.     stosb
  514.     ret
  515. aop3ext:
  516.     sub    al,4
  517.     jnc    aop3c
  518. aop3errx:
  519.     stc
  520.     ret
  521.     
  522. AOP3    ENDP
  523. ;
  524. ; either combo of a reg & rm... bit 1 of opcode set if reg is dest
  525. ; bit 0 set if size = word
  526. ;
  527. AOP4    PROC
  528.     call    noarg3
  529.     call    intsize
  530.     sub    al,al
  531.     mov    bx,offset arg1
  532.     call    sizeb0
  533.      cmp    [arg1.mode],AM_REG
  534.     jne    aop4rs
  535.     or    al,2
  536.     mov    bx,offset arg2
  537.     mov    ah,[arg1.areg1]
  538.     jmp    aop4j
  539.  
  540. aop4rs:
  541.      cmp    [arg2.mode],AM_REG
  542.     jne    aop4err
  543.     mov    bx,offset arg1
  544.     mov    ah,[arg2.areg1]
  545. aop4j:
  546.     or    al,byte ptr [si+OPCODE.COMPARE]
  547.     stosb
  548.     mov    al,ah
  549.     call    asmrm
  550.     ret
  551. aop4err:
  552.     stc
  553.     ret
  554. AOP4    ENDP
  555. ;
  556. ; use only rm, bit 0 = size (exception : jmp/call)
  557. ;
  558. AOP5    PROC
  559.     call    noarg2
  560.     call    intsize
  561.     mov    bx,offset arg1
  562.     mov    ax,[si+OPCODE.COMPARE]
  563.     test    al,1
  564.     jz    aop5cansize
  565.     cmp    [arg1.asize],DWORDSIZE    ; special sizing for jump
  566.     jne    aop5jn4
  567.     and    [PrefixBitmapWord],NOT AS_OPSIZE
  568.     or    ah,8
  569. aop5jn4:
  570.     cmp    [bx+asmop.asize],WORDSIZE
  571.     je    aop5unsized
  572.     cmp    [bx+asmop.asize],NOSIZE
  573.     je    aop5unsized
  574.     stc
  575.     ret
  576. aop5cansize:
  577.     call    sizeb0
  578. aop5unsized:
  579.     stosb
  580.     xchg    al,ah
  581.     and    al,38h
  582.     mov    bx,offset arg1
  583.     call    asmrm2
  584.     ret
  585. AOP5    ENDP
  586. ;
  587. ; rm,count or rm,cl (shifts) bit 0 = size
  588. ; bit 1 set if size = 1, bit 4 set if size = cl, otherwise follow rm with
  589. ; a count byte
  590. ;
  591. AOP6    PROC
  592.     call    noarg3
  593.     call    intsize
  594.     mov    bx,offset arg1
  595.     mov    ax,[si+opcode.compare]
  596.     call    sizeb0
  597.     cmp    [arg2.mode],AM_REG
  598.     je    aop6cl
  599.     cmp    [arg2.mode],AM_IMM
  600.     je    aop6imm
  601. aop6b:
  602.     stc
  603.     ret
  604. aop6cl:
  605.     cmp    [arg2.asize],BYTESIZE
  606.     jne    aop6b
  607.     cmp    [arg2.areg1],isECX
  608.     jne    aop6b
  609.     or    al,12h
  610.     stosb
  611.     jmp    aop6rm
  612. aop6imm:
  613.     cmp    [arg2.addrx],1
  614.     je    aop6shift1
  615.     stosb
  616.     xchg    al,ah
  617.     call    asmrm2
  618.     mov    al,byte ptr [arg2.addrx]
  619.     stosb
  620.     ret
  621. aop6shift1:
  622.     or    al,10h
  623.     stosb
  624. aop6rm:
  625.     xchg    al,ah
  626.     call    asmrm2
  627.     ret
  628. AOP6    ENDP
  629. ;
  630. ; unordered version of AOP4.  (any combo of reg and RM)
  631. ; This is XCHG instructions,
  632. ; this is unordered, so, it doesn't
  633. ; need to know which comes first
  634. ;
  635. ; bit 0 = size
  636. ;
  637. AOP7    PROC
  638.     call    noarg3
  639.     call    intsize
  640.     sub    al,al
  641.     mov    bx,offset arg1
  642.     call    sizeb0
  643.      cmp    [arg1.mode],AM_REG
  644.     jne    aop7rs
  645.     mov    bx,offset arg2
  646.     mov    ah,[arg1.areg1]
  647.     jmp    aop7j
  648.  
  649. aop7rs:
  650.      cmp    [arg2.mode],AM_REG
  651.     jne    aop7err
  652.     mov    bx,offset arg1
  653.     mov    ah,[arg2.areg1]
  654. aop7j:
  655.     or    al,byte ptr [si+OPCODE.COMPARE]
  656.     stosb
  657.     mov    al,ah
  658.     call    asmrm
  659.     ret
  660. aop7err:
  661.     stc
  662.     ret
  663. AOP7    ENDP
  664. ;
  665. ; word regrm, reg = dest.
  666. ;
  667. AOP8    PROC
  668.     call    noarg3
  669.     call    intsize
  670.     cmp    [arg1.asize],BYTESIZE
  671.     je    aop8errx
  672.     mov    bx,offset arg1
  673.     call    chkreg
  674.     mov    al,[bx+asmop.asize]
  675.     cmp    bl,1
  676.     jne    aop8ok
  677. aop8errx:
  678.     stc
  679.     ret
  680. aop8ok:
  681.     mov    al,byte ptr [si+OPCODE.COMPARE]
  682.     stosb
  683.     mov    al,[bx+asmop.areg1]
  684.     mov    bx,offset arg2
  685.     call    asmrm
  686.     ret
  687. AOP8    ENDP
  688. ;
  689. ; interrupts (imm byte)
  690. ;
  691. AOP9    PROC
  692.     call    noarg2
  693.     call    intsize
  694.     mov    bx,offset arg1
  695.     call    chkimm
  696.     cmp    byte ptr [arg1.addrx],3
  697.     je    aop9i3
  698.     mov    al,byte ptr [si+OPCODE.COMPARE]
  699.     or    al,1
  700.     stosb
  701.     mov    al,byte ptr [bx+asmop.addrx]
  702.     stosb
  703.     clc
  704.     ret
  705. aop9i3:
  706.     mov    al,0cch
  707.     stosb
  708.     ret
  709. AOP9    ENDP
  710. ;
  711. ; short relative branches
  712. ;
  713. AOP10    PROC
  714.     call    noarg2
  715.     call    intsize
  716.     mov    bx,offset arg1
  717.     call    chkimm
  718.     movzx    eax,[lastofs]
  719.     sub    eax,[bx+asmop.addrx]
  720.     neg    eax
  721.     sub    eax,2
  722.     cmp    eax,-128
  723.     jl    aop10errx
  724.     cmp    eax,127
  725.     jle    aop10ok
  726. aop10errx:
  727.     stc
  728.     ret
  729. aop10ok:
  730.     push    ax
  731.     mov    al,byte ptr [si+OPCODE.COMPARE]
  732.     stosb
  733.     pop    ax
  734.     stosb
  735.     clc
  736.     ret
  737. AOP10    ENDP
  738. ;
  739. ; RM, IMMEDIATE
  740. ; bit 0 = size
  741. ;
  742. AOP11    PROC
  743.     call    noarg3
  744.     call    intsize
  745.     mov    bx,offset arg2
  746.     call    chkimm
  747.     mov    bx,offset arg1
  748.     mov    ax,[si+OPCODE.COMPARE]
  749.     call    sizeb0
  750.     stosb
  751.     xchg    al,ah
  752.     call    asmrm2
  753.     mov    bx,offset arg2
  754.     call    rmszimm
  755.     ret
  756. AOP11    ENDP
  757. ;
  758. ; ACC,immediate
  759. ; bit 0 = size
  760. ;
  761. AOP12    PROC
  762.     call    noarg3
  763.     call    intsize
  764.     mov    bx,offset arg1
  765.     call    chkax
  766.     mov    bx,offset arg2
  767.     call    chkimm
  768.     mov    al,byte ptr [si+OPCODE.COMPARE]
  769.     call    sizeb0
  770.     stosb
  771.     call    rmszimm
  772.     ret
  773. AOP12    ENDP
  774. ;
  775. ; mem,acc
  776. ; bit 0 = size
  777. ;
  778. AOP13    PROC
  779.     call    noarg3
  780.     call    intsize
  781.     mov    bx,offset arg2
  782.     call    chkax
  783.     mov    bx,offset arg1
  784.     call    chkmem
  785.     mov    al,byte ptr [si+OPCODE.COMPARE]
  786.     call    sizeb0
  787.     stosb
  788.     call    rmszoffs
  789.     ret
  790. AOP13    ENDP
  791. ;
  792. ; sign-extended RM/IMM
  793. ; b1 = 0, treat as normal RM/IMM (aop11)
  794. ; else b01=11 means sign-extend byte to word
  795. ;
  796. AOP14    PROC
  797.     call    noarg3
  798.     call    intsize
  799.     mov    bx,offset arg2
  800.     call    chkimm
  801.     cmp    [bx+asmop.asize],BYTESIZE
  802.     je    aop11
  803.     mov    eax,[bx +asmop.addrx]
  804.     cmp    eax,-128
  805.     jl    aop11
  806.     cmp    eax,127
  807.     jge    aop11
  808. ;
  809. ; get here for signed extension
  810. ;
  811.     mov    bx,offset arg1
  812.     mov    ax,[si+opcode.compare]
  813.     or    al,3
  814.     stosb
  815.     xchg    al,ah
  816.     call    asmrm2
  817.     mov    al,byte ptr [arg2.addrx]
  818.     stosb
  819.     ret
  820. AOP14    ENDP
  821. ;
  822. ; acc,imm
  823. ; b3 of opcode = size
  824. AOP15    PROC
  825.     call    noarg3
  826.     call    intsize
  827.     mov    bx,offset arg1
  828.     call    chkax
  829.     mov    bx,offset arg2
  830.     call    chkimm
  831.     mov    al,byte ptr [si+OPCODE.COMPARE]
  832.     call    sizeb3
  833.     stosb
  834.     call    rmszimm
  835.     ret
  836. AOP15    ENDP
  837. ;
  838. ; seg,regrm or regrm,seg
  839. ; b1 set if seg is dest
  840. ;
  841. AOP16    PROC
  842.     call    noarg3
  843.     call    intsize
  844.     mov    bx,offset arg1
  845.     cmp    [bx+asmop.mode],AM_SEG
  846.     jne    aop16seg2
  847.     mov    al,byte ptr [si+OPCODE.COMPARE]
  848.     or    al,2
  849.     mov    ah,[bx+asmop.areg1]
  850.     mov    bx,offset arg2
  851.     jmp    aop16rm
  852. aop16seg2:
  853.     mov    bx,offset arg2
  854.     call    chkseg
  855.     mov    al,byte ptr [si+OPCODE.COMPARE]
  856.     mov    ah,[bx+asmop.areg1]
  857.     mov    bx,offset arg1
  858. aop16rm:
  859.     stosb
  860.     xchg    al,ah
  861.     call    asmrm
  862.     ret
  863. AOP16    ENDP
  864. ;
  865. ; returns which pop the stack
  866. ;
  867. AOP17    PROC
  868.     call    noarg2
  869.     call    intsize
  870.     mov    bx,offset arg1
  871.     call    chkimm
  872.     mov    al,byte ptr [si+OPCODE.COMPARE]
  873.     stosb
  874.     mov    ax,word ptr [bx+asmop.addrx]
  875.     stosw
  876.     clc
  877.     ret
  878. AOP17    ENDP
  879. ;
  880. ; far branch or call
  881. ;
  882. AOP18    PROC
  883.     call    noarg2
  884.     call    intsize
  885.     cmp    [arg1.mode],AM_SEGOFFS
  886.     jne    aop18bad
  887.     mov    al,byte ptr [si+OPCODE.COMPARE]
  888.     stosb
  889.     mov    ax,word ptr [arg1.addrx2]
  890.     stosw
  891.     mov    ax,word ptr [arg1.addrx]
  892.     stosw
  893.     clc
  894.     ret
  895. aop18bad:
  896.     stc
  897.     ret
  898. AOP18    ENDP
  899. ;
  900. ; ESC instruction
  901. ; imm,rm... imm is six bits and fills the low three bits of the
  902. ; opcode and the reg field
  903. ;
  904. AOP19    PROC
  905.     call    noarg3
  906.     call    intsize
  907.     mov    bx,offset arg1
  908.     call    chkimm
  909.     mov    al,byte ptr [bx+asmop.addrx]
  910.     shr    al,3
  911.     and    al,7
  912.     or    al,byte ptr [si+OPCODE.compare]
  913.     stosb
  914.     mov    al,byte ptr [bx+asmop.addrx]
  915.     and    al,7
  916.     mov    bx,offset arg2
  917.     call    asmrm
  918.     ret
  919. AOP19    ENDP
  920. ;
  921. ; long relative branch
  922. ;  (the parser fills in the 0f starter)
  923. ;
  924. AOP20    PROC
  925.     call    noarg2
  926.     call    intsize
  927.     mov    bx,offset arg1
  928.     call    chkimm
  929.     movzx    eax,[lastofs]
  930.     sub    eax,[bx+asmop.addrx]
  931.     neg    eax
  932.     sub    eax,3
  933.     cmp    byte ptr [si+OPCODE.COMPARE],0e0h
  934.     jae    aop20got
  935.     dec    eax
  936. aop20got:
  937.     cmp    eax,-32768
  938.     jl    aop20errx
  939.     cmp    eax,32767
  940.     jle    aop20ok
  941. aop20errx:
  942.     stc
  943.     ret
  944. aop20ok:
  945.     push    ax
  946.     mov    al,byte ptr [si+OPCODE.COMPARE]
  947.     stosb
  948.     pop    ax
  949.     stosw
  950.     clc
  951.     ret
  952. AOP20    ENDP
  953. ;
  954. ;    acc,dx (in instructions)
  955. ;    bit 0 = size
  956. ;
  957. AOP21    PROC
  958.     call    noarg3
  959.     call    intsize
  960.     mov    bx,offset arg2
  961.     call    chkdx
  962.     mov    bx,offset arg1
  963.     call    chkax
  964.     mov    al,byte ptr [ si+OPCODE.COMPARE]
  965.     cmp    [bx+asmop.asize],BYTESIZE
  966.     je    aop21nw
  967.     or    al,1
  968. aop21nw:
  969.     cmp    [bx +asmop.asize],DWORDSIZE    ; auto prefixing on
  970.     jne    aop21nw2        ; ins & outs is disabled
  971.     or    [PrefixBitmapWord],AS_OPSIZE
  972. aop21nw2:
  973.     stosb
  974.     clc
  975.     ret
  976. AOP21    ENDP
  977. ;
  978. ; dx,acc (out_)
  979. ; bit 0 = size
  980. ;
  981. AOP22    PROC
  982.     call    noarg3
  983.     call    intsize
  984.     mov    bx,offset arg1
  985.     call    chkdx
  986.     mov    bx,offset arg2
  987.     call    chkax
  988.     mov    al,byte ptr [ si+OPCODE.COMPARE]
  989.     cmp    [bx+asmop.asize],BYTESIZE
  990.     je    aop22nw
  991.     or    al,1
  992. aop22nw:
  993.     cmp    [bx +asmop.asize],DWORDSIZE    ; auto prefixing on
  994.     jne    aop22nw2        ; ins & outs is disabled
  995.     or    [PrefixBitmapWord],AS_OPSIZE
  996. aop22nw2:
  997.     stosb
  998.     clc
  999.     ret
  1000. AOP22    ENDP
  1001. ;
  1002. ; port,acc or acc,port
  1003. ; b0 =size, b1 = 1 if port is dest
  1004. ;
  1005. AOP23    PROC
  1006.     call    noarg3
  1007.     call    intsize
  1008.     test    byte ptr [si+OPCODE.COMPARE],2
  1009.     jz    aop23in
  1010.     mov    bx,offset arg2
  1011.     call    chkax
  1012.     mov    bx,offset arg1
  1013.     call    chkimm
  1014.     jmp    aop23j
  1015. aop23in:
  1016.     mov    bx,offset arg1
  1017.     call    chkax
  1018.     mov    bx,offset arg2
  1019.     call    chkimm
  1020. aop23j:
  1021.     mov    al,byte ptr [si+OPCODE.compare]
  1022.     cmp    [bx +asmop.asize],WORDSIZE
  1023.     jb    aop23b
  1024.            or    al,1
  1025. aop23b:
  1026.     clc
  1027.     stosb
  1028.     mov    al,byte ptr [bx +asmop.addrx]
  1029.     stosb
  1030.     ret
  1031. AOP23    ENDP
  1032. ;
  1033. ; acc,mem
  1034. ; bit 0 = size
  1035. ;
  1036. AOP24    PROC
  1037.     call    noarg3
  1038.     call    intsize
  1039.     mov    bx,offset arg1
  1040.     call    chkax
  1041.     mov    bx,offset arg2
  1042.     call    chkmem
  1043.     mov    al,byte ptr [si+OPCODE.COMPARE]
  1044.     call    sizeb0
  1045.     stosb
  1046.     call    rmszoffs
  1047.     ret
  1048. AOP24    ENDP
  1049. ;
  1050. ; immediate byte or word
  1051. ; this is push imm, bit 1 set for byte
  1052. ; we were about due for a departure from the standard...
  1053. ; anyway the op is sign-extended if it is byte size
  1054. ;
  1055. AOP25    PROC
  1056.     call    noarg2
  1057.     call    intsize
  1058.     mov    bx,offset arg1
  1059.     call    chkimm
  1060.     mov    al,byte ptr [si+OPCODE.COMPARE]
  1061.     mov    ebx,[bx+asmop.addrx]
  1062.     cmp    ebx,-128
  1063.     jl    aop25w
  1064.     cmp    ebx,127
  1065.     jg    aop25w
  1066. ;
  1067. ; byte size
  1068. ;
  1069.     or    al,2
  1070.     stosb
  1071.     mov    al,bl
  1072.     stosb
  1073.     ret
  1074. aop25w:
  1075.     stosb
  1076.     test    [PrefixBitmapWord],AS_OPSIZE
  1077.     jnz    aop25dw
  1078.     cmp    ebx,-23768
  1079.     jl    aop25dw
  1080.     cmp    ebx,32767
  1081.     jg    aop25dw
  1082.     mov    ax,bx
  1083.     stosw
  1084.     clc
  1085.     ret
  1086. aop25dw:
  1087.     or    [PrefixBitmapWord],AS_OPSIZE
  1088.     mov    eax,ebx
  1089.     stosd
  1090.     clc
  1091.     ret
  1092. AOP25    ENDP
  1093. ;
  1094. ; enter command, we have a word then a byte
  1095. ;
  1096. AOP26    PROC
  1097.     call    noarg3
  1098.     call    intsize
  1099.     mov    bx,offset arg1
  1100.     call    chkimm
  1101.     mov    [bx+asmop.asize],WORDSIZE
  1102.     mov    bx,offset arg2
  1103.     call    chkimm
  1104.     mov    [bx+asmop.asize],BYTESIZE
  1105.     mov    al,byte ptr [si+OPCODE.COMPARE]
  1106.     stosb
  1107.     mov    ax,word ptr [arg1.addrx]
  1108.     stosw
  1109.     mov    al,byte ptr [arg2.addrx]
  1110.     stosb
  1111.     ret
  1112. AOP26    ENDP
  1113. ;
  1114. ; stringu/w/d, pushaw,pushfw, etc
  1115. ; explicit byte sizing handled elsewhere (aop0)
  1116. ;
  1117. AOP27    PROC
  1118.     call    noarg1
  1119.     call    intsize
  1120.     mov    al,byte ptr [si+opcode.compare]
  1121.     cmp    [lastbyte],'w'
  1122.     je    aop27w
  1123.     cmp    [lastbyte],'d'
  1124.     je    aop27dw
  1125. ;
  1126. ; get here if no size specced.
  1127.     mov    al,byte ptr [si+opcode.compare]
  1128.     and    al,NOT 1
  1129.     cmp    al,60h        ; default for push/pop is word
  1130.     je    aop27w
  1131.     cmp    al,9ch
  1132.     je    aop27w
  1133.     stosb        ; else default is byte
  1134.     clc
  1135.     ret
  1136. aop27dw:
  1137.     or    [PrefixBitmapWord],AS_OPSIZE    ; come here if specified dword
  1138. aop27w:
  1139.     mov    al,byte ptr [si+opcode.compare] ; or here if specified word
  1140.     stosb
  1141.     clc
  1142.     ret
  1143. AOP27    ENDP
  1144. ;
  1145. ; rm,reg (test instruction)
  1146. ; bit 0 = size
  1147. AOP28    PROC
  1148.     call    noarg3
  1149.     call    intsize
  1150.     mov    bx,offset arg2
  1151.     call    chkreg
  1152.     mov    al,byte ptr [si+OPCODE.COMPARE]
  1153.     call    sizeb0
  1154.     stosb
  1155.     mov    al,[arg2.areg1]
  1156.     mov    bx,offset arg1
  1157.     call    asmrm
  1158.     ret
  1159. AOP28    ENDP
  1160. ;
  1161. ; rm, size don't care
  1162. ;
  1163. AOP29    PROC
  1164.     call    noarg2
  1165.     mov    ax,[si+OPCODE.COMPARE]
  1166.     stosb
  1167.     xchg    al,ah
  1168.     mov    bx,offset arg1
  1169.     call    asmrm2
  1170.     ret
  1171. AOP29    ENDP
  1172. ;
  1173. ; RM, shift
  1174. ; bit 0 & 1 of opcode set if uses CL
  1175. ; bit 0 & 4 set if uses uses 1
  1176. ; else nothing set
  1177. ;
  1178. AOP30    PROC
  1179.     call    noarg3
  1180.     call    intsize
  1181.     mov    ax,word ptr [si+OPCODE.compare]
  1182.     and    al,0ech    ; get rid of extraneous bits
  1183.     mov    bx,offset arg2
  1184.     cmp    [bx+asmop.areg1],isEBX
  1185.     je    aop30cl
  1186.     call    chkimm
  1187.     cmp    [bx+asmop.addrx],1
  1188.     jne    aop30xx
  1189.     or    al,11h
  1190.     stosb
  1191.     xchg    al,ah
  1192.     call    asmrm2
  1193.     ret
  1194. aop30xx:
  1195.     or    al,3
  1196.     stosb
  1197.     xchg    al,ah
  1198.     call    asmrm2
  1199.     mov    al,byte ptr [arg2.addrx]
  1200.     stosb
  1201.     ret
  1202. aop30cl:
  1203.     cmp    [bx+asmop.asize],BYTESIZE
  1204.     jne    aop30bad
  1205.     cmp    [bx+asmop.mode],AM_REG
  1206.     jne    aop30bad
  1207.     stosb
  1208.     xchg    al,ah
  1209.     call    asmrm2
  1210.     ret
  1211.  
  1212. aop30bad:
  1213.     stc
  1214.     ret
  1215. AOP30    ENDP
  1216. ;
  1217. ; reg,rm,imm or reg,imm (imul)
  1218. ; bit 1 = set if immed = signed byte
  1219. ;
  1220. AOP31    PROC
  1221.     cmp    [arg3.mode],AM_NONE
  1222.     jne    aop31three
  1223.     mov    bx,offset arg1
  1224.     call    chkreg
  1225.     mov    al,byte ptr [si+OPCODE.compare]
  1226.     mov    bx,offset arg2
  1227.     call    chkimm
  1228.     call    aop31sb
  1229.     stosb
  1230.     push    ax
  1231.     mov    al,[arg1.areg1]
  1232.     mov    ah,al
  1233.     shl    al,3
  1234.     or    al,ah
  1235.     or    al,0c0h
  1236.     stosb
  1237.     jmp    aop31sz
  1238. aop31three:
  1239.     mov    bx,offset arg1
  1240.     call    chkreg
  1241.     mov    al,byte ptr [si+OPCODE.compare]
  1242.     mov    bx,offset arg3
  1243.     call    chkimm
  1244.     call    aop31sb
  1245.     stosb
  1246.     push    ax
  1247.     push    bx
  1248.     mov    al,[arg1.areg1]
  1249.     mov    bx,offset arg2
  1250.     call    asmrm
  1251.     pop    bx
  1252.     jmp    aop31sz
  1253. aop31sz:
  1254.     pop    ax
  1255.     test    al,2
  1256.     mov    eax,dword ptr [bx +asmop.addrx]
  1257.     jnz    aop31sb1
  1258.     test    [PrefixBitmapWord],AS_OPSIZE
  1259.     jz    aop31szw
  1260.     stosd
  1261.     clc
  1262.     ret
  1263. aop31szw:
  1264.     stosw
  1265.     clc
  1266.     ret
  1267. aop31sb1:
  1268.     stosb
  1269.     clc
  1270.     ret
  1271. aop31sb    PROC
  1272.     mov    ecx,[bx+asmop.addrx]
  1273.     test    ecx,NOT 7fh
  1274.     jnz    aop31sbx
  1275.     cmp    ecx,-80h
  1276.     jl    aop31sbx
  1277.     cmp    [bx+asmop.asize],BYTESIZE
  1278.     je    aop31sbx
  1279.     or    al,2
  1280. aop31sbx:
  1281.     ret
  1282. aop31sb    ENDP
  1283.  
  1284. AOP31    ENDP
  1285. ;
  1286. ; move to/from a special register
  1287. ; bit 1 = set if spc reg is the dest
  1288. ; bit 0 & 2 define the special reg
  1289. ;
  1290. AOP32    PROC
  1291.     call    noarg3
  1292.     call    intsize
  1293.     mov    bx,offset arg1
  1294.     mov    cx,offset arg2
  1295.     mov    ax,[si+OPCODE.COMPARE]
  1296.     cmp    [arg1.asize],DWORDSIZE
  1297.     jne    aop32bad
  1298.     cmp    [arg1.mode],am_reg
  1299.     je    aop32crsource
  1300.     or    al,2
  1301.     xchg    bx,cx
  1302. aop32crsource:               
  1303.     sub    dl,dl
  1304.     cmp    [ecx+asmop.mode],AM_CR
  1305.     je    aop32c
  1306.     mov    dl,1
  1307.     cmp    [ecx+asmop.mode],AM_DR
  1308.     je    aop32c
  1309.     mov    dl,4
  1310.     cmp    [ecx+asmop.mode],AM_TR
  1311.     jne    aop32bad
  1312. aop32c:
  1313.     or    al,dl
  1314.     stosb
  1315.     
  1316.     call    chkreg
  1317.     movzx    ecx,cx
  1318.     mov    al,[ecx+asmop.areg1]
  1319.     shl    al,3
  1320.     or    al,[bx +asmop.areg1]
  1321.     or    al,ah        ; actually is a MOD/RM which is restricted
  1322.                 ; to regs
  1323.     stosb
  1324.     and    [PrefixBitmapWord],NOT AS_OPSIZE    ; don't need opsize for this
  1325.                     ; and there will be no clash
  1326.                     ; if we got this far
  1327.     ret
  1328. aop32bad:
  1329.     stc
  1330.     ret
  1331. AOP32    ENDP
  1332. ;
  1333. ; rm,reg,count (shld/shrd)
  1334. ; bit 0 = set if using CL for count
  1335. ;
  1336. ;
  1337. aop33    PROC
  1338.     mov    bx,offset arg2
  1339.     call    chkreg
  1340.     cmp    [bx+asmop.asize],BYTESIZE
  1341.     je    aop33bad
  1342.     mov    ah,[bx+asmop.areg1]
  1343.     mov    al,byte ptr [si+OPCODE.compare]
  1344.     mov    bx,offset arg3
  1345.     cmp    [bx+asmop.areg1],isECX
  1346.     je    aop33cl
  1347.     call    chkimm
  1348.     stosb
  1349.     xchg    al,ah
  1350.     mov    bx,offset arg1
  1351.     call    asmrm
  1352.     mov    al,byte ptr [arg3.addrx]
  1353.     stosb
  1354.     ret
  1355. aop33cl:
  1356.     cmp    [bx+asmop.mode],AM_REG
  1357.     jne    aop33bad
  1358.     or    al,1h
  1359.     stosb
  1360.     xchg    al,ah
  1361.     mov    bx,offset arg1
  1362.     call    asmrm
  1363.     ret
  1364.  
  1365. aop33bad:
  1366.     stc
  1367.     ret
  1368. AOP33    ENDP
  1369. ;
  1370. ; push & pop rm
  1371. ;
  1372. AOP34    PROC
  1373.     call    noarg2
  1374.     call    intsize
  1375.     mov    bx,offset arg1
  1376.     cmp    [bx+asmop.asize],BYTESIZE
  1377.     je    aop34bad
  1378.     mov    ax,[si+OPCODE.compare]
  1379.     stosb
  1380.     xchg    al,ah
  1381.     call    asmrm2
  1382.     ret
  1383. aop34bad:
  1384.     stc
  1385.     ret
  1386. AOP34    ENDP
  1387. ;
  1388. ; floating R/M
  1389. ; bit two of opcode set if size is qword
  1390. ; bit 3 of mod/rm set if last ch = 'p'
  1391. ;
  1392. AOP35    PROC
  1393.          call    noarg2
  1394.     mov    ax,[si+OPCODE.COMPARE]
  1395.     and    ax,010d8h
  1396.     cmp    [arg1.mode],AM_FPREG
  1397.     je    aop35fin
  1398.     cmp    [arg1.asize],QWORDSIZE
  1399.     jne    aop35fin
  1400.     or    al,4
  1401. aop35fin:
  1402.     cmp    [lastbyte],'p'
  1403.     jne    aop35fin2
  1404.     or    ah,8
  1405. aop35fin2:
  1406.     stosb
  1407.     xchg    al,ah
  1408.     mov    bx,offset arg1
  1409.     call    asmfrm
  1410.     ret
  1411. AOP35    ENDP
  1412. ;
  1413. ; fmathp
  1414. ; sti),st(0) or nothing
  1415. ;
  1416. AOP36    PROC
  1417.     cmp    [arg3.mode],AM_NONE
  1418.     jne    aop36errx
  1419.     mov    ax,100h
  1420.     cmp    [arg2.mode],AM_NONE
  1421.     jne    aop362arg
  1422.     call    noarg1
  1423.     jmp    aop36fin
  1424. aop362arg:
  1425.     cmp    [arg1.mode],AM_FPREG
  1426.     jne    aop36errx
  1427.     cmp    [arg2.mode],AM_FPREG
  1428.     jne    aop36errx
  1429.     cmp    [arg2.areg1],isEAX
  1430.     jne    aop36errx
  1431.     mov    ah,[arg1.areg1]
  1432. aop36fin:
  1433.     or    ax,[si+OPCODE.COMPARE]
  1434.     stosw
  1435.     ret
  1436. aop36errx:
  1437.     stc
  1438.     ret
  1439. AOP36    ENDP
  1440. ;
  1441. ; fmath
  1442. ; st(i),st(0) ; st(0), st(i), mem
  1443. ; bit two of opcode set for i dest or qword mem
  1444. ; bit 3 of mod/rm gets flipped if reg & al &6 & bit 5 of mod/rm set
  1445. ;
  1446. AOP37    PROC
  1447.     cmp    [arg3.mode],AM_NONE
  1448.     jne    aop37errx
  1449.     mov    ax,[si+OPCODE.COMPARE]
  1450.     and    al,NOT 4
  1451.     cmp    [arg2.mode], AM_NONE
  1452.     je    aop37mem
  1453.     cmp    [arg1.mode],AM_FPREG
  1454.     jne    AOP37mem
  1455.     cmp    [arg2.mode],AM_FPREG
  1456.     jne    AOP37errx
  1457.     mov    bl,[arg2.areg1]
  1458.     mov    bh,[arg1.areg1]
  1459.     cmp    bh,0
  1460.     je    aop37isrc
  1461.     cmp    bl,0
  1462.     jne    aop37errx
  1463.     xchg    bl,bh
  1464.     or    al,4
  1465. aop37isrc:
  1466.     test    al,6
  1467.     jz    aop371
  1468.     test    ah,20h
  1469.     jz    aop371
  1470.     xor    ah,8
  1471. aop371:
  1472.     or    ah,bl
  1473.     or    ah,0c0h
  1474.     stosw
  1475.     ret
  1476. aop37mem:
  1477.     cmp    [arg2.mode],AM_NONE
  1478.     jne    aop37errx
  1479.     cmp    [arg1.asize],QWORDSIZE
  1480.     jne    aop37memnq
  1481.     or    al,4
  1482. aop37memnq:
  1483.     stosb
  1484.     xchg    al,ah
  1485.     mov    bx,offset [arg1]
  1486.     call    asmfrm
  1487.     ret
  1488. aop37errx:
  1489.     stc
  1490.     ret
  1491. AOP37    ENDP
  1492. ;
  1493. ; far RM
  1494. ;
  1495. AOP38    PROC
  1496.     call    noarg2
  1497.     cmp    [arg1.asize],DWORDSIZE
  1498.     jne    aop38errx
  1499.     cmp    [arg1.mode],AM_REG
  1500.     je    aop38errx
  1501.     mov    ax,[si+opcode.compare]
  1502.     stosb
  1503.     xchg    al,ah
  1504.     mov    bx,offset arg1
  1505.     call    asmrm2
  1506.     ret
  1507. aop38errx:
  1508.     stc
  1509.     ret
  1510. AOP38    ENDP
  1511. ;
  1512. ; word regrm with reg  source
  1513. ; bug: lets arpl [bx],eax through
  1514. ;
  1515. AOP39    PROC
  1516.     cmp    [arg2.asize],BYTESIZE
  1517.     jne    AOP40
  1518.     stc
  1519.     ret
  1520. AOP39    ENDP
  1521. ;
  1522. ; regrm with reg source
  1523. ; bit 0 = size
  1524. AOP40    PROC
  1525.     call    noarg3
  1526.     call    intsize
  1527.     mov    bx,offset arg2
  1528.     call    chkreg
  1529.     mov    al,byte ptr [si+opcode.compare]
  1530.     call    sizeb0
  1531.     stosb
  1532.     mov    al,[arg2.areg1]
  1533.     mov    bx,offset arg1
  1534.     call    asmrm
  1535.     ret
  1536. AOP40    ENDP
  1537. ;
  1538. ; rm,immediate
  1539. ;
  1540. AOP41    PROC
  1541.     call    noarg3
  1542.     call    intsize
  1543.     mov    bx,offset arg2
  1544.     call    chkimm
  1545.     cmp    [arg1.asize],BYTESIZE
  1546.     je    aop41errx
  1547.     mov    ax,[si+OPCODE.COMPARE]
  1548.     stosb
  1549.     xchg    al,ah
  1550.     mov    bx,offset arg1
  1551.     call    asmrm2
  1552.     mov    al,byte ptr [arg2.addrx]
  1553.     stosb
  1554.     ret
  1555. aop41errx:
  1556.     stc
  1557.     ret
  1558. AOP41    ENDP
  1559. ;
  1560. ; regrm with reg dest & forced strictness (MOVZX & MOVSX)
  1561. ; bit 0 of opcode set if size is word
  1562. ;
  1563. AOP42    PROC
  1564.     call    noarg3
  1565.     call    intsize
  1566.     mov    bx,offset arg1
  1567.     call    chkreg
  1568.     cmp    [arg1.asize],BYTESIZE
  1569.     je    aop42errx
  1570.     cmp    [arg2.asize],NOSIZE
  1571.     je    aop42errx
  1572.     mov    bx,offset arg2
  1573.     mov    ax,[si+OPCODE.COMPARE]
  1574.     call    sizeb0
  1575.     stosb
  1576.     xchg    al,ah
  1577.     call    asmrm2
  1578.     cmp    [arg1.asize],DWORDSIZE    ; another func for which
  1579.                     ; auto extend to dword doesn't work
  1580.     jne    aop42x
  1581.     or    [PrefixBitmapWord],AS_OPSIZE
  1582. aop42x:
  1583.     clc
  1584.     ret
  1585. aop42errx:
  1586.     stc
  1587.     ret
  1588. AOP42    ENDP
  1589. ;
  1590. ; not needed in assembler, same as no args
  1591. AOP43    PROC
  1592.     jmp    aop0
  1593. AOP43    ENDP
  1594. ;
  1595. ; unused
  1596. ;
  1597. AOP44    PROC
  1598.     call    noarg2
  1599.     call    intsize
  1600.     mov    bx,offset arg1
  1601.     call    chkreg
  1602.     cmp    [bx+asmop.asize],DWORDSIZE
  1603.     jne    aop44errx
  1604.     or    [PrefixBitmapWord],AS_OPSIZE
  1605.     mov    al,byte ptr [si+OPCODE.COMPARE]
  1606.     or    al,[bx+asmop.areg1]
  1607.     stosb
  1608.     ret
  1609. aop44errx:
  1610.     stc
  1611.     ret
  1612. AOP44    ENDP
  1613. ;
  1614. ; any regrm with reg source
  1615. ; same as aop40
  1616. ;
  1617. AOP45    PROC
  1618.     jmp    aop40
  1619. AOP45    ENDP
  1620. ;
  1621. ; rm , size don't care, but no regs
  1622. ;
  1623. AOP46    PROC
  1624.     cmp    [arg1.mode],AM_FPREG
  1625.     je    aop46err
  1626.     cmp    [arg1.mode],AM_REG
  1627.     jne    aop29
  1628. aop46err:
  1629.     stc
  1630.     ret
  1631. AOP46    ENDP
  1632. ;
  1633. ; ax reg only
  1634. ;
  1635. AOP47    PROC
  1636.     call    noarg2
  1637.     mov    bx,offset arg1
  1638.     call    chkaxw
  1639.     mov    ax,[si+OPCODE.COMPARE]
  1640.     stosw
  1641.     clc
  1642.     ret
  1643. AOP47    ENDP
  1644. ;
  1645. ; bswap, 32-bit reg to bits 0-3 of opcode
  1646. ;
  1647. AOP48    PROC
  1648.     call    noarg2
  1649.     call    intsize
  1650.     mov    bx,offset arg1
  1651.     call    chkreg
  1652.     cmp    [bx+asmop.asize],DWORDSIZE
  1653.     jne    aop48errx
  1654.     or    [PrefixBitmapWord],AS_OPSIZE
  1655.     mov    al,byte ptr [si+OPCODE.COMPARE]
  1656.     or    al,[bx+asmop.areg1]
  1657.     stosb
  1658.     ret
  1659. aop48errx:
  1660.     stc
  1661.     ret
  1662. AOP48    ENDP
  1663. ;
  1664. ; fst
  1665. ; same as next but no tbyte
  1666. ;
  1667. AOP49    PROC
  1668.     cmp    [arg1.asize],TBYTESIZE
  1669.     jb    aop50
  1670.     stc
  1671.     ret
  1672. AOP49    ENDP
  1673. ;
  1674. ; fld/fstp
  1675. ; freg
  1676. ; dword,qword,tybe
  1677. ; bit 1 of opcode set for tbyte
  1678. ; bit 2 of opcode set for qword or store
  1679. ; bit 5 of modrm set if tbyte
  1680. ; bit 3 of modrm gets cleared if not tbyte && bit 4 set
  1681. ;
  1682. AOP50    PROC
  1683.     call    noarg2
  1684.     mov    ax,[si+OPCODE.COMPARE]
  1685.     AND    ax,NOT 0e006h
  1686.     cmp    [arg1.mode],AM_FPREG
  1687.     je    aop50reg
  1688.     cmp    [arg1.asize],DWORDSIZE
  1689.     jb    aop50errx
  1690. aop502:
  1691.     cmp    [arg1.asize],TBYTESIZE
  1692.     jne    aop503
  1693.     or    ax,2802h
  1694.     jmp    aop505
  1695.  
  1696. aop503:
  1697.     
  1698.     cmp    [arg1.asize],QWORDSIZE
  1699.     jne    aop504
  1700.     or    al,4
  1701. aop504:
  1702.     test    ah,10h
  1703.     jnz    aop505
  1704.     and    ah,NOT 8
  1705. aop505:
  1706.     stosb
  1707.     xchg    al,ah
  1708.     mov    bx,offset arg1
  1709.     call    asmfrm
  1710.     ret
  1711. aop50reg:
  1712.     test    ah,10h
  1713.     jnz    aop506
  1714.     and    ah,NOT 8
  1715.     jmp    aop507
  1716. aop506:
  1717.     or    al,4
  1718. aop507:
  1719.     or    ah,0c0h
  1720.     or    ah,[arg1.areg1]
  1721.     stosw
  1722.     ret
  1723. aop50errx:
  1724.     stc
  1725.     ret
  1726. AOP50    ENDP
  1727. ;
  1728. ;
  1729. ; fbld/fbstp
  1730. ; tbyte ptr mem
  1731. ;
  1732. AOP51    PROC
  1733.     call    noarg2
  1734.     cmp    [arg1.mode],AM_FPREG
  1735.     je    aop51errx
  1736.     cmp    [arg1.asize],NOSIZE
  1737.     je    aop51c
  1738.     cmp    [arg1.asize],TBYTESIZE
  1739.     jne    aop51errx
  1740. aop51c:
  1741.     mov    ax,[si+OPCODE.COMPARE]
  1742.     stosb
  1743.     xchg    al,ah
  1744.     mov    bx,offset arg1
  1745.     call    asmfrm
  1746.     ret
  1747. aop51errx:
  1748.     stc
  1749.     ret
  1750. AOP51    ENDP
  1751. ;
  1752. ; fild/fistp
  1753. ; word,dword,qword mem
  1754. ; bit 2 of opcode set if word or qword
  1755. ; bit 3 of modrm gets cleared if not qword & bit 4 is set
  1756. ; bit 5 or modrm set if qword
  1757. ;
  1758. AOP52    PROC
  1759.     call    noarg2
  1760.     mov    ax,[si+OPCODE.COMPARE]
  1761.     and    ax,NOT 2004h
  1762.     cmp    [arg1.mode],AM_FPREG
  1763.     je    aop52errx
  1764.     cmp    [arg1.asize],DWORDSIZE
  1765.     je    aop522
  1766.            or    al,4
  1767. aop522:
  1768.     cmp    [arg1.asize],QWORDSIZE
  1769.     ja    aop52errx
  1770.     jne    aop523
  1771.     or    ah,20h
  1772.     jmp    aop524
  1773. aop523:
  1774.     test    ah,10h
  1775.     jnz    aop524
  1776.     and    ah, NOT 8
  1777. aop524:    
  1778.     stosb
  1779.     xchg    al,ah
  1780.     mov    bx,offset arg1
  1781.     call    asmfrm
  1782.     ret
  1783. aop52errx:
  1784.     stc
  1785.     ret
  1786. AOP52    ENDP
  1787. ;
  1788. ; fist
  1789. ; same as above but no qword mode
  1790. ;
  1791. AOP53    PROC
  1792.     cmp    [arg1.asize],QWORDSIZE
  1793.     jb    aop52
  1794.     stc
  1795.     ret
  1796. AOP53    ENDP
  1797. ;
  1798. ; freg
  1799. ; reg put in mod/rm byte
  1800. ;
  1801. AOP54    PROC
  1802.     call    noarg2
  1803.     cmp    [arg1.mode],AM_FPREG
  1804.     jne    aop54errx
  1805.     mov    ax,[si+OPCODE.COMPARE]
  1806.     or    ah,[arg1.areg1]
  1807.     stosw
  1808.     ret
  1809. aop54errx:
  1810.     stc
  1811.     ret
  1812. AOP54    ENDP
  1813. ;
  1814. ; same as above, deault to reg 1 if no args
  1815. AOP55    PROC
  1816.     cmp    [arg3.mode],AM_NONE
  1817.     jne    aop55errx
  1818.     cmp    [arg2.mode],AM_NONE
  1819.     jne    aop55errx
  1820.     call    noarg2
  1821.     mov    ax,[si+OPCODE.COMPARE]
  1822.     cmp    [arg1.mode],AM_FPREG
  1823.     jne    aop55chknone
  1824.     or    ah,[arg1.areg1]
  1825.     stosw
  1826.     ret
  1827. aop55chknone:
  1828.     cmp    [arg1.mode],AM_NONE
  1829.     jne      aop55errx
  1830.     or    ah,1
  1831.     stosw
  1832.     ret    
  1833. aop55errx:
  1834.     stc
  1835.     ret
  1836. AOP55    ENDP
  1837. ;
  1838. ; fimath
  1839. ; word or dword arg
  1840. ; bit two gets set if word
  1841. ;
  1842. AOP56    PROC
  1843.     call    noarg2
  1844.     call    intsize
  1845.     cmp    [arg1.asize],BYTESIZE
  1846.     je    aop56errx
  1847.     cmp    [arg1.mode],AM_FPREG
  1848.     je    aop56errx
  1849.     mov    ax,[si+OPCODE.COMPARE]
  1850.     cmp    [arg1.asize],WORDSIZE
  1851.     jne    aop56c
  1852.     or    al,4
  1853. aop56c:
  1854.     stosb
  1855.     xchg    al,ah
  1856.     mov    bx,offset arg1
  1857.     call    asmfrm
  1858.     ret
  1859. aop56errx:
  1860.     ret
  1861.  
  1862. AOP56    ENDP
  1863.  
  1864. ;
  1865. ; addrsize prefix on one-byte
  1866. ;
  1867. AOP57    PROC
  1868.     or    [PrefixBitmapWord],AS_ADDRSIZE
  1869.     jmp    aop0
  1870. AOP57    ENDP
  1871. ;
  1872. ; opsize prefix on one-byte
  1873. ;
  1874. AOP58    PROC
  1875.     or    [PrefixBitmapWord],AS_OPSIZE
  1876.     jmp    aop0
  1877. AOP58    ENDP
  1878.     end