2013-05-16 23:03:38 +00:00
|
|
|
/*
|
|
|
|
* VideoCore IV code generator for the ACK
|
|
|
|
* © 2013 David Given
|
|
|
|
* This file is redistributable under the terms of the 3-clause BSD license.
|
|
|
|
* See the file 'Copying' in the root of the distribution for the full text.
|
|
|
|
*/
|
|
|
|
|
|
|
|
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
|
2013-05-20 22:27:45 +00:00
|
|
|
FLOAT32 = 4
|
|
|
|
FLOAT64 = 8
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PROPERTIES
|
|
|
|
|
|
|
|
GPR /* any GPR */
|
|
|
|
REG /* any allocatable GPR */
|
2013-05-19 22:33:42 +00:00
|
|
|
STACKABLE /* a push/popable register (r0, r6, r16, fp) */
|
|
|
|
|
|
|
|
GPR0 GPR1 GPR2 GPR3 GPR4 GPR5 GPR6 GPR7
|
2013-05-16 23:03:38 +00:00
|
|
|
GPR8 GPR9 GPR10 GPR11 GPR12 GPR13 GPR14 GPR15
|
|
|
|
GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
GPRGP GPRFP GPRSP GPRLR GPRPC
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
REGISTERS
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
R0("r0") : GPR, REG, STACKABLE, GPR0.
|
|
|
|
R1("r1") : GPR, REG, GPR1.
|
|
|
|
R2("r2") : GPR, REG, GPR2.
|
|
|
|
R3("r3") : GPR, REG, GPR3.
|
|
|
|
R4("r4") : GPR, REG, GPR4.
|
|
|
|
R5("r5") : GPR, REG, GPR5.
|
|
|
|
R6("r6") : GPR, REG, STACKABLE, GPR6 regvar.
|
|
|
|
R7("r7") : GPR, REG, GPR7 regvar.
|
|
|
|
R8("r8") : GPR, REG, GPR8 regvar.
|
|
|
|
R9("r9") : GPR, REG, GPR9 regvar.
|
|
|
|
R10("r10") : GPR, REG, GPR10 regvar.
|
|
|
|
R11("r11") : GPR, REG, GPR11 regvar.
|
|
|
|
R12("r12") : GPR, REG, GPR12 regvar.
|
|
|
|
R13("r13") : GPR, REG, GPR13 regvar.
|
|
|
|
R14("r14") : GPR, REG, GPR14 regvar.
|
|
|
|
GP("r15") : GPR, GPRGP.
|
|
|
|
|
|
|
|
R23("r23") : GPR.
|
2013-05-19 22:33:42 +00:00
|
|
|
FP("fp") : GPR, GPRFP, STACKABLE.
|
2013-05-16 23:03:38 +00:00
|
|
|
SP("sp") : GPR, GPRSP.
|
2013-05-19 22:33:42 +00:00
|
|
|
LR("lr") : GPR, GPRLR.
|
|
|
|
PC("pc") : GPR, GPRPC.
|
|
|
|
/* r26 to r31 are special and the code generator doesn't touch them. */
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
#define SCRATCH R23
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
TOKENS
|
|
|
|
|
|
|
|
/* Used only in instruction descriptions (to generate the correct syntax). */
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
GPROFFSET = { GPR reg; INT off; } 4 off "(" reg ")".
|
|
|
|
GPRGPR = { GPR reg1; GPR reg2; } 4 "(" reg1 "," reg2 ")".
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
/* Primitives */
|
|
|
|
|
|
|
|
LABEL = { ADDR adr; } 4 adr.
|
2013-05-19 22:33:42 +00:00
|
|
|
CONST = { INT val; } 4 "#" val.
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
/* Allows us to use regvar() to refer to registers */
|
|
|
|
|
|
|
|
GPRE = { GPR reg; } 4 reg.
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
/* The results of comparisons. */
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
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.
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SETS
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
TOKEN = LABEL + CONST.
|
2013-05-16 23:03:38 +00:00
|
|
|
GPRI = GPR + GPRE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
INSTRUCTIONS
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
add GPRI:wo, GPRI:ro, GPRI+CONST:ro.
|
2013-05-20 21:35:12 +00:00
|
|
|
add GPRI:rw, GPRI+CONST:ro.
|
2013-05-20 22:27:45 +00:00
|
|
|
and GPRI:rw, GPRI+CONST:ro.
|
2013-05-19 22:33:42 +00:00
|
|
|
beq "b.eq" LABEL:ro.
|
|
|
|
bne "b.ne" LABEL:ro.
|
2013-05-20 21:35:12 +00:00
|
|
|
bgt "b.gt" LABEL:ro.
|
|
|
|
bgt "b.gt" LABEL:ro.
|
|
|
|
bhi "b.hi" LABEL:ro.
|
2013-05-19 22:33:42 +00:00
|
|
|
b GPRI+LABEL:ro.
|
|
|
|
bl GPRI+LABEL:ro.
|
2013-05-20 21:35:12 +00:00
|
|
|
cmp GPRI:ro, GPRI+CONST:ro kills :cc.
|
2013-05-20 22:27:45 +00:00
|
|
|
divs GPRI:wo, GPRI:ro, GPRI+CONST:ro.
|
|
|
|
divu GPRI:wo, GPRI:ro, GPRI+CONST:ro.
|
|
|
|
eor GPRI:rw, GPRI+CONST:ro.
|
2013-05-19 22:33:42 +00:00
|
|
|
exts GPRI:wo, GPRI:ro, GPRI+CONST:ro.
|
2013-05-20 21:35:12 +00:00
|
|
|
exts GPRI:rw, GPRI+CONST:ro.
|
2013-05-19 22:33:42 +00:00
|
|
|
ld GPRI:wo, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
ldb GPRI:wo, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
ldh GPRI:wo, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
ldhs GPRI:wo, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
lea GPRI:wo, LABEL:ro.
|
2013-05-20 21:35:12 +00:00
|
|
|
lsl GPRI:rw, GPRI+CONST:ro.
|
2013-05-19 22:33:42 +00:00
|
|
|
lsl GPRI:wo, GPRI:ro, GPRI+CONST:ro.
|
|
|
|
mov GPRI:wo, GPRI+CONST:ro.
|
2013-05-20 22:27:45 +00:00
|
|
|
mul GPRI:rw, GPRI+CONST:ro.
|
2013-05-20 21:35:12 +00:00
|
|
|
neg GPRI:rw, GPRI+CONST:ro.
|
2013-05-20 22:27:45 +00:00
|
|
|
or GPRI:rw, GPRI+CONST:ro.
|
2013-05-19 22:33:42 +00:00
|
|
|
pop STACKABLE:wo.
|
|
|
|
pop STACKABLE:wo, GPRLR+GPRPC:wo.
|
|
|
|
push STACKABLE:ro.
|
|
|
|
sub GPRI:wo, GPRI:ro, CONST+GPRI:ro.
|
2013-05-20 21:35:12 +00:00
|
|
|
sub GPRI:rw, GPRI+CONST:ro.
|
2013-05-19 22:33:42 +00:00
|
|
|
st GPRI:ro, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
stb GPRI:ro, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
sth GPRI:ro, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
sths GPRI:ro, GPROFFSET+GPRGPR+LABEL:ro.
|
|
|
|
|
|
|
|
invalid "invalid".
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MOVES
|
|
|
|
|
|
|
|
from GPR to GPR
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
COMMENT("mov GPR->GPR")
|
|
|
|
mov %2, %1
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
/* GPRE exists solely to allow us to use regvar() (which can only be used in
|
|
|
|
an expression) as a register constant. */
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
from GPRE to GPR
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
mov %2, %1
|
|
|
|
|
|
|
|
/* Constants */
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
from CONST to GPR
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
mov %2, %1
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
from LABEL to GPR
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
lea %2, {LABEL, %1.adr}
|
2013-05-20 21:35:12 +00:00
|
|
|
sub %2, GP
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
/* Miscellaneous */
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
from CONST+LABEL+GPR+GPRE to GPRE
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
move %1, %2.reg
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
TESTS
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
to test GPR
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
cmp %1, {CONST, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
STACKINGRULES
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
from STACKABLE to STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
push %1
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
from GPR to STACK
|
2013-05-19 22:33:42 +00:00
|
|
|
uses STACKABLE
|
|
|
|
gen
|
|
|
|
move %1, %a
|
|
|
|
push %a
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
from GPR to STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
sub SP, SP, {CONST, 4}
|
|
|
|
st %1, {GPROFFSET, SP, 0}
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
from GPRE to STACK
|
|
|
|
uses STACKABLE
|
|
|
|
gen
|
|
|
|
move %1, %a
|
|
|
|
push %a
|
|
|
|
|
|
|
|
from GPRE to STACK
|
|
|
|
gen
|
|
|
|
sub SP, {CONST, 4}
|
|
|
|
st %1, {GPROFFSET, SP, 0}
|
|
|
|
|
|
|
|
from TOKEN to STACK
|
2013-05-19 22:33:42 +00:00
|
|
|
uses STACKABLE
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
|
|
|
move %1, %a
|
2013-05-19 22:33:42 +00:00
|
|
|
push %a
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
from TOKEN to STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
COMMENT("fallback stack")
|
2013-05-16 23:03:38 +00:00
|
|
|
move %1, SCRATCH
|
2013-05-19 22:33:42 +00:00
|
|
|
sub SP, SP, {CONST, 4}
|
|
|
|
st SCRATCH, {GPROFFSET, SP, 0}
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
COERCIONS
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
from GPRE
|
2013-05-20 21:35:12 +00:00
|
|
|
uses reusing %1, REG=%1
|
2013-05-19 22:33:42 +00:00
|
|
|
yields %a
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
from CONST
|
|
|
|
uses REG
|
|
|
|
gen
|
|
|
|
COMMENT("coerce CONST->REG")
|
|
|
|
move %1, %a
|
|
|
|
yields %a
|
|
|
|
|
|
|
|
from LABEL
|
|
|
|
uses REG
|
|
|
|
gen
|
|
|
|
COMMENT("coerce LABEL->REG")
|
2013-05-19 22:33:42 +00:00
|
|
|
move %1, %a
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
from STACK
|
2013-05-19 22:33:42 +00:00
|
|
|
uses STACKABLE
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
|
|
|
COMMENT("coerce STACK->REG")
|
2013-05-19 22:33:42 +00:00
|
|
|
pop %a
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
PATTERNS
|
|
|
|
|
|
|
|
/* Intrinsics */
|
|
|
|
|
|
|
|
pat loc /* Load constant */
|
|
|
|
yields {CONST, $1}
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
pat dup $1<=INT32 /* Duplicate word on top of stack */
|
|
|
|
with GPR
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %1 %1
|
2013-05-20 21:35:12 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat dup $1==INT64 /* Duplicate double-word on top of stack */
|
2013-05-20 21:35:12 +00:00
|
|
|
with GPR GPR
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %2 %1 %2 %1
|
|
|
|
|
|
|
|
pat exg $1==INT32 /* Exchange top two words on stack */
|
2013-05-20 21:35:12 +00:00
|
|
|
with GPR GPR
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %1 %2
|
2013-05-20 21:35:12 +00:00
|
|
|
|
|
|
|
#if 0
|
2013-05-16 23:03:38 +00:00
|
|
|
pat stl lol $1==$2 /* Store then load local */
|
|
|
|
leaving
|
2013-05-20 21:35:12 +00:00
|
|
|
dup INT32
|
2013-05-16 23:03:38 +00:00
|
|
|
stl $1
|
2013-05-20 21:35:12 +00:00
|
|
|
#endif
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat lal sti lal loi $1==$3 && $2==$4 /* Store then load local, of a different size */
|
|
|
|
leaving
|
2013-05-20 21:35:12 +00:00
|
|
|
dup $2
|
2013-05-16 23:03:38 +00:00
|
|
|
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 */
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
pat loc loc cii $1==INT8 && $2>INT8 /* signed char -> anything */
|
2013-05-19 22:33:42 +00:00
|
|
|
with REG
|
2013-05-20 21:35:12 +00:00
|
|
|
uses reusing %1, REG=%1
|
|
|
|
gen
|
|
|
|
exts %a, {CONST, 8}
|
|
|
|
yields %a
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
pat loc loc cii $1==INT16 && $2>INT16 /* signed short -> anything */
|
2013-05-19 22:33:42 +00:00
|
|
|
with REG
|
2013-05-20 21:35:12 +00:00
|
|
|
uses reusing %1, REG=%1
|
|
|
|
gen
|
|
|
|
exts %a, {CONST, 16}
|
|
|
|
yields %a
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Local variables */
|
|
|
|
|
|
|
|
pat lal /* Load address of local */
|
2013-05-20 21:35:12 +00:00
|
|
|
uses REG
|
|
|
|
gen
|
|
|
|
add %a, FP, {CONST, $1}
|
|
|
|
sub %a, GP
|
|
|
|
yields %a
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat lol inreg($1)>0 /* Load from local */
|
2013-05-20 21:35:12 +00:00
|
|
|
yields {GPRE, regvar($1)}
|
|
|
|
|
|
|
|
pat lol /* Load quad from local */
|
|
|
|
uses REG
|
|
|
|
gen
|
|
|
|
ld %a, {GPROFFSET, FP, $1}
|
|
|
|
yields %a
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat ldl /* Load double-word from local */
|
|
|
|
leaving
|
|
|
|
lal $1
|
|
|
|
loi INT32*2
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat stl inreg($1)>0 /* Store to local */
|
2013-05-20 21:35:12 +00:00
|
|
|
with CONST+GPRI
|
|
|
|
kills regvar($1)
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
|
|
|
move %1, {GPRE, regvar($1)}
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat stl /* Store to local */
|
2013-05-20 21:35:12 +00:00
|
|
|
with GPRI
|
|
|
|
gen
|
|
|
|
st %1, {GPROFFSET, FP, $1}
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
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
|
2013-05-19 22:33:42 +00:00
|
|
|
ld %a, {GPROFFSET, regvar($1), 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
|
|
|
|
|
|
|
pat lil /* Load from indirected local */
|
|
|
|
leaving
|
|
|
|
lol $1
|
|
|
|
loi INT32
|
|
|
|
|
|
|
|
pat sil /* Save to indirected local */
|
|
|
|
leaving
|
|
|
|
lol $1
|
|
|
|
sti INT32
|
|
|
|
|
|
|
|
pat stl lol $1==$2 /* Save then load (generated by C compiler) */
|
|
|
|
leaving
|
|
|
|
dup 4
|
|
|
|
stl $1
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
#if 0
|
2013-05-16 23:03:38 +00:00
|
|
|
pat ine /* Increment external */
|
|
|
|
uses REG={LABEL, $1}, REG
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
lwz %b, {GPROFFSET, %a, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
addi %b, %b, {CONST, 1}
|
2013-05-19 22:33:42 +00:00
|
|
|
stw %b, {GPROFFSET, %a, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat dee /* Decrement external */
|
|
|
|
uses REG={LABEL, $1}, REG
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
lwz %b, {GPROFFSET, %a, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
addi %b, %b, {CONST, 0-1}
|
2013-05-19 22:33:42 +00:00
|
|
|
stw %b, {GPROFFSET, %a, 0}
|
|
|
|
#endif
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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
|
2013-05-20 21:35:12 +00:00
|
|
|
uses reusing %1, REG
|
|
|
|
gen
|
|
|
|
ldb %a, {GPRGPR, %1, GP}
|
|
|
|
yields %a
|
|
|
|
with GPRE
|
|
|
|
uses reusing %1.reg, REG
|
|
|
|
gen
|
|
|
|
ldb %a, {GPRGPR, %1.reg, GP}
|
|
|
|
yields %a
|
2013-05-19 22:33:42 +00:00
|
|
|
|
|
|
|
#if 0
|
2013-05-16 23:03:38 +00:00
|
|
|
pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32 /* Load half-word indirect and sign extend */
|
|
|
|
with GPR
|
|
|
|
uses REG
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
lha %a, {GPROFFSET, %1, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
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
|
2013-05-19 22:33:42 +00:00
|
|
|
lhz %a, {GPROFFSET, %1, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
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
|
2013-05-19 22:33:42 +00:00
|
|
|
#endif
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
pat loi $1==INT32 /* Load quad indirect */
|
2013-05-16 23:03:38 +00:00
|
|
|
with GPR
|
2013-05-20 21:35:12 +00:00
|
|
|
uses reusing %1, REG
|
|
|
|
gen
|
|
|
|
add %a, %1, GP
|
|
|
|
ld %a, {GPROFFSET, %a, 0}
|
|
|
|
yields %a
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
pat loi $1==INT64 /* Load double-quad indirect */
|
2013-05-20 22:27:45 +00:00
|
|
|
with GPRI
|
|
|
|
uses reusing %1, REG, REG
|
|
|
|
gen
|
|
|
|
add %a, %1, GP
|
|
|
|
ld %b, {GPROFFSET, %a, 4}
|
|
|
|
ld %a, {GPROFFSET, %a, 0}
|
|
|
|
yields %a %b
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat loi /* Load arbitrary size */
|
|
|
|
leaving
|
|
|
|
loc $1
|
|
|
|
los INT32
|
|
|
|
|
|
|
|
pat los /* Load arbitrary size */
|
2013-05-20 22:27:45 +00:00
|
|
|
with STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
kills ALL
|
|
|
|
gen
|
|
|
|
bl {LABEL, ".los"}
|
|
|
|
|
|
|
|
pat sti $1==INT8 /* Store byte indirect */
|
2013-05-20 21:35:12 +00:00
|
|
|
with GPR GPRI
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
stb %2, {GPRGPR, %1, GP}
|
|
|
|
with GPRE GPRI
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
stb %2, {GPRGPR, %1.reg, GP}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat sti $1==INT16 /* Store half-word indirect */
|
|
|
|
with GPR GPR
|
2013-05-20 21:35:12 +00:00
|
|
|
uses REG
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
add %a, %1, GP
|
|
|
|
sth %2, {GPROFFSET, %a, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
pat sti $1==INT32 /* Store quad indirect */
|
|
|
|
with GPR GPR
|
2013-05-20 21:35:12 +00:00
|
|
|
uses REG
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
add %a, %1, GP
|
|
|
|
st %2, {GPROFFSET, %a, 0}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 22:27:45 +00:00
|
|
|
pat sti $1==INT64 /* Store double-quad indirect */
|
|
|
|
with GPR GPR
|
|
|
|
uses REG
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
add %a, %1, GP
|
|
|
|
st %1, {GPROFFSET, %a, 0}
|
|
|
|
st %2, {GPROFFSET, %a, 4}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat sti /* Store arbitrary size */
|
|
|
|
leaving
|
|
|
|
loc $1
|
|
|
|
sts INT32
|
|
|
|
|
|
|
|
pat sts /* Load arbitrary size */
|
2013-05-20 22:27:45 +00:00
|
|
|
with STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
kills ALL
|
|
|
|
gen
|
|
|
|
bl {LABEL, ".sts"}
|
2013-05-20 22:27:45 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
pat adi $1==INT32 /* Add word (second + top) */
|
2013-05-20 21:35:12 +00:00
|
|
|
with GPRI+CONST GPRI
|
|
|
|
uses reusing %2, REG=%2
|
|
|
|
gen
|
|
|
|
add %a, %1
|
|
|
|
yields %a
|
|
|
|
with GPRI GPRI+CONST
|
|
|
|
uses reusing %1, REG=%1
|
|
|
|
gen
|
|
|
|
add %a, %2
|
|
|
|
yields %a
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
pat sbi $1==INT32 /* Subtract word (second - top) */
|
|
|
|
with GPRI+CONST GPRI
|
|
|
|
uses reusing %2, REG=%2
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
sub %a, %1
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-20 21:35:12 +00:00
|
|
|
|
|
|
|
pat ngi $1==INT32 /* Negate word */
|
|
|
|
with GPRI
|
|
|
|
uses reusing %1, REG=%1
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
neg %a, %a
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-20 21:35:12 +00:00
|
|
|
|
2013-05-20 22:27:45 +00:00
|
|
|
pat and $1==INT32 /* AND word */
|
|
|
|
with GPRI+CONST GPRI
|
|
|
|
uses reusing %2, REG=%2
|
|
|
|
gen
|
|
|
|
and %a, %1
|
|
|
|
yields %a
|
|
|
|
with GPRI GPRI+CONST
|
|
|
|
uses reusing %1, REG=%1
|
|
|
|
gen
|
|
|
|
and %a, %2
|
|
|
|
yields %a
|
|
|
|
|
|
|
|
pat ior $1==INT32 /* OR word */
|
|
|
|
with GPRI+CONST GPRI
|
|
|
|
uses reusing %2, REG=%2
|
|
|
|
gen
|
|
|
|
or %a, %1
|
|
|
|
yields %a
|
|
|
|
with GPRI GPRI+CONST
|
|
|
|
uses reusing %1, REG=%1
|
|
|
|
gen
|
|
|
|
or %a, %2
|
|
|
|
yields %a
|
|
|
|
|
|
|
|
pat xor $1==INT32 /* XOR word */
|
|
|
|
with GPRI+CONST GPRI
|
|
|
|
uses reusing %2, REG=%2
|
|
|
|
gen
|
|
|
|
eor %a, %1
|
|
|
|
yields %a
|
|
|
|
with GPRI GPRI+CONST
|
|
|
|
uses reusing %1, REG=%1
|
|
|
|
gen
|
|
|
|
eor %a, %2
|
|
|
|
yields %a
|
|
|
|
|
|
|
|
pat dvi $1==INT32 /* Divide word (second / top) */
|
|
|
|
with GPRI GPRI
|
2013-05-16 23:03:38 +00:00
|
|
|
uses reusing %2, REG
|
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
divs %a, %2, %1
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-20 22:27:45 +00:00
|
|
|
|
|
|
|
pat dvu $1==INT32 /* Divide unsigned word (second / top) */
|
|
|
|
with GPRI GPRI
|
2013-05-16 23:03:38 +00:00
|
|
|
uses reusing %2, REG
|
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
divu %a, %2, %1
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-20 22:27:45 +00:00
|
|
|
|
|
|
|
pat rmu $1==INT32 /* Remainder unsigned word (second % top) */
|
|
|
|
with GPRI GPRI
|
|
|
|
uses REG
|
|
|
|
gen
|
|
|
|
divu %a, %2, %1
|
|
|
|
mul %a, %1
|
|
|
|
sub %a, %2
|
|
|
|
yields %a
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
pat mli $1==4 /* Multiply word (second * top) */
|
2013-05-16 23:03:38 +00:00
|
|
|
with REG REG
|
|
|
|
uses reusing %2, REG
|
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
mullw %a, %2, %1
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-20 22:27:45 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
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 and !defined($1) /* AND set */
|
|
|
|
with STACK
|
|
|
|
gen
|
|
|
|
bl {LABEL, ".and"}
|
|
|
|
|
|
|
|
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"}
|
2013-05-19 22:33:42 +00:00
|
|
|
#endif
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat sli $1==4 /* Shift left (second << top) */
|
2013-05-20 21:35:12 +00:00
|
|
|
with CONST+GPRI GPRI
|
|
|
|
uses reusing %2, REG=%2
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
lsl %a, %1
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-19 22:33:42 +00:00
|
|
|
|
|
|
|
#if 0
|
2013-05-16 23:03:38 +00:00
|
|
|
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"}
|
2013-05-20 22:27:45 +00:00
|
|
|
#endif
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Boolean resolutions */
|
|
|
|
|
2013-05-20 22:27:45 +00:00
|
|
|
proc anyt example teq
|
|
|
|
with GPRI
|
|
|
|
uses reusing %1, REG=%1
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
cmp %1, {CONST, 0}
|
|
|
|
mov %a, {CONST, 0}
|
|
|
|
add[1] %a, {CONST, 1}
|
2013-05-16 23:03:38 +00:00
|
|
|
yields %a
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-20 22:27:45 +00:00
|
|
|
pat cmu teq call anyt("add.eq") /* top = (top == 0) */
|
|
|
|
pat cmu tne call anyt("add.ne") /* top = (top != 0) */
|
|
|
|
pat cmu tlt call anyt("add.lo") /* top = unsigned (top < 0) */
|
|
|
|
pat cmu tle call anyt("add.ls") /* top = unsigned (top <= 0) */
|
|
|
|
pat cmu tgt call anyt("add.hi") /* top = unsigned (top > 0) */
|
|
|
|
pat cmu tge call anyt("add.hs") /* top = unsigned (top >= 0) */
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Simple branches */
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
proc anyz example zeq
|
|
|
|
with GPRI STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
cmp %1, {CONST, 0}
|
2013-05-20 21:35:12 +00:00
|
|
|
beq[1] {LABEL, $1}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
pat zeq call anyz("b.eq") /* Branch if signed top == 0 */
|
|
|
|
pat zne call anyz("b.ne") /* Branch if signed top != 0 */
|
|
|
|
pat zgt call anyz("b.gt") /* Branch if signed top > 0 */
|
2013-05-20 22:27:45 +00:00
|
|
|
pat zlt call anyz("b.lt") /* Branch if signed top < 0 */
|
|
|
|
pat zge call anyz("b.ge") /* Branch if signed top >= 0 */
|
|
|
|
pat zle call anyz("b.le") /* Branch if signed top <= 0 */
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
proc anyb example beq
|
|
|
|
with GPR+CONST GPRI STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
cmp %2, %1
|
|
|
|
beq[1] {LABEL, $1}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
pat beq call anyz("b.eq") /* Branch if signed second == top */
|
|
|
|
pat bne call anyz("b.ne") /* Branch if signed second != top */
|
|
|
|
pat bgt call anyz("b.gt") /* Branch if signed second > top */
|
2013-05-20 22:27:45 +00:00
|
|
|
pat bge call anyz("b.ge") /* Branch if signed second >= top */
|
|
|
|
pat blt call anyz("b.lt") /* Branch if signed second < top */
|
|
|
|
pat ble call anyz("b.le") /* Branch if signed second <= top */
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
proc anycmpb example cmu zeq
|
|
|
|
with GPR+CONST GPRI STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
cmp %2, %1
|
|
|
|
beq[1] {LABEL, $2}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
pat cmu zgt call anycmpb("b.hi") /* Branch if unsigned second > top */
|
|
|
|
pat cmu zlt call anycmpb("b.lo") /* Branch if unsigned second < top */
|
|
|
|
pat cmu zge call anycmpb("b.hs") /* Branch if unsigned second >= top */
|
|
|
|
pat cmu zle call anycmpb("b.ls") /* Branch if unsigned second <= top */
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
2013-05-19 22:33:42 +00:00
|
|
|
#if 0
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
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}
|
2013-05-20 21:35:12 +00:00
|
|
|
#endif
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat cmp /* Compare pointers */
|
|
|
|
leaving
|
|
|
|
cmu INT32
|
|
|
|
|
|
|
|
pat cms $1==INT32 /* Compare blocks (word sized) */
|
|
|
|
leaving
|
|
|
|
cmi INT32
|
2013-05-20 22:27:45 +00:00
|
|
|
|
|
|
|
proc anycmf64 example teq
|
|
|
|
with STACK
|
|
|
|
uses REG
|
|
|
|
gen
|
|
|
|
bl {LABEL, ".cmf8"}
|
|
|
|
mov %a, {CONST, 0}
|
|
|
|
add[1] %a, {CONST, 1}
|
|
|
|
yields %a
|
|
|
|
|
|
|
|
pat cmf tlt $1==FLOAT64 call anyt("add.lo") /* top = unsigned (top < 0) */
|
|
|
|
pat cmf tle $1==FLOAT64 call anyt("add.ls") /* top = unsigned (top <= 0) */
|
|
|
|
pat cmf tgt $1==FLOAT64 call anyt("add.hi") /* top = unsigned (top > 0) */
|
|
|
|
pat cmf tge $1==FLOAT64 call anyt("add.hs") /* top = unsigned (top >= 0) */
|
|
|
|
|
|
|
|
|
2013-05-20 21:35:12 +00:00
|
|
|
#if 0
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* 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
|
2013-05-19 22:33:42 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
pat bra /* Unconditional jump */
|
2013-05-16 23:03:38 +00:00
|
|
|
with STACK
|
|
|
|
gen
|
|
|
|
b {LABEL, $1}
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Miscellaneous */
|
|
|
|
|
|
|
|
pat cal /* Call procedure */
|
|
|
|
with STACK
|
|
|
|
kills ALL
|
|
|
|
gen
|
|
|
|
bl {LABEL, $1}
|
|
|
|
|
|
|
|
pat cai /* Call procedure indirect */
|
|
|
|
with GPR STACK
|
|
|
|
kills ALL
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
bl %1
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat lfr $1==INT32 /* Load function result, word */
|
2013-05-19 22:33:42 +00:00
|
|
|
yields R0
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat lfr $1==INT64 /* Load function result, double-word */
|
2013-05-19 22:33:42 +00:00
|
|
|
yields R0 R1
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat ret $1==0 /* Return from procedure */
|
|
|
|
gen
|
|
|
|
return
|
2013-05-19 22:33:42 +00:00
|
|
|
mov SP, FP
|
|
|
|
pop FP, PC
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat ret $1==INT32 /* Return from procedure, word */
|
2013-05-19 22:33:42 +00:00
|
|
|
with GPR0
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
|
|
|
return
|
2013-05-19 22:33:42 +00:00
|
|
|
mov SP, FP
|
|
|
|
pop FP, PC
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat ret $1==INT64 /* Return from procedure, double-word */
|
2013-05-19 22:33:42 +00:00
|
|
|
with GPR0 GPR1
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
|
|
|
return
|
2013-05-19 22:33:42 +00:00
|
|
|
mov SP, FP
|
|
|
|
pop FP, PC
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat blm /* Block move constant length */
|
2013-05-20 22:27:45 +00:00
|
|
|
with GPRI GPRI STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
uses REG
|
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
sub SP, {CONST, 12}
|
|
|
|
mov %a, {CONST, $1}
|
|
|
|
st %1, {GPROFFSET, SP, 0}
|
|
|
|
st %2, {GPROFFSET, SP, 4}
|
|
|
|
st %a, {GPROFFSET, SP, 8}
|
2013-05-16 23:03:38 +00:00
|
|
|
bl {LABEL, "_memmove"}
|
2013-05-20 22:27:45 +00:00
|
|
|
add SP, {CONST, 12}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
2013-05-20 22:27:45 +00:00
|
|
|
#if 0
|
2013-05-16 23:03:38 +00:00
|
|
|
pat bls /* Block move variable length */
|
|
|
|
with GPR GPR GPR STACK
|
|
|
|
gen
|
2013-05-19 22:33:42 +00:00
|
|
|
stwu %1, {GPROFFSET, SP, 0-4}
|
|
|
|
stwu %3, {GPROFFSET, SP, 0-4}
|
|
|
|
stwu %2, {GPROFFSET, SP, 0-4}
|
2013-05-16 23:03:38 +00:00
|
|
|
bl {LABEL, "_memmove"}
|
|
|
|
addi SP, SP, {CONST, 12}
|
2013-05-20 22:27:45 +00:00
|
|
|
#endif
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat csa /* Array-lookup switch */
|
2013-05-20 22:27:45 +00:00
|
|
|
with STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
bl {LABEL, ".csa"}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
pat csb /* Table-lookup switch */
|
2013-05-20 22:27:45 +00:00
|
|
|
with STACK
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 22:27:45 +00:00
|
|
|
bl {LABEL, ".csb"}
|
2013-05-16 23:03:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* EM specials */
|
|
|
|
|
|
|
|
pat fil /* Set current filename */
|
|
|
|
leaving
|
|
|
|
lae $1
|
|
|
|
ste ".filename"
|
|
|
|
|
|
|
|
pat lin /* Set current line number */
|
|
|
|
leaving
|
|
|
|
loc $1
|
|
|
|
ste ".linenumber"
|
|
|
|
|
|
|
|
pat lni /* Increment line number */
|
|
|
|
leaving
|
|
|
|
ine ".linenumber"
|
|
|
|
|
|
|
|
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 */
|
2013-05-20 22:27:45 +00:00
|
|
|
with GPR0
|
2013-05-16 23:03:38 +00:00
|
|
|
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
|
2013-05-20 22:27:45 +00:00
|
|
|
ld %a, {GPROFFSET, %1, FP_OFFSET}
|
|
|
|
sub %a, GP
|
2013-05-16 23:03:38 +00:00
|
|
|
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 */
|
2013-05-20 22:27:45 +00:00
|
|
|
uses REG, REG
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
|
|
|
move {LABEL, $1}, %a
|
2013-05-20 22:27:45 +00:00
|
|
|
ld %b, {GPROFFSET, %a, 8}
|
|
|
|
add FP, %b, GP
|
|
|
|
ld %b, {GPROFFSET, %a, 4}
|
|
|
|
add SP, %b, GP
|
|
|
|
ld %b, {GPROFFSET, %a, 0}
|
|
|
|
add %b, GP
|
|
|
|
b %b
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
#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 */
|
2013-05-20 21:35:12 +00:00
|
|
|
with GPRI
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
sub FP, %1, GP
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat str $1==1 /* Store SP */
|
2013-05-20 21:35:12 +00:00
|
|
|
with GPRI
|
2013-05-16 23:03:38 +00:00
|
|
|
gen
|
2013-05-20 21:35:12 +00:00
|
|
|
sub SP, %1, GP
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat str $1==2 /* Store HP */
|
|
|
|
leaving
|
|
|
|
ste ".reghp"
|
2013-05-19 22:33:42 +00:00
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat ass /* Adjust stack by variable amount */
|
2013-05-20 21:35:12 +00:00
|
|
|
with CONST+GPRI
|
|
|
|
gen
|
|
|
|
add SP, %1
|
|
|
|
|
2013-05-16 23:03:38 +00:00
|
|
|
pat asp /* Adjust stack by constant amount */
|
|
|
|
leaving
|
|
|
|
loc $1
|
|
|
|
ass
|
2013-05-19 22:33:42 +00:00
|
|
|
|