array_append(&hop->insels, insel);
}
-void hop_add_reg_insel(struct hop* hop, struct hop* reg)
+void hop_add_reg_insel(struct hop* hop, struct ir* ir, int insn_no)
{
struct insel* insel = new_insel(INSEL_REG);
- insel->u.reg = reg;
+ insel->u.reg.ir = ir;
+ insel->u.reg.insn_no = insn_no;
array_append(&hop->insels, insel);
}
break;
case INSEL_REG:
- tracef(k, "%%%d", insel->u.reg->id);
+ tracef(k, "$%d.%d", insel->u.reg.ir->id, insel->u.reg.insn_no);
break;
case INSEL_STRING:
union
{
const char* string;
- struct hop* reg;
+ struct
+ {
+ struct ir* ir;
+ int insn_no;
+ }
+ reg;
struct ir* value;
}
u;
int id;
int insn_no;
struct ir* ir;
- struct hop* result;
- ARRAYOF(struct hop) params;
ARRAYOF(struct insel) insels;
};
extern struct hop* new_hop(int insn_no, struct ir* ir);
extern void hop_add_string_insel(struct hop* hop, const char* string);
-extern void hop_add_reg_insel(struct hop* hop, struct hop* reg);
+extern void hop_add_reg_insel(struct hop* hop, struct ir* ir, int insn_no);
extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
extern void hop_add_eoi_insel(struct hop* hop);
#endif
-
if (cb(ir, user))
return ir;
- if (ir->left && !ir->left->is_sequence)
+ if (ir->left && !ir->left->is_root)
{
struct ir* irr = ir_walk(ir->left, cb, user);
if (irr)
return irr;
}
- if (ir->right && !ir->right->is_sequence)
+ if (ir->right && !ir->right->is_root)
{
struct ir* irr = ir_walk(ir->right, cb, user);
if (irr)
default:
if (ir->left)
{
- if (ir->left->is_sequence)
+ if (ir->left->is_root)
tracef(k, "$%d", ir->left->id);
else
print_expr(k, ir->left);
if (ir->right)
{
tracef(k, ", ");
- if (ir->right->is_sequence)
+ if (ir->right->is_root)
tracef(k, "$%d", ir->right->id);
else
print_expr(k, ir->right);
void* state_label; /* used by the iburg instruction selector */
int insn_no; /* the table rule number for this instruction */
- struct hop* hop; /* only for IRs that root a hardware op */
+ ARRAYOF(struct hop) hops; /* only for root IRs */
- bool is_sequence : 1;
+ bool is_root : 1;
bool is_generated : 1;
};
static int OP_LABEL(struct ir* ir)
{
- if (ir->is_generated)
+ if (ir->is_root && ir->is_generated)
{
- assert(ir->is_sequence);
return ir_to_esn(IR_REG, ir->size);
}
return ir_to_esn(ir->opcode, ir->size);
for (i=0; i<pushes.count; i++)
{
struct ir* ir = pushes.item[i];
- assert(ir->is_sequence);
+ assert(ir->is_root);
*ir = *ir->left;
- ir->is_sequence = true;
+ ir->is_root = true;
}
for (i=0; i<pops.count; i++)
for (j=1; j<pushes.count; j++)
phi = new_ir2(IR_PHI, ir->size, phi, pushes.item[j]);
- phi->is_sequence = ir->is_sequence;
+ phi->is_root = ir->is_root;
*ir = *phi;
}
}
exit(1);
}
-static void emit_reg(struct ir* ir)
+static void emit_reg(struct ir* ir, int goal)
{
- if (ir->hop)
- hop_add_reg_insel(current_hop, ir->hop);
- else
- {
- const struct burm_instruction_data* insndata = &burm_instruction_data[ir->insn_no];
- if (insndata->emitter)
- insndata->emitter(ir, &emitter_data);
- }
+ hop_add_reg_insel(current_hop, ir, goal);
}
static void emit_string(const char* data)
hop_add_string_insel(current_hop, data);
}
+static void emit_fragment(struct ir* ir, int goal)
+{
+ int insn_no = burm_rule(ir->state_label, goal);
+ const struct burm_instruction_data* insndata = &burm_instruction_data[insn_no];
+ if (insndata->emitter)
+ insndata->emitter(ir, &emitter_data);
+}
+
static void emit_value(struct ir* ir)
{
hop_add_value_insel(current_hop, ir);
static void emit_resultreg(void)
{
- hop_add_reg_insel(current_hop, current_hop);
}
static void emit_eoi(void)
static const struct burm_emitter_data emitter_data =
{
&emit_string,
+ &emit_fragment,
&emit_reg,
&emit_value,
&emit_resultreg,
struct hop* parent_hop = NULL;
int i;
- ir->insn_no = insn_no;
if (!insndata->is_fragment)
{
parent_hop = current_hop;
- current_hop = ir->hop = new_hop(insn_no, ir);
+ current_hop = new_hop(insn_no, ir);
}
burm_kids(ir, insn_no, children);
walk_instructions(children[i], nts[i]);
ir->is_generated = true;
+ ir->insn_no = insn_no;
tracef('I', "I: $%d %s selected %s %d: %s\n",
ir->id,
- ir->is_sequence ? "S" : " ",
+ ir->is_root ? "S" : " ",
insndata->is_fragment ? "fragment" : "instruction",
insn_no,
insndata->name);
insndata->emitter(ir, &emitter_data);
hop_print('I', current_hop);
- array_append(¤t_bb->hops, current_hop);
+ array_append(&ir->hops, current_hop);
current_hop = parent_hop;
}
}
-
static void select_instructions(void)
{
int i;
REGISTERS
- r0 GPR RET0;
- r1 GPR RET1;
- r2 GPR;
- r3 GPR;
- r4 GPR;
- r5 GPR;
- r6 GPR;
- r7 GPR;
- r8 GPR;
- r9 GPR;
- r10 GPR;
- r11 GPR;
-
- cc CC;
+ r0 reg4 int ret0;
+ r1 reg4 int ret1;
+ r2 reg4 int;
+ r3 reg4 int;
+ r4 reg4 int;
+ r5 reg4 int;
+ r6 reg4 int;
+ r7 reg4 int;
+ r8 reg4 int;
+ r9 reg4 int;
+ r10 reg4 int;
+ r11 reg4 int;
+
+ s0 reg4 float;
+ s1 reg4 float;
+ s2 reg4 float;
+ s3 reg4 float;
+ s4 reg4 float;
+ s5 reg4 float;
+ s6 reg4 float;
+ s7 reg4 float;
+ s8 reg4 float;
+ s9 reg4 float;
+
+ cc conditioncode;
DECLARATIONS
address fragment;
aluparam fragment;
- reg allocates(GPR);
- tristate allocates(CC);
- bistate allocates(CC);
+ reg allocates(reg4);
+ tristate allocates(conditioncode);
+ bistate allocates(conditioncode);
PATTERNS
aluparam = value:CONST4
emit "#$value";
- aluparam = reg;
+ aluparam = value:reg
+ emit "%value";
reg = value:aluparam
emit "mov %reg, %value"
reg = value:CONST4
emit "ldr %reg, #$value"
cost 8;
+
+/* FPU operations */
+
+ reg = ADDF4(left:reg, right:reg)
+ emit "fadds %reg, %left, %right"
+ cost 4;
+
int i;
assert(current_bb != NULL);
- ir->is_sequence = true;
+ ir->is_root = true;
array_append(¤t_bb->irs, ir);
ir_print('0', ir);
case op_dup:
{
struct ir* v = pop(value);
- if (!v->is_sequence)
+ if (!v->is_root)
appendir(v);
push(v);
push(v);
{
struct regclass* p = lookup(id);
if (!p || (p->kind != REGCLASS))
- yyerror("'%p' is not the name of a register class");
+ yyerror("'%s' is not the name of a register class", id);
return p;
}
static const uint32_t PATH_MISSING = 0xffffffff;
-static uint32_t find_label(Tree root, const char* name, uint32_t path)
+static uint32_t find_label(Tree root, const char* name, uint32_t path, Tree* found)
{
uint32_t p;
if (root->label && (strcmp(root->label, name) == 0))
+ {
+ if (found)
+ *found = root;
return path;
+ }
p = PATH_MISSING;
if (root->left && (p == PATH_MISSING))
- p = find_label(root->left, name, path*3 + 1);
+ p = find_label(root->left, name, path*3 + 1, found);
if (root->right && (p == PATH_MISSING))
- p = find_label(root->right, name, path*3 + 2);
+ p = find_label(root->right, name, path*3 + 2, found);
return p;
}
const char* label = f->data + 1;
if (strcmp(label, r->lhs->name) == 0)
- print("%1data->emit_resultreg();\n");
+ print("%1data->emit_reg(node, %P%s_NT);\n", label);
else
{
- uint32_t path = find_label(r->pattern, label, 0);
- print("%1data->emit_reg(");
+ Tree node;
+ uint32_t path = find_label(r->pattern, label, 0, &node);
+ Nonterm nt = node->op;
+
if (path == PATH_MISSING)
label_not_found(r, label);
+
+ if (nt->is_fragment)
+ print("%1data->emit_fragment(");
+ else
+ print("%1data->emit_reg(");
+
print_path(path);
- print(");\n");
+ print(", %P%s_NT);\n", ((Nonterm)node->op)->name);
}
break;
}
case '$':
{
const char* label = f->data + 1;
- uint32_t path = find_label(r->pattern, label, 0);
+ uint32_t path = find_label(r->pattern, label, 0, NULL);
print("%1data->emit_value(");
if (path == PATH_MISSING)
label_not_found(r, label);
struct burm_emitter_data
{
void (*emit_string)(const char* data);
- void (*emit_reg)(struct ir* ir);
+ void (*emit_fragment)(struct ir* ir, int goal);
+ void (*emit_reg)(struct ir* ir, int goal);
void (*emit_value)(struct ir* ir);
void (*emit_resultreg)(void);
void (*emit_eoi)(void);