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