diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 510190c70..35bed381b 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -28,10 +28,11 @@ void hop_add_string_insel(struct hop* hop, const char* string) 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); } @@ -72,7 +73,7 @@ void hop_print(char k, struct hop* hop) 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: diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index 8f92d898e..e6cc8f809 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -15,7 +15,12 @@ struct insel union { const char* string; - struct hop* reg; + struct + { + struct ir* ir; + int insn_no; + } + reg; struct ir* value; } u; @@ -26,15 +31,13 @@ struct hop 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); @@ -42,4 +45,3 @@ extern void hop_print(char k, struct hop* hop); #endif - diff --git a/mach/proto/mcg/ir.c b/mach/proto/mcg/ir.c index 4d61bddeb..c4755b275 100644 --- a/mach/proto/mcg/ir.c +++ b/mach/proto/mcg/ir.c @@ -71,14 +71,14 @@ struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user) 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) @@ -126,7 +126,7 @@ static void print_expr(char k, const struct ir* ir) 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); @@ -134,7 +134,7 @@ static void print_expr(char k, const struct ir* ir) 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); diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index d38ecf1d5..069a76bd5 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -20,9 +20,9 @@ struct ir 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; }; diff --git a/mach/proto/mcg/mcgg_generated_header.h b/mach/proto/mcg/mcgg_generated_header.h index fbe0603dd..a3e79afc0 100644 --- a/mach/proto/mcg/mcgg_generated_header.h +++ b/mach/proto/mcg/mcgg_generated_header.h @@ -6,9 +6,8 @@ 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); diff --git a/mach/proto/mcg/pass_convertstackops.c b/mach/proto/mcg/pass_convertstackops.c index adbe25068..6f62fe747 100644 --- a/mach/proto/mcg/pass_convertstackops.c +++ b/mach/proto/mcg/pass_convertstackops.c @@ -112,9 +112,9 @@ static void convert_block(struct procedure* proc, struct basicblock* bb) for (i=0; iis_sequence); + assert(ir->is_root); *ir = *ir->left; - ir->is_sequence = true; + ir->is_root = true; } for (i=0; isize, phi, pushes.item[j]); - phi->is_sequence = ir->is_sequence; + phi->is_root = ir->is_root; *ir = *phi; } } diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index 13d3d892a..2b0bb96c3 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -19,16 +19,9 @@ void burm_panic_cannot_match(struct ir* ir) 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) @@ -36,6 +29,14 @@ 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); @@ -43,7 +44,6 @@ static void emit_value(struct ir* ir) static void emit_resultreg(void) { - hop_add_reg_insel(current_hop, current_hop); } static void emit_eoi(void) @@ -54,6 +54,7 @@ static void emit_eoi(void) static const struct burm_emitter_data emitter_data = { &emit_string, + &emit_fragment, &emit_reg, &emit_value, &emit_resultreg, @@ -70,11 +71,10 @@ static void walk_instructions(struct ir* ir, int goal) 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); @@ -82,10 +82,11 @@ static void walk_instructions(struct ir* ir, int goal) 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); @@ -96,12 +97,11 @@ static void walk_instructions(struct ir* ir, int goal) 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; diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index 9bd39d4b5..4126b2f01 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -1,27 +1,38 @@ 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; + 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; - cc CC; + 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 @@ -158,7 +169,8 @@ PATTERNS aluparam = value:CONST4 emit "#$value"; - aluparam = reg; + aluparam = value:reg + emit "%value"; reg = value:aluparam emit "mov %reg, %value" @@ -175,3 +187,10 @@ PATTERNS reg = value:CONST4 emit "ldr %reg, #$value" cost 8; + +/* FPU operations */ + + reg = ADDF4(left:reg, right:reg) + emit "fadds %reg, %left, %right" + cost 4; + diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index a0ebe0e3f..58f19bdc2 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -76,7 +76,7 @@ static struct ir* appendir(struct ir* ir) int i; assert(current_bb != NULL); - ir->is_sequence = true; + ir->is_root = true; array_append(¤t_bb->irs, ir); ir_print('0', ir); @@ -479,7 +479,7 @@ static void insn_ivalue(int opcode, arith value) case op_dup: { struct ir* v = pop(value); - if (!v->is_sequence) + if (!v->is_root) appendir(v); push(v); push(v); diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index f29c85907..0e8cad407 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -295,7 +295,7 @@ struct regclass* getregclass(const char* id) { 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; } @@ -917,18 +917,22 @@ static void print_path(uint32_t path) 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; } @@ -963,15 +967,23 @@ static void emitinsndata(Rule rules) 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; } @@ -979,7 +991,7 @@ static void emitinsndata(Rule rules) 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); diff --git a/util/mcgg/mcgg.h b/util/mcgg/mcgg.h index 004146bb3..0bbe4ae93 100644 --- a/util/mcgg/mcgg.h +++ b/util/mcgg/mcgg.h @@ -27,7 +27,8 @@ extern void burm_trace(struct ir* p, int ruleno, int cost, int bestcost); 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);