ack/mach/i86/cg/table
1987-06-10 14:06:14 +00:00

2549 lines
67 KiB
Plaintext

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