ack/mach/powerpc/ncg/table

2198 lines
49 KiB
Plaintext
Raw Normal View History

2007-11-02 18:56:58 +00:00
EM_WSIZE = 4
EM_PSIZE = 4
EM_BSIZE = 8 /* two words saved in call frame */
INT8 = 1 /* Size of values */
INT16 = 2
INT32 = 4
INT64 = 8
FP_OFFSET = 0 /* Offset of saved FP relative to our FP */
PC_OFFSET = 4 /* Offset of saved PC relative to our FP */
#define COMMENT(n) /* noop */
#define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64)
#define smalls(n) sfit(n, 16)
#define smallu(n) ufit(n, 16)
#define lo(n) (n & 0xFFFF)
#define hi(n) ((n>>16) & 0xFFFF)
/* Use these for instructions that treat the low half as signed --- his()
* includes a modifier to produce the correct value when the low half gets
* sign extended. Er, do make sure you load the low half second. */
#define los(n) (n & 0xFFFF)
#define his(n) ((hi(n) - (lo(n)>>15)) & 0xFFFF)
#define IFFALSE {CONST, 4}
#define IFTRUE {CONST, 12}
#define ALWAYS {CONST, 20}
#define DCTRZ {CONST, 34}
#define LT {CONST, 0}
#define GT {CONST, 1}
#define EQ {CONST, 2}
PROPERTIES
GPR /* any GPR */
REG /* any allocatable GPR */
FPR /* any FPR */
FREG /* any allocatable FPR */
FSREG /* any allocatable single-precision FPR */
2007-11-02 18:56:58 +00:00
SPR /* any SPR */
CR /* any CR */
GPR0 GPRSP GPRFP GPR3 GPR4 GPR5 GPR6 GPR7
GPR8 GPR9 GPR10 GPR11 GPR12 GPR13 GPR14 GPR15
GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23
GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31
CR0 CR1
2007-11-02 18:56:58 +00:00
FPR0 FPR1 FPR2 FPR3 FPR4 FPR5 FPR6 FPR7
FPR8 FPR9 FPR10 FPR11 FPR12 FPR13 FPR14 FPR15
FPR16 FPR17 FPR18 FPR19 FPR20 FPR21 FPR22 FPR23
FPR24 FPR25 FPR26 FPR27 FPR28 FPR29 FPR30 FPR31
2007-11-02 18:56:58 +00:00
REGISTERS
/* Reverse order to encourage ncg to allocate them from r31 down */
R31("r31") : GPR, REG, GPR31 regvar.
R30("r30") : GPR, REG, GPR30 regvar.
R29("r29") : GPR, REG, GPR29 regvar.
R28("r28") : GPR, REG, GPR28 regvar.
R27("r27") : GPR, REG, GPR27 regvar.
R26("r26") : GPR, REG, GPR26 regvar.
R25("r25") : GPR, REG, GPR25 regvar.
R24("r24") : GPR, REG, GPR24 regvar.
R23("r23") : GPR, REG, GPR23 regvar.
R22("r22") : GPR, REG, GPR22 regvar.
R21("r21") : GPR, REG, GPR21 regvar.
R20("r20") : GPR, REG, GPR20 regvar.
R19("r19") : GPR, REG, GPR19 regvar.
R18("r18") : GPR, REG, GPR18 regvar.
R17("r17") : GPR, REG, GPR17 regvar.
R16("r16") : GPR, REG, GPR16 regvar.
R15("r15") : GPR, REG, GPR15 regvar.
R14("r14") : GPR, REG, GPR14 regvar.
R13("r13") : GPR, REG, GPR13 regvar.
R12("r12") : GPR, REG, GPR12.
R11("r11") : GPR, GPR11.
R10("r10") : GPR, REG, GPR10.
R9("r9") : GPR, REG, GPR9.
R8("r8") : GPR, REG, GPR8.
R7("r7") : GPR, REG, GPR7.
R6("r6") : GPR, REG, GPR6.
R5("r5") : GPR, REG, GPR5.
R4("r4") : GPR, REG, GPR4.
R3("r3") : GPR, REG, GPR3.
FP("fp") : GPR, GPRFP.
SP("sp") : GPR, GPRSP.
R0("r0") : GPR, GPR0.
2007-11-02 18:56:58 +00:00
F31("f31") : FPR, FREG, FPR31.
F30("f30") : FPR, FREG, FPR30.
F29("f29") : FPR, FREG, FPR29.
F28("f28") : FPR, FREG, FPR28.
F27("f27") : FPR, FREG, FPR27.
F26("f26") : FPR, FREG, FPR26.
F25("f25") : FPR, FREG, FPR25.
F24("f24") : FPR, FREG, FPR24.
F23("f23") : FPR, FREG, FPR23.
F22("f22") : FPR, FREG, FPR22.
F21("f21") : FPR, FREG, FPR21.
F20("f20") : FPR, FREG, FPR20.
F19("f19") : FPR, FREG, FPR19.
F18("f18") : FPR, FREG, FPR18.
F17("f17") : FPR, FREG, FPR17.
F16("f16") : FPR, FREG, FPR16.
F15("f15") : FPR, FREG, FPR15.
F14("f14") : FPR, FREG, FPR14.
F13("f13") : FPR, FREG, FPR13.
F12("f12") : FPR, FREG, FPR12.
F11("f11") : FPR, FREG, FPR11.
F10("f10") : FPR, FREG, FPR10.
F9("f9") : FPR, FREG, FPR9.
F8("f8") : FPR, FREG, FPR8.
F7("f7") : FPR, FREG, FPR7.
F6("f6") : FPR, FREG, FPR6.
F5("f5") : FPR, FREG, FPR5.
F4("f4") : FPR, FREG, FPR4.
F3("f3") : FPR, FREG, FPR3.
F2("f2") : FPR, FREG, FPR2.
F1("f1") : FPR, FREG, FPR1.
F0("f0") : FPR, FPR0.
FS31("f31")=F31 : FSREG.
FS30("f30")=F30 : FSREG.
FS29("f29")=F29 : FSREG.
FS28("f28")=F28 : FSREG.
FS27("f27")=F27 : FSREG.
FS26("f26")=F26 : FSREG.
FS25("f25")=F25 : FSREG.
FS24("f24")=F24 : FSREG.
FS23("f23")=F23 : FSREG.
FS22("f22")=F22 : FSREG.
FS21("f21")=F21 : FSREG.
FS20("f20")=F20 : FSREG.
FS19("f19")=F19 : FSREG.
FS18("f18")=F18 : FSREG.
FS17("f17")=F17 : FSREG.
FS16("f16")=F16 : FSREG.
FS15("f15")=F15 : FSREG.
FS14("f14")=F14 : FSREG.
FS13("f13")=F13 : FSREG.
FS12("f12")=F12 : FSREG.
FS11("f11")=F11 : FSREG.
FS10("f10")=F10 : FSREG.
FS9("f9")=F9 : FSREG.
FS8("f8")=F8 : FSREG.
FS7("f7")=F7 : FSREG.
FS6("f6")=F6 : FSREG.
FS5("f5")=F5 : FSREG.
FS4("f4")=F4 : FSREG.
FS3("f3")=F3 : FSREG.
FS2("f2")=F2 : FSREG.
FS1("f1")=F1 : FSREG.
/* FS0("f0")=F0 */
2007-11-02 18:56:58 +00:00
LR("lr") : SPR.
CTR("ctr") : SPR.
C0("cr0") : CR, CR0.
#define RSCRATCH R11
2007-11-02 18:56:58 +00:00
#define FSCRATCH F0
TOKENS
/* Used only in instruction descriptions (to generate the correct syntax). */
GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")".
GPRINDIRECTLO = { GPR reg; ADDR adr; } 4 ">" adr "(" reg ")". /* Warning! Do not use on labels. */
HILABEL = { ADDR adr; } 4 "<" adr.
LOLABEL = { ADDR adr; } 4 ">" adr.
/* Primitives */
LABEL = { ADDR adr; } 4 adr.
CONST = { INT val; } 4 val.
LOCAL = { INT off; } 4.
/* Allows us to use regvar() to refer to registers */
GPRE = { GPR reg; } 4 reg.
/* Expression partial results */
SUM_RC = { GPR reg; INT off; } 4.
SUM_RR = { GPR reg1; GPR reg2; } 4.
TRISTATE_RC_S = { GPR reg; INT val; } 4.
TRISTATE_RC_U = { GPR reg; INT val; } 4.
TRISTATE_RR_S = { GPR reg1; GPR reg2; } 4.
TRISTATE_RR_U = { GPR reg1; GPR reg2; } 4.
TRISTATE_FF = { FPR reg1; FPR reg2; } 4.
SEX_B = { GPR reg; } 4.
SEX_H = { GPR reg; } 4.
IND_RC_B = { GPR reg; INT off; } 4.
IND_RC_H = { GPR reg; INT off; } 4.
IND_RC_H_S = { GPR reg; INT off; } 4.
IND_RC_W = { GPR reg; INT off; } 4.
IND_RR_W = { GPR reg1; GPR reg2; } 4.
IND_LABEL_W = { ADDR adr; } 4.
IND_RC_D = { GPR reg; INT off; } 8.
IND_RR_D = { GPR reg1; GPR reg2; } 8.
IND_LABEL_D = { ADDR adr; } 8.
NOT_R = { GPR reg; } 4.
AND_RR = { GPR reg1; GPR reg2; } 4.
AND_RC = { GPR reg; INT val; } 4.
OR_RR = { GPR reg1; GPR reg2; } 4.
OR_RC = { GPR reg; INT val; } 4.
XOR_RR = { GPR reg1; GPR reg2; } 4.
XOR_RC = { GPR reg; INT val; } 4.
/* Comments */
LABELI = { ADDR msg; INT num; } 4 msg " " num.
SETS
GPRI = GPR + GPRE.
SUM_ALL = SUM_RC + SUM_RR.
TRISTATE_ALL = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S +
TRISTATE_RR_U + TRISTATE_FF.
SEX_ALL = SEX_B + SEX_H.
LOGICAL_ALL = NOT_R + AND_RR + AND_RC + OR_RR + OR_RC + XOR_RR +
XOR_RC.
IND_ALL_W = IND_RC_W + IND_RR_W + IND_LABEL_W.
IND_ALL_D = IND_RC_D + IND_RR_D + IND_LABEL_D.
OP_ALL_W = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL +
IND_ALL_W.
INSTRUCTIONS
add GPRI:wo, GPRI:ro, GPRI:ro.
addX "add." GPRI:wo, GPRI:ro, GPRI:ro.
addi GPRI:wo, GPRI:ro, CONST:ro.
addis GPRI:wo, GPRI:ro, CONST+HILABEL:ro.
and GPRI:wo, GPRI:ro, GPRI:ro.
andc GPRI:wo, GPRI:ro, GPRI:ro.
andiX "andi." GPRI:wo, GPRI:ro, CONST:ro kills :cc.
andisX "andis." GPRI:wo, GPRI:ro, CONST:ro kills :cc.
b LABEL:ro.
bc CONST:ro, CONST:ro, LABEL:ro.
bcctr CONST:ro, CONST:ro, CONST:ro.
bcctrl CONST:ro, CONST:ro, CONST:ro.
bclr CONST:ro, CONST:ro, CONST:ro.
bl LABEL:ro.
cmp CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc.
cmpi CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc.
cmpl CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc.
cmpli CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc.
divw GPRI:wo, GPRI:ro, GPRI:ro.
divwu GPRI:wo, GPRI:ro, GPRI:ro.
eqv GPRI:wo, GPRI:ro, GPRI:ro.
extsb GPRI:wo, GPRI:ro.
extsh GPRI:wo, GPRI:ro.
fadd FREG:wo, FREG:ro, FREG:ro.
fadds FSREG:wo, FSREG:ro, FSREG:ro.
fcmpo CR:wo, FPR:ro, FPR:ro.
fdiv FREG:wo, FREG:ro, FREG:ro.
fdivs FSREG:wo, FSREG:ro, FSREG:ro.
fneg FREG:wo, FREG:ro.
fneg FSREG:wo, FSREG:ro.
fmul FREG:wo, FREG:ro, FREG:ro.
fmuls FSREG:wo, FSREG:ro, FSREG:ro.
frsp FSREG:wo, FREG:ro.
fsub FREG:wo, FREG:ro, FREG:ro.
fsubs FSREG:wo, FSREG:ro, FSREG:ro.
fmr FPR:wo, FPR:ro.
fmr FSREG:wo, FSREG:ro.
2007-11-02 18:56:58 +00:00
lbzx GPRI:wo, GPR:ro, GPR:ro.
lbz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
lfd FPR:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
lfdu FPR:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
lfdx FPR:wo, GPR:ro, GPR:ro.
lfs FSREG:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
lfsu FSREG:wo, GPRINDIRECT+GPRINDIRECTLO:rw.
lfsx FSREG:wo, GPR:ro, GPR:ro.
2007-11-02 18:56:58 +00:00
lhzx GPRI:wo, GPR:ro, GPR:ro.
lhax GPRI:wo, GPR:ro, GPR:ro.
lha GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
lhz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
li32 GPRI:wo, LABEL:ro.
2007-11-02 18:56:58 +00:00
lwzu GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
lwzx GPRI:wo, GPR:ro, GPR:ro.
lwz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
nand GPRI:wo, GPRI:ro, GPRI:ro.
neg GPRI:wo, GPRI:ro.
nor GPRI:wo, GPRI:ro, GPRI:ro.
mfcr GPRI:wo.
mullw GPRI:wo, GPRI:ro, GPRI:ro.
mfspr GPRI:wo, SPR:ro.
mtspr SPR:wo, GPRI:ro.
or GPRI:wo, GPRI:ro, GPRI:ro.
orc GPRI:wo, GPRI:ro, GPRI:ro.
ori GPRI:wo, GPRI:ro, CONST+LOLABEL:ro.
orX "or." GPRI:wo, GPRI:ro, GPRI:ro kills :cc.
rlwinm GPRI:wo, GPRI:ro, CONST:ro, CONST:ro, CONST:ro.
slw GPRI:wo, GPRI:ro, GPRI:ro.
subf GPRI:wo, GPRI:ro, GPRI:ro.
sraw GPRI:wo, GPRI:ro, GPRI:ro.
srawi GPRI:wo, GPRI:ro, CONST:ro.
srw GPRI:wo, GPRI:ro, GPRI:ro.
stb GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
stbx GPRI:ro, GPR:ro, GPR:ro.
stfd FPR:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
stfdu FPR:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
stfdx FPR:ro, GPR:ro, GPR:ro.
stfs FSREG:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
stfsu FSREG:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
stfsx FSREG:ro, GPR:ro, GPR:ro.
2007-11-02 18:56:58 +00:00
sth GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
sthx GPRI:ro, GPR:ro, GPR:ro.
stw GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
stwx GPRI:ro, GPR:ro, GPR:ro.
stwu GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
xor GPRI:wo, GPRI:ro, GPRI:ro.
xori GPRI:wo, GPRI:ro, CONST:ro.
gpr_gpr_gpr GPRI:wo, GPRI:ro, GPRI:ro.
gpr_gpr_si GPRI:wo, GPRI:ro, CONST:ro.
gpr_ro_gprindirect GPRI:ro, GPRINDIRECT:rw.
gpr_ro_gpr_gpr GPRI:ro, GPRI:ro, GPRI:ro.
gpr_wo_gprindirect GPRI:wo, GPRINDIRECT:ro.
gpr_wo_gpr_gpr GPRI:wo, GPRI:ro, GPRI:ro.
2007-11-02 18:56:58 +00:00
comment "!" LABEL+LABELI:ro.
MOVES
from GPR to GPR
gen
COMMENT("move GPR->GPR")
or %2, %1, %1
/* GPRE exists solely to allow us to use regvar() (which can only be used in
an expression) as a register constant. */
from GPR to GPRE
gen
COMMENT("move GPR->GPRE")
or %2, %1, %1
/* Constants */
from CONST smalls(%val) to GPR
gen
COMMENT("move CONST->GPRE")
addi %2, R0, {CONST, lo(%1.val)}
from CONST to GPR
gen
COMMENT("move CONST->GPRE")
addis %2, R0, {CONST, hi(%1.val)}
ori %2, %2, {CONST, lo(%1.val)}
from LABEL to GPR
gen
COMMENT("move LABEL->GPR")
li32 %2, {LABEL, %1.adr}
2007-11-02 18:56:58 +00:00
/* Sign extension */
from SEX_B to GPR
gen
COMMENT("move SEX_B->GPR")
extsb %2, %1.reg
from SEX_H to GPR
gen
COMMENT("move SEX_H->GPR")
extsh %2, %1.reg
/* Register + something */
from SUM_RC smalls(%off) to GPR
gen
COMMENT("move SUM_RC->GPR smalls")
addi %2, %1.reg, {CONST, lo(%1.off)}
from SUM_RC to GPR
gen
COMMENT("move SUM_RC->GPR large")
addi %2, %1.reg, {CONST, los(%1.off)}
addis %2, %2, {CONST, his(%1.off)}
from SUM_RR to GPR
gen
COMMENT("move SUM_RR->GPR")
add %2, %1.reg1, %1.reg2
from SUM_RR to GPR
gen
COMMENT("move SUM_RR->GPRE")
add %2, %1.reg1, %1.reg2
/* Read/write byte */
from IND_RC_B smalls(%off) to GPR
gen
COMMENT("move IND_RC_B->GPR small")
lbz %2, {GPRINDIRECT, %1.reg, %1.off}
from IND_RC_B to GPR
gen
COMMENT("move IND_RC_B->GPR large")
addis RSCRATCH, %1.reg, {CONST, his(%1.off)}
lbz %2, {GPRINDIRECT, RSCRATCH, los(%1.off)}
2007-11-02 18:56:58 +00:00
from GPR to IND_RC_B smalls(%off)
gen
COMMENT("move GPR->IND_RC_B small")
stb %1, {GPRINDIRECT, %2.reg, %2.off}
from GPR to IND_RC_B
gen
COMMENT("move GPR->IND_RC_B large")
addis RSCRATCH, %2.reg, {CONST, his(%2.off)}
stb %1, {GPRINDIRECT, RSCRATCH, los(%2.off)}
2007-11-02 18:56:58 +00:00
/* Read/write short */
from IND_RC_H smalls(%off) to GPR
gen
COMMENT("move IND_RC_H->GPR small")
lhz %2, {GPRINDIRECT, %1.reg, %1.off}
from IND_RC_H to GPR
gen
COMMENT("move IND_RC_H->GPR large")
addis RSCRATCH, %1.reg, {CONST, his(%1.off)}
lhz %2, {GPRINDIRECT, RSCRATCH, los(%1.off)}
2007-11-02 18:56:58 +00:00
from IND_RC_H_S smalls(%off) to GPR
gen
COMMENT("move IND_RC_H_S->GPR small")
lha %2, {GPRINDIRECT, %1.reg, %1.off}
from IND_RC_H_S to GPR
gen
COMMENT("move IND_RC_H_S->GPR large")
addis RSCRATCH, %1.reg, {CONST, his(%1.off)}
lha %2, {GPRINDIRECT, RSCRATCH, los(%1.off)}
2007-11-02 18:56:58 +00:00
from GPR to IND_RC_H smalls(%off)
gen
COMMENT("move GPR->IND_RC_H small")
sth %1, {GPRINDIRECT, %2.reg, %2.off}
from GPR to IND_RC_H
gen
COMMENT("move GPR->IND_RC_H large")
addis RSCRATCH, %2.reg, {CONST, his(%2.off)}
sth %1, {GPRINDIRECT, RSCRATCH, los(%2.off)}
2007-11-02 18:56:58 +00:00
/* Read word */
from IND_RC_W smalls(%off) to GPR
gen
COMMENT("move IND_RC_W->GPR small")
lwz %2, {GPRINDIRECT, %1.reg, %1.off}
from IND_RC_W to GPR
gen
COMMENT("move IND_RC_W->GPR large")
addis %2, %1.reg, {CONST, his(%1.off)}
lwz %2, {GPRINDIRECT, %2, los(%1.off)}
from IND_RR_W to GPR
gen
COMMENT("move IND_RR_W->GPR")
lwzx %2, %1.reg1, %1.reg2
from IND_LABEL_W to GPR
gen
COMMENT("move IND_LABEL_W->GPR")
move {LABEL, %1.adr}, RSCRATCH
lwz %2, {GPRINDIRECT, RSCRATCH, 0}
2007-11-02 18:56:58 +00:00
from IND_RC_W smalls(%off) to FSREG
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_RC_W->FSREG small")
2007-11-02 18:56:58 +00:00
lfs %2, {GPRINDIRECT, %1.reg, %1.off}
from IND_RC_W to FSREG
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_RC_W->FSREG large")
addis RSCRATCH, %1.reg, {CONST, his(%1.off)}
lfs %2, {GPRINDIRECT, RSCRATCH, los(%1.off)}
2007-11-02 18:56:58 +00:00
from IND_RR_W to FSREG
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_RR_W->FSREG")
2007-11-02 18:56:58 +00:00
lfsx %2, %1.reg1, %1.reg2
from IND_LABEL_W to FSREG
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_LABEL_W->FSREG")
move {LABEL, %1.adr}, RSCRATCH
lfs %2, {GPRINDIRECT, RSCRATCH, 0}
2007-11-02 18:56:58 +00:00
/* Write word */
from GPR to IND_RC_W smalls(%off)
gen
COMMENT("move GPR->IND_RC_W small")
stw %1, {GPRINDIRECT, %2.reg, %2.off}
from GPR to IND_RC_W
gen
COMMENT("move GPR->IND_RC_W large")
addis RSCRATCH, %2.reg, {CONST, his(%2.off)}
stw %1, {GPRINDIRECT, RSCRATCH, los(%2.off)}
2007-11-02 18:56:58 +00:00
from GPR to IND_RR_W
gen
COMMENT("move GPR->IND_RR_W")
stwx %1, %2.reg1, %2.reg2
from GPR to IND_LABEL_W
gen
COMMENT("move GPR->IND_LABEL_D")
move {LABEL, %2.adr}, RSCRATCH
stw %1, {GPRINDIRECT, RSCRATCH, 0}
2007-11-02 18:56:58 +00:00
from FSREG to IND_RC_W smalls(%off)
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FSREG->IND_RC_W small")
2007-11-02 18:56:58 +00:00
stfs %1, {GPRINDIRECT, %2.reg, %2.off}
from FSREG to IND_RC_W
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FSREG->IND_RC_W large")
addis RSCRATCH, %2.reg, {CONST, his(%2.off)}
stfs %1, {GPRINDIRECT, RSCRATCH, los(%2.off)}
2007-11-02 18:56:58 +00:00
from FSREG to IND_RR_W
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FSREG->IND_RR_W")
2007-11-02 18:56:58 +00:00
stfsx %1, %2.reg1, %2.reg2
from FSREG to IND_LABEL_W
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FSREG->IND_LABEL_D")
move {LABEL, %2.adr}, RSCRATCH
stfs %1, {GPRINDIRECT, RSCRATCH, 0}
2007-11-02 18:56:58 +00:00
/* Read double */
from IND_RC_D smalls(%off) to FPR
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_RC_D->FPR small")
2007-11-02 18:56:58 +00:00
lfd %2, {GPRINDIRECT, %1.reg, %1.off}
from IND_RC_D to FPR
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_RC_D->FPR large")
addis RSCRATCH, %1.reg, {CONST, his(%1.off)}
lfd %2, {GPRINDIRECT, RSCRATCH, los(%1.off)}
2007-11-02 18:56:58 +00:00
from IND_RR_D to FPR
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_RR_D->FPR")
2007-11-02 18:56:58 +00:00
lfdx %2, %1.reg1, %1.reg2
from IND_LABEL_D to FPR
2007-11-02 18:56:58 +00:00
gen
COMMENT("move IND_LABEL_D->FPR")
move {LABEL, %1.adr}, RSCRATCH
lfd %2, {GPRINDIRECT, RSCRATCH, 0}
2007-11-02 18:56:58 +00:00
/* Write double */
from FPR to IND_RC_D smalls(%off)
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FPR->IND_RC_D small")
2007-11-02 18:56:58 +00:00
stfd %1, {GPRINDIRECT, %2.reg, %2.off}
from FPR to IND_RC_D
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FPR->IND_RC_D large")
addis RSCRATCH, %2.reg, {CONST, his(%2.off)}
stfd %1, {GPRINDIRECT, RSCRATCH, los(%2.off)}
2007-11-02 18:56:58 +00:00
from FPR to IND_RR_D
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FPR->IND_RR_W")
2007-11-02 18:56:58 +00:00
stfdx %1, %2.reg1, %2.reg2
from FPR to IND_LABEL_D
2007-11-02 18:56:58 +00:00
gen
COMMENT("move FPR->IND_LABEL_D")
move {LABEL, %2.adr}, RSCRATCH
stfd %1, {GPRINDIRECT, RSCRATCH, 0}
2007-11-02 18:56:58 +00:00
/* Extract condition code field (actually produces (CC&3)<<2) */
from CR0 to GPR
gen
COMMENT("move CR0->GPR")
mfcr %2
rlwinm %2, %2, {CONST, 4}, {CONST, 32-4}, {CONST, 31-2}
/* Comparisons */
from TRISTATE_RR_S to CR0
gen
cmp %2, {CONST, 0}, %1.reg1, %1.reg2
from TRISTATE_RR_U to CR0
gen
cmpl %2, {CONST, 0}, %1.reg1, %1.reg2
from TRISTATE_RC_S to CR0
gen
COMMENT("move TRISTATE_RC_S->CR0 large")
move {CONST, %1.val}, RSCRATCH
cmp %2, {CONST, 0}, %1.reg, RSCRATCH
2007-11-02 18:56:58 +00:00
from TRISTATE_RC_U smallu(%val) to CR0
gen
COMMENT("move TRISTATE_RC_U->CR0 small")
cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val}
from TRISTATE_RC_U to CR0
gen
COMMENT("move TRISTATE_RC_U->CR0")
move {CONST, %1.val}, RSCRATCH
cmpl %2, {CONST, 0}, %1.reg, RSCRATCH
2007-11-02 18:56:58 +00:00
from TRISTATE_FF to CR0
gen
COMMENT("move TRISTATE_FF->CR0")
fcmpo %2, %1.reg1, %1.reg2
2007-11-02 18:56:58 +00:00
from GPR to CR0
gen
COMMENT("move GPR->CR0")
orX RSCRATCH, %1, %1 /* alas, can't call test */
2007-11-02 18:56:58 +00:00
from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR
gen
COMMENT("move TRISTATE_R*_S->GPR")
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".tristate_s_table"}, %2
lwzx %2, %2, RSCRATCH
2007-11-02 18:56:58 +00:00
from TRISTATE_RR_U + TRISTATE_RC_U to GPR
gen
COMMENT("move TRISTATE_R*_U->GPR")
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".tristate_u_table"}, %2
lwzx %2, %2, RSCRATCH
2007-11-02 18:56:58 +00:00
/* Logicals */
from NOT_R to GPR
gen
COMMENT("move NOT_R->GPR")
nor %2, %1.reg, %1.reg
from AND_RR to GPR
gen
COMMENT("move AND_RR->GPR")
and %2, %1.reg1, %1.reg2
from AND_RC smallu(%val) to GPR
gen
COMMENT("move AND_RC->GPR small")
andiX %2, %1.reg, {CONST, %1.val}
from AND_RC to GPR
gen
COMMENT("move AND_RC->GPR")
move {CONST, %1.val}, RSCRATCH
and %2, %1.reg, RSCRATCH
2007-11-02 18:56:58 +00:00
from OR_RR to GPR
gen
COMMENT("move OR_RR->GPR")
or %2, %1.reg1, %1.reg2
from OR_RC smallu(%val) to GPR
gen
COMMENT("move OR_RC->GPR small")
ori %2, %1.reg, {CONST, %1.val}
from OR_RC to GPR
gen
COMMENT("move OR_RC->GPR")
move {CONST, %1.val}, RSCRATCH
or %2, %1.reg, RSCRATCH
2007-11-02 18:56:58 +00:00
from XOR_RR to GPR
gen
COMMENT("move XOR_RR->GPR")
xor %2, %1.reg1, %1.reg2
from XOR_RC smallu(%val) to GPR
gen
COMMENT("move XOR_RC->GPR small")
xori %2, %1.reg, {CONST, %1.val}
from XOR_RC to GPR
gen
COMMENT("move XOR_RC->GPR")
move {CONST, %1.val}, RSCRATCH
xor %2, %1.reg, RSCRATCH
2007-11-02 18:56:58 +00:00
/* Miscellaneous */
from OP_ALL_W + LABEL + CONST to GPRE
gen
move %1, %2.reg
TESTS
to test GPR
gen
orX RSCRATCH, %1, %1
2007-11-02 18:56:58 +00:00
STACKINGRULES
from LOCAL to STACK
gen
COMMENT("stack LOCAL")
stwu {GPRE, regvar(%1.off)}, {GPRINDIRECT, SP, 0-4}
from REG to STACK
2007-11-02 18:56:58 +00:00
gen
COMMENT("stack REG")
2007-11-02 18:56:58 +00:00
stwu %1, {GPRINDIRECT, SP, 0-4}
from CONST to STACK
gen
COMMENT("stack CONST")
move %1, RSCRATCH
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
2007-11-02 18:56:58 +00:00
from LABEL to STACK
gen
COMMENT("stack LABEL")
move %1, RSCRATCH
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
2007-11-02 18:56:58 +00:00
from SEX_B to STACK
gen
COMMENT("stack SEX_B")
extsb RSCRATCH, %1.reg
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
2007-11-02 18:56:58 +00:00
from SEX_H to STACK
gen
COMMENT("stack SEX_H")
extsh RSCRATCH, %1.reg
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
2007-11-02 18:56:58 +00:00
from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK
gen
move %1, {GPRE, RSCRATCH}
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
2007-11-02 18:56:58 +00:00
from IND_ALL_W to STACK
gen
move %1, RSCRATCH
stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
2007-11-02 18:56:58 +00:00
from IND_ALL_D to STACK
gen
move %1, FSCRATCH
stfdu FSCRATCH, {GPRINDIRECT, SP, 0-8}
2007-11-02 18:56:58 +00:00
from FREG to STACK
2007-11-02 18:56:58 +00:00
gen
COMMENT("stack FPR")
2007-11-02 18:56:58 +00:00
stfdu %1, {GPRINDIRECT, SP, 0-8}
from FSREG to STACK
2007-11-02 18:56:58 +00:00
gen
COMMENT("stack FSREG")
2007-11-02 18:56:58 +00:00
stfsu %1, {GPRINDIRECT, SP, 0-4}
2007-11-02 18:56:58 +00:00
COERCIONS
from REG
uses REG
gen
COMMENT("coerce REG->REG")
move %1, %a
yields %a
from CONST
uses REG
gen
COMMENT("coerce CONST->REG")
move %1, %a
yields %a
from LABEL
uses REG
gen
COMMENT("coerce LABEL->REG")
move %1, {GPRE, %a}
yields %a
from STACK
uses REG
gen
COMMENT("coerce STACK->REG")
lwz %a, {GPRINDIRECT, SP, 0}
addi SP, SP, {CONST, 4}
yields %a
from SEX_B
uses REG
gen
COMMENT("coerce SEX_B->REG")
extsb %a, %1.reg
yields %a
from SEX_H
uses REG
gen
COMMENT("coerce SEX_H->REG")
extsh %a, %1.reg
yields %a
from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL
uses REG
gen
move %1, {GPRE, %a}
yields %a
from FSREG
uses FSREG
2007-11-02 18:56:58 +00:00
gen
fmr %a, %1
yields %a
2007-11-02 18:56:58 +00:00
from FREG
uses FREG
2007-11-02 18:56:58 +00:00
gen
fmr %a, %1
yields %a
2007-11-02 18:56:58 +00:00
from STACK
uses FREG
gen
COMMENT("coerce STACK->FREG")
lfd %a, {GPRINDIRECT, SP, 0}
2007-11-02 18:56:58 +00:00
addi SP, SP, {CONST, 8}
yields %a
2007-11-02 18:56:58 +00:00
from STACK
uses FSREG
2007-11-02 18:56:58 +00:00
gen
COMMENT("coerce STACK->FSREG")
lfs %a, {GPRINDIRECT, SP, 0}
2007-11-02 18:56:58 +00:00
addi SP, SP, {CONST, 4}
yields %a
2007-11-02 18:56:58 +00:00
from IND_ALL_W
uses REG
gen
move %1, %a
yields %a
from IND_ALL_W
uses FSREG
2007-11-02 18:56:58 +00:00
gen
move %1, %a
yields %a
2007-11-02 18:56:58 +00:00
from IND_ALL_D
uses FREG
gen
move %1, %a
yields %a
2007-11-02 18:56:58 +00:00
PATTERNS
/* Intrinsics */
pat loc /* Load constant */
yields {CONST, $1}
pat dup $1==INT32 /* Duplicate word on top of stack */
with REG
2007-11-02 18:56:58 +00:00
yields %1 %1
with FSREG
yields %1 %1
2007-11-02 18:56:58 +00:00
pat dup $1==INT64 /* Duplicate double-word on top of stack */
with REG REG
2007-11-02 18:56:58 +00:00
yields %2 %1 %2 %1
with FREG
yields %1 %1
2007-11-02 18:56:58 +00:00
pat exg $1==INT32 /* Exchange top two words on stack */
with REG REG
2007-11-02 18:56:58 +00:00
yields %1 %2
pat stl lol $1==$2 /* Store then load local */
leaving
dup 4
stl $1
pat sdl ldl $1==$2 /* Store then load double local */
leaving
dup 8
sdl $1
2007-11-02 18:56:58 +00:00
pat lal sti lal loi $1==$3 && $2==$4 /* Store then load local, of a different size */
leaving
dup INT32
lal $1
sti $2
pat ste loe $1==$2 /* Store then load external */
leaving
dup 4
ste $1
/* Type conversions */
pat loc loc cii loc loc cii $1==$4 && $2==$5 /* madness, generated by the C compiler */
leaving
loc $1
loc $2
cii
pat loc loc cii loc loc cii $2==INT32 && $5==INT32 && $4<$2 /* madness, generated by the C compiler */
leaving
loc $4
loc $5
cii
pat loc loc ciu /* signed X -> unsigned X */
leaving
loc $1
loc $2
cuu
pat loc loc cuu $1==$2 /* unsigned X -> unsigned X */
/* nop */
pat loc loc cii $1==$2 /* signed X -> signed X */
/* nop */
pat loc loc cui $1==$2 /* unsigned X -> signed X */
/* nop */
pat loc loc cui $1==INT8 && $2==INT32 /* unsigned char -> signed int */
/* nop */
pat loc loc cui $1==INT16 && $2==INT32 /* unsigned short -> signed int */
/* nop */
pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */
with GPR
yields {SEX_B, %1}
pat loc loc cii $1==2 && $2==4 /* signed char -> signed short */
with GPR
yields {SEX_H, %1}
/* Local variables */
pat lal /* Load address of local */
yields {SUM_RC, FP, $1}
pat lol inreg($1)>0 /* Load from local */
yields {LOCAL, $1}
pat lol /* Load from local */
leaving
lal $1
loi INT32
pat ldl /* Load double-word from local */
leaving
lal $1
loi INT32*2
pat stl inreg($1)>0 /* Store to local */
with CONST + LABEL + GPR + OP_ALL_W
kills regvar($1), LOCAL %off==$1
gen
move %1, {GPRE, regvar($1)}
pat stl /* Store to local */
leaving
lal $1
sti INT32
pat sdl /* Store double-word to local */
leaving
lal $1
sti INT32*2
pat lil inreg($1)>0 /* Load from indirected local */
uses REG
gen
lwz %a, {GPRINDIRECT, regvar($1), 0}
yields %a
pat lil /* Load from indirected local */
leaving
lol $1
loi INT32
pat sil /* Save to indirected local */
leaving
lol $1
sti INT32
2007-11-02 18:56:58 +00:00
pat zrl /* Zero local */
leaving
loc 0
stl $1
pat inl /* Increment local */
leaving
lol $1
loc 1
adi 4
stl $1
pat del /* Decrement local */
leaving
lol $1
loc 1
sbi 4
stl $1
/* Global variables */
pat lpi /* Load address of external function */
leaving
lae $1
pat lae /* Load address of external */
yields {LABEL, $1}
pat loe /* Load word external */
leaving
lae $1
loi INT32
pat ste /* Store word external */
leaving
lae $1
sti INT32
pat lde /* Load double-word external */
leaving
lae $1
loi INT64
pat sde /* Store double-word external */
leaving
lae $1
sti INT64
pat zre /* Zero external */
leaving
loc 0
ste $1
pat ine /* Increment external */
uses REG={LABEL, $1}, REG
gen
lwz %b, {GPRINDIRECT, %a, 0}
addi %b, %b, {CONST, 1}
stw %b, {GPRINDIRECT, %a, 0}
pat dee /* Decrement external */
uses REG={LABEL, $1}, REG
gen
lwz %b, {GPRINDIRECT, %a, 0}
addi %b, %b, {CONST, 0-1}
stw %b, {GPRINDIRECT, %a, 0}
/* Structures */
pat lof /* Load word offsetted */
leaving
adp $1
loi INT32
pat ldf /* Load double-word offsetted */
leaving
adp $1
loi INT64
pat stf /* Store word offsetted */
leaving
adp $1
sti INT32
pat sdf /* Store double-word offsetted */
leaving
adp $1
sti INT64
/* Loads and stores */
pat loi $1==INT8 /* Load byte indirect */
with GPR
uses REG
gen
lbz %a, {GPRINDIRECT, %1, 0}
yields %a
with SUM_RR
uses reusing %1, REG
gen
lbzx %a, %1.reg1, %1.reg2
yields %a
with SUM_RC
uses REG
gen
move {IND_RC_B, %1.reg, %1.off}, %a
yields %a
pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32 /* Load half-word indirect and sign extend */
with GPR
uses REG
gen
lha %a, {GPRINDIRECT, %1, 0}
yields %a
with SUM_RR
uses reusing %1, REG
gen
lhax %a, %1.reg1, %1.reg2
yields %a
with SUM_RC
uses REG
gen
move {IND_RC_H_S, %1.reg, %1.off}, %a
yields %a
pat loi $1==INT16 /* Load half-word indirect */
with GPR
uses REG
gen
lhz %a, {GPRINDIRECT, %1, 0}
yields %a
with SUM_RR
uses reusing %1, REG
gen
lhzx %a, %1.reg1, %1.reg2
yields %a
with SUM_RC
uses REG
gen
move {IND_RC_H, %1.reg, %1.off}, %a
yields %a
pat loi $1==INT32 /* Load word indirect */
with GPR
yields {IND_RC_W, %1, 0}
with SUM_RC
yields {IND_RC_W, %1.reg, %1.off}
with SUM_RR
yields {IND_RR_W, %1.reg1, %1.reg2}
with LABEL
yields {IND_LABEL_W, %1.adr}
pat loi $1==INT64 /* Load double-word indirect */
with GPR
yields {IND_RC_D, %1, 0}
with SUM_RC
yields {IND_RC_D, %1.reg, %1.off}
with SUM_RR
yields {IND_RR_D, %1.reg1, %1.reg2}
with LABEL
yields {IND_LABEL_D, %1.adr}
pat loi /* Load arbitrary size */
leaving
loc $1
los INT32
pat los /* Load arbitrary size */
with GPR3 GPR4 STACK
kills ALL
gen
bl {LABEL, ".los"}
pat sti $1==INT8 /* Store byte indirect */
with GPR GPR
gen
stb %2, {GPRINDIRECT, %1, 0}
with SUM_RR GPR
gen
stbx %2, %1.reg1, %1.reg2
with SUM_RC GPR
gen
move %2, {IND_RC_B, %1.reg, %1.off}
with GPR SEX_B
gen
stb %2.reg, {GPRINDIRECT, %1, 0}
with SUM_RR SEX_B
gen
stbx %2.reg, %1.reg1, %1.reg2
with SUM_RC SEX_B
gen
move %2.reg, {IND_RC_B, %1.reg, %1.off}
pat sti $1==INT16 /* Store half-word indirect */
with GPR GPR
gen
sth %2, {GPRINDIRECT, %1, 0}
with SUM_RR GPR
gen
sthx %2, %1.reg1, %1.reg2
with SUM_RC GPR
gen
move %2, {IND_RC_H, %1.reg, %1.off}
with GPR SEX_H
gen
sth %2.reg, {GPRINDIRECT, %1, 0}
with SUM_RR SEX_H
gen
sthx %2.reg, %1.reg1, %1.reg2
with SUM_RC SEX_H
gen
move %2.reg, {IND_RC_H, %1.reg, %1.off}
pat sti $1==INT32 /* Store word indirect */
with GPR GPR+FSREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_RC_W, %1, 0}
with SUM_RR GPR+FSREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_RR_W, %1.reg1, %1.reg2}
with SUM_RC GPR+FSREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_RC_W, %1.reg, %1.off}
with LABEL GPR+FSREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_LABEL_W, %1.adr}
pat sti $1==INT64 /* Store double-word indirect */
with GPR FREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_RC_D, %1, 0}
with SUM_RR FREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_RR_D, %1.reg1, %1.reg2}
with SUM_RC FREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_RC_D, %1.reg, %1.off}
with GPR GPR GPR
gen
stw %2, {GPRINDIRECT, %1, 0}
stw %3, {GPRINDIRECT, %1, 4}
with SUM_RC GPR GPR
gen
move %2, {IND_RC_W, %1.reg, %1.off}
move %3, {IND_RC_W, %1.reg, %1.off+4}
with LABEL FREG
2007-11-02 18:56:58 +00:00
gen
move %2, {IND_LABEL_D, %1.adr}
pat sti /* Store arbitrary size */
leaving
loc $1
sts INT32
pat sts /* Load arbitrary size */
with GPR3 GPR4 STACK
kills ALL
gen
bl {LABEL, ".sts"}
/* Arithmetic wrappers */
pat ads $1==4 /* Add var to pointer */
leaving adi $1
pat sbs $1==4 /* Subtract var from pointer */
leaving sbi $1
pat adp /* Add constant to pointer */
leaving
loc $1
adi 4
pat adu /* Add unsigned */
leaving
adi $1
pat sbu /* Subtract unsigned */
leaving
sbi $1
pat inc /* Add 1 */
leaving
loc 1
adi 4
pat dec /* Subtract 1 */
leaving
loc 1
sbi 4
pat loc mlu $2==2 /* Unsigned multiply by constant */
leaving
loc $1
mli 4
pat mlu /* Unsigned multiply by var */
leaving
mli $1
pat loc slu /* Shift left unsigned by constant amount */
leaving
loc $1
sli $2
pat slu /* Shift left unsigned by variable amount */
leaving
sli $1
/* Word arithmetic */
pat adi $1==4 /* Add word (second + top) */
with REG REG
yields {SUM_RR, %1, %2}
with CONST REG
yields {SUM_RC, %2, %1.val}
with REG CONST
yields {SUM_RC, %1, %2.val}
with CONST SUM_RC
yields {SUM_RC, %2.reg, %2.off+%1.val}
with CONST LABEL
yields {LABEL, %2.adr+%1.val}
pat sbi $1==4 /* Subtract word (second - top) */
with REG REG
uses reusing %2, REG
gen
subf %a, %1, %2
yields %a
with CONST REG
yields {SUM_RC, %2, 0-%1.val}
with CONST SUM_RC
yields {SUM_RC, %2.reg, %2.off-%1.val}
with CONST LABEL
yields {LABEL, %2.adr+(0-%1.val)}
pat ngi $1==4 /* Negate word */
with REG
uses reusing %1, REG
gen
neg %a, %1
yields %a
pat mli $1==4 /* Multiply word (second * top) */
with REG REG
uses reusing %2, REG
gen
mullw %a, %2, %1
yields %a
pat dvi $1==4 /* Divide word (second / top) */
with REG REG
uses reusing %2, REG
gen
divw %a, %2, %1
yields %a
pat dvu $1==4 /* Divide unsigned word (second / top) */
with REG REG
uses reusing %2, REG
gen
divwu %a, %2, %1
yields %a
pat rmi $1==4 /* Remainder word (second % top) */
with REG REG
uses REG
gen
divw %a, %2, %1
mullw %a, %a, %1
subf %a, %a, %2
yields %a
pat rmu $1==4 /* Remainder unsigned word (second % top) */
with REG REG
uses REG
gen
divwu %a, %2, %1
mullw %a, %a, %1
subf %a, %a, %2
yields %a
pat and $1==4 /* AND word */
with GPR NOT_R
uses reusing %1, REG
gen
andc %a, %1, %2.reg
yields %a
with NOT_R GPR
uses reusing %1, REG
gen
andc %a, %2, %1.reg
yields %a
with GPR GPR
yields {AND_RR, %1, %2}
with GPR CONST
yields {AND_RC, %1, %2.val}
with CONST GPR
yields {AND_RC, %2, %1.val}
pat and !defined($1) /* AND set */
with STACK
gen
bl {LABEL, ".and"}
pat ior $1==4 /* OR word */
with GPR NOT_R
uses reusing %1, REG
gen
orc %a, %1, %2.reg
yields %a
with NOT_R GPR
uses reusing %2, REG
gen
orc %a, %2, %1.reg
yields %a
with GPR GPR
yields {OR_RR, %1, %2}
with GPR CONST
yields {OR_RC, %1, %2.val}
with CONST GPR
yields {OR_RC, %2, %1.val}
pat ior !defined($1) /* OR set */
with STACK
gen
bl {LABEL, ".ior"}
pat xor $1==4 /* XOR word */
with GPR GPR
yields {XOR_RR, %1, %2}
with GPR CONST
yields {XOR_RC, %1, %2.val}
with CONST GPR
yields {XOR_RC, %2, %1.val}
pat xor !defined($1) /* XOR set */
with STACK
gen
bl {LABEL, ".xor"}
pat com $1==INT32 /* NOT word */
with AND_RR
uses REG
gen
nand %a, %1.reg1, %1.reg2
yields %a
with OR_RR
uses REG
gen
nor %a, %1.reg1, %1.reg2
yields %a
with XOR_RR
uses REG
gen
eqv %a, %1.reg1, %1.reg2
yields %a
with GPR
yields {NOT_R, %1}
pat com !defined($1) /* NOT set */
with STACK
gen
bl {LABEL, ".com"}
pat sli $1==4 /* Shift left (second << top) */
with CONST GPR
uses reusing %2, REG
gen
rlwinm %a, %2, {CONST, (%1.val & 0x1F)}, {CONST, 0}, {CONST, 31-(%1.val & 0x1F)}
yields %a
with GPR GPR
uses reusing %2, REG
gen
slw %a, %2, %1
yields %a
pat sri $1==4 /* Shift right signed (second >> top) */
with CONST GPR
uses reusing %2, REG
gen
srawi %a, %2, {CONST, %1.val & 0x1F}
yields %a
with GPR GPR
uses reusing %2, REG
gen
sraw %a, %2, %1
yields %a
pat sru $1==4 /* Shift right unsigned (second >> top) */
with CONST GPR
uses reusing %2, REG
gen
rlwinm %a, %2, {CONST, 32-(%1.val & 0x1F)}, {CONST, (%1.val & 0x1F)}, {CONST, 31}
yields %a
with GPR GPR
uses reusing %2, REG
gen
srw %a, %2, %1
yields %a
/* Arrays */
pat aar $1==INT32 /* Index array */
with GPR3 GPR4 GPR5
gen
bl {LABEL, ".aar4"}
yields R3
pat lae lar $2==INT32 && nicesize(rom($1, 3)) /* Load array */
leaving
lae $1
aar INT32
loi rom($1, 3)
pat lar $1==INT32 /* Load array */
with GPR3 GPR4 GPR5 STACK
kills ALL
gen
bl {LABEL, ".lar4"}
pat lae sar $2==INT32 && nicesize(rom($1, 3)) /* Store array */
leaving
lae $1
aar INT32
sti rom($1, 3)
pat sar $1==INT32 /* Store array */
with GPR3 GPR4 GPR5 STACK
kills ALL
gen
bl {LABEL, ".sar4"}
/* Sets */
pat set defined($1) /* Create word with set bit */
leaving
loc 1
exg INT32
sli INT32
pat set !defined($1) /* Create structure with set bit (variable) */
with GPR3 GPR4 STACK
gen
bl {LABEL, ".set"}
pat inn defined($1) /* Test for set bit */
leaving
set INT32
and INT32
pat inn !defined($1) /* Test for set bit (variable) */
with GPR3 STACK
gen
bl {LABEL, ".inn"}
/* Boolean resolutions */
pat teq /* top = (top == 0) */
with TRISTATE_ALL + GPR
uses reusing %1, REG
gen
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".teq_table"}, %a
lwzx %a, %a, RSCRATCH
2007-11-02 18:56:58 +00:00
yields %a
pat tne /* top = (top != 0) */
with TRISTATE_ALL + GPR
uses reusing %1, REG
gen
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".tne_table"}, %a
lwzx %a, %a, RSCRATCH
2007-11-02 18:56:58 +00:00
yields %a
pat tlt /* top = (top < 0) */
with TRISTATE_ALL + GPR
uses reusing %1, REG
gen
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".tlt_table"}, %a
lwzx %a, %a, RSCRATCH
2007-11-02 18:56:58 +00:00
yields %a
pat tle /* top = (top <= 0) */
with TRISTATE_ALL + GPR
uses reusing %1, REG
gen
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".tle_table"}, %a
lwzx %a, %a, RSCRATCH
2007-11-02 18:56:58 +00:00
yields %a
pat tgt /* top = (top > 0) */
with TRISTATE_ALL + GPR
uses reusing %1, REG
gen
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".tgt_table"}, %a
lwzx %a, %a, RSCRATCH
2007-11-02 18:56:58 +00:00
yields %a
pat tge /* top = (top >= 0) */
with TRISTATE_ALL + GPR
uses reusing %1, REG
gen
move %1, C0
move C0, RSCRATCH
2007-11-02 18:56:58 +00:00
move {LABEL, ".tge_table"}, %a
lwzx %a, %a, RSCRATCH
2007-11-02 18:56:58 +00:00
yields %a
/* Simple branches */
pat zeq /* Branch if signed top == 0 */
with TRISTATE_ALL+GPR STACK
gen
move %1, C0
bc IFTRUE, EQ, {LABEL, $1}
pat beq
leaving
cmi INT32
zeq $1
pat zne /* Branch if signed top != 0 */
with TRISTATE_ALL+GPR STACK
gen
move %1, C0
bc IFFALSE, EQ, {LABEL, $1}
pat bne
leaving
cmi INT32
zne $1
pat zgt /* Branch if signed top > 0 */
with TRISTATE_ALL+GPR STACK
gen
move %1, C0
bc IFTRUE, GT, {LABEL, $1}
pat bgt
leaving
cmi INT32
zgt $1
pat zge /* Branch if signed top >= 0 */
with TRISTATE_ALL+GPR STACK
gen
move %1, C0
bc IFFALSE, LT, {LABEL, $1}
pat bge
leaving
cmi INT32
zge $1
pat zlt /* Branch if signed top < 0 */
with TRISTATE_ALL+GPR STACK
gen
move %1, C0
bc IFTRUE, LT, {LABEL, $1}
pat blt
leaving
cmi INT32
zlt $1
pat zle /* Branch if signed top >= 0 */
with TRISTATE_ALL+GPR STACK
gen
move %1, C0
bc IFFALSE, GT, {LABEL, $1}
pat ble
leaving
cmi INT32
zle $1
/* Compare and jump */
pat cmi /* Signed tristate compare */
with CONST GPR
yields {TRISTATE_RC_S, %2, %1.val}
with GPR GPR
yields {TRISTATE_RR_S, %2, %1}
pat cmu /* Unsigned tristate compare */
with CONST GPR
yields {TRISTATE_RC_U, %2, %1.val}
with GPR GPR
yields {TRISTATE_RR_U, %2, %1}
pat cmp /* Compare pointers */
leaving
cmu INT32
pat cms $1==INT32 /* Compare blocks (word sized) */
leaving
cmi INT32
/* Other branching and labelling */
pat lab topeltsize($1)==4 && !fallthrough($1)
gen
labeldef $1
yields R3
pat lab topeltsize($1)==4 && fallthrough($1)
with GPR3
gen
labeldef $1
yields %1
pat lab topeltsize($1)!=4
with STACK
kills ALL
gen
labeldef $1
pat bra topeltsize($1)==4 /* Unconditional jump with TOS GPRister */
with GPR3 STACK
gen
b {LABEL, $1}
pat bra topeltsize($1)!=4 /* Unconditional jump without TOS GPRister */
with STACK
gen
b {LABEL, $1}
/* Miscellaneous */
pat cal /* Call procedure */
with STACK
kills ALL
gen
bl {LABEL, $1}
pat cai /* Call procedure indirect */
with GPR STACK
kills ALL
gen
mtspr CTR, %1
bcctrl ALWAYS, {CONST, 0}, {CONST, 0}
pat lfr $1==INT32 /* Load function result, word */
yields R3
pat lfr $1==INT64 /* Load function result, double-word */
yields R4 R3
pat ret $1==0 /* Return from procedure */
gen
return
b {LABEL, ".ret"}
pat ret $1==INT32 /* Return from procedure, word */
with GPR3
gen
return
b {LABEL, ".ret"}
pat ret $1==INT64 /* Return from procedure, double-word */
with GPR3 GPR4
gen
return
b {LABEL, ".ret"}
pat blm /* Block move constant length */
with GPR GPR STACK
uses REG
gen
move {CONST, $1}, %a
stwu %a, {GPRINDIRECT, SP, 0-4}
stwu %2, {GPRINDIRECT, SP, 0-4}
stwu %1, {GPRINDIRECT, SP, 0-4}
bl {LABEL, "_memmove"}
addi SP, SP, {CONST, 12}
pat bls /* Block move variable length */
with GPR GPR GPR STACK
gen
stwu %1, {GPRINDIRECT, SP, 0-4}
stwu %3, {GPRINDIRECT, SP, 0-4}
stwu %2, {GPRINDIRECT, SP, 0-4}
bl {LABEL, "_memmove"}
addi SP, SP, {CONST, 12}
pat csa /* Array-lookup switch */
with GPR3 GPR4 STACK
gen
b {LABEL, ".csa"}
pat csb /* Table-lookup switch */
with GPR3 GPR4 STACK
gen
b {LABEL, ".csb"}
/* EM specials */
pat fil /* Set current filename */
leaving
lae $1
ste "hol0+4"
2007-11-02 18:56:58 +00:00
pat lin /* Set current line number */
leaving
loc $1
ste "hol0"
2007-11-02 18:56:58 +00:00
pat lni /* Increment line number */
leaving
ine "hol0"
2007-11-02 18:56:58 +00:00
pat lim /* Load EM trap ignore mask */
leaving
lde ".ignmask"
pat sim /* Store EM trap ignore mask */
leaving
ste ".ignmask"
pat trp /* Raise EM trap */
with GPR3
gen
bl {LABEL, ".trap"}
pat sig /* Set trap handler */
leaving
ste ".trppc"
pat rtt /* Return from trap */
leaving
ret 0
pat lxl $1==0 /* Load FP */
leaving
lor 0
pat lxl $1==1 /* Load caller's FP */
leaving
lxl 0
dch
pat dch /* FP -> caller FP */
with GPR
uses reusing %1, REG
gen
lwz %a, {GPRINDIRECT, %1, FP_OFFSET}
yields %a
pat lpb /* Convert FP to argument address */
leaving
adp EM_BSIZE
pat lxa /* Load caller's SP */
leaving
lxl $1
lpb
pat gto /* longjmp */
uses REG
gen
move {LABEL, $1}, %a
move {IND_RC_W, %a, 8}, FP
move {IND_RC_W, %a, 4}, SP
move {IND_RC_W, %a, 0}, %a
mtspr CTR, %a
bcctr ALWAYS, {CONST, 0}, {CONST, 0}
#if 0
pat gto /* longjmp */
with STACK
gen
ld {LABEL, $1+2}
wspec {CONST, 1}
ld {LABEL, $1+4}
wspec {CONST, 0}
ld {LABEL, $1+0}
wspec {CONST, 2}
pat str $1==1 /* Store special GPRister */
with GPR0
gen
wspec {CONST, $1}
#endif
pat lor $1==0 /* Load FP */
uses REG
gen
move FP, %a
yields %a
pat lor $1==1 /* Load SP */
uses REG
gen
move SP, %a
yields %a
pat lor $1==2 /* Load HP */
leaving
loe ".reghp"
pat str $1==0 /* Store FP */
with GPR
gen
move %1, FP
pat str $1==1 /* Store SP */
with GPR
gen
move %1, SP
pat str $1==2 /* Store HP */
leaving
ste ".reghp"
pat loc ass $1==4 /* Drop 4 bytes from stack */
with exact GPR
/* nop */
with STACK
gen
addi SP, SP, {CONST, 4}
2007-11-02 18:56:58 +00:00
pat ass /* Adjust stack by variable amount */
with CONST STACK
2007-11-02 18:56:58 +00:00
gen
move {SUM_RC, SP, %1.val}, {GPRE, SP}
with GPR STACK
2007-11-02 18:56:58 +00:00
gen
move {SUM_RR, SP, %1}, {GPRE, SP}
pat asp /* Adjust stack by constant amount */
leaving
loc $1
ass
/* Floating point support */
/* All very cheap and nasty --- this needs to be properly integrated into
* the code generator. ncg doesn't like having separate FPU registers. */
2007-11-02 18:56:58 +00:00
/* Single-precision */
pat zrf $1==INT32 /* Push zero */
leaving
loe ".fs_00000000"
pat adf $1==INT32 /* Add single */
with FSREG FSREG
uses reusing %1, FSREG
2007-11-02 18:56:58 +00:00
gen
fadds %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat sbf $1==INT32 /* Subtract single */
with FSREG FSREG
uses reusing %1, FSREG
2007-11-02 18:56:58 +00:00
gen
fsubs %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat mlf $1==INT32 /* Multiply single */
with FSREG FSREG
uses reusing %1, FSREG
2007-11-02 18:56:58 +00:00
gen
fmuls %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat dvf $1==INT32 /* Divide single */
with FSREG FSREG
uses reusing %1, FSREG
2007-11-02 18:56:58 +00:00
gen
fdivs %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat ngf $1==INT32 /* Negate single */
with FSREG
uses reusing %1, FSREG
2007-11-02 18:56:58 +00:00
gen
fneg %a, %1
yields %a
2007-11-02 18:56:58 +00:00
pat cmf $1==INT32 /* Compare single */
with FSREG FSREG
yields {TRISTATE_FF, %2.1, %1.1}
2007-11-02 18:56:58 +00:00
pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */
with FSREG
yields %1.1
2007-11-02 18:56:58 +00:00
pat loc loc cfu $1==INT32 && $2==INT32 /* Convert single to unsigned int */
with STACK
gen
bl {LABEL, ".cfu4"}
pat loc loc cfi $1==INT32 && $2==INT32 /* Convert single to signed int */
with STACK
gen
bl {LABEL, ".cfi4"}
pat loc loc cif $1==INT32 && $2==INT32 /* Convert integer to single */
with STACK
gen
bl {LABEL, ".cif4"}
pat loc loc cuf $1==INT32 && $2==INT32 /* Convert unsigned int to single */
with STACK
gen
bl {LABEL, ".cuf4"}
pat fef $1==INT32 /* Split single */
with STACK
gen
bl {LABEL, ".fef4"}
/* Double-precision */
pat zrf $1==INT64 /* Push zero */
leaving
lde ".fd_00000000"
pat adf $1==INT64 /* Add double */
with FREG FREG
2007-11-02 18:56:58 +00:00
uses FREG
gen
fadd %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat sbf $1==INT64 /* Subtract double */
with FREG FREG
2007-11-02 18:56:58 +00:00
uses FREG
gen
fsub %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat mlf $1==INT64 /* Multiply double */
with FREG FREG
2007-11-02 18:56:58 +00:00
uses reusing %1, FREG
gen
fmul %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat dvf $1==INT64 /* Divide double */
with FREG FREG
2007-11-02 18:56:58 +00:00
uses reusing %1, FREG
gen
fdiv %a, %2, %1
yields %a
2007-11-02 18:56:58 +00:00
pat ngf $1==INT64 /* Negate double */
with FREG
2007-11-02 18:56:58 +00:00
uses reusing %1, FREG
gen
fneg %a, %1
yields %a
2007-11-02 18:56:58 +00:00
pat cmf $1==INT64 /* Compare double */
with FREG FREG
yields {TRISTATE_FF, %2, %1}
2007-11-02 18:56:58 +00:00
pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */
with FREG
uses reusing %1, FSREG
2007-11-02 18:56:58 +00:00
gen
frsp %a, %1
yields %a
2007-11-02 18:56:58 +00:00
pat loc loc cfu $1==INT64 && $2==INT32 /* Convert double to unsigned int */
with STACK
gen
bl {LABEL, ".cfu8"}
pat loc loc cfi $1==INT64 && $2==INT32 /* Convert double to signed int */
with STACK
gen
bl {LABEL, ".cfi8"}
pat loc loc cif $1==INT32 && $2==INT64 /* Convert integer to double */
with STACK
kills ALL
gen
bl {LABEL, ".cif8"}
pat loc loc cuf $1==INT32 && $2==INT64 /* Convert unsigned int to double */
with STACK
gen
bl {LABEL, ".cuf8"}
pat fef $1==INT64 /* Split double */
with GPR3 GPR4
kills FPR0, FPR1, GPR6, GPR7
2007-11-02 18:56:58 +00:00
gen
bl {LABEL, ".fef8"}
yields R4 R3 R5
2007-11-02 18:56:58 +00:00
pat fif $1==INT64 /* Multiply and split double (?) */
with STACK
gen
bl {LABEL, ".fif8"}