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:
David Given 2016-10-23 21:54:14 +02:00
parent b1a3d76d6f
commit abd0cedd61
11 changed files with 419 additions and 311 deletions

View file

@ -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;

View file

@ -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 : */

View file

@ -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++)

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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,17 +138,38 @@ 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(
@ -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:
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;

View file

@ -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

View file

@ -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(&reg, NULL, NULL))->cost = 1;
rule(&reg, tree(&REG, NULL, NULL))->cost = 1;
rule(&reg, tree(&NOP, tree(&reg, NULL, NULL), NULL))->cost = 1;
rule(&reg, tree(&NOPI, tree(&reg, NULL, NULL), NULL))->cost = 1;
rule(&reg, tree(&NOPF, tree(&reg, NULL, NULL), NULL))->cost = 1;
rule(&reg, tree(&NOPL, tree(&reg, NULL, NULL), NULL))->cost = 1;
rule(&reg, tree(&NOPD, tree(&reg, 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,14 +215,10 @@ 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, '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);
}
}

View file

@ -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

View file

@ -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*