rather than the size. Much cleaner and simpler.
{
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))
{
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;
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;
break;
case burm_double_ATTR:
- case burm_pair_ATTR:
+ case burm_long_ATTR:
hop_add_insel(hop, "addi sp, sp, 8");
break;
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;
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;
-
- 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!;
+ 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! 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;
/* 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;
/* 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;
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)
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)";
/* 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;
/* 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;
/* Conversions */
+#if 0
out:(int)reg = CIU44(in:(int)reg)
with %out == %in
emit "! ciu44"
with %out == %in
emit "! cui44"
cost 4;
-
+#endif
/* ALU operations */
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; \
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;
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"
out:(double)reg = CFF48(val:(float)reg)
emit "fmr %out, %val"
cost 1;
+ #endif
/* vim: set sw=4 ts=4 expandtab : */
{
struct ir* ir = pushes.item[i].right;
ir->opcode = IR_NOP;
- ir->size = 0;
}
for (i=0; i<pops.count; i++)
{
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;
}
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);
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;
}
if (ir->opcode == IR_STORE)
{
ir->opcode = IR_NOP;
- ir->size = 0;
ir->left = ir->right;
ir->right = NULL;
}
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);
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)
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. */
{
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);
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,
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(
);
}
+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);
value = pop(srcsize->u.ivalue);
push(
- convert(value, destsize->u.ivalue, opcode)
+ convert(value, srcsize->u.ivalue, destsize->u.ivalue, opcode)
);
}
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),
push(
new_ir1(
irop, EM_wordsize,
- tristate_compare0(size, IR_COMPARES1)
+ tristate_compare0(size, IR_COMPARESI)
)
);
}
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;
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)
)
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)
)
);
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)
)
);
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)
)
);
case op_zrl:
appendir(
- new_ir2(
- IR_STORE, EM_wordsize,
- new_localir(value),
+ store(
+ EM_wordsize,
+ new_localir(value), 0,
new_wordir(0)
)
);
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)
)
);
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)
)
);
s = value;
push(
- new_ir1(
- IR_LOAD, s,
- ptradd(ptr, offset)
+ load(
+ s,
+ ptr, offset
)
);
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;
struct ir* val = pop(value);
appendir(
- new_ir2(
- IR_STORE, value,
- ptr, val
+ store(
+ value,
+ ptr, 0,
+ val
)
);
break;
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
)
);
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(
);
if (value != EM_pointersize)
- delta = convert(delta, value, IR_CII1);
+ delta = convert(delta, EM_pointersize, value, IR_FROMUI);
push(delta);
break;
#include <stdint.h>
#include <limits.h>
#include "iburg.h"
+#include "astring.h"
#define YYDEBUG 1
%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
;
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
{
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;
}
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);
}
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);
}
}
-# 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
S ?=.. CONST # must be followed by float form
S ?=.. CONSTF
V ?=.. REG
-V ?=?. NOP
+S ?=?. NOP
S I=.. LABEL
S I=.. BLOCK
V ?=.. PAIR
# 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
# 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
-
-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
+# (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
+
+# 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
/* 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*