Massive change to how IR types are handled; we use the type code for matching
rather than the size. Much cleaner and simpler.
This commit is contained in:
parent
b1a3d76d6f
commit
abd0cedd61
|
@ -99,7 +99,7 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
|
|||
{
|
||||
struct hop* hop = new_hop(bb, NULL);
|
||||
const uint32_t type_attrs =
|
||||
burm_int_ATTR | burm_pair_ATTR | burm_float_ATTR | burm_double_ATTR;
|
||||
burm_int_ATTR | burm_long_ATTR | burm_float_ATTR | burm_double_ATTR;
|
||||
|
||||
if ((src->type & type_attrs) != (dest->type & type_attrs))
|
||||
{
|
||||
|
@ -112,7 +112,7 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
|
|||
hop_add_insel(hop, "stwu %H, -4(sp)", src);
|
||||
break;
|
||||
|
||||
case burm_pair_ATTR:
|
||||
case burm_long_ATTR:
|
||||
hop_add_insel(hop, "stwu %0H, -4(sp)", src);
|
||||
hop_add_insel(hop, "stwu %1H, -4(sp)", src);
|
||||
break;
|
||||
|
@ -135,7 +135,7 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
|
|||
hop_add_insel(hop, "lwz %H, 0(sp)", dest);
|
||||
break;
|
||||
|
||||
case burm_pair_ATTR:
|
||||
case burm_long_ATTR:
|
||||
hop_add_insel(hop, "lwz %0H, 4(sp)", dest);
|
||||
hop_add_insel(hop, "lwz %1H, 0(sp)", dest);
|
||||
break;
|
||||
|
@ -160,7 +160,7 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
|
|||
break;
|
||||
|
||||
case burm_double_ATTR:
|
||||
case burm_pair_ATTR:
|
||||
case burm_long_ATTR:
|
||||
hop_add_insel(hop, "addi sp, sp, 8");
|
||||
break;
|
||||
|
||||
|
@ -220,7 +220,7 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
|
|||
hop_add_insel(hop, "mr %H, %H", dest, src);
|
||||
break;
|
||||
|
||||
case burm_pair_ATTR:
|
||||
case burm_long_ATTR:
|
||||
hop_add_insel(hop, "mr %0H, %0H", dest, src);
|
||||
hop_add_insel(hop, "mr %1H, %1H", dest, src);
|
||||
break;
|
||||
|
|
|
@ -38,21 +38,21 @@ REGISTERS
|
|||
r14 bytes4! int!;
|
||||
r13 bytes4! int!;
|
||||
|
||||
r11r12 named("r11", "r12") aliases(r11, r12) bytes8! pair! volatile;
|
||||
r9r10 named("r9", "r10") aliases(r9, r10) bytes8! pair! volatile;
|
||||
r7r8 named("r7", "r8") aliases(r7, r8) bytes8! pair! volatile;
|
||||
r5r6 named("r5", "r6") aliases(r6, r6) bytes8! pair! volatile;
|
||||
r3r4 named("r3", "r4") aliases(r3, r4) bytes8! pair! volatile pret;
|
||||
r11r12 named("r11", "r12") aliases(r11, r12) bytes8! long! volatile;
|
||||
r9r10 named("r9", "r10") aliases(r9, r10) bytes8! long! volatile;
|
||||
r7r8 named("r7", "r8") aliases(r7, r8) bytes8! long! volatile;
|
||||
r5r6 named("r5", "r6") aliases(r6, r6) bytes8! long! volatile;
|
||||
r3r4 named("r3", "r4") aliases(r3, r4) bytes8! long! volatile pret;
|
||||
|
||||
r29r30 named("r29", "r30") aliases(r29, r30) bytes8! pair!;
|
||||
r27r28 named("r27", "r28") aliases(r27, r28) bytes8! pair!;
|
||||
r25r26 named("r25", "r26") aliases(r25, r26) bytes8! pair!;
|
||||
r23r24 named("r23", "r24") aliases(r23, r24) bytes8! pair!;
|
||||
r21r22 named("r21", "r22") aliases(r21, r22) bytes8! pair!;
|
||||
r19r20 named("r19", "r20") aliases(r19, r20) bytes8! pair!;
|
||||
r17r18 named("r17", "r18") aliases(r17, r18) bytes8! pair!;
|
||||
r15r16 named("r15", "r16") aliases(r15, r16) bytes8! pair!;
|
||||
r13r14 named("r13", "r14") aliases(r13, r14) bytes8! pair!;
|
||||
r29r30 named("r29", "r30") aliases(r29, r30) bytes8! long!;
|
||||
r27r28 named("r27", "r28") aliases(r27, r28) bytes8! long!;
|
||||
r25r26 named("r25", "r26") aliases(r25, r26) bytes8! long!;
|
||||
r23r24 named("r23", "r24") aliases(r23, r24) bytes8! long!;
|
||||
r21r22 named("r21", "r22") aliases(r21, r22) bytes8! long!;
|
||||
r19r20 named("r19", "r20") aliases(r19, r20) bytes8! long!;
|
||||
r17r18 named("r17", "r18") aliases(r17, r18) bytes8! long!;
|
||||
r15r16 named("r15", "r16") aliases(r15, r16) bytes8! long!;
|
||||
r13r14 named("r13", "r14") aliases(r13, r14) bytes8! long!;
|
||||
|
||||
f14 bytes4! float! volatile;
|
||||
f13 bytes4! float! volatile;
|
||||
|
@ -142,121 +142,146 @@ PATTERNS
|
|||
|
||||
/* Special */
|
||||
|
||||
PAIR(BLOCK4, BLOCK4);
|
||||
PAIR(BLOCK.I, BLOCK.I);
|
||||
|
||||
|
||||
|
||||
/* Miscellaneous special things */
|
||||
|
||||
PUSH4(in:(int)reg)
|
||||
PUSH.I(in:(int)reg)
|
||||
emit "stwu %in, -4(sp)"
|
||||
cost 4;
|
||||
|
||||
PUSH8(in:(pair)reg)
|
||||
PUSH.L(in:(long)reg)
|
||||
emit "stwu %in.0, -4(sp)"
|
||||
emit "stwu %in.1, -4(sp)"
|
||||
cost 8;
|
||||
|
||||
out:(int)reg = POP4
|
||||
PUSH.D(in:(double)reg)
|
||||
emit "stfdu %in, -8(sp)"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = POP.I
|
||||
emit "lwz %out, 0(sp)"
|
||||
emit "addi sp, sp, 4"
|
||||
cost 8;
|
||||
|
||||
out:(pair)reg = POP8
|
||||
out:(long)reg = POP.L
|
||||
emit "lwz %out.0, 4(sp)"
|
||||
emit "lwz %out.1, 0(sp)"
|
||||
emit "addi sp, sp, 8"
|
||||
cost 12;
|
||||
|
||||
out:(float)reg = POPF4
|
||||
out:(float)reg = POP.F
|
||||
emit "lfs %out, 0(sp)"
|
||||
emit "addi sp, sp, 4"
|
||||
cost 8;
|
||||
|
||||
SETRET4(in:(ret)reg)
|
||||
SETRET.I(in:(ret)reg)
|
||||
emit "! setret4"
|
||||
cost 1;
|
||||
|
||||
SETRET8(in:(pret)reg)
|
||||
SETRET.L(in:(pret)reg)
|
||||
emit "! setret8"
|
||||
cost 1;
|
||||
|
||||
STACKADJUST4(delta:CONST4)
|
||||
STACKADJUST.I(delta:CONST.I)
|
||||
when signed_constant(%delta, 16)
|
||||
emit "addi sp, sp, $delta"
|
||||
cost 4;
|
||||
|
||||
STACKADJUST4(in:(int)reg)
|
||||
STACKADJUST.I(in:(int)reg)
|
||||
emit "add sp, sp, %in"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = GETFP4
|
||||
out:(int)reg = GETFP.I
|
||||
emit "mr %out, fp"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = FPTOARGS4(GETFP4)
|
||||
out:(int)reg = FPTOARGS.I(GETFP.I)
|
||||
emit "addi %out, fp, 8"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = FPTOARGS4(in:(int)reg)
|
||||
out:(int)reg = FPTOARGS.I(in:(int)reg)
|
||||
emit "addi %out, %in, 8"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = GETSP4
|
||||
out:(int)reg = GETSP.I
|
||||
emit "mr %out, sp"
|
||||
cost 4;
|
||||
|
||||
SETSP4(in:(int)reg)
|
||||
SETSP.I(in:(int)reg)
|
||||
emit "mr sp, %in"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = COPYF.I(in:(float)reg)
|
||||
emit "stfsu %in, -4(sp)"
|
||||
emit "lwz %out, 0(sp)"
|
||||
emit "addi sp, sp, 4"
|
||||
cost 12;
|
||||
|
||||
out:(double)reg = COPYL.D(in:(long)reg)
|
||||
emit "stwu %in.0, -4(sp)"
|
||||
emit "stwu %in.1, -4(sp)"
|
||||
emit "lfd %out, 0(sp)"
|
||||
emit "addi sp, sp, 8"
|
||||
cost 16;
|
||||
|
||||
|
||||
|
||||
/* Memory operations */
|
||||
|
||||
/* Stores */
|
||||
|
||||
STORE8(addr:address, value:(pair)reg)
|
||||
STORE.L(addr:address, value:(long)reg)
|
||||
emit "stw %value.0, 4+%addr"
|
||||
emit "stw %value.1, 0+%addr"
|
||||
cost 4;
|
||||
|
||||
STORE4(addr:address, value:(int)reg)
|
||||
STORE.I(addr:address, value:(int)reg)
|
||||
emit "stw %value, %addr"
|
||||
cost 4;
|
||||
|
||||
STORE2(addr:address, value:(int)ushortX)
|
||||
STOREH.I(addr:address, value:(int)ushortX)
|
||||
emit "sth %value, %addr"
|
||||
cost 4;
|
||||
|
||||
STORE2(ADD4(left:(int)reg, right:(int)reg), value:(int)ushortX)
|
||||
STOREH.I(ADD.I(left:(int)reg, right:(int)reg), value:(int)ushortX)
|
||||
emit "sthx %value, %left, %right"
|
||||
cost 4;
|
||||
|
||||
STORE1(addr:address, value:(int)ubyteX)
|
||||
STOREB.I(addr:address, value:(int)ushortX)
|
||||
emit "sth %value, %addr"
|
||||
cost 4;
|
||||
|
||||
STOREB.I(addr:address, value:(int)ubyteX)
|
||||
emit "stb %value, %addr"
|
||||
cost 4;
|
||||
|
||||
STORE1(ADD4(left:(int)reg, right:(int)reg), value:(int)ubyteX)
|
||||
STOREB.I(ADD.I(left:(int)reg, right:(int)reg), value:(int)ubyteX)
|
||||
emit "stbx %value, %left, %right"
|
||||
cost 4;
|
||||
|
||||
/* Loads */
|
||||
|
||||
out:(int)reg = LOAD4(addr:address)
|
||||
out:(int)reg = LOAD.I(addr:address)
|
||||
emit "lwz %out, %addr"
|
||||
cost 4;
|
||||
|
||||
out:(pair)reg = LOAD8(addr:address)
|
||||
out:(long)reg = LOAD.L(addr:address)
|
||||
emit "lwz %out.0, 4+%addr"
|
||||
emit "lwz %out.1, 0+%addr"
|
||||
cost 8;
|
||||
|
||||
out:(int)ushort0 = LOAD2(addr:address)
|
||||
out:(double)reg = LOAD.D(addr:address)
|
||||
emit "lfsd %out, %addr"
|
||||
cost 4;
|
||||
|
||||
out:(int)ushort0 = LOADH.I(addr:address)
|
||||
emit "lhz %out, %addr"
|
||||
cost 4;
|
||||
|
||||
out:(int)ubyte0 = LOAD1(addr:address)
|
||||
out:(int)ubyte0 = LOADB.I(addr:address)
|
||||
emit "lbz %out, %addr"
|
||||
cost 4;
|
||||
|
||||
|
@ -302,6 +327,38 @@ PATTERNS
|
|||
emit "! reg -> ushortX"
|
||||
cost 1;
|
||||
|
||||
|
||||
/* Extensions and conversions */
|
||||
|
||||
out:(int)reg = EXTENDB.I(in:(int)reg)
|
||||
emit "extsb %out, %in"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = EXTENDH.I(in:(int)reg)
|
||||
emit "extsh %out, %in"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = FROMSI.I(in:(int)reg)
|
||||
with %out == %in
|
||||
emit "! FROMSI.I(int) -> int"
|
||||
cost 1;
|
||||
|
||||
out:(int)reg = FROMUI.I(in:(int)reg)
|
||||
with %out == %in
|
||||
emit "! FROMUI.I(int) -> int"
|
||||
cost 1;
|
||||
|
||||
out:(long)reg = FROMSI.L(in:(int)reg)
|
||||
emit "mr %out.0, %in"
|
||||
emit "srawi %out.1, %out.0, 31"
|
||||
cost 8;
|
||||
|
||||
out:(int)reg = FROMD.I(in:(double)reg)
|
||||
with corrupted(volatile)
|
||||
emit "bl .fromd2i"
|
||||
cost 4;
|
||||
|
||||
#if 0
|
||||
/* byte conversions */
|
||||
|
||||
out:(int)ubyte0 = CIU14(in:(int)ubyte0)
|
||||
|
@ -348,22 +405,23 @@ PATTERNS
|
|||
out:(int)reg = CII24(in:(int)ushortX)
|
||||
emit "extsh %out, %in"
|
||||
cost 4;
|
||||
#endif
|
||||
|
||||
|
||||
/* Locals */
|
||||
|
||||
out:(int)reg = in:LOCAL4
|
||||
out:(int)reg = in:LOCAL.I
|
||||
emit "addi %out, fp, $in"
|
||||
cost 4;
|
||||
|
||||
address = in:LOCAL4
|
||||
address = in:LOCAL.I
|
||||
emit "$in(fp)";
|
||||
|
||||
|
||||
|
||||
/* Memory addressing modes */
|
||||
|
||||
address = ADD4(addr:(int)reg, offset:CONST4)
|
||||
address = ADD.I(addr:(int)reg, offset:CONST.I)
|
||||
when signed_constant(%offset, 16)
|
||||
emit "$offset(%addr)";
|
||||
|
||||
|
@ -374,59 +432,59 @@ PATTERNS
|
|||
|
||||
/* Branches */
|
||||
|
||||
JUMP(addr:BLOCK4)
|
||||
JUMP(addr:BLOCK.I)
|
||||
emit "b $addr"
|
||||
cost 4;
|
||||
|
||||
CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
|
||||
CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||
emit "bc 12, 2, $true" /* IFTRUE EQ */
|
||||
emit "b $false"
|
||||
cost 8;
|
||||
|
||||
CJUMPLE(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
|
||||
CJUMPLE(value:(cr)cr, PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||
emit "bc 4, 1, $true" /* IFFALSE GT */
|
||||
emit "b $false"
|
||||
cost 8;
|
||||
|
||||
CJUMPLT(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
|
||||
CJUMPLT(value:(cr)cr, PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||
emit "bc 12, 0, $true" /* IFTRUE LT */
|
||||
emit "b $false"
|
||||
cost 8;
|
||||
|
||||
CALL1(dest:LABEL4)
|
||||
CALL(dest:LABEL.I)
|
||||
with corrupted(volatile)
|
||||
emit "bl $dest"
|
||||
cost 4;
|
||||
|
||||
out:(ret)reg = CALL4(dest:LABEL4)
|
||||
out:(ret)reg = CALL.I(dest:LABEL.I)
|
||||
with corrupted(volatile)
|
||||
emit "bl $dest"
|
||||
cost 4;
|
||||
|
||||
out:(pret)reg = CALL8(dest:LABEL4)
|
||||
out:(pret)reg = CALL.L(dest:LABEL.I)
|
||||
with corrupted(volatile)
|
||||
emit "bl $dest"
|
||||
cost 4;
|
||||
|
||||
CALL1(dest:(int)reg)
|
||||
CALL(dest:(int)reg)
|
||||
with corrupted(volatile)
|
||||
emit "mtspr ctr, %dest"
|
||||
emit "bcctrl 20, 0, 0"
|
||||
cost 8;
|
||||
|
||||
out:(ret)reg = CALL4(dest:(int)reg)
|
||||
out:(ret)reg = CALL.I(dest:(int)reg)
|
||||
with corrupted(volatile)
|
||||
emit "mtspr ctr, %dest"
|
||||
emit "bcctrl 20, 0, 0"
|
||||
cost 8;
|
||||
|
||||
out:(pret)reg = CALL8(dest:(int)reg)
|
||||
out:(pret)reg = CALL.L(dest:(int)reg)
|
||||
with corrupted(volatile)
|
||||
emit "mtspr ctr, %dest"
|
||||
emit "bcctrl 20, 0, 0"
|
||||
cost 8;
|
||||
|
||||
JUMP(dest:LABEL4)
|
||||
JUMP(dest:LABEL.I)
|
||||
emit "b $dest"
|
||||
cost 4;
|
||||
|
||||
|
@ -434,40 +492,40 @@ PATTERNS
|
|||
|
||||
/* Comparisons */
|
||||
|
||||
cr:(cr)cr = COMPARES44(left:(int)reg, right:(int)reg)
|
||||
cr:(cr)cr = COMPARESI.I(left:(int)reg, right:(int)reg)
|
||||
emit "cmp %cr, 0, %left, %right"
|
||||
cost 4;
|
||||
|
||||
cr:(cr)cr = COMPARES44(left:(int)reg, right:CONST4)
|
||||
cr:(cr)cr = COMPARESI.I(left:(int)reg, right:CONST.I)
|
||||
when signed_constant(%right, 16)
|
||||
emit "cmpi %cr, 0, %left, $right"
|
||||
cost 4;
|
||||
|
||||
cr:(cr)cr = COMPAREU44(left:(int)reg, right:(int)reg)
|
||||
cr:(cr)cr = COMPAREUI.I(left:(int)reg, right:(int)reg)
|
||||
emit "cmpl %cr, 0, %left, %right"
|
||||
cost 4;
|
||||
|
||||
cr:(cr)cr = COMPAREU44(left:(int)reg, right:CONST4)
|
||||
cr:(cr)cr = COMPAREUI.I(left:(int)reg, right:CONST.I)
|
||||
when signed_constant(%right, 16)
|
||||
emit "cmpli %cr, 0, %left, $right"
|
||||
cost 4;
|
||||
|
||||
out:(cr)cr = COMPARES44(in:(cr)cr, result:CONST4)
|
||||
out:(cr)cr = COMPARESI.I(in:(cr)cr, result:CONST.I)
|
||||
when specific_constant(%result, 0)
|
||||
with %out == %in
|
||||
emit "! COMPARES(cr, 0)"
|
||||
emit "! COMPARESI.I(cr, 0)"
|
||||
cost 4;
|
||||
|
||||
|
||||
|
||||
/* Booleans */
|
||||
|
||||
out:(int)reg = IFEQ4(in:(cr)cr)
|
||||
out:(int)reg = IFEQ.I(in:(cr)cr)
|
||||
emit "mfcr %out" /* get cr0 */
|
||||
emit "rlwinm %out, %out, [32-2], 2, 31" /* extract just EQ */
|
||||
cost 8;
|
||||
|
||||
out:(int)reg = IFEQ4(in:(int)reg)
|
||||
out:(int)reg = IFEQ.I(in:(int)reg)
|
||||
emit "cntlzw %out, %in" /* returns 0..32 */
|
||||
emit "rlwinm %out, %out, [32-5], 5, 31" /* if 32, return 1, otherwise 0 */
|
||||
cost 8;
|
||||
|
@ -476,6 +534,7 @@ PATTERNS
|
|||
|
||||
/* Conversions */
|
||||
|
||||
#if 0
|
||||
out:(int)reg = CIU44(in:(int)reg)
|
||||
with %out == %in
|
||||
emit "! ciu44"
|
||||
|
@ -485,7 +544,7 @@ PATTERNS
|
|||
with %out == %in
|
||||
emit "! cui44"
|
||||
cost 4;
|
||||
|
||||
#endif
|
||||
|
||||
/* ALU operations */
|
||||
|
||||
|
@ -495,13 +554,13 @@ PATTERNS
|
|||
cost 4; \
|
||||
|
||||
#define ALUC(name, instr) \
|
||||
out:(int)reg = name(left:(int)reg, right:CONST4) \
|
||||
out:(int)reg = name(left:(int)reg, right:CONST.I) \
|
||||
when signed_constant(%right, 16) \
|
||||
emit instr " %out, %left, $right" \
|
||||
cost 4; \
|
||||
|
||||
#define ALUC_reversed(name, instr) \
|
||||
out:(int)reg = name(left:CONST4, right:(int)reg) \
|
||||
out:(int)reg = name(left:CONST.I, right:(int)reg) \
|
||||
when signed_constant(%left, 16) \
|
||||
emit instr " %out, %right, $left" \
|
||||
cost 4; \
|
||||
|
@ -510,66 +569,66 @@ PATTERNS
|
|||
ALUC(name, instr) \
|
||||
ALUC_reversed(name, instr)
|
||||
|
||||
ALUR(ADD4, "add")
|
||||
ALUCC(ADD4, "addi")
|
||||
ALUR(ADD.I, "add")
|
||||
ALUCC(ADD.I, "addi")
|
||||
|
||||
out:(int)reg = SUB4(left:(int)reg, right:(int)reg)
|
||||
out:(int)reg = SUB.I(left:(int)reg, right:(int)reg)
|
||||
emit "subf %out, %left, %right"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = SUB4(left:(int)reg, right:CONST4)
|
||||
out:(int)reg = SUB.I(left:(int)reg, right:CONST.I)
|
||||
emit "addi %out, %left, -[$right]"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = MOD4(left:(int)reg, right:(int)reg)
|
||||
out:(int)reg = MOD.I(left:(int)reg, right:(int)reg)
|
||||
emit "divw %out, %left, %right"
|
||||
emit "mullw %out, %out, %right"
|
||||
emit "subf %out, %out, %left"
|
||||
cost 12;
|
||||
|
||||
out:(int)reg = MODU4(left:(int)reg, right:(int)reg)
|
||||
out:(int)reg = MODU.I(left:(int)reg, right:(int)reg)
|
||||
emit "divwu %out, %left, %right"
|
||||
emit "mullw %out, %out, %right"
|
||||
emit "subf %out, %out, %left"
|
||||
cost 12;
|
||||
|
||||
ALUR(MUL4, "mullw")
|
||||
ALUCC(MUL4, "mulli")
|
||||
ALUR(MUL.I, "mullw")
|
||||
ALUCC(MUL.I, "mulli")
|
||||
|
||||
ALUR(DIV4, "divw")
|
||||
ALUR(DIVU4, "divwu")
|
||||
ALUR(DIV.I, "divw")
|
||||
ALUR(DIVU.I, "divwu")
|
||||
|
||||
ALUR(ASL4, "slw")
|
||||
ALUR(ASL.I, "slw")
|
||||
|
||||
ALUR(LSL4, "slw")
|
||||
ALUR(LSL.I, "slw")
|
||||
|
||||
out:(int)reg = NEG4(left:(int)reg)
|
||||
out:(int)reg = NEG.I(left:(int)reg)
|
||||
emit "neg %out, %left"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = NOT4(left:(int)reg)
|
||||
out:(int)reg = NOT.I(left:(int)reg)
|
||||
emit "cntlzw %out, %left"
|
||||
emit "rlwinm %out, %out, 32-5, 5, 31"
|
||||
cost 8;
|
||||
|
||||
ALUR(AND4, "and")
|
||||
ALUCC(AND4, "andi.")
|
||||
ALUR(AND.I, "and")
|
||||
ALUCC(AND.I, "andi.")
|
||||
|
||||
ALUR(OR4, "or")
|
||||
ALUCC(OR4, "ori")
|
||||
ALUR(OR.I, "or")
|
||||
ALUCC(OR.I, "ori")
|
||||
|
||||
ALUR(EOR4, "xor")
|
||||
ALUCC(EOR4, "xori")
|
||||
ALUR(EOR.I, "xor")
|
||||
ALUCC(EOR.I, "xori")
|
||||
|
||||
out:(int)reg = value:LABEL4
|
||||
out:(int)reg = value:LABEL.I
|
||||
emit "la %out, $value"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = value:BLOCK4
|
||||
out:(int)reg = value:BLOCK.I
|
||||
emit "la %out, $value"
|
||||
cost 4;
|
||||
|
||||
out:(int)reg = value:CONST4
|
||||
out:(int)reg = value:CONST.I
|
||||
emit "li %out, $value"
|
||||
cost 8;
|
||||
|
||||
|
@ -586,46 +645,47 @@ PATTERNS
|
|||
emit instr " %out, %left, %right" \
|
||||
cost 4; \
|
||||
|
||||
out:(float)reg = LOADF4(addr:address)
|
||||
out:(float)reg = LOAD.F(addr:address)
|
||||
emit "lfs %out, %addr"
|
||||
cost 4;
|
||||
|
||||
out:(double)reg = LOADF8(addr:address)
|
||||
out:(double)reg = LOAD.D(addr:address)
|
||||
emit "lfd %out, %addr"
|
||||
cost 4;
|
||||
|
||||
out:(float)reg = value:CONSTF4
|
||||
out:(float)reg = value:CONST.F
|
||||
emit "lfs %out, address-containing-$value"
|
||||
cost 8;
|
||||
|
||||
FPU4R(ADDF4, "fadds")
|
||||
FPU8R(ADDF8, "fadd")
|
||||
FPU4R(ADDF.F, "fadds")
|
||||
FPU8R(ADDF.D, "fadd")
|
||||
|
||||
FPU4R(SUBF4, "fsubs")
|
||||
FPU8R(SUBF8, "fsub")
|
||||
FPU4R(SUBF.F, "fsubs")
|
||||
FPU8R(SUBF.D, "fsub")
|
||||
|
||||
FPU4R(MULF4, "fmuls")
|
||||
FPU8R(MULF8, "fmul")
|
||||
FPU4R(MULF.F, "fmuls")
|
||||
FPU8R(MULF.D, "fmul")
|
||||
|
||||
FPU4R(DIVF4, "fdivs")
|
||||
FPU8R(DIVF8, "fdiv")
|
||||
FPU4R(DIVF.F, "fdivs")
|
||||
FPU8R(DIVF.D, "fdiv")
|
||||
|
||||
out:(float)reg = NEGF4(left:(float)reg)
|
||||
out:(float)reg = NEGF.F(left:(float)reg)
|
||||
emit "fneg %out, %left"
|
||||
cost 4;
|
||||
|
||||
out:(double)reg = NEGF8(left:(double)reg)
|
||||
out:(double)reg = NEGF.D(left:(double)reg)
|
||||
emit "fneg %out, %left"
|
||||
cost 4;
|
||||
|
||||
cr:(cr)cr = COMPAREF44(left:(float)reg, right:(float)reg)
|
||||
cr:(cr)cr = COMPAREF.I(left:(float)reg, right:(float)reg)
|
||||
emit "fcmpu %cr, %left, %right"
|
||||
cost 4;
|
||||
|
||||
cr:(cr)cr = COMPAREF84(left:(double)reg, right:(double)reg)
|
||||
cr:(cr)cr = COMPARED.I(left:(double)reg, right:(double)reg)
|
||||
emit "fcmpu %cr, %left, %right"
|
||||
cost 4;
|
||||
|
||||
#if 0
|
||||
out:(ret)reg = CFI44(val:(fret)reg)
|
||||
with corrupted(volatile)
|
||||
emit "bl .cfi44"
|
||||
|
@ -653,6 +713,7 @@ PATTERNS
|
|||
out:(double)reg = CFF48(val:(float)reg)
|
||||
emit "fmr %out, %val"
|
||||
cost 1;
|
||||
#endif
|
||||
|
||||
/* vim: set sw=4 ts=4 expandtab : */
|
||||
|
||||
|
|
|
@ -89,7 +89,6 @@ static void convert_block(struct basicblock* bb)
|
|||
{
|
||||
struct ir* ir = pushes.item[i].right;
|
||||
ir->opcode = IR_NOP;
|
||||
ir->size = 0;
|
||||
}
|
||||
|
||||
for (i=0; i<pops.count; i++)
|
||||
|
|
|
@ -210,14 +210,14 @@ static struct insn* walk_instructions(struct burm_node* node, int goal)
|
|||
{
|
||||
switch (node->label)
|
||||
{
|
||||
case ir_to_esn(IR_REG, 1):
|
||||
case ir_to_esn(IR_REG, 2):
|
||||
case ir_to_esn(IR_REG, 4):
|
||||
case ir_to_esn(IR_REG, 8):
|
||||
case ir_to_esn(IR_REG, 0):
|
||||
current_hop->output = node->ir->result;
|
||||
break;
|
||||
|
||||
case ir_to_esn(IR_NOP, 0):
|
||||
case ir_to_esn(IR_NOP, 'I'):
|
||||
case ir_to_esn(IR_NOP, 'F'):
|
||||
case ir_to_esn(IR_NOP, 'L'):
|
||||
case ir_to_esn(IR_NOP, 'D'):
|
||||
current_hop->output = node->left->ir->result;
|
||||
break;
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ static struct burm_node* build_shadow_tree(struct ir* root, struct ir* ir)
|
|||
|
||||
if (ir->root == root)
|
||||
{
|
||||
node->label = ir_to_esn(ir->opcode, ir->size);
|
||||
node->label = ir_to_esn(ir->opcode, ir->type);
|
||||
|
||||
if (ir->left)
|
||||
node->left = build_shadow_tree(root, ir->left);
|
||||
|
|
|
@ -63,11 +63,10 @@ static bool rewrite_loads_cb(struct ir* ir, void* user)
|
|||
if (ir->right && is_local(ir->right))
|
||||
ir->right = definition;
|
||||
|
||||
/* Otherwise, go via a IR_REG (which should, with luck, turn into no code). */
|
||||
/* Otherwise, go via a IR_NOP (which should, with luck, turn into no code). */
|
||||
if (is_local(ir))
|
||||
{
|
||||
ir->opcode = IR_NOP;
|
||||
ir->size = 0;
|
||||
ir->left = definition;
|
||||
ir->right = NULL;
|
||||
}
|
||||
|
@ -108,7 +107,6 @@ static void recursively_rewrite_tree(struct basicblock* bb)
|
|||
if (ir->opcode == IR_STORE)
|
||||
{
|
||||
ir->opcode = IR_NOP;
|
||||
ir->size = 0;
|
||||
ir->left = ir->right;
|
||||
ir->right = NULL;
|
||||
}
|
||||
|
|
|
@ -212,11 +212,11 @@ static struct ir* new_copy(char wanted, char real, struct ir* ir)
|
|||
if ((wanted == 'F') && (real == 'I'))
|
||||
opcode = IR_COPYI;
|
||||
else if ((wanted == 'D') && (real == 'L'))
|
||||
opcode = IR_COPYI;
|
||||
opcode = IR_COPYL;
|
||||
else if ((wanted == 'I') && (real == 'F'))
|
||||
opcode = IR_COPYF;
|
||||
else if ((wanted == 'L') && (real == 'D'))
|
||||
opcode = IR_COPYF;
|
||||
opcode = IR_COPYD;
|
||||
else
|
||||
fatal("type mismatch: parent IR wanted %c, child IR provided %c",
|
||||
wanted, real);
|
||||
|
|
|
@ -6,7 +6,7 @@ static int stackptr;
|
|||
static struct ir* stack[64];
|
||||
static struct ir* lastcall;
|
||||
|
||||
static struct ir* convert(struct ir* src, int destsize, int opcodebase);
|
||||
static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode);
|
||||
static struct ir* appendir(struct ir* ir);
|
||||
|
||||
static void reset_stack(void)
|
||||
|
@ -19,17 +19,22 @@ static void push(struct ir* ir)
|
|||
if (stackptr == sizeof(stack)/sizeof(*stack))
|
||||
fatal("stack overflow");
|
||||
|
||||
#if 0
|
||||
/* If we try to push something which is too small, convert it to a word
|
||||
* first. */
|
||||
|
||||
if (ir->size < EM_wordsize)
|
||||
ir = convert(ir, EM_wordsize, IR_CIU1);
|
||||
ir = convertu(ir, EM_wordsize);
|
||||
#endif
|
||||
|
||||
stack[stackptr++] = ir;
|
||||
}
|
||||
|
||||
static struct ir* pop(int size)
|
||||
{
|
||||
if (size < EM_wordsize)
|
||||
size = EM_wordsize;
|
||||
|
||||
if (stackptr == 0)
|
||||
{
|
||||
/* Nothing in our fake stack, so we have to read from the real stack. */
|
||||
|
@ -47,10 +52,12 @@ static struct ir* pop(int size)
|
|||
{
|
||||
struct ir* ir = stack[--stackptr];
|
||||
|
||||
#if 0
|
||||
/* If we try to pop something which is smaller than a word, convert it first. */
|
||||
|
||||
if (size < EM_wordsize)
|
||||
ir = convert(ir, size, IR_CIU1);
|
||||
ir = convertu(ir, size);
|
||||
#endif
|
||||
|
||||
if (ir->size != size)
|
||||
fatal("expected an item on stack of size %d, but got %d\n", size, ir->size);
|
||||
|
@ -131,18 +138,39 @@ static struct ir* address_of_external(const char* label, arith offset)
|
|||
new_labelir(label);
|
||||
}
|
||||
|
||||
static struct ir* convert(struct ir* src, int destsize, int opcode)
|
||||
static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode)
|
||||
{
|
||||
switch (src->size)
|
||||
if (srcsize == 1)
|
||||
{
|
||||
case 1: opcode += 0; break;
|
||||
case 2: opcode += 1; break;
|
||||
case 4: opcode += 2; break;
|
||||
case 8: opcode += 3; break;
|
||||
default:
|
||||
fatal("can't convert from things of size %d", src->size);
|
||||
if ((opcode == IR_FROMSI) || (opcode == IR_FROMSL))
|
||||
{
|
||||
src = new_ir1(
|
||||
IR_EXTENDB, EM_wordsize,
|
||||
src
|
||||
);
|
||||
}
|
||||
srcsize = EM_wordsize;
|
||||
}
|
||||
|
||||
if ((srcsize == 2) && (srcsize != EM_wordsize))
|
||||
{
|
||||
if ((opcode == IR_FROMSI) || (opcode == IR_FROMSL))
|
||||
{
|
||||
src = new_ir1(
|
||||
IR_EXTENDH, EM_wordsize,
|
||||
src
|
||||
);
|
||||
}
|
||||
srcsize = EM_wordsize;
|
||||
}
|
||||
|
||||
if (src->size == EM_wordsize)
|
||||
{}
|
||||
else if (src->size == (2*EM_wordsize))
|
||||
opcode++;
|
||||
else
|
||||
fatal("can't convert from %d to %d", src->size, destsize);
|
||||
|
||||
return
|
||||
new_ir1(
|
||||
opcode, destsize,
|
||||
|
@ -153,15 +181,12 @@ static struct ir* convert(struct ir* src, int destsize, int opcode)
|
|||
static struct ir* compare(struct ir* left, struct ir* right,
|
||||
int size, int opcode)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1: opcode += 0; break;
|
||||
case 2: opcode += 1; break;
|
||||
case 4: opcode += 2; break;
|
||||
case 8: opcode += 3; break;
|
||||
default:
|
||||
fatal("can't compare things of size %d", size);
|
||||
}
|
||||
if (size == EM_wordsize)
|
||||
{}
|
||||
else if (size == (2*EM_wordsize))
|
||||
opcode++;
|
||||
else
|
||||
fatal("can't compare things of size %d", size);
|
||||
|
||||
return
|
||||
new_ir2(
|
||||
|
@ -170,6 +195,66 @@ static struct ir* compare(struct ir* left, struct ir* right,
|
|||
);
|
||||
}
|
||||
|
||||
static struct ir* store(int size, struct ir* address, int offset, struct ir* value)
|
||||
{
|
||||
int opcode;
|
||||
|
||||
if (size == 1)
|
||||
{
|
||||
opcode = IR_STOREB;
|
||||
size = EM_wordsize;
|
||||
}
|
||||
else if ((size < EM_wordsize) && (size == 2))
|
||||
{
|
||||
opcode = IR_STOREH;
|
||||
size = EM_wordsize;
|
||||
}
|
||||
else
|
||||
opcode = IR_STORE;
|
||||
|
||||
if (offset > 0)
|
||||
address = new_ir2(
|
||||
IR_ADD, EM_pointersize,
|
||||
address, new_wordir(offset)
|
||||
);
|
||||
|
||||
return
|
||||
new_ir2(
|
||||
opcode, size,
|
||||
address, value
|
||||
);
|
||||
}
|
||||
|
||||
static struct ir* load(int size, struct ir* address, int offset)
|
||||
{
|
||||
int opcode;
|
||||
|
||||
if (size == 1)
|
||||
{
|
||||
opcode = IR_LOADB;
|
||||
size = EM_wordsize;
|
||||
}
|
||||
else if ((size < EM_wordsize) && (size == 2))
|
||||
{
|
||||
opcode = IR_LOADH;
|
||||
size = EM_wordsize;
|
||||
}
|
||||
else
|
||||
opcode = IR_LOAD;
|
||||
|
||||
if (offset > 0)
|
||||
address = new_ir2(
|
||||
IR_ADD, EM_pointersize,
|
||||
address, new_wordir(offset)
|
||||
);
|
||||
|
||||
return
|
||||
new_ir1(
|
||||
opcode, size,
|
||||
address
|
||||
);
|
||||
}
|
||||
|
||||
static struct ir* tristate_compare(int size, int opcode)
|
||||
{
|
||||
struct ir* right = pop(size);
|
||||
|
@ -197,7 +282,7 @@ static void simple_convert(int opcode)
|
|||
|
||||
value = pop(srcsize->u.ivalue);
|
||||
push(
|
||||
convert(value, destsize->u.ivalue, opcode)
|
||||
convert(value, srcsize->u.ivalue, destsize->u.ivalue, opcode)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -212,7 +297,7 @@ static void simple_branch2(int opcode, int size,
|
|||
appendir(
|
||||
new_ir2(
|
||||
irop, 0,
|
||||
compare(left, right, size, IR_COMPARES1),
|
||||
compare(left, right, size, IR_COMPARESI),
|
||||
new_ir2(
|
||||
IR_PAIR, 0,
|
||||
new_bbir(truebb),
|
||||
|
@ -238,7 +323,7 @@ static void simple_test(int size, int irop)
|
|||
push(
|
||||
new_ir1(
|
||||
irop, EM_wordsize,
|
||||
tristate_compare0(size, IR_COMPARES1)
|
||||
tristate_compare0(size, IR_COMPARESI)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -273,16 +358,16 @@ static void insn_simple(int opcode)
|
|||
break;
|
||||
}
|
||||
|
||||
case op_cii: simple_convert(IR_CII1); break;
|
||||
case op_ciu: simple_convert(IR_CIU1); break;
|
||||
case op_cui: simple_convert(IR_CUI1); break;
|
||||
case op_cfi: simple_convert(IR_CFI1); break;
|
||||
case op_cif: simple_convert(IR_CIF1); break;
|
||||
case op_cff: simple_convert(IR_CFF1); break;
|
||||
case op_cii: simple_convert(IR_FROMSI); break;
|
||||
case op_ciu: simple_convert(IR_FROMSI); break;
|
||||
case op_cui: simple_convert(IR_FROMUI); break;
|
||||
case op_cfi: simple_convert(IR_FROMF); break;
|
||||
case op_cif: simple_convert(IR_FROMSI); break;
|
||||
case op_cff: simple_convert(IR_FROMF); break;
|
||||
|
||||
case op_cmp:
|
||||
push(
|
||||
tristate_compare(EM_pointersize, IR_COMPAREU1)
|
||||
tristate_compare(EM_pointersize, IR_COMPAREUI)
|
||||
);
|
||||
break;
|
||||
|
||||
|
@ -468,14 +553,12 @@ static struct ir* extract_block_refs(struct basicblock* bb)
|
|||
static void change_by(struct ir* address, int amount)
|
||||
{
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize,
|
||||
address,
|
||||
store(
|
||||
EM_wordsize, address, 0,
|
||||
new_ir2(
|
||||
IR_ADD, EM_wordsize,
|
||||
new_ir1(
|
||||
IR_LOAD, EM_wordsize,
|
||||
address
|
||||
load(
|
||||
EM_wordsize, address, 0
|
||||
),
|
||||
new_wordir(amount)
|
||||
)
|
||||
|
@ -529,33 +612,33 @@ static void insn_ivalue(int opcode, arith value)
|
|||
case op_ngf: simple_alu1(opcode, value, IR_NEGF); break;
|
||||
|
||||
case op_cmu: /* fall through */
|
||||
case op_cms: push(tristate_compare(value, IR_COMPAREU1)); break;
|
||||
case op_cmi: push(tristate_compare(value, IR_COMPARES1)); break;
|
||||
case op_cmf: push(tristate_compare(value, IR_COMPAREF1)); break;
|
||||
case op_cms: push(tristate_compare(value, IR_COMPAREUI)); break;
|
||||
case op_cmi: push(tristate_compare(value, IR_COMPARESI)); break;
|
||||
case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break;
|
||||
|
||||
case op_lol:
|
||||
push(
|
||||
new_ir1(
|
||||
IR_LOAD, EM_wordsize,
|
||||
new_localir(value)
|
||||
load(
|
||||
EM_wordsize,
|
||||
new_localir(value), 0
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case op_ldl:
|
||||
push(
|
||||
new_ir1(
|
||||
IR_LOAD, EM_wordsize*2,
|
||||
new_localir(value)
|
||||
load(
|
||||
EM_wordsize*2,
|
||||
new_localir(value), 0
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case op_stl:
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize,
|
||||
new_localir(value),
|
||||
store(
|
||||
EM_wordsize,
|
||||
new_localir(value), 0,
|
||||
pop(EM_wordsize)
|
||||
)
|
||||
);
|
||||
|
@ -563,9 +646,9 @@ static void insn_ivalue(int opcode, arith value)
|
|||
|
||||
case op_sdl:
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize*2,
|
||||
new_localir(value),
|
||||
store(
|
||||
EM_wordsize*2,
|
||||
new_localir(value), 0,
|
||||
pop(EM_wordsize*2)
|
||||
)
|
||||
);
|
||||
|
@ -579,24 +662,24 @@ static void insn_ivalue(int opcode, arith value)
|
|||
|
||||
case op_lil:
|
||||
push(
|
||||
new_ir1(
|
||||
IR_LOAD, EM_wordsize,
|
||||
new_ir1(
|
||||
IR_LOAD, EM_pointersize,
|
||||
new_localir(value)
|
||||
)
|
||||
load(
|
||||
EM_wordsize,
|
||||
load(
|
||||
EM_pointersize,
|
||||
new_localir(value), 0
|
||||
), 0
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case op_sil:
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize,
|
||||
new_ir1(
|
||||
IR_LOAD, EM_pointersize,
|
||||
new_localir(value)
|
||||
),
|
||||
store(
|
||||
EM_wordsize,
|
||||
load(
|
||||
EM_pointersize,
|
||||
new_localir(value), 0
|
||||
), 0,
|
||||
pop(EM_wordsize)
|
||||
)
|
||||
);
|
||||
|
@ -612,9 +695,9 @@ static void insn_ivalue(int opcode, arith value)
|
|||
|
||||
case op_zrl:
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize,
|
||||
new_localir(value),
|
||||
store(
|
||||
EM_wordsize,
|
||||
new_localir(value), 0,
|
||||
new_wordir(0)
|
||||
)
|
||||
);
|
||||
|
@ -630,26 +713,18 @@ static void insn_ivalue(int opcode, arith value)
|
|||
|
||||
case op_loe:
|
||||
push(
|
||||
new_ir1(
|
||||
IR_LOAD, EM_wordsize,
|
||||
new_ir2(
|
||||
IR_ADD, EM_pointersize,
|
||||
new_labelir(".hol0"),
|
||||
new_wordir(value)
|
||||
)
|
||||
load(
|
||||
EM_wordsize,
|
||||
new_labelir(".hol0"), value
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case op_ste:
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize,
|
||||
new_ir2(
|
||||
IR_ADD, EM_pointersize,
|
||||
new_labelir(".hol0"),
|
||||
new_wordir(value)
|
||||
),
|
||||
store(
|
||||
EM_wordsize,
|
||||
new_labelir(".hol0"), value,
|
||||
pop(EM_wordsize)
|
||||
)
|
||||
);
|
||||
|
@ -657,13 +732,9 @@ static void insn_ivalue(int opcode, arith value)
|
|||
|
||||
case op_zre:
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize,
|
||||
new_ir2(
|
||||
IR_ADD, EM_pointersize,
|
||||
new_labelir(".hol0"),
|
||||
new_wordir(value)
|
||||
),
|
||||
store(
|
||||
EM_wordsize,
|
||||
new_labelir(".hol0"), value,
|
||||
new_wordir(0)
|
||||
)
|
||||
);
|
||||
|
@ -694,9 +765,9 @@ static void insn_ivalue(int opcode, arith value)
|
|||
s = value;
|
||||
|
||||
push(
|
||||
new_ir1(
|
||||
IR_LOAD, s,
|
||||
ptradd(ptr, offset)
|
||||
load(
|
||||
s,
|
||||
ptr, offset
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -713,13 +784,9 @@ static void insn_ivalue(int opcode, arith value)
|
|||
struct ir* ptr = pop(EM_pointersize);
|
||||
|
||||
push(
|
||||
new_ir1(
|
||||
IR_LOAD, EM_wordsize,
|
||||
new_ir2(
|
||||
IR_ADD, EM_pointersize,
|
||||
ptr,
|
||||
new_wordir(value)
|
||||
)
|
||||
load(
|
||||
EM_wordsize,
|
||||
ptr, value
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
@ -731,9 +798,10 @@ static void insn_ivalue(int opcode, arith value)
|
|||
struct ir* val = pop(value);
|
||||
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, value,
|
||||
ptr, val
|
||||
store(
|
||||
value,
|
||||
ptr, 0,
|
||||
val
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
@ -745,13 +813,9 @@ static void insn_ivalue(int opcode, arith value)
|
|||
struct ir* val = pop(EM_wordsize);
|
||||
|
||||
appendir(
|
||||
new_ir2(
|
||||
IR_STORE, EM_wordsize,
|
||||
new_ir2(
|
||||
IR_ADD, EM_pointersize,
|
||||
ptr,
|
||||
new_wordir(value)
|
||||
),
|
||||
store(
|
||||
EM_wordsize,
|
||||
ptr, value,
|
||||
val
|
||||
)
|
||||
);
|
||||
|
@ -764,7 +828,7 @@ static void insn_ivalue(int opcode, arith value)
|
|||
struct ir* ptr = pop(EM_pointersize);
|
||||
|
||||
if (value != EM_pointersize)
|
||||
off = convert(off, EM_pointersize, IR_CII1);
|
||||
off = convert(off, value, EM_pointersize, IR_FROMUI);
|
||||
|
||||
push(
|
||||
new_ir2(
|
||||
|
@ -801,7 +865,7 @@ static void insn_ivalue(int opcode, arith value)
|
|||
);
|
||||
|
||||
if (value != EM_pointersize)
|
||||
delta = convert(delta, value, IR_CII1);
|
||||
delta = convert(delta, EM_pointersize, value, IR_FROMUI);
|
||||
|
||||
push(delta);
|
||||
break;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include "iburg.h"
|
||||
#include "astring.h"
|
||||
|
||||
#define YYDEBUG 1
|
||||
|
||||
|
@ -55,8 +56,9 @@ extern int yylex(void);
|
|||
%type <rule> pattern
|
||||
%type <rule> pattern_constraints
|
||||
%type <rule> pattern_emit
|
||||
%type <stringlist> aliases;
|
||||
%type <stringlist> names;
|
||||
%type <string> nodename
|
||||
%type <stringlist> aliases
|
||||
%type <stringlist> names
|
||||
%type <stringlist> qfragments
|
||||
%type <terminfo> terminfo
|
||||
%type <tree> rhs
|
||||
|
@ -126,10 +128,15 @@ rhs
|
|||
;
|
||||
|
||||
terminfo
|
||||
: ID { $$.name = $1; }
|
||||
| '(' ID ')' ID { $$.attr = $2; $$.name = $4; }
|
||||
| ID ':' ID { $$.label = $1; $$.name = $3; }
|
||||
| ID ':' '(' ID ')' ID { $$.label = $1; $$.attr = $4; $$.name = $6; }
|
||||
: nodename { $$.name = $1; }
|
||||
| '(' ID ')' nodename { $$.attr = $2; $$.name = $4; }
|
||||
| ID ':' nodename { $$.label = $1; $$.name = $3; }
|
||||
| ID ':' '(' ID ')' nodename { $$.label = $1; $$.attr = $4; $$.name = $6; }
|
||||
;
|
||||
|
||||
nodename
|
||||
: ID { $$ = $1; }
|
||||
| ID '.' ID { $$ = aprintf("%s.%s", $1, $3); }
|
||||
;
|
||||
|
||||
pattern_emit
|
||||
|
|
|
@ -151,14 +151,20 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
const static struct terminfo reg = { "reg", NULL, "" };
|
||||
const static struct terminfo REG = { "REG", NULL, NULL };
|
||||
const static struct terminfo NOP = { "NOP", NULL, NULL };
|
||||
const static struct terminfo NOPI = { "NOP.I", NULL, NULL };
|
||||
const static struct terminfo NOPF = { "NOP.F", NULL, NULL };
|
||||
const static struct terminfo NOPL = { "NOP.L", NULL, NULL };
|
||||
const static struct terminfo NOPD = { "NOP.D", NULL, NULL };
|
||||
const static struct terminfo RET = { "RET", NULL, NULL };
|
||||
|
||||
nonterm("reg", true);
|
||||
|
||||
rule(NULL, tree(®, NULL, NULL))->cost = 1;
|
||||
rule(®, tree(®, NULL, NULL))->cost = 1;
|
||||
rule(®, tree(&NOP, tree(®, NULL, NULL), NULL))->cost = 1;
|
||||
rule(®, tree(&NOPI, tree(®, NULL, NULL), NULL))->cost = 1;
|
||||
rule(®, tree(&NOPF, tree(®, NULL, NULL), NULL))->cost = 1;
|
||||
rule(®, tree(&NOPL, tree(®, NULL, NULL), NULL))->cost = 1;
|
||||
rule(®, tree(&NOPD, tree(®, NULL, NULL), NULL))->cost = 1;
|
||||
rule(NULL, tree(&RET, NULL, NULL))->cost = 1;
|
||||
}
|
||||
|
||||
|
@ -195,10 +201,10 @@ int main(int argc, char* argv[])
|
|||
return errcnt > 0;
|
||||
}
|
||||
|
||||
static void registerterminal(const struct ir_data* data, int iropcode, int size)
|
||||
static void registerterminal(const struct ir_data* data, int iropcode, char type)
|
||||
{
|
||||
const char* s = (size == 0) ? data->name : aprintf("%s%d", data->name, size);
|
||||
int esn = ir_to_esn(iropcode, size);
|
||||
const char* s = (type == 0) ? data->name : aprintf("%s.%c", data->name, type);
|
||||
int esn = ir_to_esn(iropcode, type);
|
||||
|
||||
term(s, esn);
|
||||
}
|
||||
|
@ -209,15 +215,11 @@ static void registerterminals(void)
|
|||
|
||||
for (i=0; i<IR__COUNT; i++)
|
||||
{
|
||||
if (ir_data[i].flags & IRF_SIZED)
|
||||
{
|
||||
registerterminal(&ir_data[i], i, 1);
|
||||
registerterminal(&ir_data[i], i, 2);
|
||||
registerterminal(&ir_data[i], i, 4);
|
||||
registerterminal(&ir_data[i], i, 8);
|
||||
}
|
||||
else
|
||||
registerterminal(&ir_data[i], i, 0);
|
||||
registerterminal(&ir_data[i], i, 'I');
|
||||
registerterminal(&ir_data[i], i, 'F');
|
||||
registerterminal(&ir_data[i], i, 'L');
|
||||
registerterminal(&ir_data[i], i, 'D');
|
||||
registerterminal(&ir_data[i], i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
# Flags:
|
||||
# S: has size (use in CONST1, CONST2, CONST4, CONST8 forms)
|
||||
# V: has no size (use in JUMP, CJUMP, RET forms)
|
||||
#
|
||||
# Types:
|
||||
#
|
||||
# I, F, L, D: int, float, long, double
|
||||
|
@ -13,7 +9,7 @@
|
|||
S ?=.. CONST # must be followed by float form
|
||||
S ?=.. CONSTF
|
||||
V ?=.. REG
|
||||
V ?=?. NOP
|
||||
S ?=?. NOP
|
||||
S I=.. LABEL
|
||||
S I=.. BLOCK
|
||||
V ?=.. PAIR
|
||||
|
@ -24,13 +20,14 @@ V ?=.. PHI
|
|||
# Magic stack operations
|
||||
S ?=?. PUSH
|
||||
S ?=.. POP
|
||||
S ?=.. POPF
|
||||
|
||||
# Memory operations
|
||||
S ?=I. LOAD # must be followed by float form
|
||||
S f=I. LOADF
|
||||
S ?=I. LOAD
|
||||
S I=I. LOADB
|
||||
S I=I. LOADH
|
||||
S ?=I? STORE
|
||||
S ?=If STOREF
|
||||
S ?=I? STOREB
|
||||
S ?=I? STOREH
|
||||
|
||||
# Arithemetic operations
|
||||
S i=ii ADD
|
||||
|
@ -59,58 +56,38 @@ S i=ii LSR
|
|||
|
||||
# Bitwise conversions
|
||||
# (Remember, these don't change the value, merely move it)
|
||||
S i=f. COPYF
|
||||
S f=i. COPYI
|
||||
# (order is important here; the 8-byte version of each must immediate succeed
|
||||
# the 4-byte version)
|
||||
S F=I. COPYI
|
||||
S I=F. COPYF
|
||||
S D=L. COPYL
|
||||
S L=D. COPYD
|
||||
|
||||
# Semantic conversions
|
||||
S F=D. D2F
|
||||
S D=F. F2D
|
||||
# (order is important here; the 8-byte version of each must immediate succeed
|
||||
# the 4-byte version)
|
||||
S ?=I. FROMUI
|
||||
S ?=L. FROMUL
|
||||
S ?=I. FROMSI
|
||||
S ?=L. FROMSL
|
||||
S ?=F. FROMF
|
||||
S ?=D. FROMD
|
||||
|
||||
S I=I. CII1
|
||||
S I=I. CII2
|
||||
S I=I. CII4
|
||||
S L=L. CII8
|
||||
|
||||
S I=I. CIU1
|
||||
S I=I. CIU2
|
||||
S I=I. CIU4
|
||||
S L=L. CIU8
|
||||
|
||||
S I=I. CUI1
|
||||
S I=I. CUI2
|
||||
S I=I. CUI4
|
||||
S L=L. CUI8
|
||||
|
||||
S I=F. CFI1
|
||||
S I=F. CFI2
|
||||
S I=F. CFI4
|
||||
S L=D. CFI8
|
||||
|
||||
S I=F. CIF1
|
||||
S I=F. CIF2
|
||||
S I=F. CIF4
|
||||
S L=D. CIF8
|
||||
|
||||
S F=F. CFF1
|
||||
S F=F. CFF2
|
||||
S F=F. CFF4
|
||||
S D=D. CFF8
|
||||
# The H versions are only used if wordsize > 2
|
||||
S I=I. EXTENDB
|
||||
S I=I. EXTENDH
|
||||
S I=I. TRUNCATEB
|
||||
S I=I. TRUNCATEH
|
||||
|
||||
# Tristate comparisons
|
||||
S I=II COMPARES1
|
||||
S I=II COMPARES2
|
||||
S I=II COMPARES4
|
||||
S I=LL COMPARES8
|
||||
|
||||
S I=II COMPAREU1
|
||||
S I=II COMPAREU2
|
||||
S I=II COMPAREU4
|
||||
S I=LL COMPAREU8
|
||||
|
||||
S I=FF COMPAREF1
|
||||
S I=FF COMPAREF2
|
||||
S I=FF COMPAREF4
|
||||
S I=DD COMPAREF8
|
||||
# (order is important here; the 8-byte version of each must immediate succeed
|
||||
# the 4-byte version)
|
||||
S I=II COMPARESI
|
||||
S I=LL COMPARESL
|
||||
S I=II COMPAREUI
|
||||
S I=LL COMPAREUL
|
||||
S I=FF COMPAREF
|
||||
S I=DD COMPARED
|
||||
|
||||
# Tristate to boolean conversion
|
||||
S I=I. IFEQ
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
/* Excruciating macro which packs ir opcodes and sizes into an int for iburg's benefit.
|
||||
*
|
||||
* Sizes are mapped as: 0=1, 1=1, 2=2, 4=3, 8=4.
|
||||
* Types are mapped to: I=1, F=2, L=3, D=4
|
||||
*/
|
||||
#define ir_to_esn(iropcode, size) \
|
||||
((iropcode)*4 + \
|
||||
(((size) == 4) ? 2 : \
|
||||
((size) == 8) ? 3 : \
|
||||
((size) == 0) ? 0 : \
|
||||
(size-1)))
|
||||
#define ir_to_esn(iropcode, type) \
|
||||
((iropcode)*5 + \
|
||||
(((type) == 'I') ? 1 : \
|
||||
((type) == 'F') ? 2 : \
|
||||
((type) == 'L') ? 3 : \
|
||||
((type) == 'D') ? 4 : 0))
|
||||
|
||||
#define STATE_TYPE void*
|
||||
|
||||
|
|
Loading…
Reference in a new issue