"$Header$" /* * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. * * This product is part of the Amsterdam Compiler Kit. * * Permission to use, sell, duplicate or disclose this software must be * obtained in writing. Requests for such permissions may be sent to * * Dr. Andrew S. Tanenbaum * Wiskundig Seminarium * Vrije Universiteit * Postbox 7161 * 1007 MC Amsterdam * The Netherlands * */ #define SL 4 #define SSL "4" #define REGVARS /******************************************************** * Back end tables for Intel 8086 * * Author : Ed Keizer * * Added register variables: Ceriel Jacobs * * * wordsize = 2 bytes, pointersize = 2 bytes. * * * * Register bp is used as LB, sp is used for SP. * * Some global variables are used: * * - .reghp : the heap pointer * * - .ignmask : trap ignore mask * * - .trppc : address of user defined trap handler * * * * Floating point arithmetic and constants are not * * implemented. * * ********************************************************/ /* #define DEEPER 1 /* When DEEPER is disabled, the table contains some heuristics based on the assumption that look-ahead will be minimal. Example: Addition of constants to registers will no take place via ax, but in an address register, in the rules for ads. Thereby assuming that the resulting register will be used to access memory. When DEEPER is enabled these heuristics are disabled thereby allowing the code-generator too see for itself which code will be shorter. */ #define SPEED 1 /* This definition produces a slightly different table, producing slightly less efficient code with greater speed */ #ifdef SPEED #define NO nocoercions : #else #define NO #endif EM_WSIZE=2 EM_PSIZE=2 EM_BSIZE=SL SIZEFACTOR=5 REGISTERS: al = ("al", 2), REG1, ACC1. ah = ("ah", 2), REG1. bl = ("bl", 2), REG1. bh = ("bh", 2), REG1. cl = ("cl", 2), REG1, SHIFT_CREG. ch = ("ch", 2), REG1. dl = ("dl", 2), REG1. dh = ("dh", 2), REG1. ax = ("ax", 2, al, ah), REG, GENREG, ACC. cx = ("cx", 2, cl, ch), REG, GENREG, CXREG, SHIFT_CREG. dx = ("dx", 2, dl, dh), REG, GENREG, DXREG. bx = ("bx", 2, bl, bh), REG, GENREG, BREG, BXREG, ADDREG. #ifdef REGVARS si = ("si", 2) regvar, RREG, RADDREG. di = ("di", 2) regvar, RREG, RADDREG. #else si = ("si", 2), REG, IREG, SIREG, ADDREG. di = ("di", 2), REG, IREG, DIREG, ADDREG. #endif bp = ("bp", 2), BREG. TOKENS: /******************************** * Types on the EM-machine * ********************************/ ANYCON = { INT val ; } 2 cost=(2, 1) "%[val]" ADDR_EXTERN = { STRING off ; } 2 cost=(2, 1) "%[off]" EXTERN1 = { STRING off ; } 2 cost=(2,12) "(%[off])" EXTERN2 = { STRING off ; } 2 cost=(2,12) "(%[off])" ADDR_LOCAL = { INT ind ; } 2 cost=(1, 9) "%[ind](bp)" LOCAL2 = { INT ind, size ; } 2 cost=(1,15) "%[ind](bp)" LOCAL1 = { INT ind, size ; } 2 cost=(1,15) "%[ind](bp)" /******************************************************** * Now mostly addressing modes of target machine * ********************************************************/ /***************************************** * 'Half modes' consisting of summations * * of constant and or register(s) * *****************************************/ Xreg_off = { REGISTER reg; STRING off; } 2 cost=(1, 9) "%[off](%[reg])" Xbpreg_off = { REGISTER reg; INT ind; } 2 cost=(1,11) "%[ind](bp)(%[reg])" Rreg_off = { REGISTER reg; STRING off; } 2 cost=(1, 9) "%[off](%[reg])" Rbpreg_off = { REGISTER reg; INT ind; } 2 cost=(1,11) "%[ind](bp)(%[reg])" /************************************************** * Indirect through registers and the modes above * * Token names ending on digits are indirect * **************************************************/ ind_reg2 = { REGISTER reg; } 2 cost=(0,11) "(%[reg])" ind_regoff2 = { REGISTER reg; STRING off; } 2 cost=(1,15) "%[off](%[reg])" ind_bpregoff2 = { REGISTER reg; INT ind; } 2 cost=(1,18) "%[ind](bp)(%[reg])" ind_reg1 = { REGISTER reg; } 2 cost=(0,11) "(%[reg])" ind_regoff1 = { REGISTER reg; STRING off; } 2 cost=(1,15) "%[off](%[reg])" ind_bpregoff1 = { REGISTER reg; INT ind; } 2 cost=(1,18) "%[ind](bp)(%[reg])" TOKENEXPRESSIONS: /* SCRATCH REGISTERS */ X_ACC = ACC*SCRATCH X_ACC1 = ACC1*SCRATCH X_REG = REG*SCRATCH X_BXREG = BXREG*SCRATCH X_DXREG = DXREG*SCRATCH X_CXREG = CXREG*SCRATCH #ifndef REGVARS X_SIREG = SIREG*SCRATCH X_DIREG = DIREG*SCRATCH #endif X_ADDREG = ADDREG*SCRATCH #ifdef REGVARS IREG = RREG #endif /* Mode refering to a word in memory */ memory2 = EXTERN2 + ind_reg2 + ind_regoff2 + ind_bpregoff2 + LOCAL2 /* Mode refering to a byte in memory */ memory1 = EXTERN1 + ind_reg1 + ind_regoff1 + ind_bpregoff1 + LOCAL1 /* Modes allowed in instructions */ const = ANYCON + ADDR_EXTERN register = REG #ifdef REGVARS + RREG #endif anyreg = register + BREG addreg = ADDREG #ifdef REGVARS + RADDREG #endif rm = anyreg + memory2 rmnoacc = RREG + BREG + CXREG + memory2 rmorconst = const + rm noregvar = const + REG + BREG + memory2 regorconst = const + anyreg #ifdef REGVARS /* Needed because there is a shortage of ADDREG-registers. This is the main penalty for having register variables. */ regorconstnoaddr = const + RREG + ACC + CXREG + DXREG #else regorconstnoaddr = regorconst #endif dest = register + memory2 rm1 = REG1 + memory1 rmorconst1 = const + rm1 regorconst12 = REG1 + GENREG + const dest1 = REG1 + memory1 /* Modes used to indicate tokens to be removed from the fakestack */ reg_indexed = ind_reg2 + ind_regoff2 + ind_reg1 + ind_regoff1 lb_indexed = ind_bpregoff2 + ind_bpregoff1 indexed = reg_indexed + lb_indexed externals = EXTERN2 + EXTERN1 locals = LOCAL2 + LOCAL1 all_locals = locals + lb_indexed indirects = externals + reg_indexed referals = indirects + locals /* Miscellaneous */ reg_off = Xreg_off + Rreg_off bpreg_off = Xbpreg_off + Rbpreg_off halfindir = reg_off + bpreg_off + ADDR_LOCAL a_word = rmorconst + rm1 + halfindir no_reg_off = rmorconst + rm1 + ADDR_LOCAL #ifdef REGVARS uses_bx = ADDREG + Xreg_off + Xbpreg_off #endif CODE: /******************************************************** * Group 1 : load instructions. * * * * For most load instructions no code is generated. * * Action : put something on the fake-stack. * ********************************************************/ loc | | | {ANYCON, $1} | | ldc | | | {ANYCON, highw(1)} {ANYCON, loww(1)} | | #ifdef REGVARS lol inreg($1)==2 | | | regvar($1) | | #endif lol | | | {LOCAL2, $1, 2} | | loe | | | {EXTERN2, $1} | | loe loe $1==$2 | | allocate(REG={EXTERN2, $1}) | %[a] %[a] | | #ifdef REGVARS lol lol $1==$2 && inreg($1)!=2 | | allocate(REG={LOCAL2, $1, 2})| %[a] %[a] | | #else lol lol $1==$2 | | allocate(REG={LOCAL2, $1, 2})| %[a] %[a] | | #endif #ifdef REGVARS lil inreg($1)==2 | | | {ind_reg2, regvar($1)} | | #endif lil | | allocate(ADDREG={ind_regoff2, bp, tostring($1)}) | {ind_reg2, %[a]} | | lof | nocoercions : reg_off | | {ind_regoff2, %[1.reg], %[1.off]+"+"+tostring($1)} | | ... | addreg | | {ind_regoff2,%[1],tostring($1)} | | ... | nocoercions : bpreg_off | | {ind_bpregoff2,%[1.reg], %[1.ind]+$1} | | ... | nocoercions : ADDR_EXTERN| | {EXTERN2,%[1.off]+"+"+tostring($1)} | | ... | nocoercions : ADDR_LOCAL | | {LOCAL2, %[1.ind] + $1,2} | | lal | | | {ADDR_LOCAL, $1} | | lae | | | {ADDR_EXTERN, $1} | | lpb | | | | adp SL | lxl $1==0 | | | {ADDR_LOCAL, 0} | | lxl $1==1 | | | {LOCAL2 ,SL, 2} | | lxl $1==2 | | allocate(ADDREG={ind_regoff2, bp, SSL}) | {ind_regoff2,%[a], SSL} | | lxl $1>2 | | allocate(ADDREG={ind_regoff2, bp, SSL}, CXREG={ANYCON,$1-1}) "1:\tmov %[a],4(%[a])" "loop 1b" samecc erase(%[a]) erase(%[b]) | %[a] | | lxa $1==0 | | | {ADDR_LOCAL, SL} | | lxa $1==1 | | allocate(ADDREG={ind_regoff2, bp, SSL }) | {Xreg_off, %[a], SSL } | | lxa $1==2 | | allocate(ADDREG={ind_regoff2, bp, SSL }) move({ind_regoff2, %[a], SSL }, %[a]) | {Xreg_off, %[a], SSL } | | lxa $1 > 2 | | allocate(ADDREG={ind_regoff2,bp,SSL}, CXREG={ANYCON,$1-1}) "1:\tmov %[a],4(%[a])" "loop 1b" samecc erase(%[a]) erase(%[b]) | {Xreg_off, %[a], SSL } | | dch | | | | loi 2 | loi $1==2 | addreg | | {ind_reg2, %[1]} | | ... | nocoercions : reg_off | | {ind_regoff2, %[1.reg], %[1.off]} | | ... | nocoercions : bpreg_off | | {ind_bpregoff2, %[1.reg], %[1.ind]} | | ... | nocoercions : ADDR_EXTERN| | {EXTERN2, %[1.off]} | | ... | nocoercions : ADDR_LOCAL | | {LOCAL2, %[1.ind],2} | | loi $1==1 | addreg | | {ind_reg1, %[1]} | | ... | nocoercions : reg_off | | {ind_regoff1, %[1.reg], %[1.off]} | | ... | nocoercions : bpreg_off | | {ind_bpregoff1, %[1.reg], %[1.ind]} | | ... | nocoercions : ADDR_EXTERN | | {EXTERN1, %[1.off]} | | ... | nocoercions : ADDR_LOCAL | | {LOCAL1, %[1.ind],1} | | loi $1==4 | addreg | | {ind_regoff2,%[1],"2"} {ind_reg2,%[1]}| | ... | nocoercions : reg_off | | {ind_regoff2,%[1.reg], %[1.off]+"+2"} {ind_regoff2,%[1.reg], %[1.off]} | | ... | nocoercions : bpreg_off | | {ind_bpregoff2, %[1.reg], %[1.ind]+2} {ind_bpregoff2, %[1.reg], %[1.ind]} | | ... | nocoercions : ADDR_LOCAL | | {LOCAL2,%[1.ind]+2,2} {LOCAL2,%[1.ind],2} | | ... | nocoercions : ADDR_EXTERN| | {EXTERN2, %[1.off]+"+2"} {EXTERN2, %[1.off]} | | /* loi $1>4 | noregvar | remove(ALL) allocate(CXREG={ANYCON,$1/2}) "mov ax,si" "mov bx,di" "mov si,%[1]" "sub sp,%($1%)" "mov di,sp" "rep movs" "mov si,ax" "mov di,bx" erase(%[a]) | | | (16,16+$1*9) WRONG! */ loi $1>4 | X_BXREG | remove(ALL) allocate(CXREG={ANYCON,$1}) "call .loi" erase(%[a]) erase(%[1]) | | | (3,40+$1*9) los $1==2 | X_CXREG X_BXREG | remove(ALL) "call .loi" erase(%[1]) erase(%[2]) | | | los !defined($1)| rm X_CXREG X_BXREG | remove(ALL) "cmp %[1],2" "jne .unknown" "call .loi" erase(%[2]) erase(%[3]) | | | ldl | | | {LOCAL2, $1+2,2} {LOCAL2, $1,2} | | lde | | | {EXTERN2, $1+"+2"} {EXTERN2, $1} | | ldf | nocoercions : reg_off | | {ind_regoff2, %[1.reg], %[1.off]+"+2+"+tostring($1)} {ind_regoff2, %[1.reg], %[1.off]+"+"+tostring($1)} | | ... | addreg | | {ind_regoff2, %[1], tostring($1+2)} {ind_regoff2, %[1], tostring($1)} | | ... | nocoercions : bpreg_off | | {ind_bpregoff2,%[1.reg], %[1.ind]+2+$1} {ind_bpregoff2,%[1.reg], %[1.ind]+$1} | | ... | nocoercions : ADDR_EXTERN | | {EXTERN2,%[1.off]+"+2+"+tostring($1)} {EXTERN2,%[1.off]+"+"+tostring($1)} | | ... | nocoercions : ADDR_LOCAL | | {LOCAL2, %[1.ind] + $1 + 2, 2} {LOCAL2, %[1.ind] + $1, 2} | | lpi | | | {ADDR_EXTERN, $1} | | /* This code sequence is generated by the C-compiler to tackle char parameters, on the 8086 it reduces to nil */ lol lal sti $1==$2 && $3<=2 | | | | | /**************************************************************** * Group 2 : Store instructions. * * * * These instructions are likely to ruin the fake-stack. * * We don't expect many items on the fake-stack anyway * * because we seem to have evaluated an expression just now. * ****************************************************************/ #ifdef REGVARS stl inreg($1)==2 | rmorconst | move(%[1], regvar($1)) | | | ... | nocoercions : STACK | "pop %(regvar($1)%)" samecc | | |(1,8) #endif stl | regorconst | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) move(%[1],{ind_regoff2,bp,tostring($1)})| | | ... | nocoercions : STACK | "pop $1(bp)" samecc | | |(2,26) ste | regorconst | remove(indirects) move(%[1], {EXTERN2, $1 }) | | | ... | nocoercions : STACK | "pop ($1)" samecc | | | #ifdef REGVARS sil inreg($1)==2| regorconst | remove(referals) move(%[1],{ind_reg2, regvar($1)}) | | | ... | nocoercions : STACK | "pop (%(regvar($1)%))" samecc | | |(2,26) #endif sil | regorconstnoaddr | allocate(ADDREG={ind_regoff2, bp, tostring($1)}) remove(referals) move(%[1], {ind_reg2, %[a]}) | | | ... | STACK | allocate(ADDREG={ind_regoff2, bp, tostring($1)}) remove(referals) "pop (%[a])" samecc | | | (2,26) stf | addreg regorconst | remove(referals) move(%[2],{ind_regoff2,%[1],tostring($1)})| | | ... | nocoercions : addreg STACK | remove(referals) "pop $1(%[1])" samecc | | | ... | reg_off regorconst | remove(referals) move(%[2],{ind_regoff2,%[1.reg], %[1.off]+"+"+tostring($1)}) | | | ... | nocoercions : halfindir STACK | remove(referals) "pop $1+%[1]" samecc | | | ... | nocoercions : ADDR_LOCAL | | | stl %[1.ind]+$1 | ... | bpreg_off regorconst | remove(all_locals) remove(indexed) move(%[2],{ind_bpregoff2,%[1.reg], %[1.ind]+$1}) | | | /* ... | ADDR_EXTERN regorconst | remove(indirects) move(%[2],{EXTERN2,%[1.off]+"+"+tostring($1)})| | | */ sti $1==2 | addreg regorconst | remove(referals) move(%[2],{ind_reg2,%[1]}) | | | ... | nocoercions : addreg STACK | remove(referals) "pop (%[1])" samecc | | | ... | reg_off regorconst | remove(referals) move(%[2],{ind_regoff2,%[1.reg],%[1.off]}) | | | ... | nocoercions : reg_off STACK | remove(referals) "pop %[1]" samecc | | | ... | nocoercions : ADDR_LOCAL | | | stl %[1.ind] | ... | bpreg_off regorconst | remove(all_locals) remove(indexed) move(%[2],{ind_bpregoff2,%[1.reg], %[1.ind]}) | | | ... | nocoercions : bpreg_off STACK | remove(all_locals) remove(indexed) "pop %[1]" samecc | | | ... | ADDR_EXTERN regorconst | remove(indirects) move(%[2],{EXTERN2,%[1.off]}) | | | ... | nocoercions : ADDR_EXTERN STACK | remove(indirects) "pop (%[1])" samecc | | | sti $1==1 | addreg regorconst12 | remove(referals) move(%[2],{ind_reg1,%[1]}) | | | ... | reg_off regorconst12 | remove(referals) move(%[2],{ind_regoff1,%[1.reg],%[1.off]}) | | | ... | bpreg_off regorconst12 | remove(all_locals) remove(indexed) move(%[2],{ind_bpregoff1,%[1.reg], %[1.ind]}) | | | ... | ADDR_EXTERN regorconst12 | remove(indirects) move(%[2],{EXTERN1,%[1.off]}) | | | ... | ADDR_LOCAL regorconst12 | remove(indexed) remove(locals, %[ind]<=%[1.ind] && %[ind]+%[size]>%[1.ind] ) move(%[2],{LOCAL1, %[1.ind], 1}) | | | sti $1==4 | addreg regorconst regorconst | remove(referals) move(%[2],{ind_reg2,%[1]}) move(%[3],{ind_regoff2,%[1],"2"}) | | | ... | reg_off regorconst regorconst | remove(referals) move(%[2],{ind_regoff2,%[1.reg],%[1.off]}) move(%[3],{ind_regoff2,%[1.reg],%[1.off]+"+2"})| | | ... | bpreg_off regorconst regorconst | remove(all_locals) remove(indexed) move(%[2],{ind_bpregoff2,%[1.reg], %[1.ind]}) move(%[3],{ind_bpregoff2,%[1.reg], %[1.ind]+2})| | | ... | ADDR_EXTERN regorconst regorconst | remove(indirects) move(%[2],{EXTERN2,%[1.off]}) move(%[3],{EXTERN2,%[1.off]+"+2"}) | | | ... | ADDR_LOCAL regorconst regorconst | remove(indexed) remove(locals, %[ind]>=%[1.ind] && %[ind]<%[1.ind]+4 ) move(%[2],{ind_regoff2, bp, tostring(%[1.ind])}) move(%[3],{ind_regoff2, bp, tostring(%[1.ind]+2)})| | | /* sti $1>4 | noregvar | remove(ALL) allocate(CXREG={ANYCON,$1/2}) "mov ax,si" "mov bx,di" "mov si,sp" "mov di,%[1]" "rep movs" "mov sp,si" "mov si,ax" "mov di,bx" erase(%[a]) | | | (14,12+$1*8) WRONG! */ sti $1>4 | X_BXREG | remove(ALL) allocate(CXREG={ANYCON,$1}) "call .sti" erase(%[a]) erase(%[1]) | | | (3,40+$1*9) /* This sort of construction gives problems in the codegenerator because of the potential verly large lookahead ... | X_ADDREG | remove(ALL) "pop (%[1])" "add %[1],2" erase(%[1]) | %[1] | sti $1-2 | (5,30) */ sts $1==2 | X_CXREG X_BXREG | remove(ALL) "call .sti" erase(%[1]) erase(%[2]) | | | sdl | | | | stl $1 stl $1+2 | sde | | | | ste $1 ste $1+"+2" | sdf | addreg regorconst regorconst | remove(referals) move(%[2],{ind_regoff2,%[1],tostring($1)}) move(%[3],{ind_regoff2,%[1],tostring($1+2)})| | | ... | nocoercions : addreg STACK | remove(referals) "pop $1(%[1])" "pop %($1+2%)(%[1])" samecc | | | ... | reg_off regorconst regorconst | remove(referals) move(%[2],{ind_regoff2,%[1.reg], %[1.off]+"+"+tostring($1)}) move(%[3],{ind_regoff2,%[1.reg], %[1.off]+"+"+tostring($1+2)}) | | | ... | nocoercions : halfindir STACK | remove(referals) "pop $1+%[1]" "pop %($1+2%)+%[1]" samecc | | | /* Funny things happen when the sign changes in the stl parameters */ ... | nocoercions: ADDR_LOCAL | | | stl %[1.ind]+$1 stl %[1.ind]+$1+2 | ... | bpreg_off regorconst regorconst | remove(all_locals) remove(indexed) move(%[2],{ind_bpregoff2,%[1.reg], %[1.ind]+$1}) move(%[3],{ind_bpregoff2,%[1.reg], %[1.ind]+$1+2}) | | | ... | halfindir regorconst | remove(referals) "mov %[1],%[2]" samecc | %[1] | stf $1+2 | (0,12)+%[1]+%[2]+%[1] /**************************************************************** * Group 3 : Integer arithmetic. * * * * Implemented (sometimes with the use of subroutines) : * * all 2 and 4 byte arithmetic. * ****************************************************************/ adi $1==2 | NO X_REG rmorconst | "add %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (2,3) + %[2] ... | rmorconst X_REG | "add %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | X_ACC const | "add %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (3,4) ... | const X_ACC | "add %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) adi $1==4 | NO X_REG X_REG rmorconst rmorconst | "add %[1],%[3]" "adc %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(4,6)+%[4]+%[3] ... | X_ACC X_REG const rmorconst | "add %[1],%[3]" "adc %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(5,7)+%[4] ... | rmorconst rmorconst X_REG X_REG | "add %[3],%[1]" "adc %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(4,6)+%[1]+%[2] ... | const rmorconst X_ACC X_REG | "add %[3],%[1]" "adc %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(5,7)+%[2] adi !defined($1)| X_CXREG X_ACC | remove(ALL) "call .adi" erase(%[1]) erase(%[2]) | ax | | sbi $1==2 | rmorconst X_REG | "sub %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | const X_ACC | "sub %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) ... | NO X_REG rmorconst | "sub %[1],%[2]" "neg %[1]" erase(%[1]) setcc(%[1]) | %[1] | | (4,6) + %[2] ... | NO X_ACC const | "sub %[1],%[2]" "neg %[1]" erase(%[1]) setcc(%[1]) | %[1] | | (5,7) sbi $1==4 | rmorconst rmorconst X_REG X_REG | "sub %[3],%[1]" "sbb %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(4,6)+%[1]+%[2] ... | const rmorconst-ACC X_ACC X_REG | "sub %[3],%[1]" "sbb %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(5,7)+%[2] sbi !defined($1)| X_CXREG X_ACC | remove(ALL) "call .sbi" erase(%[1]) erase(%[2]) | ax | | mli $1==2 | X_ACC rm | allocate(%[2],DXREG) "mul %[2]" /* mul and imul have same low order result but mul is faster */ nocc erase(%[1]) | %[1] | |(2,118)+%[2] ... | rmnoacc rmorconst | allocate(%[2],ACC=%[2],DXREG) "mul %[1]" nocc erase(%[a]) | ax | |(2,118)+%[1] mli $1==4 | X_ACC X_DXREG | remove(ALL) "call .mli4" erase(ax) erase(dx) setcc(dx) | dx ax | | /* Not now, mli !defined($1)| X_ACC | remove(ALL) "call .mli" | | | */ dvi $1==2 | rmnoacc rmorconst | allocate(%[2], ACC=%[2], DXREG) "cwd" "idiv %[1]" erase(%[a]) | ax | |(3,176)+%[1] dvi $1==4 | | remove(ALL) "call .dvi4" | dx ax | | /* dvi !defined($1)| X_ACC | remove(ALL) "call .dvi" erase(%[1]) | | | */ #ifdef LONGEMPAT loc loc cii dvi loc loc cii $1==2 && $2==4 && $4==4 && $5==4 && $6==2 | rmnoacc X_ACC X_DXREG | "idiv %[1]" erase(%[2]) erase(%[3]) | ax | |(2,171)+%[1] #endif rmi $1==2 | rmnoacc rmorconst | allocate(%[2], ACC=%[2], DXREG) "cwd" "idiv %[1]" erase(%[a]) | dx | |(3,176)+%[1] rmi $1==4 | | remove(ALL) "call .rmi4" | dx ax | | /* rmi !defined($1)| X_ACC | remove(ALL) "call .rmi" erase(%[1]) | | | */ #ifdef LONGEMPAT loc loc cii rmi loc loc cii $1==2 && $2==4 && $4==4 && $5==4 && $6==2 | rmnoacc X_ACC X_DXREG | "idiv %[1]" erase(%[2]) erase(%[3]) | dx | |(2,171)+%[1] #endif ngi $1==2 | X_REG | "neg %[1]" setcc(%[1]) erase(%[1]) | %[1] | |(2,3) ngi $1==4 | X_REG X_REG | "neg %[2]" "neg %[1]" "sbb %[2],0" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | | (8,10) /* ngi !defined($1)| X_ACC | remove(ALL) "call .ngi" | | | */ loc sli $1==1 && $2==2 | X_REG | "sal %[1],1" setcc(%[1]) erase(%[1]) | %[1] | | (2,2) loc sli $1==1 && $2==4 | X_REG X_REG | "sal %[1],1" "rcl %[2],1" erase(%[1]) erase(%[2]) | %[2] %[1] | | sli $1==2 | SHIFT_CREG X_REG | "sal %[2],cl" setcc(%[2]) erase(%[2]) | %[2] | | (2,8) sli $1==4 | X_CXREG X_REG X_REG | "jcxz 1f" "2: sal %[2],1" "rcl %[3],1" "loop 2b\n1:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | /* sli !defined($1)| X_ACC | remove(ALL) "call .sli" | | | */ loc sri $1==1 && $2==2 | X_REG | "sar %[1],1" setcc(%[1]) erase(%[1]) | %[1] | | (2,2) loc sri $1==1 && $2==4 | X_REG X_REG | "sar %[2],1" "rcr %[1],1" erase(%[1]) erase(%[2]) | %[2] %[1] | | sri $1==2 | SHIFT_CREG X_REG | "sar %[2],cl" setcc(%[2]) erase(%[2]) | %[2] | | (2,8) sri $1==4 | X_CXREG X_REG X_REG | "jcxz 1f" "2: sar %[3],1" "rcr %[2],1" "loop 2b\n1:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | /* sri !defined($1)| X_ACC | remove(ALL) "call .sri" | | | */ /************************************************ * Group 4 : unsigned arithmetic * * * * adu = adi * * sbu = sbi * * slu = sli * * mlu = mli * * * * Supported : 2- and 4 byte arithmetic. * ************************************************/ adu | | | | adi $1 | sbu | | | | sbi $1 | mlu | | | | mli $1 | dvu $1==2 | rmnoacc rmorconst | allocate(%[2],ACC=%[2],DXREG={ANYCON,0}) "div %[1]" erase(%[b]) erase(%[a]) | ax | |(2,149)+%[1] dvu $1==4 | | remove(ALL) "call .dvu4" | dx ax | | /* dvu !defined($1)| X_ACC | remove(ALL) "call .dvu" erase(%[1]) | | | */ rmu $1==2 | rmnoacc rmorconst | allocate(%[2],ACC=%[2],DXREG={ANYCON,0}) "div %[1]" erase(%[b]) erase(%[a]) | dx | |(3,149)+%[1] rmu $1==4 | | remove(ALL) "call .rmu4" | dx ax | | /* rmu !defined($1)| X_ACC | remove(ALL) "call .rmu" erase(%[1]) | | | */ slu | | | | sli $1 | loc sru $1==1 && $2==2 | X_REG | "shr %[1],1" setcc(%[1]) erase(%[1]) | %[1] | | (2,2) sru $1==2 | SHIFT_CREG X_REG | "shr %[2],cl" setcc(%[2]) erase(%[2]) | %[2] | | (2,8) sru $1==4 | X_CXREG X_REG X_REG | "jcxz 1f" /* result => samecc */ "2: shr %[3],1" "rcr %[2],1" "loop 2b\n1:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | /* sru !defined($1)| X_ACC | remove(ALL) "call .sru" | | | */ /************************************************ * Group 5 : Floating point arithmetic * * * ************************************************/ adf $1==4 | | remove(ALL) "call .adf4" | | | adf $1==8 | | remove(ALL) "call .adf8" | | | adf !defined($1) | X_CXREG | remove(ALL) "call .adf" erase(%[1]) | | | sbf $1==4 | | remove(ALL) "call .sbf4" | | | sbf $1==8 | | remove(ALL) "call .sbf8" | | | sbf !defined($1) | X_CXREG | remove(ALL) "call .sbf" erase(%[1]) | | | mlf $1==4 | | remove(ALL) "call .mlf4" | | | mlf $1==8 | | remove(ALL) "call .mlf8" | | | mlf !defined($1) | X_CXREG | remove(ALL) "call .mlf" erase(%[1]) | | | dvf $1==4 | | remove(ALL) "call .dvf4" | | | dvf $1==8 | | remove(ALL) "call .dvf8" | | | dvf !defined($1) | X_CXREG | remove(ALL) "call .dvf" erase(%[1]) | | | ngf $1==4 | | remove(ALL) "call .ngf4" | | | ngf $1==8 | | remove(ALL) "call .ngf8" | | | ngf !defined($1) | X_CXREG | remove(ALL) "call .ngf" erase(%[1]) | | | fif $1==4 | | remove(ALL) "call .fif4" | | | fif $1==8 | | remove(ALL) "call .fif8" | | | fif !defined($1) | X_CXREG | remove(ALL) "call .fif" erase(%[1]) | | | fef $1==4 | | remove(ALL) "call .fef4" | | | fef $1==8 | | remove(ALL) "call .fef8" | | | fef !defined($1) | X_CXREG | remove(ALL) "call .fef" erase(%[1]) | | | /**************************************** * Group 6 : pointer arithmetic. * * * * Pointers have size 2 bytes. * ****************************************/ adp $1==1 | nocoercions : Xreg_off | | {Xreg_off, %[1.reg],%[1.off]+"+"+tostring($1)} | | ... | nocoercions : Rreg_off | | {Rreg_off, %[1.reg],%[1.off]+"+"+tostring($1)} | | ... | nocoercions : ADDR_EXTERN | | {ADDR_EXTERN, %[1.off]+"+"+tostring($1)} | | ... | nocoercions : ADDR_LOCAL | | {ADDR_LOCAL, %[1.ind]+$1 } | | ... | nocoercions : Xbpreg_off | | {Xbpreg_off, %[1.reg], %[1.ind]+$1} | | ... | nocoercions : Rbpreg_off | | {Rbpreg_off, %[1.reg], %[1.ind]+$1} | | ... | X_REG | "inc %[1]" erase(%[1]) setcc(%[1]) | %[1] | | (1,2) ... | X_ADDREG | | {Xreg_off, %[1], tostring($1)} | | ... | nocoercions : RADDREG | | {Rreg_off, %[1], tostring($1)} | | adp $1 == 0-1 | nocoercions : Xreg_off | | {Xreg_off, %[1.reg],%[1.off]+tostring($1)} | | ... | nocoercions : Rreg_off | | {Rreg_off, %[1.reg],%[1.off]+tostring($1)} | | ... | nocoercions : ADDR_EXTERN | | {ADDR_EXTERN, %[1.off]+tostring($1)} | | ... | nocoercions : ADDR_LOCAL| |{ADDR_LOCAL, %[1.ind]+$1 } | | ... | nocoercions : Xbpreg_off | | {Xbpreg_off, %[1.reg], %[1.ind]+$1} | | ... | nocoercions : Rbpreg_off | | {Rbpreg_off, %[1.reg], %[1.ind]+$1} | | ... | X_REG | "dec %[1]" erase(%[1]) setcc(%[1]) | %[1] | | (1,2) ... | X_ADDREG | | {Xreg_off, %[1], tostring($1)} | | ... | nocoercions : RADDREG | | {Rreg_off, %[1], tostring($1)} | | adp | nocoercions : Xreg_off | | {Xreg_off, %[1.reg],%[1.off]+"+"+tostring($1)} | | ... | nocoercions : Rreg_off | | {Rreg_off, %[1.reg],%[1.off]+"+"+tostring($1)} | | ... | nocoercions : ADDR_EXTERN | | {ADDR_EXTERN, %[1.off]+"+"+tostring($1)} | | ... | nocoercions : ADDR_LOCAL | | {ADDR_LOCAL, %[1.ind]+$1 } | | ... | nocoercions : Xbpreg_off | | {Xbpreg_off, %[1.reg], %[1.ind]+$1} | | ... | nocoercions : Rbpreg_off | | {Rbpreg_off, %[1.reg], %[1.ind]+$1} | | ... | X_ADDREG | | {Xreg_off, %[1], tostring($1)} | | ... | nocoercions : RADDREG | | {Rreg_off, %[1], tostring($1)} | | ... | X_REG | "add %[1],$1" erase(%[1]) setcc(%[1]) | %[1] | | (4,4) ads $1==2 | nocoercions : ANYCON Rreg_off | | {Rreg_off, %[2.reg], %[2.off]+"+"+tostring(%[1.val])} | | ... | nocoercions : ADDR_EXTERN Rreg_off | | {Rreg_off, %[2.reg], %[2.off]+"+"+%[1.off]} | | ... | nocoercions : ANYCON Xreg_off | | {Xreg_off, %[2.reg], %[2.off]+"+"+tostring(%[1.val])} | | ... | nocoercions : ADDR_EXTERN Xreg_off | | {Xreg_off, %[2.reg], %[2.off]+"+"+%[1.off]} | | ... | rm Xreg_off | "add %[2.reg],%[1]" erase(%[2.reg]) setcc(%[2.reg]) | {Xreg_off, %[2.reg], %[2.off]} | | (2,3) + %[1] ... | nocoercions : ANYCON Xbpreg_off | | {Xbpreg_off, %[2.reg], %[2.ind]+%[1.val]} | | ... | nocoercions : ANYCON Rbpreg_off | | {Rbpreg_off, %[2.reg], %[2.ind]+%[1.val]} | | ... | rm Xbpreg_off | "add %[2.reg],%[1]" erase(%[2.reg]) setcc(%[2.reg]) | {Xbpreg_off, %[2.reg], %[2.ind]} | | (2,3) + %[1] ... | Xreg_off rmorconst | "add %[1.reg],%[2]" erase(%[1.reg]) setcc(%[1.reg]) | {Xreg_off, %[1.reg], %[1.off]} | | (2,3) + %[2] ... | Xbpreg_off rmorconst | "add %[1.reg],%[2]" erase(%[1.reg]) setcc(%[1.reg]) | {Xbpreg_off, %[1.reg], %[1.ind]} | | (2,3) + %[2] ... | nocoercions : Xreg_off ANYCON | | {Xreg_off, %[1.reg], %[1.off]+"+"+tostring(%[2.val])} | | ... | nocoercions : Xreg_off ADDR_EXTERN | | {Xreg_off, %[1.reg], %[1.off]+"+"+%[2.off]} | | ... | nocoercions : Rreg_off ANYCON | | {Rreg_off, %[1.reg], %[1.off]+"+"+tostring(%[2.val])} | | ... | nocoercions : Rreg_off ADDR_EXTERN | | {Rreg_off, %[1.reg], %[1.off]+"+"+%[2.off]} | | ... | nocoercions : Xreg_off reg_off | "add %[1.reg],%[2.reg]" erase(%[1.reg]) setcc(%[1.reg]) | {Xreg_off,%[1.reg],%[1.off]+"+"+%[2.off]} | | (2,3) #ifndef REGVARS ... | IREG ADDR_LOCAL | | {bpreg_off,%[1],%[2.ind]} | | /* ... | (REG-IREG) ADDR_LOCAL | allocate(%[1],ADDREG=%[1]) "add %[a],bp" | {reg_off, %[a], tostring(%[2.ind])} | | (2,3) */ #else ... | nocoercions: RREG ADDR_LOCAL | | {Rbpreg_off,%[1],%[2.ind]} | | #endif #ifdef DEEPER ... | X_REG rmorconst | "add %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (2,3) + %[2] ... | rmorconst X_REG | "add %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | X_ACC const | "add %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (3,4) ... | const X_ACC | "add %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) #else ... | X_ADDREG ADDR_EXTERN | | {Xreg_off, %[1], %[2.off]} | | ... | X_ADDREG rm | "add %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (2,3) + %[2] ... | ADDR_EXTERN X_ADDREG | | {Xreg_off, %[2], %[1.off]} | | ... | rm X_ADDREG | "add %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] #endif sbs $1==2 | nocoercions : ANYCON Xreg_off | | {Xreg_off, %[2.reg], %[2.off]+"-"+tostring(%[1.val])} | | ... | nocoercions : ANYCON Rreg_off | | {Rreg_off, %[2.reg], %[2.off]+"-"+tostring(%[1.val])} | | ... | nocoercions : ANYCON ADDR_LOCAL | | {ADDR_LOCAL, %[2.ind]-%[1.val]} | | ... | rm Xreg_off | "sub %[2.reg],%[1]" erase(%[2.reg]) setcc(%[2.reg]) | {Xreg_off, %[2.reg], %[2.off]} | | /* Should not occur ... | nocoercions : reg_off ANYCON | | {reg_off, %[1.reg], %[1.off]+"-"+tostring(%[2.val])} | | ... | ANYCON ADDR_EXTERN | | {ADDR_EXTERN, %[2.off]+"+"+tostring(%[1.val])} | | ... | nocoercions : ANYCON ADDR_LOCAL | | {ADDR_LOCAL, %[1.val]+%[2.ind]} | | */ ... | rm X_REG | "sub %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | const X_ACC | "sub %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) /**************************************** * Group 7 : increment/decrement/zero * ****************************************/ inc | X_REG | "inc %[1]" setcc(%[1]) erase(%[1]) | %[1] | |(1,2) #ifdef REGVARS inl inreg($1)==2| | "inc %(regvar($1)%)" setcc(regvar($1)) | | |(1,2) #endif inl | | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "inc $1(bp)" setcc({LOCAL2,$1,2}) | | |(3,24) ine | | remove(indirects) "inc ($1)" setcc({EXTERN2,$1}) | | |(4,21) dec | X_REG | "dec %[1]" setcc(%[1]) erase(%[1]) | %[1] | |(1,2) #ifdef REGVARS del inreg($1)==2| | "dec %(regvar($1)%)" setcc(regvar($1)) | | |(1,2) #endif del | | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "dec $1(bp)" setcc({LOCAL2,$1,2}) | | |(3,24) dee | | remove(indirects) "dec ($1)" setcc({EXTERN2,$1}) | | |(4,21) #ifdef REGVARS zrl inreg($1)==2| | move({ANYCON,0},regvar($1)) | | | #endif zrl | | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) move({ANYCON,0},{LOCAL2,$1,2}) | | | zre | | remove(indirects) move({ANYCON,0},{EXTERN2,$1})| | | zrf $1==4 | | remove(ALL) "call .zrf4" | | | zrf $1==8 | | remove(ALL) "call .zrf8" | | | zrf !defined($1) | X_CXREG | remove(ALL) "call .zrf" erase(%[1]) | | | zer $1==2 | | | {ANYCON,0} | | zer $1==4 | | | {ANYCON,0} {ANYCON,0} | | zer $1==6 | | | {ANYCON,0} {ANYCON,0} {ANYCON,0} | | zer $1==8 | | | {ANYCON,0} {ANYCON,0} {ANYCON,0} {ANYCON,0} | | zer defined($1) | | remove(ALL) move({ANYCON,$1/2},cx) move({ANYCON,0},bx) "1: push bx" "loop 1b" samecc erase(cx) | | |(3,10+$1*4) zer !defined($1)| X_CXREG | remove(ALL) move({ANYCON,0},bx) "sar cx,1" "1:\tpush bx" "loop 1b" samecc erase(%[1]) | | | #ifdef REGVARS lol adi stl $1==$3 && $2==2 && inreg($1)==2 | rmorconst | "add %(regvar($1)%),%[1]" setcc(regvar($1)) | | | #endif lol adi stl $1==$3 && $2==2 | regorconst | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "add $1(bp),%[1]" setcc({LOCAL2, $1, 2}) | | | ldl adi sdl $1==$3 && $2==4 | regorconst regorconst | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+4 ) "add $1(bp),%[1]" "adc %($1+2%)(bp),%[2]" | | | #ifdef REGVARS lol ngi stl $1==$3 && $2==2 && inreg($1)==2 | | "neg %(regvar($1)%)" setcc(regvar($1)) | | | #endif lol ngi stl $1==$3 && $2==2 | | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "neg $1(bp)" setcc({LOCAL2, $1, 2}) | | | ldl ngi sdl $1==$3 && $2==4 | | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+4 ) "neg $1(bp)" "neg %($1+2%)(bp)" "sbb %($1+2%)(bp),0" | | | lol ads stl $1==$3 && $2==2 | | | | lol $1 adi 2 stl $1 | #ifdef REGVARS lol lol adp stl $1==$2 && $1==$4 && inreg($1)==2 | | allocate(ADDREG=regvar($1)) | %[a] | lol $2 adp $3 stl $2 | lol inl $1==$2 && inreg($1)==2 | | allocate(REG=regvar($1)) | %[a] | inl $1 | lol del $1==$2 && inreg($1)==2 | | allocate(REG=regvar($1)) | %[a] | del $1 | #endif lol lol adp stl $1==$2 && $1==$4 | | allocate(ADDREG={LOCAL2,$1,2}) | %[a] | lol $2 adp $3 stl $2 | lol inl $1==$2 | | allocate(REG={LOCAL2,$1,2}) | %[a] | inl $1 | lol del $1==$2 | | allocate(REG={LOCAL2,$1,2}) | %[a] | del $1 | lol adp stl $1==$3 && $2==1 | | | | inl $1 | lol adp stl $1==$3 && $2==0-1 | | | | del $1 | #ifdef REGVARS lol adp stl $1==$3 && inreg($1)==2 | | "add %(regvar($1)%),$2" setcc(regvar($1)) | | | #endif lol adp stl $1==$3 | | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "add $1(bp),$2" setcc({LOCAL2, $1, 2}) | | | #ifdef REGVARS lol and stl $1==$3 && $2==2 && inreg($1)==2 | rmorconst | "and %(regvar($1)%),%[1]" setcc(regvar($1)) | | | #endif lol and stl $1==$3 && $2==2 | regorconst | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "and $1(bp),%[1]" setcc({LOCAL2, $1, 2}) | | | #ifdef REGVARS lol ior stl $1==$3 && $2==2 && inreg($1)==2 | rmorconst | "or %(regvar($1)%),%[1]" setcc(regvar($1)) | | | #endif lol ior stl $1==$3 && $2==2 | regorconst | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "or $1(bp),%[1]" setcc({LOCAL2, $1, 2}) | | | #ifdef REGVARS lol com stl $1==$3 && $2==2 && inreg($1)==2 | | "not %(regvar($1)%)" samecc | | | #endif lol com stl $1==$3 && $2==2 | | remove(indexed) remove(locals, %[ind]>=$1 && %[ind]<$1+2 ) "not $1(bp)" samecc | | | #ifdef REGVARS lil adi sil $1==$3 && $2==2 && inreg($1)==2 | regorconst | remove(referals) "add (%(regvar($1)%)),%[1]" setcc({ind_reg2, regvar($1)}) | | | #endif lil adi sil $1==$3 && $2==2 | regorconstnoaddr | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "add (%[a]),%[1]" setcc({ind_reg2, %[a]}) | | | #ifdef REGVARS lil ngi sil $1==$3 && $2==2 && inreg($1)==2 | | remove(referals) "neg (%(regvar($1)%))" setcc({ind_reg2, regvar($1)}) | | | #endif lil ngi sil $1==$3 && $2==2 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "neg (%[a])" setcc({ind_reg2, %[a]}) | | | lil ads sil $1==$3 && $2==2 | | | | lil $1 adi 2 sil $1 | #ifdef REGVARS lil adp sil $1==$3 && $2==1 && inreg($1)==2 | | remove(referals) "inc (%(regvar($1)%))" setcc({ind_reg2, regvar($1)}) | | | #endif lil adp sil $1==$3 && $2==1 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "inc (%[a])" setcc({ind_reg2, %[a]}) | | | #ifdef REGVARS lil adp sil $1==$3 && $2==0-1 && inreg($1)==2 | | remove(referals) "dec (%(regvar($1)%))" setcc({ind_reg2, regvar($1)}) | | | #endif lil adp sil $1==$3 && $2==0-1 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "dec (%[a])" setcc({ind_reg2, %[a]}) | | | #ifdef REGVARS lil adp sil $1==$3 && inreg($1)==2 | | remove(referals) "add (%(regvar($1)%)),$2" setcc({ind_reg2, regvar($1)}) | | | #endif lil adp sil $1==$3 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "add (%[a]),$2" setcc({ind_reg2, %[a]}) | | | #ifdef REGVARS lil and sil $1==$3 && $2==2 && inreg($1)==2 | regorconst | remove(referals) "and (%(regvar($1)%)),%[1]" setcc({ind_reg2, regvar($1)}) | | | #endif lil and sil $1==$3 && $2==2 | regorconstnoaddr | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "and (%[a]),%[1]" setcc({ind_reg2, %[a]}) | | | #ifdef REGVARS lil ior sil $1==$3 && $2==2 && inreg($1)==2 | regorconst | remove(referals) "or (%(regvar($1)%)),%[1]" setcc({ind_reg2, regvar($1)}) | | | #endif lil ior sil $1==$3 && $2==2 | regorconstnoaddr | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "or (%[a]),%[1]" setcc({ind_reg2, %[a]}) | | | #ifdef REGVARS lil com sil $1==$3 && $2==2 && inreg($1)==2 | | remove(referals) "not (%(regvar($1)%))" samecc | | | #endif lil com sil $1==$3 && $2==2 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "not (%[a])" samecc | | | #ifdef REGVARS lol lof adi lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==2 | regorconst | remove(referals) "add $2(%(regvar($1)%)),%[1]" setcc({ind_regoff2, regvar($1), tostring($2)}) | | | #endif lol lof adi lol stf $1==$4 && $2==$5 && $3==2 | regorconstnoaddr | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "add $2(%[a]),%[1]" setcc({ind_regoff2, %[a], tostring($2)}) | | | #ifdef REGVARS lol lof ngi lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==2 | | remove(referals) "neg $2(%(regvar($1)%))" setcc({ind_regoff2, regvar($1), tostring($2)}) | | | #endif lol lof ngi lol stf $1==$4 && $2==$5 && $3==2 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "neg $2(%[a])" setcc({ind_regoff2, %[a], tostring($2)}) | | | lol lof ads lol stf $1==$4 && $2==$5 && $3==2 | | | | lol $1 lof $2 adi 2 lol $1 stf $2 | #ifdef REGVARS lol lof adp lol stf $1==$4 && $2==$5 && $3==1 && inreg($1)==2 | | remove(referals) "inc $2(%(regvar($1)%))" setcc({ind_regoff2, regvar($1), tostring($2)}) | | | #endif lol lof adp lol stf $1==$4 && $2==$5 && $2==1 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "inc $2(%[a])" setcc({ind_regoff2, %[a], tostring($2)}) | | | #ifdef REGVARS lol lof adp lol stf $1==$4 && $2==$5 && $3==0-1 && inreg($1)==2 | | remove(referals) "dec $2(%(regvar($1)%))" setcc({ind_regoff2, regvar($1), tostring($2)}) | | | #endif lol lof adp lol stf $1==$4 && $2==$5 && $3==0-1 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "dec $2(%[a])" setcc({ind_regoff2, %[a], tostring($2)}) | | | #ifdef REGVARS lol lof adp lol stf $1==$4 && $2==$5 && inreg($1)==2 | | remove(referals) "add $2(%(regvar($1)%)),$3" setcc({ind_regoff2, regvar($1),tostring($2)}) | | | #endif lol lof adp lol stf $1==$4 && $2==$5 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "add $2(%[a]),$3" setcc({ind_regoff2, %[a], tostring($2)}) | | | #ifdef REGVARS lol lof and lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==2 | regorconst | remove(referals) "and $2(%(regvar($1)%)),%[1]" setcc({ind_regoff2, regvar($1), tostring($2)}) | | | #endif lol lof and lol stf $1==$4 && $2==$5 && $3==2 | regorconstnoaddr | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "and $2(%[a]),%[1]" setcc({ind_regoff2, %[a], tostring($2)}) | | | #ifdef REGVARS lol lof ior lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==2 | regorconst | remove(referals) "or $2(%(regvar($1)%)),%[1]" setcc({ind_regoff2, regvar($1), tostring($2)}) | | | #endif lol lof ior lol stf $1==$4 && $2==$5 && $3==2 | regorconstnoaddr | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "or $2(%[a]),%[1]" setcc({ind_regoff2, %[a], tostring($2)}) | | | #ifdef REGVARS lol lof com lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==2 | | remove(referals) "not $2(%(regvar($1)%))" samecc | | | #endif lol lof com lol stf $1==$4 && $2==$5 && $3==2 | | allocate(ADDREG={LOCAL2, $1, 2}) remove(referals) "not $2(%[a])" samecc | | | loe adi ste $1==$3 && $2==2 | regorconst | remove(indirects) "add ($1),%[1]" setcc({EXTERN2, $1}) | | | lde adi sde $1==$3 && $2==4 | regorconst regorconst | remove(indirects) "add ($1),%[1]" "adc ($1+2),%[2]" | | | loe ngi ste $1==$3 && $2==2 | | remove(indirects) "neg ($1)" setcc({EXTERN2, $1}) | | | lde ngi sde $1==$3 && $2==4 | | remove(indirects) "neg ($1)" "neg ($1+2)" "sbb ($1+2),0" | | | loe ads ste $1==$3 && $2==2 | regorconst | remove(indirects) "add ($1),%[1]" setcc({EXTERN2, $1}) | | | loe loe adp ste $1==$4 && $1==$4 | | allocate(ADDREG={EXTERN2,$1}) | %[a] | loe $1 adp $3 ste $1 | loe ine $1==$2 | | allocate(REG={EXTERN2,$1}) | %[a] | ine $1 | loe dee $1==$2 | | allocate(REG={EXTERN2,$1}) | %[a] | dee $1 | loe adp ste $1==$3 && $2==1 | | remove(indirects) "inc ($1)" setcc({EXTERN2, $1}) | | | loe adp ste $1==$3 && $2==0-1 | | remove(indirects) "dec ($1)" setcc({EXTERN2, $1}) | | | loe adp ste $1==$3 | | remove(indirects) "add ($1),$2" setcc({EXTERN2, $1}) | | | loe and ste $1==$3 && $2==2 | regorconst | remove(indirects) "and ($1),%[1]" setcc({EXTERN2, $1}) | | | loe ior ste $1==$3 && $2==2 | regorconst | remove(indirects) "or ($1),%[1]" setcc({EXTERN2, $1}) | | | loe com ste $1==$3 && $2==2 | | remove(indirects) "not ($1)" samecc | | | loe lof adi loe stf $1==$4 && $2==$5 && $3==2 | regorconstnoaddr | allocate(ADDREG={EXTERN2, $1}) remove(referals) "add $2(%[a]),%[1]" setcc({ind_regoff2, %[a], tostring($2)}) | | | loe lof ngi loe stf $1==$4 && $2==$5 && $3==2 | | allocate(ADDREG={EXTERN2, $1}) remove(referals) "neg $2(%[a])" setcc({ind_regoff2, %[a], tostring($2)}) | | | loe lof ads loe stf $1==$4 && $2==$5 && $3==2 | | | | loe $1 lof $2 adi 2 loe $1 stf $2 | loe lof adp loe stf $1==$4 && $2==$5 && $2==1 | | allocate(ADDREG={EXTERN2, $1}) remove(referals) "inc $2(%[a])" setcc({ind_regoff2, %[a], tostring($2)}) | | | loe lof adp loe stf $1==$4 && $2==$5 && $3==0-1 | | allocate(ADDREG={EXTERN2, $1}) remove(referals) "dec $2(%[a])" setcc({ind_regoff2, %[a], tostring($2)}) | | | loe lof adp loe stf $1==$4 && $2==$5 | | allocate(ADDREG={EXTERN2, $1}) remove(referals) "add $2(%[a]),$3" setcc({ind_regoff2, %[a], tostring($2)}) | | | loe lof and loe stf $1==$4 && $2==$5 && $3==2 | regorconstnoaddr | allocate(ADDREG={EXTERN2, $1}) remove(referals) "and $2(%[a]),%[1]" setcc({ind_regoff2, %[a], tostring($2)}) | | | loe lof ior loe stf $1==$4 && $2==$5 && $3==2 | regorconstnoaddr | allocate(ADDREG={EXTERN2, $1}) remove(referals) "or $2(%[a]),%[1]" setcc({ind_regoff2, %[a], tostring($2)}) | | | loe lof com loe stf $1==$4 && $2==$5 && $3==2 | | allocate(ADDREG={EXTERN2, $1}) remove(referals) "not $2(%[a])" samecc | | | /**************************************** * Group 8 : Convert instructions * ****************************************/ cii | CXREG DXREG X_ACC | remove(ALL) "call .cii" erase(%[3]) | %[3] | | ciu | | | | cuu | cui | | | | cuu | cuu | CXREG DXREG X_ACC | remove(ALL) "call .cuu" erase(%[3]) | %[3] | | cif | CXREG DXREG | remove(ALL) "call .cif" | | | cuf | CXREG DXREG | remove(ALL) "call .cuf" | | | cfi | CXREG DXREG | remove(ALL) "call .cfi" | | | cfu | CXREG DXREG | remove(ALL) "call .cfu" | | | cff | CXREG DXREG | remove(ALL) "call .cff" | | | loc loc cii $1==1 && $2==2 | X_ACC | "cbw" samecc | ax | |(1,2) ... | nocoercions: rmorconst1 | allocate(%[1], ACC1 = %[1]) "cbw" samecc | ax | |(1,2) loc loc cii $1==1 && $2==4 | X_ACC | allocate(DXREG) "cbw" "cwd" samecc | %[a] ax | |(2,7) ... | nocoercions: rmorconst1 | allocate(%[1], ACC1 = %[1], DXREG) "cbw" "cwd" samecc | dx ax | |(2,7) loc loc cii $1==2 && $2==4 | ACC | allocate(DXREG) "cwd" samecc | %[a] ax | |(1,5) loc loc cii $1==4 && $2==2 | a_word a_word | | %[1] | | loc loc ciu | | | | loc $1 loc $2 cuu | loc loc cui | | | | loc $1 loc $2 cuu | loc loc cuu $1==$2 | | | | | loc loc cuu $1==2 && $2==4 | a_word | allocate(REG={ANYCON,0})| %[a] %[1] | | loc loc cuu $1==4 && $2==2 | a_word a_word | | %[1] | | /**************************************** * Group 9 : Logical instructions * ****************************************/ and $1==2 | NO X_REG rmorconst | "and %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (2,3) + %[2] ... | rmorconst X_REG | "and %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | X_ACC const | "and %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (3,4) ... | const X_ACC | "and %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) and $1==4 | NO X_REG X_REG rmorconst rmorconst | "and %[1],%[3]" "and %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(4,6)+%[4]+%[3] ... | X_ACC X_REG const rmorconst | "and %[1],%[3]" "and %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(5,7)+%[4] ... | rmorconst rmorconst X_REG X_REG | "and %[3],%[1]" "and %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(4,6)+%[1]+%[2] ... | const rmorconst-ACC X_ACC X_REG | "and %[3],%[1]" "and %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(5,7)+%[2] and defined($1) | | remove(ALL) "mov cx,$1" "call .and" | | | and !defined($1)| X_CXREG | remove(ALL) "call .and" erase(%[1]) | | | ior $1==2 | X_REG rmorconst | "or %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (2,3) + %[2] ... | NO rmorconst X_REG | "or %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | X_ACC const | "or %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (3,4) ... | const X_ACC | "or %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) ior $1==4 | NO X_REG X_REG rmorconst rmorconst | "or %[1],%[3]" "or %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(4,6)+%[4]+%[3] ... | X_ACC X_REG const rmorconst | "or %[1],%[3]" "or %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(5,7)+%[4] ... | rmorconst rmorconst X_REG X_REG | "or %[3],%[1]" "or %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(4,6)+%[1]+%[2] ... | const rmorconst-ACC X_ACC X_REG | "or %[3],%[1]" "or %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(5,7)+%[2] ior defined($1) | | remove(ALL) "mov cx,$1" "call .ior" | | | ior !defined($1)| X_CXREG | remove(ALL) "call .ior" erase(%[1]) | | | xor $1==2 | NO X_REG rmorconst | "xor %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (2,3) + %[2] ... | rmorconst X_REG | "xor %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | X_ACC const | "xor %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (3,4) ... | const X_ACC | "xor %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) xor $1==4 | NO X_REG X_REG rmorconst rmorconst | "xor %[1],%[3]" "xor %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(4,6)+%[4]+%[3] ... | X_ACC X_REG const rmorconst | "xor %[1],%[3]" "xor %[2],%[4]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] %[1] | |(5,7)+%[4] ... | rmorconst rmorconst X_REG X_REG | "xor %[3],%[1]" "xor %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(4,6)+%[1]+%[2] ... | const rmorconst-ACC X_ACC X_REG | "xor %[3],%[1]" "xor %[4],%[2]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] %[3] | |(5,7)+%[2] xor defined($1) | | remove(ALL) "mov cx,$1" "call .xor" | | | xor !defined($1)| X_CXREG | remove(ALL) "call .xor" erase(%[1]) | | | com $1==2 | X_REG | "not %[1]" samecc erase(%[1]) | %[1] | |(2,3) com $1==4 | X_REG X_REG | "not %[2]" "not %[1]" samecc erase(%[1]) erase(%[2]) | %[2] %[1] | |(4,6) com defined($1) | | remove(ALL) "mov cx,$1" "call .com" | | | com !defined($1)| X_CXREG | remove(ALL) "call .com" erase(%[1]) | | | loc rol $1==1 && $2==2 | X_REG | "rol %[1],1" samecc erase(%[1]) | %[1] | | (2,2) rol $1==2 | SHIFT_CREG X_REG | "rol %[2],cl" samecc erase(%[2]) | %[2] | | (2,8) rol $1==4 | X_CXREG X_REG X_REG | "jcxz 1f" "2: sal %[2],1" "rcl %[3],1" "adc %[2],0" "loop 2b\n1:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | /* rol !defined($1)| X_CXREG | remove(ALL) "call .rol" | | | */ loc ror $1==1 && $2==2 | X_REG | "ror %[1],1" samecc erase(%[1]) | %[1] | | (2,2) ror $1==2 | SHIFT_CREG X_REG | "ror %[2],cl" samecc erase(%[2]) | %[2] | | (2,8) ror $1==4 | X_CXREG X_REG X_REG | "jcxz 1f" "neg cx" "add cx,32" "2: sal %[2],1" "rcl %[3],1" "adc %[2],0" "loop 2b\n1:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | /* ror !defined($1)| X_CXREG | remove(ALL) "call .ror" | | | */ /******************************** * Group 10 : Set instructions * ********************************/ inn $1==2 | SHIFT_CREG X_REG | "shr %[2],cl" "and %[2],1" setcc(%[2]) erase(%[2]) | %[2] | |(6,13) ... | SHIFT_CREG X_ACC | "shr %[2],cl" "and %[2],1" setcc(%[2]) erase(%[2]) | %[2] | |(5,13) loc inn $1==1 && $2==2 | X_REG | "shr %[1],1" "and %[1],1" setcc(%[1]) erase(%[1]) | %[1] | |(6,6) ... | X_ACC | "shr %[1],1" "and %[1],1" setcc(%[1]) erase(%[1]) | %[1] | |(5,6) loc inn $1==0 && $2==2 | X_REG | "and %[1],1" setcc(%[1]) erase(%[1]) | %[1] | |(6,6) ... | X_ACC | "and %[1],1" setcc(%[1]) erase(%[1]) | %[1] | |(5,6) inn defined($1) | X_ACC | remove(ALL) move({ANYCON,$1},cx) "call .inn" erase(ax) | ax | | inn !defined($1)| CXREG X_ACC | remove(ALL) "call .inn" erase(%[2]) | ax | | loc inn zeq $2==2 | rm STACK | "test %[1],%(1<<$1%)" "je $3" | | | loc inn zne $2==2 | rm STACK | "test %[1],%(1<<$1%)" "jne $3" | | | set $1==2 | SHIFT_CREG | allocate(REG={ANYCON,1}) "shl %[a],cl" setcc(%[a]) erase(%[a]) | %[a] | | set defined($1) | X_ACC | remove(ALL) move({ANYCON,$1},cx) "call .set" erase(%[1]) | | | set !defined($1)| CXREG X_ACC | remove(ALL) "call .set" erase(%[2]) | | | /**************************************** * Group 11 : Array instructions * ****************************************/ lae aar $2==2 && rom(1,3)==1 && rom(1,1)==0 | | | | ads 2 | lae aar $2==2 && rom(1,3)==1 && rom(1,1)!=0 | | | | adp 0-rom(1,1) ads 2 | lae aar $2==2 && rom(1,3)==2 && rom(1,1)==0 | X_ADDREG | "sal %[1],1" erase(%[1]) | %[1] | ads 2 | lae aar $2==2 && rom(1,3)==2 && rom(1,1)!=0 | X_ADDREG | "sal %[1],1" erase(%[1]) | %[1] | adp 0-2*rom(1,1) ads 2 | lae aar $2==2 && rom(1,3)==4 && rom(1,1)==0 | X_ADDREG | "sal %[1],1" "sal %[1],1" erase(%[1]) | %[1] | ads 2 | lae aar $2==2 && rom(1,3)==4 && rom(1,1)!=0 | X_ADDREG | "sal %[1],1" "sal %[1],1" erase(%[1]) | %[1] | adp 0-4*rom(1,1) ads 2 | lae aar $2==2 && rom(1,1)==0 | X_ACC | allocate(DXREG,REG={ANYCON,rom(1,3)}) "mul %[b]" erase(%[1]) | %[1] | ads 2 | lae aar $2==2 && defined(rom(1,1)) | X_ACC | allocate(DXREG,REG={ANYCON,rom(1,3)}) "mul %[b]" erase(%[1]) | %[1] | adp 0-rom(1,1)*rom(1,3) ads 2 | loc sli ads $1==1 && $2==2 && $3==2 | X_ADDREG | "sal %[1],1" erase(%[1]) | %[1] | ads 2 | #ifdef REGVARS ... | nocoercions: rmorconst-ADDREG uses_bx | allocate(%[2],REG=%[2],ADDREG=%[1]) "sal %[b],1" erase(%[b]) | %[b] %[a] | ads 2 | #endif loc sli ads $1==2 && $2==2 && $3==2 | X_ADDREG | "sal %[1],1" "sal %[1],1" erase(%[1]) | %[1] | ads 2 | #ifdef REGVARS ... | nocoercions: rmorconst-ADDREG uses_bx | allocate(%[2],REG=%[2],ADDREG=%[1]) "sal %[b],1" "sal %[b],1" erase(%[b]) | %[b] %[a] | ads 2 | #endif loc sli ads $2==2 && $3==2 | X_ADDREG | allocate(CXREG={ANYCON, $1}) "sal %[1],cl" erase(%[1]) | %[1] | ads 2 | #ifdef REGVARS ... | nocoercions: rmorconst-(ADDREG+CXREG) uses_bx | allocate(%[2],REG=%[2],ADDREG=%[1],CXREG={ANYCON,$1}) "sal %[b],cl" erase(%[b]) | %[b] %[a] | ads 2 | #endif aar $1==2 | halfindir X_ACC X_ADDREG | allocate(DXREG) "sub %[2],%[1]" "mul 4+%[1]" "add %[3],%[2]" erase(%[2]) erase(%[3]) | %[3] | | ... | ADDR_EXTERN X_ACC X_ADDREG | allocate(DXREG) "sub %[2],(%[1])" "mul (4+%[1])" "add %[3],%[2]" erase(%[2]) erase(%[3]) | %[3] | | lae sar defined(rom(1,3)) | | | | lae $1 aar $2 sti rom(1,3) | lae lar defined(rom(1,3)) | | | | lae $1 aar $2 loi rom(1,3) | aar !defined($1) | | remove(ALL) "call .iaar" | bx | | sar $1==2 | X_BXREG X_ACC | remove(ALL) "call .sar2" erase(%[1]) erase(%[2]) | | | sar !defined($1) | | remove(ALL) "call .isar" | | | lar $1==2 | X_BXREG X_ACC | remove(ALL) "call .lar2" erase(%[1]) erase(%[2]) | | | lar !defined($1) | | remove(ALL) "call .ilar" | | | /**************************************** * group 12 : Compare instructions * ****************************************/ cmi $1==2 | NO register rmorconst | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jl 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(4,4) ... | rmorconst register | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jl 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(4,4) ... | ACC const | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jl 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(3,4) ... | const ACC | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jl 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(3,4) cmi $1==4 | | remove(ALL) "call .cmi4" | ax | | cmu $1==2 | | | | cmp | cmu $1==4 | | remove(ALL) "call .cmu4" | ax | | cms $1==2 | NO X_REG rmorconst | "sub %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (2,3) + %[2] ... | rmorconst X_REG | "sub %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (2,3) + %[1] ... | X_ACC const | "sub %[1],%[2]" erase(%[1]) setcc(%[1]) | %[1] | | (3,4) ... | const X_ACC | "sub %[2],%[1]" erase(%[2]) setcc(%[2]) | %[2] | | (3,4) cms $1==4 | rmorconst rmorconst X_REG X_REG | "sub %[3],%[1]" "sbb %[4],%[2]" "or %[4],%[3]" setcc(%[4]) erase(%[3]) erase(%[4]) | %[4] | | ... | NO X_REG X_REG rmorconst rmorconst | "sub %[1],%[3]" "sbb %[2],%[4]" "or %[2],%[1]" setcc(%[2]) erase(%[1]) erase(%[2]) | %[2] | | cms defined($1) | | remove(ALL) move({ANYCON,$1},cx) "call .cms" erase(cx) | cx | | cms !defined($1)| X_CXREG | remove(ALL) "call .cms" erase(cx) | cx | | cmf $1==4 | | remove(ALL) "call .cmf4" | | | cmf $1==8 | | remove(ALL) "call .cmf8" | | | cmf !defined($1) | X_CXREG | remove(ALL) "call .cmf" erase(%[1]) | | | /* The costs with cmp are the cost of the 8086 cmp instruction */ cmp | NO register rmorconst | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jb 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(4,4) ... | rmorconst register | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jb 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(4,4) ... | ACC const | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jb 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(3,4) ... | const ACC | allocate(REG = {ANYCON,0}) "cmp %[1],%[2]" "je 2f" "jb 1f" "inc %[a]" "jmp 2f" "1:\tdec %[a]\n2:" setcc(%[a]) erase(%[a]) | %[a] | |(3,4) tlt | rm | allocate(REG={ANYCON,0}) test(%[1]) "jge 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | tle | rm | allocate(REG={ANYCON,0}) test(%[1]) "jg 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | teq | rm | allocate(REG={ANYCON,0}) test(%[1]) "jne 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | tne | rm | allocate(REG={ANYCON,0}) test(%[1]) "je 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | tge | rm | allocate(REG={ANYCON,0}) test(%[1]) "jl 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | tgt | rm | allocate(REG={ANYCON,0}) test(%[1]) "jle 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | tlt ior $2==2 | rm X_REG | test(%[1]) "jge 1f" "or %[2],1\n1:" erase(%[2]) | %[2] | | tle ior $2==2 | rm X_REG | test(%[1]) "jg 1f" "or %[2],1\n1:" erase(%[2]) | %[2] | | teq ior $2==2 | rm X_REG | test(%[1]) "jne 1f" "or %[2],1\n1:" erase(%[2]) | %[2] | | tne ior $2==2 | rm X_REG | test(%[1]) "je 1f" "or %[2],1\n1:" erase(%[2]) | %[2] | | tge ior $2==2 | rm X_REG | test(%[1]) "jl 1f" "or %[2],1\n1:" erase(%[2]) | %[2] | | tgt ior $2==2 | rm X_REG | test(%[1]) "jle 1f" "or %[2],1\n1:" erase(%[2]) | %[2] | | cmi tlt ior $1==2 && $3==2 | regorconst rm X_REG | "cmp %[2],%[1]" "jge 1f" "or %[3],1\n1:" erase(%[3]) | %[3] | | cmi tle ior $1==2 && $3==2 | regorconst rm X_REG | "cmp %[2],%[1]" "jg 1f" "or %[3],1\n1:" erase(%[3]) | %[3] | | cmi teq ior $1==2 && $3==2 | regorconst rm X_REG | "cmp %[2],%[1]" "jne 1f" "or %[3],1\n1:" erase(%[3]) | %[3] | | cmi tne ior $1==2 && $3==2 | regorconst rm X_REG | "cmp %[2],%[1]" "je 1f" "or %[3],1\n1:" erase(%[3]) | %[3] | | cmi tge ior $1==2 && $3==2 | regorconst rm X_REG | "cmp %[2],%[1]" "jl 1f" "or %[3],1\n1:" erase(%[3]) | %[3] | | cmi tgt ior $1==2 && $3==2 | regorconst rm X_REG | "cmp %[2],%[1]" "jle 1f" "or %[3],1\n1:" erase(%[3]) | %[3] | | /* The cmp instruction has a special form for comparing a byte ( sign-extended ) to a word (e.g. a register) The "cmp ax,0" and "cmp bx,0" instructions have widely different encodings but take the same amount of time and space. Conclusion, using the special instruction for comparing constants with ax is only better when the constant is <-128 or >127. This relatively rare event wasn't worth extra entries in this table. */ cmi tlt $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jge 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jle 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmi tle $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jg 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jl 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmi teq $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jne 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jne 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmi tne $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "je 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "je 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmi tge $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jl 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jg 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmi tgt $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jle 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jge 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmp tlt | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jae 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jbe 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmp tle | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "ja 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jb 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmp teq | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jne 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jne 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmp tne | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "je 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "je 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmp tge | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jb 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "ja 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmp tgt | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jbe 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jae 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cms teq $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "jne 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "jne 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cms tne $1==2 | regorconst rm | allocate(REG={ANYCON,0}) "cmp %[2],%[1]" "je 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | ... | NO rm regorconst | allocate(REG={ANYCON,0}) "cmp %[1],%[2]" "je 1f" "inc %[a]\n1:" erase(%[a]) | %[a] | | cmp zlt | regorconst rm STACK | "cmp %[2],%[1]" "jb $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "ja $2" | | | cmp zle | regorconst rm STACK | "cmp %[2],%[1]" "jbe $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jae $2" | | | cmp zeq | regorconst rm STACK | "cmp %[2],%[1]" "je $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "je $2" | | | cmp zne | regorconst rm STACK | "cmp %[2],%[1]" "jne $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jne $2" | | | cmp zge | regorconst rm STACK | "cmp %[2],%[1]" "jae $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jbe $2" | | | cmp zgt | regorconst rm STACK | "cmp %[2],%[1]" "ja $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jb $2" | | | cms zeq $1==2 | regorconst rm STACK | "cmp %[2],%[1]" "je $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "je $2" | | | cms zne $1==2 | regorconst rm STACK | "cmp %[2],%[1]" "jne $2" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jne $2" | | | ldc cmi zlt highw(1)==0 && loww(1)==0 && $2==4 | rmorconst rmorconst | | %[2] | zlt $3 | ldc cmi zge highw(1)==0 && loww(1)==0 && $2==4 | rmorconst rmorconst | | %[2] | zge $3 | ldc cms zeq $2==4 && loww(1)==0 && highw(1)==0 | rmorconst X_REG | remove(ALL) "or %[2],%[1]" "je $3" | | | ... | X_REG rmorconst | remove(ALL) "or %[1],%[2]" "je $3" | | | ldc cms zne $2==4 && loww(1)==0 && highw(1)==0 | rmorconst X_REG | remove(ALL) "or %[2],%[1]" "jne $3" | | | ... | X_REG rmorconst | remove(ALL) "or %[1],%[2]" "jne $3" | | | ldc cms zeq $2==4 | rmorconst rmorconst | remove(ALL) "cmp %[1],%(loww(1)%)" "jne 1f" "cmp %[2],%(highw(1)%)" "je $3" "1:" | | | ldc cms zne $2==4 | rmorconst rmorconst | remove(ALL) "cmp %[1],%(loww(1)%)" "jne $3" "cmp %[2],%(highw(1)%)" "jne $3" | | | cms zne $1==4 | regorconst regorconst rm rm STACK | "cmp %[3],%[1]" "jne $2" "cmp %[4],%[2]" "jne $2" | | | ... | NO rm rm regorconst regorconst | remove(ALL) "cmp %[1],%[3]" "jne $2" "cmp %[2],%[4]" "jne $2" | | | cms zeq $1==4 | regorconst regorconst rm rm STACK | "cmp %[3],%[1]" "jne 1f" "cmp %[4],%[2]" "je $2\n1:" | | | ... | NO rm rm regorconst regorconst | remove(ALL) "cmp %[1],%[3]" "jne 1f" "cmp %[2],%[4]" "je $2\n1:" | | | and zeq $1==2 | regorconst rm STACK | "test %[2],%[1]" "je $2" | | | ... | NO rm regorconst | remove(ALL) "test %[1],%[2]" "je $2" | | | and zne $1==2 | regorconst rm STACK | "test %[2],%[1]" "jne $2" | | | ... | NO rm regorconst | remove(ALL) "test %[1],%[2]" "jne $2" | | | loc and zeq $1<256 && $1>=0 && $2==2 | nocoercions : rm1 + memory2 | remove(ALL) "testb %[1],$1" "je $3" | | | (1,3) + %[1] ... | GENREG STACK | "testb %[1.1],$1" "je $3" | | | (1,3) + %[1] ... | nocoercions : IREG | remove(ALL) "test %[1],$1" "je $3" | | | (2,3) + %[1] loc and zne $1<256 && $1>=0 && $2==2 | nocoercions : rm1 + memory2 | remove(ALL) "testb %[1],$1" "jne $3" | | | (1,3) + %[1] ... | GENREG STACK | "testb %[1.1],$1" "jne $3" | | | (1,3) + %[1] ... | nocoercions : IREG | remove(ALL) "test %[1],$1" "jne $3" | | | (2,3) + %[1] loc beq $1<256 && $1>=0 | nocoercions : rm1 | remove(ALL) "cmpb %[1],$1" "je $2" | | | (1,3) + %[1] ... | rm STACK | "cmp %[1],$1" "je $2" | | | (2,3) + %[1] loc bne $1<256 && $1>=0 | nocoercions : rm1 | remove(ALL) "cmpb %[1],$1" "jne $2" | | | (1,3) + %[1] ... | rm STACK | "cmp %[1],$1" "jne $2" | | | (2,3) + %[1] /* Note: test for <,<=,>,>= can be done in this way, with use of the unsigned conditional jumps, jb, etc. */ loc cmu zeq $1<256 && $1>=0 && $2==2 | nocoercions : rm1 | remove(ALL) "cmpb %[1],$1" "je $3" | | | (1,3) + %[1] ... | rm STACK | "cmp %[1],$1" "je $3" | | | (2,3) + %[1] loc cmu zne $1<256 && $1>=0 && $2==2 | nocoercions : rm1 | remove(ALL) "cmpb %[1],$1" "jne $3" | | | (1,3) + %[1] ... | rm STACK | "cmp %[1],$1" "jne $3" | | | (2,3) + %[1] /**************************************** * Group 13 : Branch instructions * ****************************************/ bra | | remove(ALL) "jmp $1" samecc | | | blt | regorconst rm STACK | "cmp %[2],%[1]" "jl $1" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jg $1" | | | ble | regorconst rm STACK | "cmp %[2],%[1]" "jle $1" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jge $1" | | | beq | regorconst rm STACK | "cmp %[2],%[1]" "je $1" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "je $1" | | | bne | regorconst rm STACK | "cmp %[2],%[1]" "jne $1" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jne $1" | | | bge | regorconst rm STACK | "cmp %[2],%[1]" "jge $1" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jle $1" | | | bgt | regorconst rm STACK | "cmp %[2],%[1]" "jg $1" | | | ... | NO rm regorconst | remove(ALL) "cmp %[1],%[2]" "jl $1" | | | zlt | rm STACK | test(%[1]) "jl $1" | | | zle | rm STACK | test(%[1]) "jle $1" | | | zeq | rm+rm1 STACK | test(%[1]) "je $1" | | | zne | rm+rm1 STACK | test(%[1]) "jne $1" | | | zge | rm STACK | test(%[1]) "jge $1" | | | zgt | rm STACK | test(%[1]) "jg $1" | | | /************************************************ * group 14 : Procedure call instructions * ************************************************/ cal | | remove(ALL) "call $1" | | | cai | rm | remove(ALL) "call %[1]" | | | lfr $1==2 | | | ax | | lfr $1==4 | | | dx ax | | lfr $1==6 | | remove(ALL) "call .lfr6" | | | lfr $1==8 | | remove(ALL) "call .lfr8" | | | ret $1==0 | | remove(ALL) #ifdef REGVARS return #else "mov sp,bp" "pop bp" "ret" #endif | | | ret $1==2 | ACC | remove(ALL) #ifdef REGVARS return #else "mov sp,bp" "pop bp" "ret" #endif | | | ret $1==4 | ACC DXREG | remove(ALL) #ifdef REGVARS return #else "mov sp,bp" "pop bp" "ret" #endif | | | ret $1==6 | STACK | "call .ret6" #ifdef REGVARS return #else "mov sp,bp" "pop bp" "ret" #endif | | | ret $1==8 | STACK | "call .ret8" #ifdef REGVARS return #else "mov sp,bp" "pop bp" "ret" #endif | | | /************************************************ * Group 15 : Miscellaneous instructions * ************************************************/ asp $1==2 | nocoercions : a_word | | | | ... | STACK | allocate(BXREG) "pop %[a]" erase(%[a]) samecc | | | (1,8) asp $1==4 | nocoercions : a_word a_word | | | | ... | STACK | allocate(BXREG) "pop %[a]" "pop %[a]" erase(%[a]) samecc | | | (2,16) asp $1==0-2 | | /* Anything will do */ | bp | | asp | STACK | "add sp,$1" | | | (4,4) ass $1==2 | rmorconst STACK | "add sp,%[1]" | | | ass !defined($1)| rm rmorconst STACK | "cmp %[1],2" "jne .unknown" "add sp,%[2]" | | | blm $1==0 | | | | asp 4 | blm $1>0 | | remove(ALL) allocate(CXREG={ANYCON,$1/2}) "call .blm" erase(%[a]) | | | bls $1==2 | X_CXREG | remove(ALL) "sar cx,1" "call .blm" erase(%[1]) | | | bls !defined($1)| rm-CXREG X_CXREG | remove(ALL) "cmp %[1],2" "jne .unknown" "sar cx,1" "call .blm" erase(%[2]) | | | csa $1==2 | X_BXREG X_ACC | remove(ALL) "jmp .csa2" erase(%[1]) erase(%[2]) | | | csa !defined($1)| rm-BXREG-ACC X_BXREG X_ACC | remove(ALL) "cmp %[1],2" "jne .unknown" "jmp .csa2" erase(%[2]) erase(%[3]) | | | csb $1==2 | X_BXREG X_ACC | remove(ALL) "jmp .csb2" erase(%[1]) erase(%[2]) | | | csb !defined($1)| rm-BXREG-ACC X_BXREG X_ACC | remove(ALL) "cmp %[1],2" "jne .unknown" "jmp .csb2" erase(%[2]) erase(%[3]) | | | dup $1==2 | regorconst | | %[1] %[1] | | ... | ACC1 | | %[1] %[1] | | dup $1==4 | regorconst regorconst | | %[2] %[1] %[2] %[1] | | dup | | remove(ALL) move({ANYCON, $1}, cx) "call .dup" erase(cx) | | | dus $1==2 | X_CXREG | remove(ALL) "call .dup" erase(%[1]) | | | dus !defined($1)| rm-CXREG X_CXREG | remove(ALL) "cmp %[1],2" "jne .unknown" "call .dup" erase(%[2]) | | | exg $1==2 | a_word a_word | | %[1] %[2] | | exg $1==4 | a_word a_word a_word a_word | | %[2] %[1] %[4] %[3] | | exg defined($1) | | remove(ALL) move({ANYCON,$1},cx) "call .exg" erase(cx) | | | exg | rmorconst | remove(ALL) move(%[1],cx) "call .exg" erase(cx) | | | gto | | remove(ALL) "mov bx,$1" "jmp .gto" | | | fil | | "mov (hol0+4),$1" | | | lim | | allocate(REG) "mov %[a],(.ignmask)" | %[a] | | lin | | "mov (hol0),$1" | | | lni | | "inc (hol0)" | | | lor $1==0 | | | bp | | lor $1==1 | STACK | allocate(REG) "mov %[a],sp" | %[a] | | lor $1==2 | | allocate(REG) "mov %[a],(.reghp)" | %[a] | | mon | X_ACC | remove(ALL) "call .mon" | | | nop | | remove(ALL) "call .nop" | | | rck $1==2 | BXREG ACC | "call .rck" | ax | | rck !defined($1)| rm-BXREG-ACC BXREG ACC | "cmp %[1],2" "jne .unknown" "call .rck" | ax | | rtt | | | | ret 0 | sig | X_REG | "xchg (.trppc),%[1]" erase(%[1]) | %[1] | | sim | regorconst | "mov (.ignmask),%[1]" | | | str $1==0 | rmorconst | "mov bp,%[1]" | | | str $1==1 | rmorconst STACK | "mov sp,%[1]" | | | str $1==2 | | remove(ALL) "call .strhp" | | | trp | X_ACC | remove(ALL) "call .trp" | | | /******************************** * From source to register * ********************************/ | rmorconst | allocate(%[1],REG=%[1]) | %[a] | | | Xreg_off | "add %[1.reg],%[1.off]" erase(%[1.reg]) setcc(%[1.reg]) | %[1.reg] | |(2,3) + %[1] | halfindir | allocate(%[1],REG) move(%[1],%[a]) samecc | %[a] | |(0,0) | halfindir | allocate(%[1],ADDREG) move(%[1],%[a]) samecc | %[a] | |(0,0) /******************************** * From source to token * ********************************/ | ANYCON | | {ADDR_EXTERN,tostring(%[1.val])} | | /******************************** * From source1 * ********************************/ | rm1 | allocate(%[1],REG1=%[1]) | %[a] | | | rm1 | allocate(%[1],GENREG) move(%[1],%[a.1]) "xorb %[a.2],%[a.2]" | %[a] | |(2,3) | ACC1 | allocate(%[1],ACC) "xorb %[a.2],%[a.2]" | %[a] | |(2,3) /* | BLREG | allocate(%[1],BXREG) "xorb %[a.2],%[a.2]" | %[a] | |(2,3) */ /************************ * From STACK coercions * ************************/ | STACK | allocate(REG) "pop %[a]" samecc | %[a] | | (2,8) MOVES: (ACC, EXTERN2, "mov %[2],%[1]" samecc, (3,16)) (ACC1, EXTERN1, "movb %[2],%[1]" samecc, (3,16)) (ACC, EXTERN1, "movb %[2],%[1.1]" samecc, (3,16)) (EXTERN2, ACC, "mov %[2],%[1]" samecc, (3,14)) (EXTERN1, ACC1, "movb %[2],%[1]" samecc, (3,14)) (rm, register, "mov %[2],%[1]" samecc, (2,2) + %[1] ) (anyreg, dest, "mov %[2],%[1]" samecc, (2,3) + %[2] ) (halfindir, register, "lea %[2],%[1]" samecc, (2,3) + %[1] ) (rm1, REG1, "movb %[2],%[1]" samecc, (2,2) + %[1] ) (REG1, rm1, "movb %[2],%[1]" samecc, (2,3) + %[2] ) (GENREG, rm1, "movb %[2],%[1.1]" samecc, (2,3) + %[2] ) (ANYCON %[val]==0, register, "xor %[2],%[2]" setcc(%[2]), (2,3)) (ANYCON %[val]==0, REG1, "xorb %[2],%[2]" setcc(%[2]),(2,3)) (const, register, "mov %[2],%[1]" samecc, (3,4)) (const, REG1, "movb %[2],%[1]" samecc, (2,4)) (const, dest, "mov %[2],%[1]" samecc, (4,4) + %[2] ) (const, rm1, "movb %[2],%[1]" samecc, (3,4) + %[2] ) TESTS: (anyreg, "or %[1],%[1]", (2,3)) (memory2, "cmp %[1],0", (3,11)+%[1]) (REG1, "orb %[1],%[1]", (2,3)) (memory1, "cmpb %[1],0", (3,11)+%[1]) STACKS: (anyreg, , "push %[1]" samecc , (1,10) ) (memory2, , "push %[1]" samecc , (2,10) + %[1] ) (const, REG, move(%[1],%[a]) "push %[a]" samecc , (4,11) ) (const, , ".sect .data\n1: .data2 %[1]\n.sect .text" "push (1b)" samecc , (6,24) ) (rm1, GENREG, move({ANYCON,0},%[a]) move(%[1],%[a.1]) "push %[a]" samecc , (2,10) + %[1] ) (rm1, , "push %[1]" "push si" "mov si,sp" "movb 3(si),0" "pop si" samecc , (10,60) + %[1] ) (Xreg_off, , "add %[1.reg],%[1.off]" "push %[1.reg]" erase(%[1.reg]) setcc(%[1.reg]) , ( 4,14) ) (Xbpreg_off, , move(%[1],%[1.reg]) "push %[1.reg]" samecc , ( 6,17) + %[1] ) (ADDR_LOCAL %[ind]==0 , , "push bp" samecc , ( 1, 10) ) (halfindir, REG,move(%[1],%[a]) "push %[a]" samecc , ( 6,17) + %[1] ) (halfindir, , "push ax" "push si" "lea ax,%[1]" "mov si,sp" "xchg 2(si),ax" "pop si" samecc , (10,59) + %[1] )