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