/* * (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ rscid = "$Header$" /* * Back end tables for Intel 80386 * * Author : Ceriel J.H. Jacobs * * Partly adapted from Intel 8086 table * * wordsize = 4 bytes, pointersize = 4 bytes. * * Register ebp is used as LB, esp is used for SP. * Some global variables are used: * - .reghp : the heap pointer * - .ignmask : trap ignore mask * - .trppc : address of user defined trap handler * */ #define WS 4 #define PS 4 SL = 8 SSL = "8" EM_WSIZE = WS EM_PSIZE = PS EM_BSIZE = 8 SIZEFACTOR = 5/1 #define REGVARS #define EXACT exact /* to improve code but slow down code generator, define it to nothing */ /*****************************************************************/ PROPERTIES /*****************************************************************/ REG1 /* general 1 byte register */ REG2 /* general 2 byte register */ ACC1 /* 1 byte accumulator */ ACC2 /* 2 byte accumulator */ REG /* allocatable register */ GENREG /* register with sub-registers */ ACC /* accumulator */ SHIFT_CREG /* shift count register */ BXREG /* ebx register */ AREG /* address register */ ADDREG /* allocatable address register */ CXREG /* ecx register */ DXREG /* edx register */ IREG /* index register */ RREG /* register variable, or register without subregs */ /*****************************************************************/ REGISTERS /*****************************************************************/ al : REG1 , ACC1 . ah,bl, bh, ch,dl,dh : REG1 . cl : REG1 , SHIFT_CREG . ax = al + ah : REG2 , ACC2 . bx = bl + bh : REG2 . cx = cl + ch : REG2 . dx = dl + dh : REG2 . eax = al + ah : REG, GENREG, IREG, ACC, ADDREG, AREG. ebx = bl + bh : REG, GENREG, IREG, BXREG, ADDREG, AREG. ecx = cl + ch : REG, GENREG, IREG, CXREG, SHIFT_CREG, ADDREG , AREG . edx = dl + dh : REG, GENREG, IREG, DXREG, ADDREG, AREG . #ifndef REGVARS esi : REG, RREG, IREG, AREG, ADDREG . edi : REG, RREG, IREG, AREG, ADDREG . #else esi : AREG , IREG , RREG regvar(reg_any) . edi : AREG , IREG , RREG regvar(reg_any) . #endif ebp : AREG , IREG . esp : AREG . /*****************************************************************/ TOKENS /*****************************************************************/ ANYCON = { INT val; } 4 cost(4,0) val . CONSTR = { ADDR off; } 4 cost(4,0) off . ADDR_EXTERN = { ADDR off; } 4 cost(4,0) off . EXTERN1 = { ADDR off; } 4 cost(4,5) "(" off ")" . EXTERN2 = { ADDR off; } 4 cost(4,5) "(" off ")" . EXTERN = { ADDR off; } 4 cost(4,5) "(" off ")" . ADDR_LOCAL = { INT ind; } 4 cost(1,0) ind "(ebp)" . LOCAL = { INT ind; INT size; } 4 cost(1,5) ind "(ebp)" . LOCAL1 = { INT ind; INT size; } 4 cost(1,5) ind "(ebp)" . LOCAL2 = { INT ind; INT size; } 4 cost(1,5) ind "(ebp)" . Rreg_off = { AREG reg; ADDR off;} 4 cost(4,0) off "(" reg ")" . Xreg_off = { AREG reg; ADDR off;} 4 cost(4,0) off "(" reg ")" . indexed_r_off = { AREG reg; IREG reg2; INT scale; ADDR off;} 4 cost(5,0) off "(" reg ")" "(" reg2 "*" scale ")" . indexed_off = { IREG reg; INT scale; ADDR off;} 4 cost(5,0) off "(" reg "*" scale ")" . indir_r = { AREG reg;} 4 cost(0,5) "(" reg ")" . indir_r1 = { AREG reg;} 4 cost(0,5) "(" reg ")" . indir_r2 = { AREG reg;} 4 cost(0,5) "(" reg ")" . indir_r_off = { AREG reg; ADDR off;} 4 cost(4,5) off "(" reg ")" . indir_r_off1 = { AREG reg; ADDR off;} 4 cost(4,5) off "(" reg ")" . indir_r_off2 = { AREG reg; ADDR off;} 4 cost(4,5) off "(" reg ")" . indir_indexed_r_off = { AREG reg; IREG reg2; INT scale; ADDR off;} 4 cost(5,5) off "(" reg ")" "(" reg2 "*" scale ")" . indir_indexed_r_off1 = { AREG reg; IREG reg2; INT scale; ADDR off;} 4 cost(5,5) off "(" reg ")" "(" reg2 "*" scale ")" . indir_indexed_r_off2 = { AREG reg; IREG reg2; INT scale; ADDR off;} 4 cost(5,5) off "(" reg ")" "(" reg2 "*" scale ")" . indir_indexed_off = { IREG reg; INT scale; ADDR off;} 4 cost(5,5) off "(" reg "*" scale ")" . indir_indexed_off1 = { IREG reg; INT scale; ADDR off;} 4 cost(5,5) off "(" reg "*" scale ")" . indir_indexed_off2 = { IREG reg; INT scale; ADDR off;} 4 cost(5,5) off "(" reg "*" scale ")" . label = { ADDR off;} 4 off . /*****************************************************************/ SETS /*****************************************************************/ /* Mode refering to a word in memory */ memory2 = EXTERN2 + indir_r2 + indir_r_off2 + LOCAL2 + indir_indexed_r_off2 + indir_indexed_off2 . memory1 = EXTERN1 + indir_r1 + indir_r_off1 + LOCAL1 + indir_indexed_r_off1 + indir_indexed_off1 . memory = EXTERN + indir_r + indir_r_off + LOCAL + indir_indexed_r_off + indir_indexed_off . noacc = EXTERN + LOCAL + BXREG + CXREG + RREG . const = ANYCON + ADDR_EXTERN + CONSTR . register = REG + ADDREG + RREG + IREG . addreg = ADDREG + RREG . anyreg = register + AREG . rm = anyreg + memory . rmorconst = const + rm . regorconst = const + anyreg . dest = register + memory . rm1 = REG1 + memory1 . rmorconst1 = const + rm1 . rm2 = REG2 + memory2 . rmorconst2 = const + rm2 . regorconst124 = REG1 + REG2 + GENREG + const . regorconst24 = REG2 + GENREG + const . dest1 = REG1 + memory1 . dest2 = REG2 + memory2 . /* Modes used to indicate tokens to be removed from the fakestack */ reg_indir = indir_r1 + indir_r2 + indir_r_off1 + indir_r_off2 + indir_r + indir_r_off . indexed = indir_indexed_r_off1 + indir_indexed_r_off2 + indir_indexed_r_off + indir_indexed_off1 + indir_indexed_off2 + indir_indexed_off . indir = reg_indir + indexed . externals = EXTERN2 + EXTERN1 + EXTERN . locals = LOCAL2 + LOCAL1 + LOCAL . mem_nonlocals = externals + reg_indir . all_mems = mem_nonlocals + locals . /* Miscellaneous */ reg_off = Xreg_off + Rreg_off . halfindir = reg_off + ADDR_LOCAL + indexed_r_off + indexed_off . some_off = halfindir + ADDR_EXTERN + AREG . a_word = rmorconst + halfindir . /*****************************************************************/ INSTRUCTIONS /*****************************************************************/ cost(2,2) adc rm:rw:cc, regorconst:ro. adc anyreg:rw:cc, rmorconst:ro. #ifdef REGVARS add LOCAL:rw:cc, rmorconst:ro. /* only for register variables; UNSAFE !!! */ #endif add anyreg:rw:cc, rmorconst:ro. add rm:rw:cc, regorconst:ro. #ifdef REGVARS axx "syntax error" LOCAL:rw:cc, rmorconst:ro. /* only for register variables; UNSAFE !!! */ #endif axx "syntax error" anyreg:rw:cc, rmorconst:ro. axx "syntax error" rm:rw:cc, regorconst:ro. #ifdef REGVARS and LOCAL:rw:cc, rmorconst:ro. /* only for register variables; UNSAFE !!! */ #endif and rm:rw:cc, regorconst:ro. and anyreg:rw:cc, rmorconst:ro. cdq kills edx cost(1,3). cmp rm:ro, regorconst:ro kills :cc. cmp anyreg:ro, rmorconst:ro kills :cc. cmpb rm1:rw, const:ro kills :cc. cmpw "o16 cmp" rm2:rw, const:ro kills :cc cost(3,2). dec anyreg:rw:cc cost(1,2). dec rm:rw:cc. div rm:ro kills:cc eax edx cost(2,43). idiv rm:ro kills:cc eax edx cost(2,43). imul rm:rw, anyreg:ro kills:cc cost(3,41). imul anyreg:rw, rm:ro kills:cc cost(3,41). imul anyreg:wo, rm:ro, const:ro kills :cc cost(2,38). inc anyreg:rw:cc cost(1,2). inc rm:rw:cc. ja label cost(1,4). jae label cost(1,4). jb label cost(1,4). jbe label cost(1,4). jcxz label cost(1,4). je label cost(1,4). jg label cost(1,4). jge label cost(1,4). jl label cost(1,4). jle label cost(1,4). jne label cost(1,4). jmp label cost(1,4). proccall "call" label+rm cost(1,8). jxx "syntax error" label cost(1,4). lea anyreg:rw, halfindir:ro. lea LOCAL:rw, halfindir:ro. /* only for register variables, UNSAFE!!! */ leave cost(1,4). loop label kills ecx. #ifdef REGVARS mov LOCAL:wo, rmorconst:ro. /* only for register variables, UNSAFE!!! */ #endif mov a_word:wo, regorconst:ro. mov anyreg:wo, rmorconst:ro. movb rm1:wo, regorconst124:ro. movb REG1:wo, rm1:ro. movw "o16 mov" rm2:wo, regorconst124:ro cost(3,2). movw "o16 mov" REG2:wo, rmorconst2:ro cost(3,2). movsxb anyreg:wo, REG+rm1:ro. movsx anyreg:wo, REG+rm2:ro. movzxb anyreg:wo, REG+rm1:ro. movzx anyreg:wo, REG+rm2:ro. mul rmorconst:ro kills :cc eax edx cost(2,41). neg rmorconst:rw:cc. not rmorconst:rw. ORB "orb" REG1:ro, REG1:ro:cc. /* use ORB for tests */ ORW "o16 or" REG2:ro, REG2:ro:cc. /* use ORW for tests */ OR "or" anyreg:ro, anyreg:ro:cc. /* Use OR for tests */ #ifdef REGVARS or LOCAL:rw:cc, rmorconst:ro. /* only for register variables; UNSAFE !!! */ #endif or rm:rw:cc, regorconst:ro. or anyreg:rw:cc, rmorconst:ro. pop anyreg:wo cost(1,4). pop rm:wo. push anyreg:ro cost(1,2). push const:ro cost(1,2). push rm:ro cost(2,5). rcl rm:rw:cc, ANYCON+SHIFT_CREG:ro cost(2,10). rcr rm:rw:cc, ANYCON+SHIFT_CREG:ro cost(2,10). ret cost(1,10). rol rm:rw:cc, ANYCON+SHIFT_CREG:ro. ror rm:rw:cc, ANYCON+SHIFT_CREG:ro. sal rm:rw:cc, ANYCON+SHIFT_CREG:ro. sar rm:rw:cc, ANYCON+SHIFT_CREG:ro. sbb rm:rw:cc, regorconst:ro. sbb anyreg:rw:cc, rmorconst:ro. shl rm:rw:cc, ANYCON+SHIFT_CREG:ro. shr rm:rw:cc, ANYCON+SHIFT_CREG:ro. sxx rm:rw:cc, ANYCON+SHIFT_CREG:ro. #ifdef REGVARS sub LOCAL:rw:cc, rmorconst:ro. /* only for register variables; UNSAFE !!! */ #endif sub rm:rw:cc, regorconst:ro. sub anyreg:rw:cc, rmorconst+halfindir:ro. check "test" rm:ro, regorconst:ro kills :cc. check "test" anyreg:ro, rmorconst:ro kills :cc. testb "testb" rm1:ro, regorconst:ro kills :cc. testb "testb" REG1:ro, rmorconst:ro kills :cc. testw "o16 test" rm2:ro, regorconst:ro kills :cc. testw "o16 test" REG2:ro, rmorconst:ro kills :cc. uxx "syntax error" rm:rw:cc. xchg rm:rw, anyreg:rw. xchg anyreg:rw, rm:rw. xor rm:rw:cc, regorconst:ro. xor anyreg:rw:cc, rmorconst:ro. xorb rm1:rw:cc, regorconst124:ro. xorb anyreg:rw:cc, rmorconst1:ro. xorw "o16 xor" rm2:rw:cc, regorconst124:ro. xorw "o16 xor" anyreg:rw:cc, rmorconst2:ro. killreg "! kill" anyreg:wo cost(0,0). /*****************************************************************/ MOVES /*****************************************************************/ #ifdef REGVARS from rmorconst to LOCAL /* unsafe !!! */ gen mov %2,%1 #endif from rm to register gen mov %2,%1 from anyreg to dest gen mov %2,%1 from halfindir to register+AREG gen lea %2,%1 from halfindir to LOCAL /* unsafe !!! */ gen lea %2,%1 from rm1 to REG1 gen movb %2,%1 from rm2 to REG2 gen movw %2,%1 from GENREG to rm1 gen movb %2,%1.1 from GENREG to rm2 gen movw %2,%1 from REG2 to rm1 gen movb %2,%1.1 from ANYCON %val==0 to register gen xor %2,%2 from ANYCON %val==0 to REG1 gen xorb %2,%2 from ANYCON %val==0 to REG2 gen xorw %2,%2 from const to dest gen mov %2,%1 from const+REG1 to rm1 gen movb %2,%1 from const+REG2 to rm2 gen movw %2,%1 /*****************************************************************/ TESTS /*****************************************************************/ to test anyreg gen OR %1,%1 to test memory gen cmp %1, {ANYCON,0} to test REG1 gen ORB %1,%1 to test memory1 gen cmpb %1, {ANYCON,0} to test REG2 gen ORW %1,%1 to test memory2 gen cmpw %1, {ANYCON,0} /*****************************************************************/ STACKINGRULES /*****************************************************************/ from rm to STACK gen push %1 from const to STACK gen push %1 from rm1 to STACK uses REG gen movzxb %a,%1 push %a from rm1 to STACK gen push eax movzxb eax,%1 xchg {indir_r,esp},eax from rm2 to STACK uses REG gen movzx %a,%1 push %a from rm2 to STACK gen push eax movzx eax,%1 xchg {indir_r,esp},eax from Xreg_off to STACK gen add %1.reg,{CONSTR,%1.off} push %1.reg from ADDR_LOCAL %ind==0 to STACK gen push ebp from halfindir to STACK uses REG gen move %1,%a push %a from halfindir to STACK gen push eax lea eax,%1 xchg {indir_r,esp},eax /*****************************************************************/ COERCIONS /*****************************************************************/ /*************************** * From source to register * ***************************/ from rmorconst uses reusing %1,REG=%1 yields %a from rmorconst uses reusing %1,IREG=%1 yields %a from Xreg_off gen add %1.reg,{CONSTR,%1.off} yields %1.reg from halfindir uses reusing %1,ADDREG gen move %1,%a yields %a from halfindir uses reusing %1,REG gen move %1,%a yields %a from halfindir uses reusing %1,IREG gen move %1,%a yields %a /************************ * From source to token * ************************/ from ANYCON yields {ADDR_EXTERN,%1.val} /**************** * From source1 * ****************/ from rm1 uses reusing %1,REG1=%1 yields %a from rm1 uses GENREG gen movzxb %a,%1 yields %a /**************** * From source2 * ****************/ from rm2 uses reusing %1,REG2=%1 yields %a from rm2 uses GENREG gen movzx %a,%1 yields %a /************************ * From STACK coercions * ************************/ from STACK uses REG gen pop %a yields %a /*****************************************************************/ PATTERNS /*****************************************************************/ /****************************************************************** * Group 1 : Load Instructions * ******************************************************************/ pat loc yields {ANYCON,$1} pat ldc leaving loc 18 trp pat lol yields {LOCAL,$1,4} pat stl lol $1==$2 #ifdef REGVARS && inreg($1) <= 0 #endif leaving dup 4 stl $1 pat sdl ldl $1==$2 leaving dup 8 sdl $1 pat lol lol $1==$2 #ifdef REGVARS && inreg($1) <= 0 #endif leaving lol $1 dup 4 #ifdef REGVARS pat lol lol stl $1==$2 && inreg($1) <= 0 && inreg($3) > 0 kills regvar($3) gen move {LOCAL,$1,4}, {LOCAL,$3,4} yields {LOCAL,$3,4} #endif pat loe yields {EXTERN,$1} pat ste loe $1==$2 leaving dup 4 ste $1 pat sde lde $1==$2 leaving dup 8 sde $1 pat loe loe $1==$2 leaving loe $1 dup 4 #ifdef REGVARS pat loe loe stl $1==$2 && inreg($3) > 0 kills regvar($3) gen move {EXTERN,$1}, {LOCAL,$3,4} yields {LOCAL,$3,4} #endif #ifdef REGVARS pat lil inreg($1) > 0 yields {indir_r, regvar($1)} #endif pat lil uses ADDREG={indir_r_off,ebp,$1} yields {indir_r,%a} pat lil lil $1==$2 leaving lil $1 dup 4 pat lil lil stl $1==$2 leaving lil $1 stl $3 lol $3 pat sil lil $1==$2 leaving dup 4 sil $1 pat lof with exact indexed_r_off yields {indir_indexed_r_off,%1.reg,%1.reg2, %1.scale,%1.off+$1} with exact indexed_off yields {indir_indexed_off,%1.reg, %1.scale,%1.off+$1} with exact reg_off yields {indir_r_off,%1.reg,%1.off+$1} with exact ADDR_EXTERN yields {EXTERN,%1.off+$1} with exact ADDR_LOCAL yields {LOCAL,%1.ind + $1,4} with addreg yields {indir_r_off,%1,$1} pat lal yields {ADDR_LOCAL,$1} pat lae yields {ADDR_EXTERN,$1} pat lpb leaving adp SL pat lxl $1==0 yields {ADDR_LOCAL,0} pat lxl $1==1 yields {LOCAL,SL,4} pat lxl $1==2 uses ADDREG={indir_r_off,ebp,SSL} yields {indir_r_off,%a,SSL} pat lxl $1>2 uses ADDREG={indir_r_off,ebp,SSL}, CXREG={ANYCON,$1-1} gen 1: mov %a,{indir_r_off,%a,SSL} loop {label,1b} yields %a pat lxa $1==0 yields {ADDR_LOCAL,SL} pat lxa $1==1 uses ADDREG={indir_r_off,ebp,SSL} yields {Xreg_off,%a,SSL} pat lxa $1==2 uses ADDREG={indir_r_off,ebp,SSL} gen move {indir_r_off,%a,SSL},%a yields {Xreg_off,%a,SSL} pat lxa $1>2 uses ADDREG={indir_r_off,ebp,SSL}, CXREG={ANYCON,$1-1} gen 1: mov %a,{indir_r_off,%a,SSL} loop {label,1b} yields {Xreg_off,%a,SSL} pat dch leaving loi 4 pat loi $1==2 with addreg yields {indir_r2,%1} with exact indexed_r_off yields {indir_indexed_r_off2, %1.reg, %1.reg2, %1.scale, %1.off} with exact indexed_off yields {indir_indexed_off2, %1.reg, %1.scale, %1.off} with exact reg_off yields {indir_r_off2,%1.reg,%1.off} with exact ADDR_EXTERN yields {EXTERN2,%1.off} with exact ADDR_LOCAL yields {LOCAL2,%1.ind,2} pat loi $1==1 with addreg yields {indir_r1,%1} with exact indexed_r_off yields {indir_indexed_r_off1, %1.reg, %1.reg2, %1.scale, %1.off} with exact indexed_off yields {indir_indexed_off1, %1.reg, %1.scale, %1.off} with exact reg_off yields {indir_r_off1,%1.reg,%1.off} with exact ADDR_EXTERN yields {EXTERN1,%1.off} with exact ADDR_LOCAL yields {LOCAL1,%1.ind,1} pat loi $1==4 with addreg yields {indir_r,%1} with exact indexed_r_off yields {indir_indexed_r_off, %1.reg, %1.reg2, %1.scale, %1.off} with exact indexed_off yields {indir_indexed_off, %1.reg, %1.scale, %1.off} with exact reg_off yields {indir_r_off,%1.reg,%1.off} with exact ADDR_EXTERN yields {EXTERN,%1.off} with exact ADDR_LOCAL yields {LOCAL,%1.ind,4} pat loi $1==8 with addreg yields {indir_r_off,%1,4} {indir_r,%1} with exact indexed_r_off yields {indir_indexed_r_off, %1.reg, %1.reg2, %1.scale, %1.off+4} {indir_indexed_r_off, %1.reg, %1.reg2, %1.scale, %1.off} with exact indexed_off yields {indir_indexed_off, %1.reg, %1.scale, %1.off+4} {indir_indexed_off, %1.reg, %1.scale, %1.off} with exact reg_off yields {indir_r_off,%1.reg,%1.off+4} {indir_r_off,%1.reg,%1.off} with exact ADDR_LOCAL yields {LOCAL,%1.ind+4,4} {LOCAL,%1.ind,4} with exact ADDR_EXTERN yields {EXTERN,%1.off + 4} {EXTERN,%1.off} pat loi with BXREG kills ALL gen mov ecx,{ANYCON,$1} proccall {label,".loi"} pat los $1==4 with CXREG BXREG kills ALL gen proccall {label,".los"} pat ldl yields {LOCAL,$1+4,4} {LOCAL,$1,4} pat lde yields {EXTERN,$1+4} {EXTERN,$1} pat ldf with exact reg_off yields {indir_r_off,%1.reg, %1.off + 4 + $1} {indir_r_off,%1.reg, %1.off + $1} with exact indexed_r_off yields {indir_indexed_r_off, %1.reg, %1.reg2, %1.scale, %1.off+$1+4} {indir_indexed_r_off, %1.reg, %1.reg2, %1.scale, %1.off+$1} with exact indexed_off yields {indir_indexed_off, %1.reg, %1.scale, %1.off+$1+4} {indir_indexed_off, %1.reg, %1.scale, %1.off+$1} with addreg yields {indir_r_off,%1,$1+4} {indir_r_off,%1,$1} with exact ADDR_EXTERN yields {EXTERN,%1.off+4+$1} {EXTERN,%1.off+$1} with exact ADDR_LOCAL yields {LOCAL,%1.ind + $1 + 4,4} {LOCAL,%1.ind + $1,4} pat lpi yields {ADDR_EXTERN,$1} /* this code sequence is generated by the C-compiler to tackle char parameters, on the 80386 it reduces to nil */ pat lol lal sti $1==$2 && $3<=4 /******************************************************************* * Group 2 : Store Instructions * *******************************************************************/ #ifdef REGVARS pat stl inreg($1)==reg_any with rmorconst kills regvar($1) gen move %1, {LOCAL,$1,4} with exact halfindir kills regvar($1) gen move %1, {LOCAL,$1,4} with exact STACK kills regvar($1) gen pop {LOCAL, $1, 4} #endif pat stl with regorconst kills indir,locals %ind+%size > $1 && %ind < $1+4 gen move %1,{LOCAL,$1,4} with exact STACK kills ALL gen pop {indir_r_off,ebp,$1} pat ste with regorconst kills mem_nonlocals gen move %1,{EXTERN,$1} with exact STACK kills ALL gen pop {EXTERN,$1} #ifdef REGVARS pat sil inreg($1)==reg_any with regorconst kills all_mems gen move %1,{indir_r,regvar($1)} with exact STACK kills ALL gen pop {indir_r,regvar($1)} #endif pat sil with regorconst kills all_mems uses ADDREG={indir_r_off,ebp,$1} gen move %1,{indir_r,%a} killreg %a with exact STACK kills ALL uses ADDREG={indir_r_off,ebp,$1} gen pop {indir_r,%a} killreg %a pat stf with addreg regorconst kills all_mems gen move %2,{indir_r_off,%1,$1} with exact addreg STACK kills ALL gen pop {indir_r_off, %1,$1} with reg_off regorconst kills all_mems gen move %2,{indir_r_off,%1.reg,%1.off+$1} with exact reg_off STACK gen pop {indir_r_off,%1.reg,$1+%1.off} with indexed_r_off regorconst kills all_mems gen move %2,{indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+$1} with exact indexed_r_off STACK kills all_mems gen pop {indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+$1} with indexed_off regorconst kills all_mems gen move %2,{indir_indexed_off,%1.reg,%1.scale,%1.off+$1} with exact indexed_off STACK kills all_mems gen pop {indir_indexed_off,%1.reg,%1.scale,%1.off+$1} with ADDR_LOCAL regorconst kills indir,locals %ind+%size > %1.ind+$1 && %ind < %1.ind+$1+4 gen move %2,{LOCAL,%1.ind+$1,4} with exact ADDR_LOCAL STACK kills indir,locals %ind+%size > %1.ind+$1 && %ind < %1.ind+$1+4 gen pop {LOCAL,%1.ind+$1,4} with ADDR_EXTERN regorconst kills mem_nonlocals gen move %2,{EXTERN,%1.off+$1} with exact ADDR_EXTERN STACK kills mem_nonlocals gen pop {EXTERN,%1.off+$1} pat sti $1==4 with addreg regorconst kills all_mems gen move %2,{indir_r,%1} with exact addreg STACK kills all_mems gen pop {indir_r,%1} with reg_off regorconst kills all_mems gen move %2,{indir_r_off,%1.reg,%1.off} with exact reg_off STACK kills all_mems gen pop {indir_r_off,%1.reg,%1.off} with indexed_r_off regorconst kills all_mems gen move %2,{indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off} with exact indexed_r_off STACK kills all_mems gen pop {indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off} with indexed_off regorconst kills all_mems gen move %2,{indir_indexed_off,%1.reg,%1.scale,%1.off} with exact indexed_off STACK kills all_mems gen pop {indir_indexed_off,%1.reg,%1.scale,%1.off} with ADDR_LOCAL regorconst kills indir,locals %ind+%size > %1.ind && %ind < %1.ind+4 gen move %2,{LOCAL,%1.ind,4} with exact ADDR_LOCAL STACK kills indir,locals %ind+%size > %1.ind && %ind < %1.ind+4 gen pop {LOCAL,%1.ind,4} with ADDR_EXTERN regorconst kills mem_nonlocals gen move %2,{EXTERN,%1.off} with exact ADDR_EXTERN STACK kills mem_nonlocals gen pop {EXTERN,%1.off} pat sti $1==1 with addreg regorconst124 kills all_mems gen move %2,{indir_r1,%1} with reg_off regorconst124 kills all_mems gen move %2,{indir_r_off1,%1.reg,%1.off} with indexed_r_off regorconst124 kills all_mems gen move %2,{indir_indexed_r_off1,%1.reg,%1.reg2,%1.scale,%1.off} with indexed_off regorconst124 kills all_mems gen move %2,{indir_indexed_off1,%1.reg,%1.scale,%1.off} with ADDR_EXTERN regorconst124 kills mem_nonlocals gen move %2,{EXTERN1,%1.off} with ADDR_LOCAL regorconst124 kills indir,locals %ind<%1.ind+1 && %ind+%size>%1.ind gen move %2,{indir_r_off1,ebp,%1.ind} pat sti $1==2 with addreg regorconst24 kills all_mems gen move %2,{indir_r2,%1} with reg_off regorconst24 kills all_mems gen move %2,{indir_r_off2,%1.reg,%1.off} with indexed_r_off regorconst24 kills all_mems gen move %2,{indir_indexed_r_off2,%1.reg,%1.reg2,%1.scale,%1.off} with indexed_off regorconst24 kills all_mems gen move %2,{indir_indexed_off2,%1.reg,%1.scale,%1.off} with ADDR_EXTERN regorconst24 kills mem_nonlocals gen move %2,{EXTERN2,%1.off} with ADDR_LOCAL regorconst24 kills indir,locals %ind<%1.ind+2 && %ind+%size>%1.ind gen move %2,{indir_r_off2,ebp,%1.ind} pat sti $1==8 leaving sdf 0 pat sti with BXREG kills ALL gen mov ecx,{ANYCON,$1} proccall {label, ".sti"} /* this sort of construction gives problems in the codegenerator because of the potential very large lookahead with addreg kills ALL gen pop (%1) add %1,{ANYCON,2} yields %1 leaving sti $1-4 */ pat sts $1==4 with CXREG BXREG kills ALL gen proccall {label,".sts"} pat sdl with regorconst regorconst yields %2 %1 leaving stl $1 stl $1+4 with exact STACK leaving stl $1 stl $1+4 pat sde with regorconst regorconst yields %2 %1 leaving ste $1 ste $1+4 with exact STACK leaving ste $1 ste $1+4 pat sdf with addreg regorconst regorconst kills all_mems gen move %2,{indir_r_off,%1,$1} move %3,{indir_r_off,%1,$1+4} with exact addreg STACK kills all_mems gen pop {indir_r_off,%1,$1} pop {indir_r_off,%1,$1+4} with reg_off regorconst regorconst kills all_mems gen move %2,{indir_r_off,%1.reg,%1.off+$1} move %3,{indir_r_off,%1.reg,%1.off+$1+4} with exact reg_off STACK kills all_mems gen pop {indir_r_off,%1.reg,$1+%1.off} pop {indir_r_off,%1.reg,$1+%1.off+4} with indexed_r_off regorconst regorconst kills all_mems gen move %2,{indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+$1} move %3,{indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+4+$1} with exact indexed_r_off STACK kills all_mems gen pop {indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+$1} pop {indir_indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+4+$1} with indexed_off regorconst regorconst kills all_mems gen move %2,{indir_indexed_off,%1.reg,%1.scale,%1.off+$1} move %3,{indir_indexed_off,%1.reg,%1.scale,%1.off+4+$1} with exact indexed_off STACK kills all_mems gen pop {indir_indexed_off,%1.reg,%1.scale,%1.off+$1} pop {indir_indexed_off,%1.reg,%1.scale,%1.off+4+$1} with ADDR_LOCAL regorconst regorconst kills indir,locals %ind+%size > $1 && %ind < $1+8 gen move %2,{LOCAL,%1.ind+$1,4} move %3,{LOCAL,%1.ind+$1+4,4} with exact ADDR_LOCAL STACK kills indir,locals %ind+%size > $1 && %ind < $1+8 gen pop {LOCAL,%1.ind+$1,4} pop {LOCAL,%1.ind+$1+4,4} with ADDR_EXTERN regorconst regorconst kills mem_nonlocals gen move %2,{EXTERN,%1.off+$1} move %3,{EXTERN,%1.off+$1+4} with exact ADDR_EXTERN STACK kills mem_nonlocals gen pop {EXTERN,%1.off+$1} pop {EXTERN,%1.off+$1+4} with halfindir regorconst kills all_mems gen mov %1,%2 yields %1 leaving stf $1+4 /**************************************************************** * Group 3 : Integer Arithmetic. * * * * Implemented (sometimes with the use of subroutines) : * * 4 byte arithmetic. * ****************************************************************/ pat adi $1==4 #ifdef REGVARS with exact ANYCON RREG yields {Rreg_off,%2,%1.val} with exact RREG ANYCON yields {Rreg_off,%1,%2.val} #endif with REG rmorconst gen add %1,%2 yields %1 with rmorconst REG gen add %2,%1 yields %2 with EXACT rmorconst const uses reusing %1,REG=%1 gen add %a,%2 yields %a /* pat adi !defined($1) with CXREG ACC kills ALL gen proccall {label,".adi"} yields eax */ pat sbi $1==4 with rmorconst REG gen sub %2,%1 yields %2 with EXACT REG rmorconst gen sub %1,%2 neg %1 yields %1 /* pat sbi !defined($1) with CXREG ACC kills ALL gen proccall {label,".sbi"} yields eax */ pat mli $1==4 with rm REG gen imul %2,%1 yields %2 with REG rm gen imul %1,%2 yields %1 with const rm uses reusing %2,REG gen imul %a,%2,%1 yields %a with rm const uses reusing %1,REG gen imul %a,%1,%2 yields %a /* pat mli !defined($1) with ACC kills ALL gen proccall {label,".mli"} */ pat dvi $1==4 with noacc ACC uses DXREG gen cdq. idiv %1 yields eax /* pat dvi !defined($1) with ACC kills ALL gen proccall {label,".dvi"} */ pat rmi $1==4 with noacc ACC uses DXREG gen cdq. idiv %1 yields edx /* pat rmi !defined($1) with ACC kills ALL gen proccall {label,".rmi"} */ pat ngi $1==4 with REG gen neg %1 yields %1 /* pat ngi !defined($1) with ACC kills ALL gen proccall {label,".ngi"} */ pat sli $1==4 with ANYCON REG gen sal %2,%1 yields %2 with SHIFT_CREG REG gen sal %2,cl yields %2 /* pat sli !defined($1) with ACC kills ALL gen proccall {label,".sli"} */ pat sri $1==4 with SHIFT_CREG REG gen sar %2,cl yields %2 with ANYCON REG gen sar %2,%1 yields %2 /* pat sri !defined($1) with ACC kills ALL gen proccall {label,".sri"} */ /******************************************************************* * Group 4: Unsigned Arithmetic * *******************************************************************/ pat adu leaving adi $1 pat loc lol adu stl $1==1 && $3==4 && $2==$4 leaving inl $2 pat loc loe adu ste $1==1 && $3==4 && $2==$4 leaving ine $2 pat loc lol adu $1==1 && $3==4 leaving lol $2 inc pat loc loe adu $1==1 && $3==4 leaving loe $2 inc pat loc lil adu $1==1 && $3==4 leaving lil $2 inc pat loc lol adu stl $1==0-1 && $3==4 && $2==$4 leaving del $2 pat loc loe adu ste $1==0-1 && $3==4 && $2==$4 leaving dee $2 pat loc lol adu $1==0-1 && $3==4 leaving lol $2 dec pat loc loe adu $1==0-1 && $3==4 leaving loe $2 dec pat loc lil adu $1==0-1 && $3==4 leaving lil $2 dec pat sbu leaving sbi $1 pat lol loc sbu stl $1==$4 && $2==1 && $3==4 leaving del $1 pat loe loc sbu ste $1==$4 && $2==1 && $3==4 leaving dee $1 pat lol loc sbu $2==1 && $3==4 leaving lol $1 dec pat loe loc sbu $2==1 && $3==4 leaving loe $1 dec pat lil loc sbu $2==1 && $3==4 leaving lil $1 dec pat lol loc sbu stl $1==$4 && $2==0-1 && $3==4 leaving inl $1 pat loe loc sbu ste $1==$4 && $2==0-1 && $3==4 leaving ine $1 pat lol loc sbu $2==0-1 && $3==4 leaving lol $1 inc pat loe loc sbu $2==0-1 && $3==4 leaving loe $1 inc pat lil loc sbu $2==0-1 && $3==4 leaving lil $1 inc pat mlu leaving mli $1 pat dvu $1==4 with noacc ACC uses DXREG={ANYCON,0} gen div %1 yields eax /* pat dvu !defined($1) with ACC STACK kills ALL gen proccall {label,".dvu"} */ pat rmu $1==4 with noacc ACC uses DXREG={ANYCON,0} gen div %1 yields edx /* pat rmu !defined($1) with ACC STACK kills ALL gen proccall {label,".rmu"} */ pat slu leaving sli $1 pat sru $1==4 with SHIFT_CREG REG gen shr %2,cl yields %2 with ANYCON REG gen shr %2,%1 yields %2 /* pat sru !defined($1) with ACC STACK kills ALL gen proccall {label,".sru"} */ /******************************************************************* * Group 5: Floating Point Instructions * *******************************************************************/ pat adf $1==4 leaving cal ".adf4" asp 4 pat adf $1==8 leaving cal ".adf8" asp 8 pat sbf $1==4 leaving cal ".sbf4" asp 4 pat sbf $1==8 leaving cal ".sbf8" asp 8 pat mlf $1==4 leaving cal ".mlf4" asp 4 pat mlf $1==8 leaving cal ".mlf8" asp 8 pat dvf $1==4 leaving cal ".dvf4" asp 4 pat dvf $1==8 leaving cal ".dvf8" asp 8 pat ngf $1==4 leaving cal ".ngf4" pat ngf $1==8 leaving cal ".ngf8" pat fif $1==4 leaving lor 1 cal ".fif4" asp 4 pat fif $1==8 leaving lor 1 cal ".fif8" asp 4 pat fef $1==4 leaving lor 1 adp 0-4 cal ".fef4" pat fef $1==8 leaving lor 1 adp 0-4 cal ".fef8" /****************************************************************** * Group 6: Pointer Arithmetic * ******************************************************************/ pat adp $1==1 with exact Xreg_off yields {Xreg_off,%1.reg,%1.off+$1} with exact Rreg_off yields {Rreg_off,%1.reg,%1.off+$1} with exact indexed_r_off yields {indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+$1} with exact indexed_off yields {indexed_off,%1.reg,%1.scale,%1.off+$1} with exact ADDR_EXTERN yields {ADDR_EXTERN,%1.off+$1} with exact ADDR_LOCAL yields {ADDR_LOCAL,%1.ind+$1} with REG gen inc %1 yields %1 with ADDREG gen killreg %1 yields {Xreg_off, %1, $1} with exact RREG yields {Rreg_off, %1, $1} pat adp $1==0-1 with exact Xreg_off yields {Xreg_off,%1.reg,%1.off+$1} with exact Rreg_off yields {Rreg_off,%1.reg,%1.off+$1} with exact indexed_r_off yields {indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+$1} with exact indexed_off yields {indexed_off,%1.reg,%1.scale,%1.off+$1} with exact ADDR_EXTERN yields {ADDR_EXTERN,%1.off+$1} with exact ADDR_LOCAL yields {ADDR_LOCAL,%1.ind+$1} with REG gen dec %1 yields %1 with ADDREG gen killreg %1 yields {Xreg_off, %1, $1} with exact RREG yields {Rreg_off, %1, $1} pat adp with exact Xreg_off yields {Xreg_off,%1.reg,%1.off+$1} with exact Rreg_off yields {Rreg_off,%1.reg,%1.off+$1} with exact indexed_r_off yields {indexed_r_off,%1.reg,%1.reg2,%1.scale,%1.off+$1} with exact indexed_off yields {indexed_off,%1.reg,%1.scale,%1.off+$1} with exact ADDR_EXTERN yields {ADDR_EXTERN,%1.off+$1} with exact ADDR_LOCAL yields {ADDR_LOCAL,%1.ind+$1} with ADDREG gen killreg %1 yields {Xreg_off,%1,$1} with exact RREG yields {Rreg_off, %1, $1} with REG gen add %1,{ANYCON,$1} yields %1 pat ads stl $1==4 leaving adi 4 stl $2 pat ads ste $1==4 leaving adi 4 ste $2 pat ads sil $1==4 leaving adi 4 sil $2 pat ads lol stf $1==4 leaving adi 4 lol $2 stf $3 pat ads loe stf $1==4 leaving adi 4 loe $2 stf $3 pat ads $1==4 with exact ANYCON Rreg_off yields {Rreg_off,%2.reg,%2.off+%1.val} with exact ANYCON Xreg_off yields {Xreg_off,%2.reg,%2.off+%1.val} with exact ANYCON indexed_r_off yields {indexed_r_off,%2.reg,%2.reg2, %2.scale,%2.off+%1.val} with exact ANYCON indexed_off yields {indexed_off,%2.reg,%2.scale,%2.off+%1.val} with exact ADDR_EXTERN Rreg_off yields {Rreg_off,%2.reg,%2.off+%1.off} with exact ADDR_EXTERN Xreg_off yields {Xreg_off,%2.reg,%2.off+%1.off} with exact ADDR_EXTERN indexed_r_off yields {indexed_r_off,%2.reg,%2.reg2, %2.scale,%2.off+%1.off} with exact ADDR_EXTERN indexed_off yields {indexed_off,%2.reg,%2.scale,%2.off+%1.off} with exact IREG reg_off yields {indexed_r_off,%2.reg,%1,1,%2.off} with exact reg_off IREG yields {indexed_r_off,%1.reg,%2,1,%1.off} with exact IREG ADDR_LOCAL yields {indexed_r_off,ebp,%1,1,%2.ind} with exact ADDR_LOCAL IREG yields {indexed_r_off,ebp,%2,1,%1.ind} with rmorconst Xreg_off gen add %2.reg,%1 yields %2 with Xreg_off rmorconst gen add %1.reg,%2 yields %1 with exact Xreg_off ANYCON yields {Xreg_off,%1.reg,%1.off+%2.val} with exact Rreg_off ANYCON yields {Rreg_off,%1.reg,%1.off+%2.val} with exact indexed_r_off ANYCON yields {indexed_r_off,%1.reg,%1.reg2, %1.scale,%1.off+%2.val} with exact indexed_off ANYCON yields {indexed_off,%1.reg,%1.scale,%1.off+%2.val} with exact Xreg_off ADDR_EXTERN yields {Xreg_off,%1.reg,%1.off+%2.off} with exact Rreg_off ADDR_EXTERN yields {Rreg_off,%1.reg,%1.off+%2.off} with exact indexed_r_off ADDR_EXTERN yields {indexed_r_off,%1.reg,%1.reg2, %1.scale,%1.off+%2.off} with exact indexed_off ADDR_EXTERN yields {indexed_off,%1.reg,%1.scale,%1.off+%2.off} with exact Xreg_off reg_off gen add %1.reg,%2.reg yields {Xreg_off,%1.reg,%1.off+%2.off} with exact RREG ADDR_EXTERN yields {Rreg_off, %1, %2.off} with exact ADDR_EXTERN RREG yields {Rreg_off,%2,%1.off} with exact rmorconst ADDR_EXTERN uses reusing %1,ADDREG=%1 yields {Xreg_off,%a,%2.off} with exact ADDR_EXTERN rmorconst uses reusing %2,ADDREG=%2 yields {Xreg_off,%a,%1.off} with rmorconst ADDREG gen add %2,%1 yields %2 with ADDREG rmorconst gen add %1,%2 yields %1 pat sbs $1==4 with exact ANYCON Xreg_off yields {Xreg_off,%2.reg,%2.off+"-"+%1.val} with exact ANYCON Rreg_off yields {Rreg_off,%2.reg,%2.off+"-"+%1.val} with exact ANYCON indexed_r_off yields {indexed_r_off,%2.reg,%2.reg2,%2.scale, %2.off+"-"+%1.val} with exact ANYCON indexed_off yields {indexed_off,%2.reg,%2.scale,%2.off+"-"+%1.val} with exact ANYCON ADDR_LOCAL yields {ADDR_LOCAL,%2.ind-%1.val} with rm Xreg_off gen sub %2.reg,%1 yields {Xreg_off,%2.reg,%2.off} /* Should not occur with exact reg_off ANYCON yields {reg_off,%1.reg,%1.off-%2.val} with ANYCON ADDR_EXTERN yields {ADDR_EXTERN,%2.off+%1.val} with exact ANYCON ADDR_LOCAL yields {ADDR_LOCAL,%1.val+%2.ind} */ with rm REG gen sub %2,%1 yields %2 with const ACC gen sub %2,%1 yields %2 /******************************************************************* * Group 7 : Increment/Decrement Zero * *******************************************************************/ pat inc with REG gen inc %1 yields %1 #ifdef REGVARS pat inl inreg($1)==reg_any kills regvar($1) gen inc {LOCAL,$1,4} #endif pat inl kills indir, locals %ind + %size>$1 && %ind<$1+4 gen inc {LOCAL,$1,4} pat ine kills mem_nonlocals gen inc {EXTERN,$1} pat dec with REG gen dec %1 yields %1 #ifdef REGVARS pat del inreg($1)==reg_any kills regvar($1) gen dec {LOCAL,$1,4} #endif pat del kills indir, locals %ind+%size>$1 && %ind<$1+4 gen dec {LOCAL, $1, 4} pat dee kills mem_nonlocals gen dec {EXTERN, $1} #ifdef REGVARS pat zrl inreg($1)==reg_any kills regvar($1) gen move {ANYCON, 0}, {LOCAL,$1,4} #endif pat zrl kills indir, locals %ind+%size>$1 && %ind<$1+4 gen move {ANYCON, 0}, {LOCAL,$1,4} pat zre kills mem_nonlocals gen move {ANYCON, 0}, {EXTERN, $1} pat zrf leaving zer $1 pat zer $1==4 yields {ANYCON, 0} pat zer $1==8 yields {ANYCON, 0} {ANYCON, 0} pat zer $1==12 yields {ANYCON, 0} {ANYCON, 0} {ANYCON, 0} pat zer $1==16 yields {ANYCON, 0} {ANYCON, 0} {ANYCON, 0} {ANYCON, 0} pat zer defined($1) with STACK gen move {ANYCON, $1/4}, ecx move {ANYCON, 0}, ebx 1: push ebx loop {label,1b} pat zer !defined($1) with CXREG STACK gen move {ANYCON, $1/4}, ebx sar ecx,{ANYCON, 1} 1: push ebx loop {label,1b} #ifdef REGVARS proc lolrxxxstl example lol adi stl with rmorconst kills regvar($1) gen axx* {LOCAL, $1, 4}, %1 proc lilrxxxsil example lil adi sil with regorconst kills all_mems gen axx* {indir_r, regvar($1)}, %1 proc xxxrstl example adi stl with rmorconst regorconst-RREG kills regvar($2) gen move %1, {LOCAL, $2, 4} axx* {LOCAL, $2, 4}, %2 pat lol adi stl $1==$3 && $2==4 && inreg($1)==reg_any call lolrxxxstl("add") pat lol adu stl $1==$3 && $2==4 && inreg($1)==reg_any call lolrxxxstl("add") pat lol ads stl $1==$3 && $2==4 && inreg($1)==reg_any call lolrxxxstl("add") pat lol and stl $1==$3 && $2==4 && inreg($1)==reg_any call lolrxxxstl("and") pat lol ior stl $1==$3 && $2==4 && inreg($1)==reg_any call lolrxxxstl("or") pat lol xor stl $1==$3 && $2==4 && inreg($1)==reg_any call lolrxxxstl("xor") pat lil adi sil $1==$3 && $2==4 && inreg($1)==reg_any call lilrxxxsil("add") pat lil adu sil $1==$3 && $2==4 && inreg($1)==reg_any call lilrxxxsil("add") pat lil ads sil $1==$3 && $2==4 && inreg($1)==reg_any call lilrxxxsil("add") pat lil and sil $1==$3 && $2==4 && inreg($1)==reg_any call lilrxxxsil("and") pat lil ior sil $1==$3 && $2==4 && inreg($1)==reg_any call lilrxxxsil("or") pat lil xor sil $1==$3 && $2==4 && inreg($1)==reg_any call lilrxxxsil("xor") pat adi stl $1==4 && inreg($2)==reg_any call xxxrstl("add") pat adu stl $1==4 && inreg($2)==reg_any call xxxrstl("add") pat ads stl $1==4 && inreg($2)==reg_any call xxxrstl("add") pat and stl $1==4 && inreg($2)==reg_any call xxxrstl("and") pat ior stl $1==4 && inreg($2)==reg_any call xxxrstl("or") pat xor stl $1==4 && inreg($2)==reg_any call xxxrstl("xor") #endif proc lolxxxstl example lol adi stl with regorconst kills indir, locals %ind+%size>$1 && %ind<$1+4 gen axx* {LOCAL, $1, 4}, %1 pat lol adi stl $1==$3 && $2==4 call lolxxxstl("add") pat lol adu stl $1==$3 && $2==4 call lolxxxstl("add") pat lol ads stl $1==$3 && $2==4 call lolxxxstl("add") pat lol and stl $1==$3 && $2==4 call lolxxxstl("and") pat lol ior stl $1==$3 && $2==4 call lolxxxstl("or") pat lol xor stl $1==$3 && $2==4 call lolxxxstl("xor") proc lilxxxsil example lil adi sil with regorconst kills all_mems uses ADDREG={LOCAL, $1, 4} gen axx* {indir_r, %a}, %1 killreg %a pat lil adi sil $1==$3 && $2==4 call lilxxxsil("add") pat lil adu sil $1==$3 && $2==4 call lilxxxsil("add") pat lil ads sil $1==$3 && $2==4 call lilxxxsil("add") pat lil and sil $1==$3 && $2==4 call lilxxxsil("and") pat lil ior sil $1==$3 && $2==4 call lilxxxsil("or") pat lil xor sil $1==$3 && $2==4 call lilxxxsil("xor") #ifdef REGVARS proc lilruxxsil example lil ngi sil kills all_mems gen uxx* {indir_r, regvar($1)} pat lil ngi sil $1==$3 && $2==4 && inreg($1)==reg_any call lilruxxsil("neg") pat lil com sil $1==$3 && $2==4 && inreg($1)==reg_any call lilruxxsil("not") pat lil dec sil $1==$3 && inreg($1)==reg_any call lilruxxsil("dec") pat lil inc sil $1==$3 && inreg($1)==reg_any call lilruxxsil("inc") pat lil adp sil $1==$3 && inreg($1)==reg_any && $2==1 call lilruxxsil("inc") pat lil adp sil $1==$3 && inreg($1)==reg_any && $2==(0-1) call lilruxxsil("dec") #endif proc liluxxsil example lil ngi sil kills all_mems uses ADDREG={LOCAL, $1, 4} gen uxx* {indir_r, %a} killreg %a pat lil ngi sil $1==$3 && $2==4 call liluxxsil("neg") pat lil com sil $1==$3 && $2==4 call liluxxsil("not") pat lil dec sil $1==$3 call liluxxsil("dec") pat lil inc sil $1==$3 call liluxxsil("inc") pat lil adp sil $1==$3 && $2==1 call liluxxsil("inc") pat lil adp sil $1==$3 && $2==(0-1) call liluxxsil("dec") proc loexxxste example loe adi ste with regorconst kills mem_nonlocals gen axx* {EXTERN, $1}, %1 pat loe adi ste $1==$3 && $2==4 call loexxxste("add") pat loe adu ste $1==$3 && $2==4 call loexxxste("add") pat loe ads ste $1==$3 && $2==4 call loexxxste("add") pat loe and ste $1==$3 && $2==4 call loexxxste("and") pat loe ior ste $1==$3 && $2==4 call loexxxste("or") pat loe xor ste $1==$3 && $2==4 call loexxxste("xor") #ifdef REGVARS proc lofrxxxsof example lol lof adi lol stf with regorconst kills all_mems gen axx* {indir_r_off, regvar($1), $2}, %1 pat lol lof adi lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofrxxxsof("add") pat lol lof adu lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofrxxxsof("add") pat lol lof ads lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofrxxxsof("add") pat lol lof and lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofrxxxsof("and") pat lol lof ior lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofrxxxsof("or") pat lol lof xor lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofrxxxsof("xor") proc lofruxxsof example lol lof inc lol stf kills all_mems gen uxx* {indir_r_off, regvar($1), $2} pat lol lof inc lol stf $1==$4 && $2==$5 && inreg($1)==reg_any call lofruxxsof("inc") pat lol lof adp lol stf $1==$4 && $2==$5 && inreg($1)==reg_any && $3==1 call lofruxxsof("inc") pat lol lof dec lol stf $1==$4 && $2==$5 && inreg($1)==reg_any call lofruxxsof("dec") pat lol lof adp lol stf $1==$4 && $2==$5 && inreg($1)==reg_any && $3==(0-1) call lofruxxsof("dec") pat lol lof ngi lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofruxxsof("neg") pat lol lof com lol stf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any call lofruxxsof("not") pat lol lof dup adp lol stf $1==$5 && $2==$6 && $3==4 && inreg($1)==reg_any kills all_mems uses ADDREG={indir_r_off, regvar($1), $2} gen add {indir_r_off, regvar($1), $2}, {ANYCON, $4} yields %a #endif proc lofuxxsof example lol lof inc lol stf kills all_mems uses ADDREG={LOCAL,$1,4} gen uxx* {indir_r_off, %a, $2} killreg %a pat lol lof ngi lol stf $1==$4 && $2==$5 && $3==4 call lofuxxsof("neg") pat lol lof com lol stf $1==$4 && $2==$5 && $3==4 call lofuxxsof("not") pat lol lof dec lol stf $1==$4 && $2==$5 call lofuxxsof("dec") pat lol lof inc lol stf $1==$4 && $2==$5 call lofuxxsof("inc") pat lol lof adp lol stf $1==$4 && $2==$5 && $3==1 call lofuxxsof("inc") pat lol lof adp lol stf $1==$4 && $2==$5 && $3==(0-1) call lofuxxsof("dec") proc lofxxxsof example lol lof adi lol stf with regorconst kills all_mems uses ADDREG={LOCAL,$1,4} gen axx* {indir_r_off, %a, $2}, %1 killreg %a pat lol lof adi lol stf $1==$4 && $2==$5 && $3==4 call lofxxxsof("add") pat lol lof adu lol stf $1==$4 && $2==$5 && $3==4 call lofxxxsof("add") pat lol lof ads lol stf $1==$4 && $2==$5 && $3==4 call lofxxxsof("add") pat lol lof and lol stf $1==$4 && $2==$5 && $3==4 call lofxxxsof("and") pat lol lof ior lol stf $1==$4 && $2==$5 && $3==4 call lofxxxsof("or") pat lol lof xor lol stf $1==$4 && $2==$5 && $3==4 call lofxxxsof("xor") pat lol lof dup adp lol stf $1==$5 && $2==$6 && $3==4 kills all_mems uses ADDREG={LOCAL,$1,4},ADDREG gen mov %b, {indir_r_off, %a, $2} add {indir_r_off, %a, $2}, {ANYCON, $4} killreg %a yields %b proc lefuxxsef example loe lof inc loe stf kills all_mems uses ADDREG={EXTERN,$1} gen uxx* {indir_r_off, %a, $2} killreg %a pat loe lof ngi loe stf $1==$4 && $2==$5 && $3==4 call lefuxxsef("neg") pat loe lof com loe stf $1==$4 && $2==$5 && $3==4 call lefuxxsef("not") pat loe lof dec loe stf $1==$4 && $2==$5 call lefuxxsef("dec") pat loe lof inc loe stf $1==$4 && $2==$5 call lefuxxsef("inc") pat loe lof adp loe stf $1==$4 && $2==$5 && $3==1 call lefuxxsef("inc") pat loe lof adp loe stf $1==$4 && $2==$5 && $3==(0-1) call lefuxxsef("dec") proc lefxxxsef example loe lof adi loe stf with regorconst kills all_mems uses ADDREG={EXTERN,$1} gen axx* {indir_r_off, %a, $2}, %1 killreg %a pat loe lof adi loe stf $1==$4 && $2==$5 && $3==4 call lefxxxsef("add") pat loe lof adu loe stf $1==$4 && $2==$5 && $3==4 call lefxxxsef("add") pat loe lof ads loe stf $1==$4 && $2==$5 && $3==4 call lefxxxsef("add") pat loe lof and loe stf $1==$4 && $2==$5 && $3==4 call lefxxxsef("and") pat loe lof ior loe stf $1==$4 && $2==$5 && $3==4 call lefxxxsef("or") pat loe lof xor loe stf $1==$4 && $2==$5 && $3==4 call lefxxxsef("xor") pat loe lof dup adp loe stf $1==$5 && $2==$6 && $3==4 kills all_mems uses ADDREG={EXTERN,$1},ADDREG gen mov %b, {indir_r_off, %a, $2} add {indir_r_off, %a, $2}, {ANYCON, $4} killreg %a yields %b proc leiuxxsei example loe loi inc loe sti kills all_mems uses ADDREG={EXTERN,$1} gen uxx* {indir_r, %a} killreg %a pat loe loi ngi loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leiuxxsei("neg") pat loe loi com loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leiuxxsei("not") pat loe loi dec loe sti $1==$4 && $2==4 && $5==4 call leiuxxsei("dec") pat loe loi inc loe sti $1==$4 && $2==4 && $5==4 call leiuxxsei("inc") pat loe loi adp loe sti $1==$4 && $2==4 && $5==4 && $3==1 call leiuxxsei("inc") pat loe loi adp loe sti $1==$4 && $2==4 && $5==4 && $3==(0-1) call leiuxxsei("dec") proc leixxxsei example loe loi adi loe sti with regorconst kills all_mems uses ADDREG={EXTERN,$1} gen axx* {indir_r, %a}, %1 killreg %a pat loe loi adi loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leixxxsei("add") pat loe loi adu loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leixxxsei("add") pat loe loi ads loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leixxxsei("add") pat loe loi and loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leixxxsei("and") pat loe loi ior loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leixxxsei("or") pat loe loi xor loe sti $1==$4 && $2==4 && $5==4 && $3==4 call leixxxsei("xor") #ifdef REGVARS proc lifuxxsif example lil lof inc lil stf kills all_mems uses ADDREG={indir_r,regvar($1)} gen uxx* {indir_r_off, %a, $2} killreg %a pat lil lof ngi lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifuxxsif("neg") pat lil lof com lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifuxxsif("not") pat lil lof dec lil stf $1==$4 && $2==$5 && inreg($1)>0 call lifuxxsif("dec") pat lil lof inc lil stf $1==$4 && $2==$5 && inreg($1)>0 call lifuxxsif("inc") pat lil lof adp lil stf $1==$4 && $2==$5 && inreg($1)>0 && $3==1 call lifuxxsif("inc") pat lil lof adp lil stf $1==$4 && $2==$5 && inreg($1)>0 && $3==(0-1) call lifuxxsif("dec") proc lifxxxsif example lil lof adi lil stf with regorconst kills all_mems uses ADDREG={indir_r,regvar($1)} gen axx* {indir_r_off, %a, $2}, %1 killreg %a pat lil lof adi lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifxxxsif("add") pat lil lof adu lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifxxxsif("add") pat lil lof ads lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifxxxsif("add") pat lil lof and lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifxxxsif("and") pat lil lof ior lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifxxxsif("or") pat lil lof xor lil stf $1==$4 && $2==$5 && $3==4 && inreg($1)>0 call lifxxxsif("xor") proc liiuxxsii example lil loi inc lil sti kills all_mems uses ADDREG={indir_r,regvar($1)} gen uxx* {indir_r, %a} killreg %a pat lil loi ngi lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liiuxxsii("neg") pat lil loi com lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liiuxxsii("not") pat lil loi dec lil sti $1==$4 && $2==4 && $5==4 && inreg($1)>0 call liiuxxsii("dec") pat lil loi inc lil sti $1==$4 && $2==4 && $5==4 && inreg($1)>0 call liiuxxsii("inc") pat lil loi adp lil sti $1==$4 && $2==4 && $5==4 && inreg($1)>0 && $3==1 call liiuxxsii("inc") pat lil loi adp lil sti $1==$4 && $2==4 && $5==4 && inreg($1)>0 && $3==(0-1) call liiuxxsii("dec") proc liixxxsii example lil loi adi lil sti with regorconst kills all_mems uses ADDREG={indir_r,regvar($1)} gen axx* {indir_r, %a}, %1 killreg %a pat lil loi adi lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liixxxsii("add") pat lil loi adu lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liixxxsii("add") pat lil loi ads lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liixxxsii("add") pat lil loi and lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liixxxsii("and") pat lil loi ior lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liixxxsii("or") pat lil loi xor lil sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)>0 call liixxxsii("xor") proc lolcrxxstl example lol loc sbi stl kills regvar($1) gen axx* {LOCAL,$1,4},{ANYCON,$2} pat lol loc sbi stl $1==$4 && $3==4 && inreg($1)==reg_any call lolcrxxstl("sub") pat lol loc sbu stl $1==$4 && $3==4 && inreg($1)==reg_any call lolcrxxstl("sub") pat lol loc sli stl $1==$4 && $3==4 && inreg($1)==reg_any call lolcrxxstl("sal") pat lol loc slu stl $1==$4 && $3==4 && inreg($1)==reg_any call lolcrxxstl("sal") pat lol loc sri stl $1==$4 && $3==4 && inreg($1)==reg_any call lolcrxxstl("sar") pat lol loc sru stl $1==$4 && $3==4 && inreg($1)==reg_any call lolcrxxstl("shr") #endif proc lolcxxstl example lol loc sbi stl kills indir, locals %ind+%size>$1 && %ind<$1+4 gen axx* {LOCAL,$1,4},{ANYCON,$2} pat lol loc sbi stl $1==$4 && $3==4 call lolcxxstl("sub") pat lol loc sbu stl $1==$4 && $3==4 call lolcxxstl("sub") pat lol loc adi stl $1==$4 && $3==4 call lolcxxstl("add") pat lol loc adi stl $1==$4 && $3==4 call lolcxxstl("add") pat lol loc sli stl $1==$4 && $3==4 call lolcxxstl("sal") pat lol loc slu stl $1==$4 && $3==4 call lolcxxstl("sal") pat lol loc sri stl $1==$4 && $3==4 call lolcxxstl("sar") pat lol loc sru stl $1==$4 && $3==4 call lolcxxstl("shr") proc loecxxste example loe loc sbi ste kills mem_nonlocals gen axx* {EXTERN,$1},{ANYCON,$2} pat loe loc sbi ste $1==$4 && $3==4 call loecxxste("sub") pat loe loc sbu ste $1==$4 && $3==4 call loecxxste("sub") pat loe loc adu ste $1==$4 && $3==4 call loecxxste("add") pat loe loc adi ste $1==$4 && $3==4 call loecxxste("add") pat loe loc sli ste $1==$4 && $3==4 call loecxxste("sal") pat loe loc slu ste $1==$4 && $3==4 call loecxxste("sal") pat loe loc sri ste $1==$4 && $3==4 call loecxxste("sar") pat loe loc sru ste $1==$4 && $3==4 call loecxxste("shr") #ifdef REGVARS proc lilcxxsil example lil loc sbi sil kills mem_nonlocals gen axx* {indir_r,regvar($1)},{ANYCON,$2} pat lil loc sbi sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("sub") pat lil loc sbu sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("sub") pat lil loc adu sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("add") pat lil loc adi sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("add") pat lil loc sli sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("sal") pat lil loc slu sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("sal") pat lil loc sri sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("sar") pat lil loc sru sil $1==$4 && $3==4 && inreg($1)>0 call lilcxxsil("shr") pat lol ngi stl $1==$3 && $2==4 && inreg($1)==reg_any kills regvar($1) gen neg {LOCAL, $1, 4} #endif pat lol ngi stl $1==$3 && $2==4 kills indir, locals %ind+%size>$1 && %ind<$1+4 gen neg {LOCAL, $1, 4} pat lol lol adp stl loi stl $1==$2 && $2==$4 && $5<=4 leaving lol $1 loi $5 stl $6 lol $2 adp $3 stl $4 #ifdef REGVARS pat lol lol adp stl loi loc loc cii $1==$2 && $2==$4 && $5==1 && inreg($1) > 0 && $6==1 && $7==4 uses REG gen movsxb %a,{indir_r1, regvar($1)} yields %a leaving lol $2 adp $3 stl $4 pat lol lol adp stl loi $1==$2 && $2==$4 && $5==1 && inreg($1) > 0 uses REG1 = {indir_r1, regvar($1)} yields %a leaving lol $2 adp $3 stl $4 pat lol lol adp stl loi loc loc cii $1==$2 && $2==$4 && $5==2 && inreg($1) > 0 && $6==2 && $7==4 uses REG gen movsx %a,{indir_r2, regvar($1)} yields %a leaving lol $2 adp $3 stl $4 pat lol lol adp stl loi $1==$2 && $2==$4 && $5==2 && inreg($1) > 0 uses REG2 = {indir_r2, regvar($1)} yields %a leaving lol $2 adp $3 stl $4 pat lol lol adp stl loi $1==$2 && $2==$4 && $5==4 && inreg($1) > 0 uses REG = {indir_r, regvar($1)} yields %a leaving lol $2 adp $3 stl $4 pat adp stl inreg($2) > 0 leaving stl $2 lol $2 adp $1 stl $2 #endif pat lol lol adp stl $1==$2 && $2==$4 uses ADDREG={LOCAL,$1,4} yields %a leaving lol $2 adp $3 stl $2 pat lol inl $1==$2 uses REG={LOCAL,$1,4} yields %a leaving inl $1 pat lol del $1==$2 uses REG={LOCAL,$1,4} yields %a leaving del $1 pat lol adp stl $1==$3 && $2==1 leaving inl $1 pat lol adp stl $1==$3 && $2==0-1 leaving del $1 pat lol adp stl $1==$3 leaving loc $2 lol $1 adi 4 stl $3 #ifdef REGVARS pat lol com stl $1==$3 && $2==4 && inreg($1)==reg_any kills regvar($1) gen not {LOCAL,$1,4} #endif pat lol com stl $1==$3 && $2==4 kills indir, locals %ind+%size>$1 && %ind<$1+4 gen not {LOCAL, $1, 4} #ifdef REGVARS pat lil lil adp sil $1==$2 && $1==$4 && inreg($1)==reg_any uses ADDREG={indir_r, regvar($1)} yields %a leaving lil $1 adp $3 sil $4 pat lil lil inc sil $1==$2 && $1==$4 && inreg($1)==reg_any uses REG={indir_r, regvar($1)} yields %a leaving lil $1 inc sil $4 pat lil lil dec sil $1==$2 && $1==$4 && inreg($1)==reg_any uses REG={indir_r, regvar($1)} yields %a leaving lil $1 dec sil $4 #endif pat lil adp sil $1==$3 leaving loc $2 lil $1 adi 4 sil $3 #ifdef REGVARS pat lol lof lol lof adp lol stf $1==$3 && $1==$6 && $2==$4 && $2==$7 && inreg($1)==reg_any uses ADDREG={indir_r_off, regvar($1), $2} yields %a leaving lol $1 lof $2 adp $5 lol $6 stf $7 pat lol lof lol lof inc lol stf $1==$3 && $1==$6 && $2==$4 && $2==$7 && inreg($1)==reg_any uses REG={indir_r_off, regvar($1), $2} yields %a leaving lol $1 lof $2 inc lol $6 stf $7 pat lol lof lol lof dec lol stf $1==$3 && $1==$6 && $2==$4 && $2==$7 && inreg($1)==reg_any uses REG={indir_r_off, regvar($1), $2} yields %a leaving lol $1 lof $2 dec lol $6 stf $7 #endif pat lol lof adp lol stf $1==$4 && $2==$5 leaving loc $3 lol $1 lof $2 adi 4 lol $4 stf $5 pat loe ngi ste $1==$3 && $2==4 kills mem_nonlocals gen neg {EXTERN, $1} pat loe loe adp ste $1==$2 && $1==$4 uses REG={EXTERN,$1} yields %a leaving loe $1 adp $3 ste $1 pat loe ine $1==$2 uses REG={EXTERN,$1} yields %a leaving ine $1 pat loe dee $1==$2 uses REG={EXTERN,$1} yields %a leaving dee $1 pat loe adp ste $1==$3 && $2==1 leaving ine $1 pat loe adp ste $1==$3 && $2==0-1 leaving dee $1 pat loe adp ste $1==$3 leaving loc $2 loe $1 adi 4 ste $3 pat loe com ste $1==$3 && $2==4 kills mem_nonlocals gen not {EXTERN, $1} pat loe lof adp loe stf $1==$4 && $2==$5 leaving loc $3 loe $1 lof $2 adi 4 loe $1 stf $2 pat lil lof adp lil stf $1==$4 && $2==$5 leaving loc $3 lil $1 lof $2 adi 4 lil $1 stf $2 /******************************************************************* * Group 8: Convert Instructions * *******************************************************************/ pat cii with CXREG DXREG ACC kills ALL gen proccall {label,".cii"} yields %3 pat ciu leaving cuu pat cui leaving cuu pat cuu pat loc loc cii loc and zeq $4<256 && $4>=0 && $5==4 && $1==1 && $2==4 leaving loc $4 and $5 zeq $6 pat loc loc cii loc and zne $4<256 && $4>=0 && $5==4 && $1==1 && $2==4 leaving loc $4 and $5 zne $6 pat loc loc cii loc and zeq $4<65536 && $4>=0 && $5==4 && $1==2 && $2==4 leaving loc $4 and $5 zeq $6 pat loc loc cii loc and zne $4<65536 && $4>=0 && $5==4 && $1==2 && $2==4 leaving loc $4 and $5 zne $6 pat loc loc cii $1==1 && $2==4 with ACC gen movsxb %1,%1 yields eax with exact rm1 uses reusing %1, GENREG gen movsxb %a,%1 yields %a pat loc loc cii $1==2 && $2==4 with ACC gen movsx %1,%1 yields eax with exact rm2 uses reusing %1,GENREG gen movsx %a,%1 yields %a pat loc loc ciu leaving loc $1 loc $2 cuu pat loc loc cui leaving loc $1 loc $2 cuu pat loc loc cuu $1==$2 pat loc loc cif $1==4 && $2==4 leaving loc 4 cal ".cif4" asp 4 pat loc loc cif $1==4 && $2==8 leaving loc 4 cal ".cif8" pat loc loc cuf $1==4 && $2==4 leaving loc 4 cal ".cuf4" asp 4 pat loc loc cuf $1==4 && $2==8 leaving loc 4 cal ".cuf8" pat loc loc cfi leaving loc $1 loc $2 cal ".cfi" asp 8+($1-4) pat loc loc cfu leaving loc $1 loc $2 cal ".cfu" asp 8+($1-4) pat loc loc cff $1==8 && $2==4 leaving cal ".cff4" asp 4 pat loc loc cff $1==4 && $2==8 with REG kills ALL gen push {ANYCON,0} push %1 leaving cal ".cff8" /******************************************************************** * Group 9 : Logical Instructions * ********************************************************************/ pat and $1==4 with REG rmorconst gen and %1,%2 yields %1 with rmorconst REG gen and %2,%1 yields %2 pat loc and $1==255 && $2==4 with GENREG yields %1.1 pat and $1==8 with EXACT REG REG rmorconst rmorconst gen and %1,%3 and %2,%4 yields %2 %1 with rmorconst rmorconst REG REG gen and %3,%1 and %4,%2 yields %4 %3 pat and defined($1) kills ALL gen mov ecx,{ANYCON,$1} proccall {label, ".and"} pat and !defined($1) with CXREG kills ALL gen proccall {label, ".and"} pat ior $1==4 with REG rmorconst gen or %1,%2 yields %1 with rmorconst REG gen or %2,%1 yields %2 pat ior $1==8 with EXACT REG REG rmorconst rmorconst gen or %1,%3 or %2,%4 yields %2 %1 with rmorconst rmorconst REG REG gen or %3,%1 or %4,%2 yields %4 %3 pat ior defined($1) kills ALL gen mov ecx,{ANYCON,$1} proccall {label, ".ior"} pat ior !defined($1) with CXREG kills ALL gen proccall {label, ".ior"} pat xor $1==4 with REG rmorconst gen xor %1,%2 yields %1 with rmorconst REG gen xor %2,%1 yields %2 pat xor $1==8 with EXACT REG REG rmorconst rmorconst gen xor %1,%3 xor %2,%4 yields %2 %1 with rmorconst rmorconst REG REG gen xor %3,%1 xor %4,%2 yields %4 %3 pat xor defined($1) kills ALL gen mov ecx,{ANYCON,$1} proccall {label, ".xor"} pat xor !defined($1) with CXREG kills ALL gen proccall {label, ".xor"} pat com $1==4 with REG gen not %1 yields %1 pat com $1==8 with REG REG gen not %2 not %1 yields %2 %1 pat com defined($1) kills ALL gen mov ecx,{ANYCON,$1} proccall {label, ".com"} pat com !defined($1) with CXREG kills ALL gen proccall {label, ".com"} pat rol $1==4 with SHIFT_CREG REG gen rol %2,cl yields %2 with ANYCON REG gen rol %2,%1 yields %2 pat ror $1==4 with SHIFT_CREG REG gen ror %2,cl yields %2 with ANYCON REG gen ror %2,%1 yields %2 /******************************************************************* * Group 10 : Set Instructions * *******************************************************************/ pat inn $1==4 with SHIFT_CREG REG gen shr %2,cl and %2,{ANYCON, 1} yields %2 with ANYCON REG gen shr %2,%1 and %2,{ANYCON, 1} yields %2 pat loc inn $1==0 && $2==4 with REG gen and %1,{ANYCON, 1} yields %1 pat inn defined($1) with ACC kills ALL gen mov ecx,{ANYCON, $1} proccall {label,".inn"} yields eax pat inn !defined($1) with CXREG ACC kills ALL gen proccall {label,".inn"} yields eax pat loc inn zeq $2==4 with rm STACK gen check %1,{ANYCON,1<<$1} je {label,$3} pat loc inn zne $2==4 with rm STACK gen check %1,{ANYCON,1<<$1} jne {label,$3} pat set $1==4 with SHIFT_CREG uses REG={ANYCON, 1} gen shl %a,cl yields %a pat set defined($1) with ACC kills ALL gen mov ecx,{ANYCON, $1} proccall {label,".set"} pat set !defined($1) with CXREG ACC kills ALL gen proccall {label,".set"} /******************************************************************** * Group 11 : Array Instructions * ********************************************************************/ pat lae aar $2==4 && rom($1,3)==1 && rom($1,1)==0 leaving ads 4 pat lae aar $2==4 && rom($1,3)==1 && rom($1,1)!=0 leaving adp 0-rom($1,1) ads 4 pat lae aar $2==4 && rom($1,3)==2 && rom($1,1)==0 leaving loc 1 sli 4 ads 4 pat lae aar $2==4 && rom($1,3)==2 && rom($1,1)!=0 leaving adp 0-rom($1,1) loc 1 sli 4 ads 4 pat lae aar $2==4 && rom($1,3)==4 && rom($1,1)==0 leaving loc 2 sli 4 ads 4 pat lae aar $2==4 && rom($1,3)==4 && rom($1,1)!=0 leaving adp 0-rom($1,1) loc 2 sli 4 ads 4 pat lae aar $2==4 && rom($1,3)==8 && rom($1,1)==0 leaving loc 3 sli 4 ads 4 pat lae aar $2==4 && rom($1,3)==8 && rom($1,1)!=0 leaving adp 0-rom($1,1) loc 3 sli 4 ads 4 pat lae aar $2==4 && rom($1,1)==0 with ADDREG gen imul %1,%1,{ANYCON,rom($1,3)} yields %1 leaving ads 4 pat lae aar $2==4 && defined(rom($1,1)) with ADDREG gen imul %1,%1,{ANYCON,rom($1,3)} yields %1 leaving adp 0-rom($1,1)*rom($1,3) ads 4 /* when followed by an LOI or STI instruction, use indexed mode */ pat loc sli ads loi ($1==1 || $1==2 || $1==3) && $2==4 && $3==4 with IREG ADDR_LOCAL yields {indexed_r_off,ebp,%1,1<<$1,%2.ind} leaving loi $4 with IREG ADDR_EXTERN yields {indexed_off,%1,1<<$1,%2.off} leaving loi $4 with IREG ADDREG yields {indexed_r_off,%2,%1,1<<$1,0} leaving loi $4 pat loc sli ads sti ($1==1 || $1==2 || $1==3) && $2==4 && $3==4 with IREG ADDR_LOCAL yields {indexed_r_off,ebp,%1,1<<$1,%2.ind} leaving sti $4 with IREG ADDR_EXTERN yields {indexed_off,%1,1<<$1,%2.off} leaving sti $4 with IREG ADDREG yields {indexed_r_off,%2,%1,1<<$1,0} leaving sti $4 pat loc sli ads ($1==1 || $1==2 || $1==3) && $2==4 && $3==4 with IREG ADDR_LOCAL yields {indexed_r_off,ebp,%1,1<<$1,%2.ind} with IREG ADDR_EXTERN yields {indexed_off,%1,1<<$1,%2.off} with IREG ADDREG yields {indexed_r_off,%2,%1,1<<$1,0} with REG rmorconst gen sal %1,{ANYCON,$1} yields %2 %1 leaving ads 4 pat aar $1==4 with AREG REG gen sub %2,{indir_r,%1} imul %2,{indir_r_off,%1,8} yields %2 leaving ads 4 with reg_off REG gen sub %2,{indir_r_off, %1.reg, %1.off} imul %2,{indir_r_off, %1.reg, 8+%1.off} yields %2 leaving ads 4 with ADDR_LOCAL REG gen sub %2,{LOCAL,%1.ind,4} imul %2,{LOCAL,8+%1.ind,4} yields %2 leaving ads 4 with ADDR_EXTERN REG gen sub %2,{EXTERN,%1.off} imul %2,{EXTERN,8+%1.off} yields %2 leaving ads 4 pat lae lar defined(rom($1,3)) leaving lae $1 aar $2 loi rom($1,3) pat lae sar defined(rom($1,3)) leaving lae $1 aar $2 sti rom($1,3) pat aar !defined($1) kills ALL gen proccall {label,".iaar"} yields ebx pat sar $1==4 with BXREG ACC kills ALL gen proccall {label,".sar4"} pat sar !defined($1) kills ALL gen proccall {label,".isar"} pat lar $1==4 with BXREG ACC kills ALL gen proccall {label,".lar4"} pat lar !defined($1) kills ALL gen proccall {label,".ilar"} /******************************************************************* * Group 12 : Compare Instructions * *******************************************************************/ pat cmi $1==4 with register rmorconst uses REG={ANYCON,0} gen cmp %1,%2 je {label,2f} jl {label,1f} inc %a jmp {label,2f} 1: dec %a 2: yields %a with rmorconst register uses REG={ANYCON,0} gen cmp %2,%1 je {label,2f} jg {label,1f} inc %a jmp {label,2f} 1: dec %a 2: yields %a pat cmu $1==4 leaving cmp pat cms $1==4 with REG rmorconst gen sub %1,%2 yields %1 with rmorconst REG gen sub %2,%1 yields %2 pat cms $1==8 with rmorconst rmorconst REG REG gen sub %3,%1 sbb %4,%2 or %4,%3 yields %4 with REG REG rmorconst rmorconst gen sub %1,%3 sbb %2,%4 or %2,%1 yields %2 pat cms defined($1) kills ALL gen mov ecx,{ANYCON,$1} proccall {label,".cms"} yields ecx pat cms !defined($1) with CXREG kills ALL gen proccall {label,".cms"} yields ecx pat cmf $1==4 kills ALL gen proccall {label,".cmf4"} leaving asp 8 lfr 4 pat cmf $1==8 kills ALL gen proccall {label,".cmf8"} leaving asp 16 lfr 4 pat cmp with register rmorconst uses REG = {ANYCON,0} gen cmp %1,%2 je {label,2f} jb {label,1f} inc %a jmp {label,2f} 1: dec %a 2: yields %a with rmorconst register uses REG = {ANYCON,0} gen cmp %2,%1 je {label,2f} ja {label,1f} inc %a jmp {label,2f} 1: dec %a 2: yields %a proc txx with rm uses REG = {ANYCON,0} gen test %1 jxx* {label,1f} inc %a 1: yields %a pat tlt call txx("jge") pat tle call txx("jg") pat teq call txx("jne") pat tne call txx("je") pat tge call txx("jl") pat tgt call txx("jle") proc txxior with rm REG gen test %1 jxx* {label,1f} or %2,{ANYCON,1} 1: yields %2 pat tlt ior $2==4 call txxior("jge") pat tle ior $2==4 call txxior("jg") pat teq ior $2==4 call txxior("jne") pat tne ior $2==4 call txxior("je") pat tge ior $2==4 call txxior("jl") pat tgt ior $2==4 call txxior("jle") proc cmixxior with regorconst rm REG gen cmp %2,%1 jxx* {label,1f} or %3,{ANYCON,1} 1: yields %3 pat cmi tlt ior $1==4 && $3==4 call cmixxior("jge") pat cmi tle ior $1==4 && $3==4 call cmixxior("jg") pat cmi teq ior $1==4 && $3==4 call cmixxior("jne") pat cmi tne ior $1==4 && $3==4 call cmixxior("je") pat cmi tge ior $1==4 && $3==4 call cmixxior("jl") pat cmi tgt ior $1==4 && $3==4 call cmixxior("jle") proc cmxtxx with regorconst rm uses REG = {ANYCON,0} gen cmp %2,%1 jxx[1] {label,1f} inc %a 1: yields %a with rm regorconst uses REG = {ANYCON,0} gen cmp %1,%2 jxx[2] {label,1f} inc %a 1: yields %a pat cmi tlt $1==4 call cmxtxx("jge","jle") pat cmi tle $1==4 call cmxtxx("jg","jl") pat cmi teq $1==4 call cmxtxx("jne","jne") pat cmi tne $1==4 call cmxtxx("je","je") pat cmi tge $1==4 call cmxtxx("jl","jg") pat cmi tgt $1==4 call cmxtxx("jle","jge") pat cmp tlt call cmxtxx("jae","jbe") pat cmp tle call cmxtxx("ja","jb") pat cmp teq call cmxtxx("jne","jne") pat cmp tne call cmxtxx("je","je") pat cmp tge call cmxtxx("jb","ja") pat cmp tgt call cmxtxx("jbe","jae") pat cms teq $1==4 call cmxtxx("jne","jne") pat cms tne $1==4 call cmxtxx("je","je") proc cmxzxx example cmp zlt with regorconst rm STACK gen cmp %2,%1 jxx[1] {label,$2} with rm regorconst STACK gen cmp %1,%2 jxx[2] {label,$2} pat cmp zlt call cmxzxx("jb","ja") pat cmp zle call cmxzxx("jbe","jae") pat cmp zeq call cmxzxx("je","je") pat cmp zne call cmxzxx("jne","jne") pat cmp zge call cmxzxx("jae","jbe") pat cmp zgt call cmxzxx("ja","jb") pat cms zeq $1==4 call cmxzxx("je","je") pat cms zne $1==4 call cmxzxx("jne","jne") pat cms zne $1==8 with regorconst regorconst rm rm STACK gen cmp %3,%1 jne {label,$2} cmp %4,%2 jne {label,$2} with rm rm regorconst regorconst STACK kills ALL gen cmp %1,%3 jne {label,$2} cmp %2,%4 jne {label,$2} pat cms zeq $1==8 with regorconst regorconst rm rm STACK gen cmp %3,%1 jne {label, 1f} cmp %4,%2 je {label,$2} 1: with rm rm regorconst regorconst STACK kills ALL gen cmp %1,%3 jne {label,1f} cmp %2,%4 je {label,$2} 1: proc andzxx example and zeq with regorconst rm STACK gen check %2,%1 jxx* {label,$2} with exact rm regorconst kills ALL gen check %1,%2 jxx* {label,$2} pat and zeq $1==4 call andzxx("je") pat and zne $1==4 call andzxx("jne") proc locandzxx example loc and zeq with rm1 STACK gen testb %1,{ANYCON,$1} jxx* {label,$3} with GENREG STACK gen testb %1.1,{ANYCON,$1} jxx* {label,$3} with exact RREG kills ALL gen check %1,{ANYCON,$1} jxx* {label,$3} pat loc and zeq $1<256 && $1>=0 && $2==4 call locandzxx("je") pat loc and zne $1<256 && $1>=0 && $2==4 call locandzxx("jne") proc locbxx example loc beq with rm1 STACK gen cmpb %1,{ANYCON,$1} jxx* {label,$2} with rm STACK gen cmp %1,{ANYCON,$1} jxx* {label,$2} pat loc beq $1<256 && $1>=0 call locbxx("je") pat loc bne $1<256 && $1>=0 call locbxx("jne") proc loccmuzxx example loc cmu zeq with rm1 STACK gen cmpb %1,{ANYCON,$1} jxx* {label,$3} with rm STACK gen cmp %1,{ANYCON,$1} jxx* {label,$3} pat loc cmu zeq $1<256 && $1>=0 && $2==4 call loccmuzxx("je") pat loc cmu zne $1<256 && $1>=0 && $2==4 call loccmuzxx("jne") /******************************************************************* * Group 13 : Branch Instructions * *******************************************************************/ pat bra with STACK gen jmp {label,$1} proc bxx example blt with regorconst rm STACK gen cmp %2,%1 jxx[1] {label,$1} with rm regorconst STACK gen cmp %1,%2 jxx[2] {label,$1} pat blt call bxx("jl","jg") pat ble call bxx("jle","jge") pat beq call bxx("je","je") pat bne call bxx("jne","jne") pat bge call bxx("jge","jle") pat bgt call bxx("jg","jl") proc zxx example zlt with rm STACK gen test %1 jxx* {label,$1} pat zlt call zxx("jl") pat zle call zxx("jle") pat zge call zxx("jge") pat zgt call zxx("jg") pat zne with rm+rm1 STACK gen test %1 jne {label,$1} pat zeq with rm+rm1 STACK gen test %1 je {label,$1} /******************************************************************* * Group 14 : Procedure-call Instructions * *******************************************************************/ pat cal kills ALL gen proccall {label,$1} pat cai with rm kills ALL gen proccall %1 #ifdef REGVARS pat lfr adi stl $1==4 && $2==4 && inreg($3) > 0 kills ALL gen pop {LOCAL,$3,4} add {LOCAL,$3,4}, eax #endif pat lfr $1==4 yields eax pat lfr $1==8 yields edx eax pat ret $1==0 kills ALL gen #ifdef REGVARS return #else leave. ret. #endif pat ret $1==4 with ACC kills ALL gen #ifdef REGVARS return #else leave. ret. #endif pat ret $1==8 with ACC DXREG kills ALL gen #ifdef REGVARS return #else leave. ret. #endif /******************************************************************** * Group 15 : Miscellaneous Instructions * ********************************************************************/ pat asp $1==4 with exact a_word with STACK uses CXREG /* GENREG may contain lfr area */ gen pop %a pat asp $1==8 with exact a_word a_word with STACK uses CXREG /* GENREG may contain lfr area */ gen pop %a pop %a pat asp $1==0-4 with STACK yields ebp pat asp with STACK gen add esp,{ANYCON,$1} pat ass $1==4 with rmorconst STACK gen add esp,%1 pat ass !defined($1) with rm rmorconst STACK gen cmp %1,{ANYCON,4} jne {label, ".unknown"} add esp,%2 pat blm $1==0 leaving asp 4 pat blm $1>0 kills ALL gen mov ecx,{ANYCON,$1/4} proccall {label, ".blm"} pat bls $1==4 with CXREG kills ALL gen sar ecx,{ANYCON,2} proccall {label, ".blm"} pat bls !defined($1) with rm-CXREG CXREG kills ALL gen cmp %1,{ANYCON,4} jne {label, ".unknown"} sar ecx,{ANYCON,2} proccall {label, ".blm"} pat csa $1==4 with BXREG ACC kills ALL gen jmp {label, ".csa4"} pat csa !defined($1) with rm-BXREG-ACC BXREG ACC kills ALL gen cmp %1,{ANYCON,4} jne {label, ".unknown"} jmp {label, ".csa4"} pat csb $1==4 with BXREG ACC kills ALL gen jmp {label, ".csb4"} pat csb !defined($1) with rm-BXREG-ACC BXREG ACC gen cmp %1,{ANYCON,4} jne {label, ".unknown"} jmp {label, ".csb4"} pat dup $1==4 with anyreg yields %1 %1 with ACC1 yields %1 %1 pat dup $1==8 with regorconst regorconst yields %2 %1 %2 %1 pat dup kills ALL gen mov ecx,{ANYCON,$1} proccall {label, ".dup"} pat dus $1==4 with CXREG kills ALL gen proccall {label, ".dup"} pat dus !defined($1) with rm-CXREG CXREG kills ALL gen cmp %1,{ANYCON,4} jne {label, ".unknown"} proccall {label, ".dup"} pat exg $1==4 with a_word a_word yields %1 %2 pat exg $1==8 with a_word a_word a_word a_word yields %2 %1 %4 %3 pat exg defined($1) kills ALL gen mov ecx,{ANYCON,$1} proccall {label, ".exg"} pat exg with CXREG kills ALL gen proccall {label, ".exg"} pat gto kills ALL gen mov ebx,{ADDR_EXTERN,$1} jmp {label, ".gto"} pat fil gen mov {EXTERN,"hol0+4"},{ADDR_EXTERN,$1} pat lim uses REG gen mov %a,{EXTERN,".ignmask"} yields %a pat lin gen mov {EXTERN,"hol0"},{ANYCON,$1} pat lni gen inc {EXTERN,"hol0"} pat lor $1==0 yields ebp pat lor $1==1 with STACK uses REG gen mov %a,esp yields %a pat lor $1==2 uses REG gen mov %a,{EXTERN,".reghp"} yields %a pat mon with ACC kills ALL gen proccall {label, ".mon"} pat nop kills ALL /* gen proccall {label, ".nop"} */ pat rck $1==4 with BXREG ACC kills ALL gen proccall {label, ".rck"} yields eax pat rck !defined($1) with rm-BXREG-ACC BXREG ACC kills ALL gen cmp %1,{ANYCON,4} jne {label, ".unknown"} proccall {label, ".rck"} yields eax pat rtt leaving ret 0 pat sig with REG gen xchg {EXTERN,".trppc"},%1 yields %1 pat sim with regorconst gen mov {EXTERN,".ignmask"},%1 pat str $1==0 with rmorconst gen mov ebp,%1 pat str $1==1 with rmorconst STACK gen mov esp,%1 pat str $1==2 kills ALL gen proccall {label, ".strhp"} pat trp with ACC kills ALL gen proccall {label, ".Xtrp"}