Add FRAME_V tokens for local variables.
When storing to a local, stop killing the tokens of other locals, unless they might overlap with the stored local. This helps some procedures that juggle locals when the locals aren't in registers. Also use FRAME_V tokens for locals in statically enclosing procedures. Rewrite _lxa_ as _lxl_, to skip the `addi ?,?,8` if we can add 8 to the next constant. The PowerPC code from _lxl_ is now sometimes better, sometimes worse than before. The i386 table provided the idea to use %size to find overlapping locals.
This commit is contained in:
parent
4bb31c296d
commit
2eeee36f78
|
@ -9,7 +9,6 @@ INT64 = 8
|
||||||
|
|
||||||
FP_OFFSET = 0 /* Offset of saved FP relative to our FP */
|
FP_OFFSET = 0 /* Offset of saved FP relative to our FP */
|
||||||
PC_OFFSET = 4 /* Offset of saved PC relative to our FP */
|
PC_OFFSET = 4 /* Offset of saved PC relative to our FP */
|
||||||
SL_OFFSET = 8 /* Offset of static link */
|
|
||||||
|
|
||||||
#define COMMENT(n) /* comment {LABEL, n} */
|
#define COMMENT(n) /* comment {LABEL, n} */
|
||||||
|
|
||||||
|
@ -19,6 +18,12 @@ SL_OFFSET = 8 /* Offset of static link */
|
||||||
#define smalls(n) sfit(n, 16)
|
#define smalls(n) sfit(n, 16)
|
||||||
#define smallu(n) ufit(n, 16)
|
#define smallu(n) ufit(n, 16)
|
||||||
|
|
||||||
|
/* Finds FRAME_V tokens that overlap myoff, mysize. */
|
||||||
|
#define fover(myoff, mysize) (%off+%size>(myoff) && %off<((myoff)+(mysize)))
|
||||||
|
|
||||||
|
/* Checks if we can use {LXFRAME, x}. */
|
||||||
|
#define nicelx(x) ((x)>=1 && (x)<=0x8000)
|
||||||
|
|
||||||
#define lo(n) ((n) & 0xFFFF)
|
#define lo(n) ((n) & 0xFFFF)
|
||||||
#define hi(n) (((n)>>16) & 0xFFFF)
|
#define hi(n) (((n)>>16) & 0xFFFF)
|
||||||
|
|
||||||
|
@ -138,6 +143,8 @@ TOKENS
|
||||||
DIV_RR = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 signed */
|
DIV_RR = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 signed */
|
||||||
DIV_RR_U = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 unsigned */
|
DIV_RR_U = { GPR reg1; GPR reg2; } 4. /* reg1 / reg2 unsigned */
|
||||||
|
|
||||||
|
/* Indirect loads and stores */
|
||||||
|
|
||||||
IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")".
|
IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")".
|
||||||
IND_RL_B = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")".
|
IND_RL_B = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")".
|
||||||
IND_RR_B = { GPR reg1; GPR reg2; } 4.
|
IND_RR_B = { GPR reg1; GPR reg2; } 4.
|
||||||
|
@ -154,6 +161,23 @@ TOKENS
|
||||||
IND_RL_D = { GPR reg; ADDR adr; } 8 "lo16[" adr "](" reg ")".
|
IND_RL_D = { GPR reg; ADDR adr; } 8 "lo16[" adr "](" reg ")".
|
||||||
IND_RR_D = { GPR reg1; GPR reg2; } 8.
|
IND_RR_D = { GPR reg1; GPR reg2; } 8.
|
||||||
|
|
||||||
|
/* Local variables in frame */
|
||||||
|
|
||||||
|
FRAME_B = { INT level; GPR reg; INT off; INT size; }
|
||||||
|
4 off "(" reg ")".
|
||||||
|
FRAME_H = { INT level; GPR reg; INT off; INT size; }
|
||||||
|
4 off "(" reg ")".
|
||||||
|
FRAME_H_S = { INT level; GPR reg; INT off; INT size; }
|
||||||
|
4 off "(" reg ")".
|
||||||
|
FRAME_W = { INT level; GPR reg; INT off; INT size; }
|
||||||
|
4 off "(" reg ")".
|
||||||
|
FRAME_D = { INT level; GPR reg; INT off; INT size; }
|
||||||
|
8 off "(" reg ")".
|
||||||
|
|
||||||
|
LXFRAME = { INT level; } 4.
|
||||||
|
|
||||||
|
/* Bitwise logic */
|
||||||
|
|
||||||
NOT_R = { GPR reg; } 4. /* ~reg */
|
NOT_R = { GPR reg; } 4. /* ~reg */
|
||||||
AND_RIS = { GPR reg; INT valhi; } 4.
|
AND_RIS = { GPR reg; INT valhi; } 4.
|
||||||
AND_RC = { GPR reg; INT val; } 4.
|
AND_RC = { GPR reg; INT val; } 4.
|
||||||
|
@ -170,6 +194,8 @@ TOKENS
|
||||||
NOR_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 | reg2) */
|
NOR_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 | reg2) */
|
||||||
EQV_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 ^ reg2) */
|
EQV_RR = { GPR reg1; GPR reg2; } 4. /* ~(reg1 ^ reg2) */
|
||||||
|
|
||||||
|
/* Comparisons */
|
||||||
|
|
||||||
COND_RC = { GPR reg; INT val; } 4.
|
COND_RC = { GPR reg; INT val; } 4.
|
||||||
COND_RR = { GPR reg1; GPR reg2; } 4.
|
COND_RR = { GPR reg1; GPR reg2; } 4.
|
||||||
CONDL_RC = { GPR reg; INT val; } 4.
|
CONDL_RC = { GPR reg; INT val; } 4.
|
||||||
|
@ -200,27 +226,37 @@ SETS
|
||||||
|
|
||||||
CONST = C + CONST_STACK.
|
CONST = C + CONST_STACK.
|
||||||
|
|
||||||
IND_ALL_B = IND_RC_B + IND_RL_B + IND_RR_B.
|
SET_RC_B = IND_RC_B + IND_RL_B + FRAME_B.
|
||||||
IND_ALL_H = IND_RC_H + IND_RL_H + IND_RR_H +
|
SET_RC_H = IND_RC_H + IND_RL_H + FRAME_H.
|
||||||
IND_RC_H_S + IND_RL_H_S + IND_RR_H_S.
|
SET_RC_H_S = IND_RC_H_S + IND_RL_H_S + FRAME_H_S.
|
||||||
IND_ALL_W = IND_RC_W + IND_RL_W + IND_RR_W.
|
SET_RC_W = IND_RC_W + IND_RL_W + FRAME_W.
|
||||||
IND_ALL_D = IND_RC_D + IND_RL_D + IND_RR_D.
|
SET_RC_D = IND_RC_D + IND_RL_D + FRAME_D.
|
||||||
|
|
||||||
|
IND_ALL_B = IND_RC_B + IND_RL_B + IND_RR_B.
|
||||||
|
IND_ALL_H = IND_RC_H + IND_RL_H + IND_RR_H +
|
||||||
|
IND_RC_H_S + IND_RL_H_S + IND_RR_H_S.
|
||||||
|
IND_ALL_W = IND_RC_W + IND_RL_W + IND_RR_W.
|
||||||
|
IND_ALL_D = IND_RC_D + IND_RL_D + IND_RR_D.
|
||||||
|
IND_V = IND_ALL_B + IND_ALL_H + IND_ALL_W + IND_ALL_D.
|
||||||
|
|
||||||
|
FRAME_V = FRAME_B + FRAME_H + FRAME_H_S + FRAME_W + FRAME_D.
|
||||||
|
|
||||||
/* anything killed by sti (store indirect) */
|
/* anything killed by sti (store indirect) */
|
||||||
MEMORY = IND_ALL_B + IND_ALL_H + IND_ALL_W + IND_ALL_D.
|
MEMORY = IND_V + FRAME_V.
|
||||||
|
|
||||||
/* any integer from stack that we can easily move to GPR */
|
/* any integer from stack that we can easily move to GPR */
|
||||||
INT_W = REG + CONST_STACK + SEX_B + SEX_H +
|
INT_W = REG + CONST_STACK + SEX_B + SEX_H +
|
||||||
SUM_RIS + SUM_RC + SUM_RL + SUM_RR +
|
SUM_RIS + SUM_RC + SUM_RL + SUM_RR +
|
||||||
SUB_RR + NEG_R + MUL_RR + DIV_RR + DIV_RR_U +
|
SUB_RR + NEG_R + MUL_RR + DIV_RR + DIV_RR_U +
|
||||||
IND_ALL_B + IND_ALL_H + IND_ALL_W +
|
IND_ALL_B + IND_ALL_H + IND_ALL_W +
|
||||||
|
FRAME_B + FRAME_H + FRAME_H_S + FRAME_W +
|
||||||
NOT_R + AND_RIS + AND_RC + AND_RR + ANDC_RR +
|
NOT_R + AND_RIS + AND_RC + AND_RR + ANDC_RR +
|
||||||
OR_RIS + OR_RC + OR_RR + ORC_RR +
|
OR_RIS + OR_RC + OR_RR + ORC_RR +
|
||||||
XOR_RIS + XOR_RC + XOR_RR + NAND_RR + NOR_RR + EQV_RR +
|
XOR_RIS + XOR_RC + XOR_RR + NAND_RR + NOR_RR + EQV_RR +
|
||||||
XEQ + XNE + XGT + XGE + XLT + XLE.
|
XEQ + XNE + XGT + XGE + XLT + XLE.
|
||||||
|
|
||||||
FLOAT_D = FREG + IND_ALL_D.
|
FLOAT_D = FREG + IND_ALL_D + FRAME_D.
|
||||||
FLOAT_W = FSREG + IND_ALL_W.
|
FLOAT_W = FSREG + IND_ALL_W + FRAME_W.
|
||||||
|
|
||||||
|
|
||||||
INSTRUCTIONS
|
INSTRUCTIONS
|
||||||
|
@ -293,21 +329,21 @@ INSTRUCTIONS
|
||||||
frsp FSREG+LOCAL:wo, FREG:ro cost(4, 5).
|
frsp FSREG+LOCAL:wo, FREG:ro cost(4, 5).
|
||||||
fsub FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 5).
|
fsub FREG+DLOCAL:wo, FREG:ro, FREG:ro cost(4, 5).
|
||||||
fsubs FSREG+LOCAL:wo, FSREG:ro, FSREG:ro cost(4, 5).
|
fsubs FSREG+LOCAL:wo, FSREG:ro, FSREG:ro cost(4, 5).
|
||||||
lbz GPR:wo, IND_RC_B+IND_RL_B:ro cost(4, 3).
|
lbz GPR:wo, SET_RC_B:ro cost(4, 3).
|
||||||
lbzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
lbzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
||||||
lfd FPR+DLOCAL:wo, IND_RC_D+IND_RL_D:ro cost(4, 5).
|
lfd FPR+DLOCAL:wo, SET_RC_D:ro cost(4, 5).
|
||||||
lfdu FPR:wo, IND_RC_D:ro cost(4, 5).
|
lfdu FPR:wo, IND_RC_D:ro cost(4, 5).
|
||||||
lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5).
|
lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5).
|
||||||
lfs FSREG+LOCAL:wo, IND_RC_W+IND_RL_W:ro cost(4, 4).
|
lfs FSREG+LOCAL:wo, SET_RC_W:ro cost(4, 4).
|
||||||
lfsu FSREG:wo, IND_RC_W:rw cost(4, 4).
|
lfsu FSREG:wo, IND_RC_W:rw cost(4, 4).
|
||||||
lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4).
|
lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4).
|
||||||
lha GPR:wo, IND_RC_H_S+IND_RL_H_S:ro cost(4, 3).
|
lha GPR:wo, SET_RC_H_S:ro cost(4, 3).
|
||||||
lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
||||||
lhz GPR:wo, IND_RC_H+IND_RL_H:ro cost(4, 3).
|
lhz GPR:wo, SET_RC_H:ro cost(4, 3).
|
||||||
lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
||||||
lwzu GPR:wo, IND_RC_W:rw cost(4, 3).
|
lwzu GPR:wo, IND_RC_W:rw cost(4, 3).
|
||||||
lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3).
|
||||||
lwz GPR+LOCAL:wo, IND_RC_W+IND_RL_W:ro cost(4, 3).
|
lwz GPR+LOCAL:wo, SET_RC_W:ro cost(4, 3).
|
||||||
mfcr GPR:wo cost(4,2).
|
mfcr GPR:wo cost(4,2).
|
||||||
mfspr GPR:wo, SPR:ro cost(4, 3).
|
mfspr GPR:wo, SPR:ro cost(4, 3).
|
||||||
mtspr SPR:wo, GPR:ro cost(4, 2).
|
mtspr SPR:wo, GPR:ro cost(4, 2).
|
||||||
|
@ -336,17 +372,17 @@ INSTRUCTIONS
|
||||||
sraw GPR+LOCAL:wo, GPR:ro, GPR:ro cost(4, 2).
|
sraw GPR+LOCAL:wo, GPR:ro, GPR:ro cost(4, 2).
|
||||||
srawi GPR+LOCAL:wo, GPR:ro, CONST:ro cost(4, 2).
|
srawi GPR+LOCAL:wo, GPR:ro, CONST:ro cost(4, 2).
|
||||||
srw GPR+LOCAL:wo, GPR:ro, GPR:ro.
|
srw GPR+LOCAL:wo, GPR:ro, GPR:ro.
|
||||||
stb GPR:ro, IND_RC_B+IND_RL_B:rw cost(4, 3).
|
stb GPR:ro, SET_RC_B:rw cost(4, 3).
|
||||||
stbx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
|
stbx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
|
||||||
stfd FPR:ro, IND_RC_D+IND_RL_D:rw cost(4, 4).
|
stfd FPR:ro, SET_RC_D:rw cost(4, 4).
|
||||||
stfdu FPR:ro, IND_RC_D:rw cost(4, 4).
|
stfdu FPR:ro, IND_RC_D:rw cost(4, 4).
|
||||||
stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4).
|
stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4).
|
||||||
stfs FSREG:ro, IND_RC_W+IND_RL_W:rw cost(4, 3).
|
stfs FSREG:ro, SET_RC_W:rw cost(4, 3).
|
||||||
stfsu FSREG:ro, IND_RC_W:rw cost(4, 3).
|
stfsu FSREG:ro, IND_RC_W:rw cost(4, 3).
|
||||||
stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3).
|
stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3).
|
||||||
sth GPR:ro, IND_RC_H+IND_RL_H:rw cost(4, 3).
|
sth GPR:ro, SET_RC_H:rw cost(4, 3).
|
||||||
sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
|
sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
|
||||||
stw GPR:ro, IND_RC_W+IND_RL_W:rw cost(4, 3).
|
stw GPR:ro, SET_RC_W:rw cost(4, 3).
|
||||||
stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
|
stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3).
|
||||||
stwu GPR:ro, IND_RC_W:rw cost(4, 3).
|
stwu GPR:ro, IND_RC_W:rw cost(4, 3).
|
||||||
xor GPR:wo, GPR:ro, GPR:ro.
|
xor GPR:wo, GPR:ro, GPR:ro.
|
||||||
|
@ -439,7 +475,7 @@ MOVES
|
||||||
|
|
||||||
/* Read byte */
|
/* Read byte */
|
||||||
|
|
||||||
from IND_RC_B+IND_RL_B to GPR
|
from SET_RC_B to GPR
|
||||||
gen lbz %2, %1
|
gen lbz %2, %1
|
||||||
|
|
||||||
from IND_RR_B to GPR
|
from IND_RR_B to GPR
|
||||||
|
@ -447,7 +483,7 @@ MOVES
|
||||||
|
|
||||||
/* Write byte */
|
/* Write byte */
|
||||||
|
|
||||||
from GPR to IND_RC_B+IND_RL_B
|
from GPR to SET_RC_B
|
||||||
gen stb %1, %2
|
gen stb %1, %2
|
||||||
|
|
||||||
from GPR to IND_RR_B
|
from GPR to IND_RR_B
|
||||||
|
@ -455,13 +491,13 @@ MOVES
|
||||||
|
|
||||||
/* Read halfword (short) */
|
/* Read halfword (short) */
|
||||||
|
|
||||||
from IND_RC_H+IND_RL_H to GPR
|
from SET_RC_H to GPR
|
||||||
gen lhz %2, %1
|
gen lhz %2, %1
|
||||||
|
|
||||||
from IND_RR_H to GPR
|
from IND_RR_H to GPR
|
||||||
gen lhzx %2, %1.reg1, %1.reg2
|
gen lhzx %2, %1.reg1, %1.reg2
|
||||||
|
|
||||||
from IND_RC_H_S+IND_RL_H_S to GPR
|
from SET_RC_H_S to GPR
|
||||||
gen lha %2, %1
|
gen lha %2, %1
|
||||||
|
|
||||||
from IND_RR_H_S to GPR
|
from IND_RR_H_S to GPR
|
||||||
|
@ -469,7 +505,7 @@ MOVES
|
||||||
|
|
||||||
/* Write halfword */
|
/* Write halfword */
|
||||||
|
|
||||||
from GPR to IND_RC_H+IND_RL_H
|
from GPR to SET_RC_H
|
||||||
gen sth %1, %2
|
gen sth %1, %2
|
||||||
|
|
||||||
from GPR to IND_RR_H
|
from GPR to IND_RR_H
|
||||||
|
@ -477,13 +513,13 @@ MOVES
|
||||||
|
|
||||||
/* Read word */
|
/* Read word */
|
||||||
|
|
||||||
from IND_RC_W+IND_RL_W to GPR
|
from SET_RC_W to GPR
|
||||||
gen lwz %2, %1
|
gen lwz %2, %1
|
||||||
|
|
||||||
from IND_RR_W to GPR
|
from IND_RR_W to GPR
|
||||||
gen lwzx %2, %1.reg1, %1.reg2
|
gen lwzx %2, %1.reg1, %1.reg2
|
||||||
|
|
||||||
from IND_RC_W+IND_RL_W to FSREG
|
from SET_RC_W to FSREG
|
||||||
gen lfs %2, %1
|
gen lfs %2, %1
|
||||||
|
|
||||||
from IND_RR_W to FSREG
|
from IND_RR_W to FSREG
|
||||||
|
@ -491,13 +527,13 @@ MOVES
|
||||||
|
|
||||||
/* Write word */
|
/* Write word */
|
||||||
|
|
||||||
from GPR to IND_RC_W+IND_RL_W
|
from GPR to SET_RC_W
|
||||||
gen stw %1, %2
|
gen stw %1, %2
|
||||||
|
|
||||||
from GPR to IND_RR_W
|
from GPR to IND_RR_W
|
||||||
gen stwx %1, %2.reg1, %2.reg2
|
gen stwx %1, %2.reg1, %2.reg2
|
||||||
|
|
||||||
from FSREG to IND_RC_W+IND_RL_W
|
from FSREG to SET_RC_W
|
||||||
gen stfs %1, %2
|
gen stfs %1, %2
|
||||||
|
|
||||||
from FSREG to IND_RR_W
|
from FSREG to IND_RR_W
|
||||||
|
@ -505,7 +541,7 @@ MOVES
|
||||||
|
|
||||||
/* Read double */
|
/* Read double */
|
||||||
|
|
||||||
from IND_RC_D+IND_RL_D to FPR
|
from SET_RC_D to FPR
|
||||||
gen lfd %2, %1
|
gen lfd %2, %1
|
||||||
|
|
||||||
from IND_RR_D to FPR
|
from IND_RR_D to FPR
|
||||||
|
@ -513,12 +549,41 @@ MOVES
|
||||||
|
|
||||||
/* Write double */
|
/* Write double */
|
||||||
|
|
||||||
from FPR to IND_RC_D+IND_RL_D
|
from FPR to SET_RC_D
|
||||||
gen stfd %1, %2
|
gen stfd %1, %2
|
||||||
|
|
||||||
from FPR to IND_RR_D
|
from FPR to IND_RR_D
|
||||||
gen stfdx %1, %2.reg1, %2.reg2
|
gen stfdx %1, %2.reg1, %2.reg2
|
||||||
|
|
||||||
|
/* LXFRAME is a lexical frame from the static chain. We define a move
|
||||||
|
so "uses REG={LXFRAME, $1}" may find a register with the same
|
||||||
|
frame, and not repeat the move. This move can't search for a REG
|
||||||
|
with {LXFRAME, $1-1}, but must always start from fp. The static
|
||||||
|
chain, if it exists, is the argument at fp + EM_BSIZE. */
|
||||||
|
|
||||||
|
from LXFRAME %level==1 to REG
|
||||||
|
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
|
||||||
|
from LXFRAME %level==2 to REG
|
||||||
|
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
|
||||||
|
/* PowerPC can't add r0 + EM_BSIZE,
|
||||||
|
* so %2 must not be r0. */
|
||||||
|
lwz %2, {IND_RC_W, %2, EM_BSIZE}
|
||||||
|
from LXFRAME %level==3 to REG
|
||||||
|
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
|
||||||
|
lwz %2, {IND_RC_W, %2, EM_BSIZE}
|
||||||
|
lwz %2, {IND_RC_W, %2, EM_BSIZE}
|
||||||
|
from LXFRAME %level==4 to REG
|
||||||
|
gen lwz %2, {IND_RC_W, fp, EM_BSIZE}
|
||||||
|
lwz %2, {IND_RC_W, %2, EM_BSIZE}
|
||||||
|
lwz %2, {IND_RC_W, %2, EM_BSIZE}
|
||||||
|
lwz %2, {IND_RC_W, %2, EM_BSIZE}
|
||||||
|
from LXFRAME to REG /* assuming %level in 2 to 0x8000 */
|
||||||
|
gen li %2, {C, %1.level-1}
|
||||||
|
mtspr ctr, %2
|
||||||
|
lwz %2, {IND_RC_W, fp, EM_BSIZE}
|
||||||
|
1: lwz %2, {IND_RC_W, %2, EM_BSIZE}
|
||||||
|
bdnz {LABEL, "1b"}
|
||||||
|
|
||||||
/* Logicals */
|
/* Logicals */
|
||||||
|
|
||||||
from NOT_R to GPR
|
from NOT_R to GPR
|
||||||
|
@ -661,6 +726,11 @@ TESTS
|
||||||
|
|
||||||
STACKINGRULES
|
STACKINGRULES
|
||||||
|
|
||||||
|
/* We don't allow GPR-REG on the stack. The intent is to ban
|
||||||
|
* r0 from the stack, but this also bans fp from the stack.
|
||||||
|
* This is odd because most other tables for ncg allow the
|
||||||
|
* frame pointer on the stack.
|
||||||
|
*/
|
||||||
from REG to STACK
|
from REG to STACK
|
||||||
gen
|
gen
|
||||||
COMMENT("stack REG")
|
COMMENT("stack REG")
|
||||||
|
@ -760,6 +830,11 @@ COERCIONS
|
||||||
gen move {SUM_RR, %1.reg1, %1.reg2}, r12
|
gen move {SUM_RR, %1.reg1, %1.reg2}, r12
|
||||||
yields {IND_RC_W, r12, 4} {IND_RC_W, r12, 0}
|
yields {IND_RC_W, r12, 4} {IND_RC_W, r12, 0}
|
||||||
|
|
||||||
|
from FRAME_D %off<=0x7FFA
|
||||||
|
yields
|
||||||
|
{FRAME_W, %1.level, %1.reg, %1.off+4, 4}
|
||||||
|
{FRAME_W, %1.level, %1.reg, %1.off, 4}
|
||||||
|
|
||||||
|
|
||||||
PATTERNS
|
PATTERNS
|
||||||
|
|
||||||
|
@ -897,24 +972,47 @@ PATTERNS
|
||||||
uses REG={SUM_RIS, fp, his($1)}
|
uses REG={SUM_RIS, fp, his($1)}
|
||||||
yields {SUM_RC, %a, los($1)}
|
yields {SUM_RC, %a, los($1)}
|
||||||
|
|
||||||
|
pat lal loi smalls($1) && $2==1 /* Load byte from local */
|
||||||
|
yields {FRAME_B, 0, fp, $1, 1}
|
||||||
|
|
||||||
|
/* Load half-word from local and sign-extend */
|
||||||
|
pat lal loi loc loc cii smalls($1) && $2==2 && $3==2 && $4==4
|
||||||
|
yields {FRAME_H_S, 0, fp, $1, 1}
|
||||||
|
|
||||||
|
pat lal loi smalls($1) && $2==2 /* Load half-word from local */
|
||||||
|
yields {FRAME_H, 0, fp, $1, 1}
|
||||||
|
|
||||||
/* Load word from local */
|
/* Load word from local */
|
||||||
pat lol inreg($1)==reg_any || inreg($1)==reg_float
|
pat lol inreg($1)==reg_any || inreg($1)==reg_float
|
||||||
yields {LOCAL, $1}
|
yields {LOCAL, $1}
|
||||||
|
pat lol smalls($1)
|
||||||
|
yields {FRAME_W, 0, fp, $1, 4}
|
||||||
pat lol
|
pat lol
|
||||||
leaving
|
leaving
|
||||||
lal $1
|
lal $1
|
||||||
loi 4
|
loi 4
|
||||||
|
|
||||||
/* Load double-word from local */
|
pat ldl inreg($1)==reg_float /* Load double-word from local */
|
||||||
pat ldl inreg($1)==reg_float
|
|
||||||
yields {DLOCAL, $1}
|
yields {DLOCAL, $1}
|
||||||
|
pat ldl smalls($1) && smalls($1+4)
|
||||||
|
/* smalls($1+4) implies FRAME_D %off<=0xFFFA */
|
||||||
|
yields {FRAME_D, 0, fp, $1, 8}
|
||||||
pat ldl
|
pat ldl
|
||||||
leaving
|
leaving
|
||||||
lal $1
|
lal $1
|
||||||
loi 8
|
loi 8
|
||||||
|
|
||||||
/* Store word to local */
|
pat lal sti smalls($1) && $2==1 /* Store byte to local */
|
||||||
pat stl inreg($1)==reg_any
|
with REG
|
||||||
|
kills IND_V, FRAME_V %level==0 && fover($1, 1)
|
||||||
|
gen move %1, {FRAME_B, 0, fp, $1, 1}
|
||||||
|
|
||||||
|
pat lal sti smalls($1) && $2==2 /* Store half-word to local */
|
||||||
|
with REG
|
||||||
|
kills IND_V, FRAME_V %level==0 && fover($1, 2)
|
||||||
|
gen move %1, {FRAME_H, 0, fp, $1, 2}
|
||||||
|
|
||||||
|
pat stl inreg($1)==reg_any /* Store word to local */
|
||||||
with exact INT_W
|
with exact INT_W
|
||||||
/* ncg fails to infer that regvar($1) is dead! */
|
/* ncg fails to infer that regvar($1) is dead! */
|
||||||
kills regvar($1)
|
kills regvar($1)
|
||||||
|
@ -924,58 +1022,69 @@ PATTERNS
|
||||||
lwz {LOCAL, $1}, {IND_RC_W, sp, 0}
|
lwz {LOCAL, $1}, {IND_RC_W, sp, 0}
|
||||||
addi sp, sp, {C, 4}
|
addi sp, sp, {C, 4}
|
||||||
pat stl inreg($1)==reg_float
|
pat stl inreg($1)==reg_float
|
||||||
with exact FSREG+IND_ALL_W
|
with exact FLOAT_W
|
||||||
kills regvar_w($1, reg_float)
|
kills regvar_w($1, reg_float)
|
||||||
gen move %1, {FSREG_EXPR, regvar_w($1, reg_float)}
|
gen move %1, {FSREG_EXPR, regvar_w($1, reg_float)}
|
||||||
with STACK
|
with STACK
|
||||||
gen
|
gen
|
||||||
lfs {LOCAL, $1}, {IND_RC_W, sp, 0}
|
lfs {LOCAL, $1}, {IND_RC_W, sp, 0}
|
||||||
addi sp, sp, {C, 4}
|
addi sp, sp, {C, 4}
|
||||||
|
pat stl smalls($1)
|
||||||
|
with REG+FSREG
|
||||||
|
kills IND_V, FRAME_V %level==0 && fover($1, 4)
|
||||||
|
gen move %1, {FRAME_W, 0, fp, $1, 4}
|
||||||
pat stl
|
pat stl
|
||||||
leaving
|
leaving
|
||||||
lal $1
|
lal $1
|
||||||
sti 4
|
sti 4
|
||||||
|
|
||||||
/* Store double-word to local */
|
pat sdl inreg($1)==reg_float /* Store double-word to local */
|
||||||
pat sdl inreg($1)==reg_float
|
with exact FLOAT_D
|
||||||
with exact FREG+IND_ALL_D
|
|
||||||
kills regvar_d($1, reg_float)
|
kills regvar_d($1, reg_float)
|
||||||
gen move %1, {FPR_EXPR, regvar_d($1, reg_float)}
|
gen move %1, {FPR_EXPR, regvar_d($1, reg_float)}
|
||||||
with STACK
|
with STACK
|
||||||
gen
|
gen
|
||||||
lfd {DLOCAL, $1}, {IND_RC_D, sp, 0}
|
lfd {DLOCAL, $1}, {IND_RC_D, sp, 0}
|
||||||
addi sp, sp, {C, 8}
|
addi sp, sp, {C, 8}
|
||||||
|
pat sdl smalls($1) && smalls($1+4)
|
||||||
|
with REG REG
|
||||||
|
kills IND_V, FRAME_V %level==0 && fover($1, 8)
|
||||||
|
gen
|
||||||
|
move %1, {FRAME_W, 0, fp, $1, 4}
|
||||||
|
move %2, {FRAME_W, 0, fp, $1+4, 4}
|
||||||
|
with FREG
|
||||||
|
kills IND_V, FRAME_V %level==0 && fover($1, 4)
|
||||||
|
gen move %1, {FRAME_D, 0, fp, $1, 8}
|
||||||
pat sdl
|
pat sdl
|
||||||
leaving
|
leaving
|
||||||
lal $1
|
lal $1
|
||||||
sti 8
|
sti 8
|
||||||
|
|
||||||
/* Load indirect from local */
|
pat lil inreg($1)==reg_any /* Load indirect from local */
|
||||||
pat lil inreg($1)==reg_any
|
|
||||||
yields {IND_RC_W, regvar($1), 0}
|
yields {IND_RC_W, regvar($1), 0}
|
||||||
pat lil
|
pat lil
|
||||||
leaving
|
leaving
|
||||||
lol $1
|
lol $1
|
||||||
loi 4
|
loi 4
|
||||||
|
|
||||||
pat sil /* Save to indirected local */
|
pat sil /* Store indirect to local */
|
||||||
leaving
|
leaving
|
||||||
lol $1
|
lol $1
|
||||||
sti 4
|
sti 4
|
||||||
|
|
||||||
pat zrl /* Zero local */
|
pat zrl /* Zero local */
|
||||||
leaving
|
leaving
|
||||||
loc 0
|
loc 0
|
||||||
stl $1
|
stl $1
|
||||||
|
|
||||||
pat inl /* Increment local */
|
pat inl /* Increment local */
|
||||||
leaving
|
leaving
|
||||||
lol $1
|
lol $1
|
||||||
loc 1
|
loc 1
|
||||||
adi 4
|
adi 4
|
||||||
stl $1
|
stl $1
|
||||||
|
|
||||||
pat del /* Decrement local */
|
pat del /* Decrement local */
|
||||||
leaving
|
leaving
|
||||||
lol $1
|
lol $1
|
||||||
loc 1
|
loc 1
|
||||||
|
@ -983,9 +1092,87 @@ PATTERNS
|
||||||
stl $1
|
stl $1
|
||||||
|
|
||||||
|
|
||||||
|
/* Local variables of procedures on static chain */
|
||||||
|
|
||||||
|
/* lxa (lexical argument base) -> lxl (lexical local base) */
|
||||||
|
pat lxa adp nicelx($1)
|
||||||
|
leaving lxl $1 adp $2+EM_BSIZE
|
||||||
|
pat lxa lof nicelx($1)
|
||||||
|
leaving lxl $1 lof $2+EM_BSIZE
|
||||||
|
pat lxa ldf nicelx($1)
|
||||||
|
leaving lxl $1 ldf $2+EM_BSIZE
|
||||||
|
pat lxa stf nicelx($1)
|
||||||
|
leaving lxl $1 stf $2+EM_BSIZE
|
||||||
|
pat lxa sdf nicelx($1)
|
||||||
|
leaving lxl $1 stf $2+EM_BSIZE
|
||||||
|
pat lxa $1==0 || nicelx($1)
|
||||||
|
leaving lxl $1 adp EM_BSIZE
|
||||||
|
|
||||||
|
/* Load locals in statically enclosing procedures */
|
||||||
|
pat lxl adp loi nicelx($1) && smalls($2) && $3==1
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
yields {FRAME_B, $1, %a, $2, 1}
|
||||||
|
pat lxl adp loi loc loc cii nicelx($1) && smalls($2) &&
|
||||||
|
$3==2 && $4==2 && $5==4
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
yields {FRAME_H_S, $1, %a, $2, 2}
|
||||||
|
pat lxl adp loi nicelx($1) && smalls($2) && $3==2
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
yields {FRAME_H, $1, %a, $2, 2}
|
||||||
|
pat lxl lof nicelx($1) && smalls($2)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
yields {FRAME_W, $1, %a, $2, 4}
|
||||||
|
pat lxl ldf nicelx($1) && smalls($2) && smalls($2+4)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
/* smalls($2+4) implies FRAME_D %off<=0xFFFA */
|
||||||
|
yields {FRAME_D, $1, %a, $2, 8}
|
||||||
|
|
||||||
|
/* Store locals in statically enclosing procedures */
|
||||||
|
pat lxl adp sti nicelx($1) && smalls($2) && $3==1
|
||||||
|
with REG
|
||||||
|
kills IND_V, FRAME_V %level==$1 && fover($2, 1)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
gen move %1, {FRAME_B, $1, %a, $2, 1}
|
||||||
|
pat lxl adp sti nicelx($1) && smalls($2) && $3==2
|
||||||
|
with REG
|
||||||
|
kills IND_V, FRAME_V %level==$1 && fover($2, 2)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
gen move %1, {FRAME_H, $1, %a, $2, 2}
|
||||||
|
pat lxl stf nicelx($1) && smalls($2)
|
||||||
|
with REG+FSREG
|
||||||
|
kills IND_V, FRAME_V %level==$1 && fover($2, 4)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
gen move %1, {FRAME_W, $1, %a, $2, 4}
|
||||||
|
pat lxl sdf nicelx($1) && smalls($2) && smalls($2+4)
|
||||||
|
with REG REG
|
||||||
|
kills IND_V, FRAME_V %level==$1 && fover($2, 8)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
gen
|
||||||
|
move %1, {FRAME_W, $1, %a, $2, 4}
|
||||||
|
move %2, {FRAME_W, $1, %a, $2+4, 4}
|
||||||
|
with FREG
|
||||||
|
kills IND_V, FRAME_V %level==$1 && fover($2, 8)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
gen move %1, {FRAME_D, $1, %a, $2, 8}
|
||||||
|
|
||||||
|
/* Programs use "lxl cal" to pass the static chain and call a
|
||||||
|
* nested procedure. This must push a token LXFRAME or the
|
||||||
|
* register fp to the real stack. */
|
||||||
|
|
||||||
|
/* Local base of procedure on static chain */
|
||||||
|
pat lxl nicelx($1)
|
||||||
|
uses REG={LXFRAME, $1}
|
||||||
|
yields %a /* Can't yield LXFRAME. */
|
||||||
|
|
||||||
|
pat lxl $1==0 /* Our local base */
|
||||||
|
with STACK
|
||||||
|
gen stwu fp, {IND_RC_W, sp, 0-4}
|
||||||
|
/* Can't yield fp. */
|
||||||
|
|
||||||
|
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
|
|
||||||
pat lpi /* Load address of external function */
|
pat lpi /* Load address of function */
|
||||||
leaving
|
leaving
|
||||||
lae $1
|
lae $1
|
||||||
|
|
||||||
|
@ -2008,30 +2195,11 @@ PATTERNS
|
||||||
leaving
|
leaving
|
||||||
ret 0
|
ret 0
|
||||||
|
|
||||||
/*
|
/* Our caller's local base, "lxl 0 dch", appears in
|
||||||
* Lexical local base: lxl 0 yields our fp, lxl n yields the
|
* lang/cem/libcc.ansi/setjmp/setjmp.e, lang/m2/libm2/par_misc.e
|
||||||
* fp of the nth statically enclosing procedure.
|
|
||||||
*/
|
*/
|
||||||
pat lxl $1==0
|
pat lxl dch $1==0
|
||||||
leaving
|
yields {IND_RC_W, fp, FP_OFFSET}
|
||||||
lor 0
|
|
||||||
pat lxl $1==1
|
|
||||||
yields {IND_RC_W, fp, SL_OFFSET}
|
|
||||||
pat lxl $1==2
|
|
||||||
uses REG={IND_RC_W, fp, SL_OFFSET}
|
|
||||||
yields {IND_RC_W, %a, SL_OFFSET}
|
|
||||||
pat lxl $1==3
|
|
||||||
uses REG={IND_RC_W, fp, SL_OFFSET}, reusing %a, REG
|
|
||||||
gen move {IND_RC_W, %a, SL_OFFSET}, %b
|
|
||||||
yields {IND_RC_W, %b, SL_OFFSET}
|
|
||||||
pat lxl $1>=4 && $1<=0x8000
|
|
||||||
uses REG={IND_RC_W, fp, SL_OFFSET},
|
|
||||||
REG={CONST_0000_7FFF, $1-1}
|
|
||||||
gen
|
|
||||||
mtspr ctr, %b
|
|
||||||
1: lwz %a, {IND_RC_W, %a, SL_OFFSET}
|
|
||||||
bdnz {LABEL, "1b"}
|
|
||||||
yields %a
|
|
||||||
|
|
||||||
pat dch /* Dynamic chain: LB -> caller's LB */
|
pat dch /* Dynamic chain: LB -> caller's LB */
|
||||||
with REG
|
with REG
|
||||||
|
@ -2041,11 +2209,6 @@ PATTERNS
|
||||||
leaving
|
leaving
|
||||||
adp EM_BSIZE
|
adp EM_BSIZE
|
||||||
|
|
||||||
pat lxa /* Lexical argument base */
|
|
||||||
leaving
|
|
||||||
lxl $1
|
|
||||||
lpb
|
|
||||||
|
|
||||||
pat gto /* longjmp */
|
pat gto /* longjmp */
|
||||||
with STACK
|
with STACK
|
||||||
uses REG
|
uses REG
|
||||||
|
@ -2058,26 +2221,20 @@ PATTERNS
|
||||||
bctr.
|
bctr.
|
||||||
|
|
||||||
pat lor $1==0 /* Load local base */
|
pat lor $1==0 /* Load local base */
|
||||||
uses REG
|
leaving lxl 0
|
||||||
gen
|
|
||||||
move fp, %a
|
|
||||||
yields %a
|
|
||||||
|
|
||||||
pat lor $1==1 /* Load stack pointer */
|
pat lor $1==1 /* Load stack pointer */
|
||||||
uses REG
|
with STACK
|
||||||
gen
|
uses REG=sp
|
||||||
move sp, %a
|
yields %a /* Can't yield sp. */
|
||||||
yields %a
|
|
||||||
|
|
||||||
pat str $1==0 /* Store local base */
|
pat str $1==0 /* Store local base */
|
||||||
with REG
|
with REG
|
||||||
gen
|
gen move %1, fp
|
||||||
move %1, fp
|
|
||||||
|
|
||||||
pat str $1==1 /* Store stack pointer */
|
pat str $1==1 /* Store stack pointer */
|
||||||
with REG
|
with REG
|
||||||
gen
|
gen move %1, sp
|
||||||
move %1, sp
|
|
||||||
|
|
||||||
pat lae rck $2==4 /* Range check */
|
pat lae rck $2==4 /* Range check */
|
||||||
with REG
|
with REG
|
||||||
|
|
Loading…
Reference in a new issue