3223 lines
83 KiB
Plaintext
3223 lines
83 KiB
Plaintext
/*
|
|
* (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
|
|
rscid = "$Id$"
|
|
|
|
/*
|
|
* 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).
|
|
setxx "syntax error" REG1:rw cost(2,4).
|
|
seta REG1:rw cost(2,4).
|
|
setb REG1:rw cost(2,4).
|
|
setl REG1:rw cost(2,4).
|
|
setle REG1:rw cost(2,4).
|
|
setg REG1:rw cost(2,4).
|
|
setne REG1:rw cost(2,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.
|
|
negb rm1:rw:cc.
|
|
not rmorconst:rw.
|
|
#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.
|
|
orb REG1:rw, REG1: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, ANYCON+SHIFT_CREG:ro kills :cc cost(2,10).
|
|
rcr rm:rw, ANYCON+SHIFT_CREG:ro kills :cc cost(2,10).
|
|
ret cost(1,10).
|
|
rol rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
|
|
ror rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
|
|
sal rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
|
|
sar rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
|
|
sbb rm:rw:cc, regorconst:ro.
|
|
sbb anyreg:rw:cc, rmorconst:ro.
|
|
shl rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
|
|
shld rm:rw, anyreg:ro, ANYCON+SHIFT_CREG:ro kills :cc cost(2,3).
|
|
shr rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
|
|
shrd rm:rw, anyreg:ro, ANYCON+SHIFT_CREG:ro kills :cc cost(2,3).
|
|
#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, regorconst124:ro kills :cc.
|
|
testb "testb" REG1:ro, rmorconst1:ro kills :cc.
|
|
testw "o16 test" rm2:ro, regorconst24:ro kills :cc.
|
|
testw "o16 test" REG2:ro, rmorconst2:ro kills :cc.
|
|
testl "test" rm:ro, regorconst:ro kills :cc.
|
|
testl "test" REG: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).
|
|
killcc "! kill cc" kills:cc 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 testl %1,%1
|
|
|
|
to test memory
|
|
gen cmp %1, {ANYCON,0}
|
|
|
|
to test REG1
|
|
gen testb %1,%1
|
|
|
|
to test memory1
|
|
gen cmpb %1, {ANYCON,0}
|
|
|
|
to test REG2
|
|
gen testw %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}
|
|
|
|
#if 0
|
|
/* wrong because .Xtrp assumes trap < 16 */
|
|
pat ldc leaving loc 18 trp
|
|
#endif
|
|
|
|
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
|
|
|
|
#ifdef REGVARS
|
|
pat lol dup stl $2==4 && 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
|
|
|
|
#ifdef REGVARS
|
|
pat loe dup stl $2==4 && 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 dup stl $2==4 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}
|
|
|
|
|
|
/****************************************************************
|
|
* 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 $1==8
|
|
with EXACT REG REG rmorconst rmorconst
|
|
gen add %1,%3
|
|
adc %2,%4 yields %2 %1
|
|
with rmorconst rmorconst REG REG
|
|
gen add %3,%1
|
|
adc %4,%2 yields %4 %3
|
|
|
|
/*
|
|
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 $1==8
|
|
with rmorconst rmorconst REG REG
|
|
gen sub %3,%1
|
|
sbb %4,%2 yields %4 %3
|
|
|
|
/*
|
|
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 $1==8
|
|
with ACC DXREG
|
|
kills ALL
|
|
gen proccall {label,".mli8"} yields edx eax
|
|
|
|
/*
|
|
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 $1==8
|
|
kills ALL
|
|
gen proccall {label,".dvi8"} yields ebx 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 $1==8
|
|
kills ALL
|
|
gen proccall {label,".rmi8"} yields ecx 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 $1==8
|
|
with REG REG
|
|
gen neg %2
|
|
neg %1
|
|
sbb %2,{ANYCON,0} yields %2 %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 $1==8
|
|
with SHIFT_CREG REG REG
|
|
gen testb cl,{ANYCON,32}
|
|
jne {label,1f}
|
|
shld %3,%2,cl
|
|
sal %2,cl
|
|
jmp {label,2f}
|
|
1:
|
|
mov %3,%2
|
|
sal %3,cl
|
|
xor %2,%2
|
|
2: yields %3 %2
|
|
|
|
pat loc sli ($1&32)==0 && $2==8
|
|
with REG REG
|
|
gen shld %2,%1,{ANYCON,$1&31}
|
|
sal %1,{ANYCON,$1&31} yields %2 %1
|
|
pat loc sli ($1&63)==32 && $2==8
|
|
with a_word a_word yields %1 {ANYCON,0}
|
|
pat loc sli ($1&32)!=0 && $2==8
|
|
with REG a_word
|
|
gen sal %1,{ANYCON,$1&31} yields %1 {ANYCON,0}
|
|
|
|
/*
|
|
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 $1==8
|
|
with SHIFT_CREG REG REG
|
|
gen testb cl,{ANYCON,32}
|
|
jne {label,1f}
|
|
shrd %2,%3,cl
|
|
sar %3,cl
|
|
jmp {label,2f}
|
|
1:
|
|
mov %2,%3
|
|
sar %2,cl
|
|
sar %3,{ANYCON,31}
|
|
2: yields %3 %2
|
|
|
|
pat loc sri ($1&32)==0 && $2==8
|
|
with REG REG
|
|
gen shrd %1,%2,{ANYCON,$1&31}
|
|
sar %2,{ANYCON,$1&31} yields %2 %1
|
|
pat loc sri ($1&63)==32
|
|
with a_word ACC
|
|
gen cdq. yields edx eax
|
|
pat loc sri ($1&32)!=0 && $2==8
|
|
with a_word ACC
|
|
gen sar eax,{ANYCON,$1&31}
|
|
cdq. yields edx eax
|
|
|
|
/*
|
|
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 loe loc loe adu ste $1==$3 && $1==$5 && $4==4
|
|
uses REG = {EXTERN, $1}
|
|
yields %a leaving loc $2 loe $3 adu 4 ste $3
|
|
|
|
pat lol loc lol adu stl $1==$3 && $1==$5 && $4==4
|
|
uses REG = {LOCAL, $1, 4}
|
|
yields %a leaving loc $2 lol $3 adu 4 stl $3
|
|
|
|
pat loe loc loe adi ste $1==$3 && $1==$5 && $4==4
|
|
uses REG = {EXTERN, $1}
|
|
yields %a leaving loc $2 loe $3 adi 4 ste $3
|
|
|
|
pat lol loc lol adi stl $1==$3 && $1==$5 && $4==4
|
|
uses REG = {LOCAL, $1, 4}
|
|
yields %a leaving loc $2 lol $3 adi 4 stl $3
|
|
|
|
pat dvu $1==4
|
|
with noacc ACC
|
|
uses DXREG={ANYCON,0}
|
|
gen div %1 yields eax
|
|
|
|
pat dvu $1==8
|
|
kills ALL
|
|
gen proccall {label,".dvu8"} yields ebx 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 $1==8
|
|
kills ALL
|
|
gen proccall {label,".rmu8"} yields ecx edx
|
|
|
|
/*
|
|
pat rmu !defined($1)
|
|
with ACC STACK
|
|
kills ALL
|
|
gen proccall {label,".rmu"}
|
|
*/
|
|
|
|
pat slu leaving sli $1
|
|
pat loc slu leaving loc $1 sli $2
|
|
|
|
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 $1==8
|
|
with SHIFT_CREG REG REG
|
|
gen testb cl,{ANYCON,32}
|
|
jne {label,1f}
|
|
shrd %2,%3,cl
|
|
shr %3,cl
|
|
jmp {label,2f}
|
|
1:
|
|
mov %2,%3
|
|
shr %2,cl
|
|
xor %3,%3
|
|
2: yields %3 %2
|
|
|
|
pat loc sru ($1&32)==0 && $2==8
|
|
with REG REG
|
|
gen shrd %2,%1,{ANYCON,$1&31}
|
|
shr %1,{ANYCON,$1&31} yields %2 %1
|
|
pat loc sru ($1&63)==32 && $2==8
|
|
with a_word a_word yields {ANYCON,0} %2
|
|
pat loc sru ($1&32)!=0 && $2==8
|
|
with a_word REG
|
|
gen shr %2,{ANYCON,$1&31} yields {ANYCON,0} %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")
|
|
|
|
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 dup adp stl loi stl $1==$4 && $2==4 && $5<=4
|
|
leaving lol $1 loi $5 stl $6 lol $1 adp $3 stl $4
|
|
|
|
#ifdef REGVARS
|
|
pat lol dup adp stl loi loc loc cii $1==$4 && $2==4 && $5==1 && inreg($1) > 0 && $6==1 && $7==4
|
|
uses REG
|
|
gen movsxb %a,{indir_r1, regvar($1)}
|
|
yields %a
|
|
leaving lol $1 adp $3 stl $4
|
|
|
|
pat lol dup adp stl loi $1==$4 && $2==4 && $5==1 && inreg($1) > 0
|
|
uses REG1 = {indir_r1, regvar($1)}
|
|
yields %a
|
|
leaving lol $1 adp $3 stl $4
|
|
|
|
pat lol dup adp stl loi loc loc cii $1==$4 && $2==4 && $5==2 && inreg($1) > 0 && $6==2 && $7==4
|
|
uses REG
|
|
gen movsx %a,{indir_r2, regvar($1)}
|
|
yields %a
|
|
leaving lol $1 adp $3 stl $4
|
|
|
|
pat lol dup adp stl loi $1==$4 && $2==4 && $5==2 && inreg($1) > 0
|
|
uses REG2 = {indir_r2, regvar($1)}
|
|
yields %a
|
|
leaving lol $4 adp $3 stl $4
|
|
|
|
pat lol dup adp stl loi $1==$4 && $2==4 && $5==4 && inreg($1) > 0
|
|
uses REG = {indir_r, regvar($1)}
|
|
yields %a
|
|
leaving lol $4 adp $3 stl $4
|
|
pat adp stl inreg($2) > 0 leaving stl $2 lol $2 adp $1 stl $2
|
|
#endif
|
|
|
|
pat lol dup adp stl $1==$4 && $2==4
|
|
uses ADDREG={LOCAL,$1,4} yields %a
|
|
leaving lol $4 adp $3 stl $4
|
|
|
|
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 dup adp sil $1==$4 && $2==4 && inreg($1)==reg_any
|
|
uses ADDREG={indir_r, regvar($1)}
|
|
yields %a
|
|
leaving lil $4 adp $3 sil $4
|
|
|
|
pat lil dup inc sil $1==$4 && $2==4 && inreg($1)==reg_any
|
|
uses REG={indir_r, regvar($1)}
|
|
yields %a
|
|
leaving lil $4 inc sil $4
|
|
|
|
pat lil dup dec sil $1==$4 && $2==4 && inreg($1)==reg_any
|
|
uses REG={indir_r, regvar($1)}
|
|
yields %a
|
|
leaving lil $4 dec sil $4
|
|
#endif
|
|
|
|
pat lil adp sil $1==$3 && $2==1 leaving lil $1 inc sil $1
|
|
|
|
pat lil adp sil $1==$3 && $2==0-1 leaving lil $1 dec sil $1
|
|
|
|
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
|
|
|
|
pat lol lof dup adp lol stf
|
|
$1==$5 && $2==$6 && $3==4 && inreg($1)==reg_any
|
|
uses REG={indir_r_off, regvar($1), $2}
|
|
yields %a
|
|
leaving lol $1 lof $2 adp $4 lol $1 stf
|
|
$2
|
|
|
|
pat lol lof dup inc lol stf
|
|
$1==$5 && $2==$6 && $3==4 && inreg($1)==reg_any
|
|
uses REG={indir_r_off, regvar($1), $2}
|
|
yields %a
|
|
leaving lol $1 lof $2 inc lol $1 stf $2
|
|
|
|
pat lol lof dup dec lol stf
|
|
$1==$5 && $2==$6 && $3==4 && inreg($1)==reg_any
|
|
uses REG={indir_r_off, regvar($1), $2}
|
|
yields %a
|
|
leaving lol $1 lof $2 dec lol $1 stf $2
|
|
|
|
#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 lol lof dup adp lol stf
|
|
$1==$5 && $2==$6 && $3==4 && $4==1
|
|
kills all_mems
|
|
uses REG={LOCAL,$1,4}, REG
|
|
gen move {indir_r_off, %a, $2},%b
|
|
inc {indir_r_off, %a, $2}
|
|
yields %b
|
|
|
|
pat loe lof dup adp loe stf
|
|
$1==$5 && $2==$6 && $3==4 && $4==1
|
|
kills all_mems
|
|
uses REG={EXTERN,$1}, REG
|
|
gen move {indir_r_off, %a, $2},%b
|
|
inc {indir_r_off, %a, $2}
|
|
yields %b
|
|
|
|
pat loe loi dup adp loe sti
|
|
$1==$5 && $2==$6 && $3==4 && $2==4 && $4==1
|
|
kills all_mems
|
|
uses REG={EXTERN,$1}, REG
|
|
gen move {indir_r, %a},%b
|
|
inc {indir_r, %a}
|
|
yields %b
|
|
|
|
pat lol lof dup adp lol stf
|
|
$1==$5 && $2==$6 && $3==4 && $4==(0-1)
|
|
kills all_mems
|
|
uses REG={LOCAL,$1,4}, REG
|
|
gen move {indir_r_off, %a, $2},%b
|
|
dec {indir_r_off, %a, $2}
|
|
yields %b
|
|
|
|
pat loe lof dup adp loe stf
|
|
$1==$5 && $2==$6 && $3==4 && $4==(0-1)
|
|
kills all_mems
|
|
uses REG={EXTERN,$1}, REG
|
|
gen move {indir_r_off, %a, $2},%b
|
|
dec {indir_r_off, %a, $2}
|
|
yields %b
|
|
pat loe loi dup adp loe sti
|
|
$1==$5 && $2==$6 && $3==4 && $2==4 && $4==(0-1)
|
|
kills all_mems
|
|
uses REG={EXTERN,$1}, REG
|
|
gen move {indir_r, %a},%b
|
|
dec {indir_r, %a}
|
|
yields %b
|
|
|
|
pat lol lof dup adp lol stf
|
|
$1==$5 && $2==$6 && $3==4
|
|
kills all_mems
|
|
uses REG={LOCAL,$1,4}, REG
|
|
gen move {indir_r_off, %a, $2},%b
|
|
add {indir_r_off, %a, $2}, {ANYCON, $4}
|
|
yields %b
|
|
|
|
pat loe lof dup adp loe stf
|
|
$1==$5 && $2==$6 && $3==4
|
|
kills all_mems
|
|
uses REG={EXTERN,$1}, REG
|
|
gen move {indir_r_off, %a, $2},%b
|
|
add {indir_r_off, %a, $2}, {ANYCON, $4}
|
|
yields %b
|
|
|
|
pat loe loi dup adp loe sti
|
|
$1==$5 && $2==$6 && $3==4 && $2==4
|
|
kills all_mems
|
|
uses REG={EXTERN,$1}, REG
|
|
gen move {indir_r, %a},%b
|
|
add {indir_r, %a}, {ANYCON, $4}
|
|
yields %b
|
|
|
|
|
|
pat loe ngi ste $1==$3 && $2==4
|
|
kills mem_nonlocals
|
|
gen neg {EXTERN, $1}
|
|
|
|
pat loe dup adp ste $1==$4 && $2==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 loe loi adp loe sti $1==$4 && $2==$5 && $2==4
|
|
leaving loc $3 loe $1 loi $2 adi 4 loe $1 sti $2
|
|
|
|
pat lil lof adp lil stf $1==$4 && $2==$5 && $3==1
|
|
leaving lil $1 lof $2 inc lil $1 stf $2
|
|
pat lil lof adp lil stf $1==$4 && $2==$5 && $3==0-1
|
|
leaving lil $1 lof $2 dec lil $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
|
|
pat lil loi adp lil sti $1==$4 && $2==$5 && $2==4 && $3==1
|
|
leaving lil $1 loi $2 inc lil $1 sti $2
|
|
pat lil loi adp lil sti $1==$4 && $2==$5 && $2==4 && $3==0-1
|
|
leaving lil $1 loi $2 dec lil $1 sti $2
|
|
pat lil loi adp lil sti $1==$4 && $2==$5 && $2==4
|
|
leaving loc $3 lil $1 loi $2 adi 4 lil $1 sti $2
|
|
|
|
/*******************************************************************
|
|
* Group 8: Convert Instructions *
|
|
*******************************************************************/
|
|
|
|
pat cii
|
|
with CXREG DXREG ACC
|
|
kills ALL
|
|
gen proccall {label,".cii"} yields %3
|
|
|
|
#if 0
|
|
/* wrong when integer size > 4 */
|
|
pat ciu leaving cuu
|
|
pat cui leaving cuu
|
|
|
|
pat cuu
|
|
#endif
|
|
|
|
pat loc loc cii zeq $1==1
|
|
with GENREG STACK
|
|
gen test %1.1
|
|
je {label, $4}
|
|
|
|
pat loc loc cii zne $1==1
|
|
with GENREG STACK
|
|
gen test %1.1
|
|
jne {label, $4}
|
|
|
|
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 cii $1==4 && $2==8
|
|
with ACC
|
|
gen cdq. yields edx eax
|
|
|
|
pat loc loc cii $1<4 && $2==8 leaving loc $1 loc 4 cii loc 4 loc $2 cii
|
|
|
|
pat loc loc cii $1==8 && $2==4
|
|
with a_word a_word yields %1
|
|
|
|
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 cuu $1==4 && $2==8
|
|
with a_word yields {ANYCON,0} %1
|
|
|
|
pat loc loc cuu $1==8 && $2==4
|
|
with a_word a_word yields %1
|
|
|
|
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 rol $1==8
|
|
with SHIFT_CREG REG REG
|
|
uses REG
|
|
gen testb cl,{ANYCON,32}
|
|
je {label,1f}
|
|
xchg %2,%3
|
|
1:
|
|
mov %a,%3
|
|
shld %3,%2,cl
|
|
shld %2,%a,cl yields %3 %2
|
|
|
|
pat loc rol ($1&32)==0 && $2==8
|
|
with REG REG
|
|
uses REG
|
|
gen mov %a,%2
|
|
shld %2,%1,{ANYCON,$1&31}
|
|
shld %1,%a,{ANYCON,$1&31} yields %2 %1
|
|
pat loc rol ($1&63)==32 && $2==8
|
|
leaving exg 4
|
|
pat loc rol ($1&32)!=0 && $2==8
|
|
leaving loc (0-$1)&31 ror 8
|
|
|
|
pat ror $1==4
|
|
with SHIFT_CREG REG
|
|
gen ror %2,cl yields %2
|
|
with ANYCON REG
|
|
gen ror %2,%1 yields %2
|
|
|
|
pat ror $1==8
|
|
with SHIFT_CREG REG REG
|
|
uses REG
|
|
gen testb cl,{ANYCON,32}
|
|
je {label,1f}
|
|
xchg %2,%3
|
|
1:
|
|
mov %a,%2
|
|
shrd %2,%3,cl
|
|
shrd %3,%a,cl yields %3 %2
|
|
|
|
pat loc ror ($1&32)==0 && $2==8
|
|
with REG REG
|
|
uses REG
|
|
gen mov %a,%1
|
|
shrd %1,%2,{ANYCON,$1&31}
|
|
shrd %2,%a,{ANYCON,$1&31} yields %2 %1
|
|
pat loc ror ($1&63)==32 && $2==8
|
|
leaving exg 4
|
|
pat loc ror ($1&32)!=0 && $2==8
|
|
leaving loc (0-$1)&31 rol 8
|
|
|
|
/*******************************************************************
|
|
* 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 cmi $1==8
|
|
with rmorconst rmorconst GENREG GENREG
|
|
/* Let dx = 0x100 or 0x101 if a < b, 0 if a == b, 1 if a > b.
|
|
Shift left so 0x100 becomes the sign bit of edx. */
|
|
/* can't use 5th REG */
|
|
gen sub %3,%1
|
|
setne %3.1
|
|
sbb %4,%2
|
|
setl %4.2
|
|
setg %4.1
|
|
orb %4.1,%3.1
|
|
shl %4,{ANYCON,23} yields %4
|
|
|
|
pat cmu $1==4 leaving cmp
|
|
|
|
pat cmu $1==8
|
|
with rmorconst rmorconst GENREG GENREG
|
|
gen sub %3,%1
|
|
setne %3.1
|
|
sbb %4,%2
|
|
setb %4.2
|
|
seta %4.1
|
|
orb %4.1,%3.1
|
|
shl %4,{ANYCON,23} yields %4
|
|
|
|
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 GENREG = {ANYCON,0}
|
|
gen test %1
|
|
setxx* %a.1 yields %a
|
|
|
|
pat tlt call txx("sets")
|
|
pat teq call txx("sete")
|
|
pat tne call txx("setne")
|
|
pat tge call txx("setns")
|
|
|
|
/* Explicit test for TLE and TGT. We must make sure that the OC
|
|
flag is cleared.
|
|
*/
|
|
pat tle
|
|
with rm
|
|
uses GENREG = {ANYCON,0}
|
|
gen
|
|
killcc.
|
|
test %1
|
|
setle %a.1
|
|
yields %a
|
|
|
|
pat tgt
|
|
with rm
|
|
uses GENREG = {ANYCON,0}
|
|
gen
|
|
killcc.
|
|
test %1
|
|
setg %a.1
|
|
yields %a
|
|
|
|
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")
|
|
|
|
proc cmx8txxn example cmi tgt
|
|
with GENREG REG rmorconst rmorconst
|
|
/* can't use 5th REG */
|
|
gen sub %1,%3
|
|
sbb %2,%4
|
|
setxx* %2.1
|
|
movzxb %2,%2.1 yields %2
|
|
proc cmx8txxy example cmi tlt
|
|
with rmorconst rmorconst GENREG REG
|
|
gen sub %3,%1
|
|
sbb %4,%2
|
|
setxx* %4.1
|
|
movzxb %4,%4.1 yields %4
|
|
|
|
pat cmi tlt $1==8 call cmx8txxy("setl")
|
|
pat cmi tle $1==8 call cmx8txxn("setge")
|
|
pat cmi tge $1==8 call cmx8txxy("setge")
|
|
pat cmi tgt $1==8 call cmx8txxn("setl")
|
|
pat cmu tlt $1==8 call cmx8txxy("setb")
|
|
pat cmu tle $1==8 call cmx8txxn("setae")
|
|
pat cmu tge $1==8 call cmx8txxy("setae")
|
|
pat cmu tgt $1==8 call cmx8txxn("setb")
|
|
|
|
proc cmx8zxxn example cmi zgt
|
|
with REG REG rmorconst rmorconst STACK
|
|
gen sub %1,%3
|
|
sbb %2,%4
|
|
jxx* {label,$2}
|
|
proc cmx8zxxy example cmi zlt
|
|
with rmorconst rmorconst REG REG STACK
|
|
gen sub %3,%1
|
|
sbb %4,%2
|
|
jxx* {label,$2}
|
|
|
|
pat cmi zlt $1==8 call cmx8zxxy("jl")
|
|
pat cmi zle $1==8 call cmx8zxxn("jge")
|
|
pat cmi zge $1==8 call cmx8zxxy("jge")
|
|
pat cmi zgt $1==8 call cmx8zxxn("jl")
|
|
pat cmu zlt $1==8 call cmx8zxxy("jb")
|
|
pat cmu zle $1==8 call cmx8zxxn("jae")
|
|
pat cmu zge $1==8 call cmx8zxxy("jae")
|
|
pat cmu zgt $1==8 call cmx8zxxn("jb")
|
|
|
|
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 lab topeltsize($1)==4 && !fallthrough($1)
|
|
with STACK
|
|
kills ALL
|
|
gen labeldef $1 yields eax
|
|
|
|
pat lab topeltsize($1)==4 && fallthrough($1)
|
|
with ACC STACK
|
|
kills ALL
|
|
gen labeldef $1 yields eax
|
|
|
|
pat lab topeltsize($1)!=4
|
|
with STACK
|
|
kills ALL
|
|
gen labeldef $1
|
|
|
|
pat bra topeltsize($1)==4
|
|
with ACC STACK
|
|
gen jmp {label,$1}
|
|
|
|
pat bra topeltsize($1)!=4
|
|
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("js")
|
|
pat zge call zxx("jns")
|
|
|
|
/* Explicit test for ZLE and ZGT. We must make sure that the OC
|
|
flag is cleared.
|
|
*/
|
|
pat zle
|
|
with rm STACK
|
|
gen
|
|
killcc.
|
|
test %1
|
|
jle {label,$1}
|
|
|
|
pat zgt
|
|
with rm STACK
|
|
gen
|
|
killcc.
|
|
test %1
|
|
jg {label, $1}
|
|
|
|
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 $1==8
|
|
with BXREG ACC DXREG
|
|
kills ALL
|
|
gen jmp {label, ".csa8"}
|
|
|
|
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 $1==8
|
|
with BXREG ACC DXREG
|
|
kills ALL
|
|
gen jmp {label, ".csb8"}
|
|
|
|
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
|
|
#ifdef DEBUG
|
|
gen proccall {label, ".nop"}
|
|
#endif
|
|
|
|
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"}
|