diff --git a/src/arm-codegen.c b/src/arm-codegen.c index 4d6666a5..00a538d3 100644 --- a/src/arm-codegen.c +++ b/src/arm-codegen.c @@ -9,9 +9,107 @@ #include "arm.c" -void emit(int code) +void update_elf_offset_by_ph2_ir(ph2_ir_t *ph2_ir) { - elf_write_code_int(code); + switch (ph2_ir->op) { + case OP_load_constant: + /* ARMv7 uses 12 bits to encode immediate value, but the + * higher 4 bits are for rotation. See A5.2.4 "Modified + * immediate constants in ARM instructions" in ARMv7-A + * manual. + */ + if (ph2_ir->src0 < 0) + elf_offset += 12; + else if (ph2_ir->src0 > 255) + elf_offset += 8; + else + elf_offset += 4; + return; + case OP_address_of: + case OP_global_address_of: + /* ARMv7 uses 12 bits to encode immediate value, but the + * higher 4 bits are for rotation. See A5.2.4 "Modified + * immediate constants in ARM instructions" in ARMv7-A + * manual. + */ + if (ph2_ir->src0 > 255) + elf_offset += 12; + else if (ph2_ir->src0 >= 0) + elf_offset += 4; + else + abort(); + return; + case OP_assign: + if (ph2_ir->dest != ph2_ir->src0) + elf_offset += 4; + return; + case OP_load: + case OP_global_load: + /* ARMv7 straight uses 12 bits to encode the offset of + * load instruction (no rotation). + */ + if (ph2_ir->src0 > 4095) + elf_offset += 16; + else if (ph2_ir->src0 >= 0) + elf_offset += 4; + else + abort(); + return; + case OP_store: + case OP_global_store: + /* ARMv7 straight uses 12 bits to encode the offset of + * store instruction (no rotation). + */ + if (ph2_ir->src1 > 4095) + elf_offset += 16; + else if (ph2_ir->src1 >= 0) + elf_offset += 4; + else + abort(); + return; + case OP_read: + case OP_write: + case OP_jump: + case OP_call: + case OP_load_func: + case OP_indirect: + case OP_add: + case OP_sub: + case OP_mul: + case OP_div: + case OP_lshift: + case OP_rshift: + case OP_bit_and: + case OP_bit_or: + case OP_bit_xor: + case OP_negate: + case OP_log_and: + case OP_bit_not: + elf_offset += 4; + return; + case OP_load_data_address: + elf_offset += 8; + return; + case OP_address_of_func: + case OP_mod: + case OP_eq: + case OP_neq: + case OP_gt: + case OP_lt: + case OP_geq: + case OP_leq: + case OP_log_not: + case OP_log_or: + elf_offset += 12; + return; + case OP_branch: + case OP_return: + elf_offset += 24; + return; + default: + printf("Unknown opcode\n"); + abort(); + } } void cfg_flatten() @@ -24,40 +122,9 @@ void cfg_flatten() ph2_ir_t *ph2_ir; for (ph2_ir = GLOBAL_FUNC.fn->bbs->ph2_ir_list.head; ph2_ir; - ph2_ir = ph2_ir->next) { - switch (ph2_ir->op) { - case OP_load_constant: - if (ph2_ir->src0 < 0) - elf_offset += 12; - else if (ph2_ir->src0 > 255) - elf_offset += 8; - else - elf_offset += 4; - break; - case OP_global_address_of: - if (ph2_ir->src0 < 0) - abort(); - else if (ph2_ir->src0 > 255) - elf_offset += 12; - else - elf_offset += 4; - break; - case OP_assign: - elf_offset += 4; - break; - case OP_global_store: - if (ph2_ir->src1 < 0) - abort(); - else if (ph2_ir->src1 > 4095) - elf_offset += 16; - else - elf_offset += 4; - break; - default: - printf("Unknown opcode\n"); - abort(); - } - } + ph2_ir = ph2_ir->next) + update_elf_offset_by_ph2_ir(ph2_ir); + /* prepare `argc` and `argv`, then proceed to `main` function */ elf_offset += 24; @@ -79,139 +146,238 @@ void cfg_flatten() ph2_ir_t *insn; for (insn = bb->ph2_ir_list.head; insn; insn = insn->next) { - switch (insn->op) { - case OP_load_constant: - flatten_ir = add_ph2_ir(OP_load_constant); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - - /* ARMv7 uses 12 bits to encode immediate value, but the - * higher 4 bits are for rotation. See A5.2.4 "Modified - * immediate constants in ARM instructions" in ARMv7-A - * manual. - */ - if (flatten_ir->src0 < 0) - elf_offset += 12; - else if (flatten_ir->src0 > 255) - elf_offset += 8; - else - elf_offset += 4; - - break; - case OP_assign: - if (insn->dest != insn->src0) { - flatten_ir = add_ph2_ir(OP_assign); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 4; - } - break; - case OP_address_of: - case OP_global_address_of: - flatten_ir = add_ph2_ir(OP_address_of); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); + if (insn->op == OP_assign && insn->dest == insn->src0) + continue; - /* ARMv7 uses 12 bits to encode immediate value, but the - * higher 4 bits are for rotation. See A5.2.4 "Modified - * immediate constants in ARM instructions" in ARMv7-A - * manual. - */ - if (flatten_ir->src0 > 255) - elf_offset += 12; - else - elf_offset += 4; + flatten_ir = add_ph2_ir(OP_generic); + memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - break; - case OP_load: - case OP_global_load: - flatten_ir = add_ph2_ir(OP_address_of); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); + if (insn->op == OP_return) + /* restore sp */ + flatten_ir->src1 = bb->belong_to->func->stack_size; - /* ARMv7 straight uses 12 bits to encode the offset of - * load instruction (no rotation). - */ - if (flatten_ir->src0 > 4095) - elf_offset += 16; - else - elf_offset += 4; + update_elf_offset_by_ph2_ir(flatten_ir); + } + } + } +} - break; - case OP_store: - case OP_global_store: - flatten_ir = add_ph2_ir(OP_address_of); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); +void emit(int code) +{ + elf_write_code_int(code); +} - /* ARMv7 straight uses 12 bits to encode the offset of - * store instruction (no rotation). - */ - if (flatten_ir->src1 > 4095) - elf_offset += 16; - else - elf_offset += 4; +void emit_from_ph2_ir(ph2_ir_t *ph2_ir) +{ + int rd = ph2_ir->dest; + int rn = ph2_ir->src0; + int rm = ph2_ir->src1; + int ofs; - break; - case OP_read: - case OP_write: - case OP_jump: - case OP_call: - case OP_load_func: - case OP_indirect: - case OP_add: - case OP_sub: - case OP_mul: - case OP_div: - case OP_lshift: - case OP_rshift: - case OP_bit_and: - case OP_bit_or: - case OP_bit_xor: - case OP_negate: - case OP_log_and: - case OP_bit_not: - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 4; - break; - case OP_load_data_address: - flatten_ir = add_ph2_ir(OP_load_data_address); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 8; - break; - case OP_address_of_func: - case OP_mod: - case OP_eq: - case OP_neq: - case OP_gt: - case OP_lt: - case OP_geq: - case OP_leq: - case OP_log_not: - case OP_log_or: - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 12; - break; - case OP_branch: - flatten_ir = add_ph2_ir(OP_branch); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 24; - break; - case OP_return: - flatten_ir = add_ph2_ir(OP_return); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - flatten_ir->src1 = bb->belong_to->func->stack_size; - elf_offset += 24; - break; - default: - printf("Unknown opcode\n"); - abort(); - } - } - } + switch (ph2_ir->op) { + case OP_define: + emit(__sw(__AL, __lr, __sp, -4)); + emit(__movw(__AL, __r8, ph2_ir->src0 + 4)); + emit(__movt(__AL, __r8, ph2_ir->src0 + 4)); + emit(__sub_r(__AL, __sp, __sp, __r8)); + return; + case OP_load_constant: + if (ph2_ir->src0 < 0) { + emit(__movw(__AL, __r8, -ph2_ir->src0)); + emit(__movt(__AL, __r8, -ph2_ir->src0)); + emit(__rsb_i(__AL, rd, 0, __r8)); + } else if (ph2_ir->src0 > 255) { + emit(__movw(__AL, rd, ph2_ir->src0)); + emit(__movt(__AL, rd, ph2_ir->src0)); + } else + emit(__mov_i(__AL, rd, ph2_ir->src0)); + return; + case OP_address_of: + if (ph2_ir->src0 > 255) { + emit(__movw(__AL, __r8, ph2_ir->src0)); + emit(__movt(__AL, __r8, ph2_ir->src0)); + emit(__add_r(__AL, rd, __sp, __r8)); + } else + emit(__add_i(__AL, rd, __sp, ph2_ir->src0)); + return; + case OP_global_address_of: + if (ph2_ir->src0 > 255) { + emit(__movw(__AL, __r8, ph2_ir->src0)); + emit(__movt(__AL, __r8, ph2_ir->src0)); + emit(__add_r(__AL, rd, __r12, __r8)); + } else + emit(__add_i(__AL, rd, __r12, ph2_ir->src0)); + return; + case OP_assign: + emit(__mov_r(__AL, rd, rn)); + return; + case OP_load: + if (ph2_ir->src0 > 4095) { + emit(__movw(__AL, __r8, ph2_ir->src0)); + emit(__movt(__AL, __r8, ph2_ir->src0)); + emit(__add_r(__AL, __r8, __sp, __r8)); + emit(__lw(__AL, rd, __r8, 0)); + } else + emit(__lw(__AL, rd, __sp, ph2_ir->src0)); + return; + case OP_store: + if (ph2_ir->src1 > 4095) { + emit(__movw(__AL, __r8, ph2_ir->src1)); + emit(__movt(__AL, __r8, ph2_ir->src1)); + emit(__add_r(__AL, __r8, __sp, __r8)); + emit(__sw(__AL, rn, __r8, 0)); + } else + emit(__sw(__AL, rn, __sp, ph2_ir->src1)); + return; + case OP_global_load: + if (ph2_ir->src0 > 4095) { + emit(__movw(__AL, __r8, ph2_ir->src0)); + emit(__movt(__AL, __r8, ph2_ir->src0)); + emit(__add_r(__AL, __r8, __r12, __r8)); + emit(__lw(__AL, rd, __r8, 0)); + } else + emit(__lw(__AL, rd, __r12, ph2_ir->src0)); + return; + case OP_global_store: + if (ph2_ir->src1 > 4095) { + emit(__movw(__AL, __r8, ph2_ir->src1)); + emit(__movt(__AL, __r8, ph2_ir->src1)); + emit(__add_r(__AL, __r8, __r12, __r8)); + emit(__sw(__AL, rn, __r8, 0)); + } else + emit(__sw(__AL, rn, __r12, ph2_ir->src1)); + return; + case OP_read: + if (ph2_ir->src1 == 1) + emit(__lb(__AL, rd, rn, 0)); + else if (ph2_ir->src1 == 4) + emit(__lw(__AL, rd, rn, 0)); + else + abort(); + return; + case OP_write: + if (ph2_ir->dest == 1) + emit(__sb(__AL, rm, rn, 0)); + else if (ph2_ir->dest == 4) + emit(__sw(__AL, rm, rn, 0)); + else + abort(); + return; + case OP_branch: + ofs = ph2_ir->else_bb->elf_offset; + emit(__movw(__AL, __r8, ofs + elf_code_start)); + emit(__movt(__AL, __r8, ofs + elf_code_start)); + emit(__teq(rn)); + emit(__b(__NE, 8)); + emit(__blx(__AL, __r8)); + emit(__b(__AL, ph2_ir->then_bb->elf_offset - elf_code_idx)); + return; + case OP_jump: + emit(__b(__AL, ph2_ir->next_bb->elf_offset - elf_code_idx)); + return; + case OP_call: + emit(__bl(__AL, find_func(ph2_ir->func_name)->fn->bbs->elf_offset - + elf_code_idx)); + return; + case OP_load_data_address: + emit(__movw(__AL, rd, ph2_ir->src0 + elf_data_start)); + emit(__movt(__AL, rd, ph2_ir->src0 + elf_data_start)); + return; + case OP_address_of_func: + ofs = + elf_code_start + find_func(ph2_ir->func_name)->fn->bbs->elf_offset; + emit(__movw(__AL, __r8, ofs)); + emit(__movt(__AL, __r8, ofs)); + emit(__sw(__AL, __r8, rn, 0)); + return; + case OP_load_func: + emit(__mov_r(__AL, __r8, rn)); + return; + case OP_indirect: + emit(__blx(__AL, __r8)); + return; + case OP_return: + if (ph2_ir->src0 == -1) + emit(__mov_r(__AL, __r0, __r0)); + else + emit(__mov_r(__AL, __r0, rn)); + emit(__movw(__AL, __r8, ph2_ir->src1 + 4)); + emit(__movt(__AL, __r8, ph2_ir->src1 + 4)); + emit(__add_r(__AL, __sp, __sp, __r8)); + emit(__lw(__AL, __lr, __sp, -4)); + emit(__mov_r(__AL, __pc, __lr)); + return; + case OP_add: + emit(__add_r(__AL, rd, rn, rm)); + return; + case OP_sub: + emit(__sub_r(__AL, rd, rn, rm)); + return; + case OP_mul: + emit(__mul(__AL, rd, rn, rm)); + return; + case OP_div: + emit(__div(__AL, rd, rm, rn)); + return; + case OP_mod: + emit(__div(__AL, __r8, rm, rn)); + emit(__mul(__AL, __r8, rm, __r8)); + emit(__sub_r(__AL, rd, rn, __r8)); + return; + case OP_lshift: + emit(__sll(__AL, rd, rn, rm)); + return; + case OP_rshift: + emit(__srl(__AL, rd, rn, rm)); + return; + case OP_eq: + case OP_neq: + case OP_gt: + case OP_lt: + case OP_geq: + case OP_leq: + emit(__cmp_r(__AL, rn, rm)); + emit(__zero(rd)); + emit(__mov_i(arm_get_cond(ph2_ir->op), rd, 1)); + return; + case OP_negate: + emit(__rsb_i(__AL, rd, 0, rn)); + return; + case OP_bit_not: + emit(__mvn_r(__AL, rd, rn)); + return; + case OP_bit_and: + emit(__and_r(__AL, rd, rn, rm)); + return; + case OP_bit_or: + emit(__or_r(__AL, rd, rn, rm)); + return; + case OP_bit_xor: + emit(__eor_r(__AL, rd, rn, rm)); + return; + case OP_log_not: + emit(__teq(rn)); + emit(__mov_i(__NE, rd, 0)); + emit(__mov_i(__EQ, rd, 1)); + return; + case OP_log_and: + /* FIXME: bad logical-and instruction */ + emit(__and_r(__AL, rd, rn, rm)); + return; + case OP_log_or: + emit(__or_r(__AL, rd, rn, rm)); + emit(__teq(rd)); + emit(__mov_i(__NE, rd, 1)); + return; + default: + printf("Unknown opcode\n"); + abort(); } } void code_generate() { - int elf_data_start = elf_code_start + elf_offset; + elf_data_start = elf_code_start + elf_offset; /* start */ emit(__movw(__AL, __r8, GLOBAL_FUNC.stack_size)); @@ -241,51 +407,9 @@ void code_generate() ph2_ir_t *ph2_ir; for (ph2_ir = GLOBAL_FUNC.fn->bbs->ph2_ir_list.head; ph2_ir; - ph2_ir = ph2_ir->next) { - int rd = ph2_ir->dest; - int rn = ph2_ir->src0; + ph2_ir = ph2_ir->next) + emit_from_ph2_ir(ph2_ir); - switch (ph2_ir->op) { - case OP_load_constant: - if (ph2_ir->src0 < 0) { - emit(__movw(__AL, __r8, -ph2_ir->src0)); - emit(__movt(__AL, __r8, -ph2_ir->src0)); - emit(__rsb_i(__AL, rd, 0, __r8)); - } else if (ph2_ir->src0 > 255) { - emit(__movw(__AL, rd, ph2_ir->src0)); - emit(__movt(__AL, rd, ph2_ir->src0)); - } else - emit(__mov_i(__AL, rd, ph2_ir->src0)); - break; - case OP_global_address_of: - if (ph2_ir->src0 < 0) - abort(); - else if (ph2_ir->src0 > 255) { - emit(__movw(__AL, __r8, ph2_ir->src0)); - emit(__movt(__AL, __r8, ph2_ir->src0)); - emit(__add_r(__AL, rd, __r12, __r8)); - } else - emit(__add_i(__AL, rd, __r12, ph2_ir->src0)); - break; - case OP_assign: - emit(__mov_r(__AL, rd, rn)); - break; - case OP_global_store: - if (ph2_ir->src1 < 0) - abort(); - else if (ph2_ir->src1 > 4095) { - emit(__movw(__AL, __r8, ph2_ir->src1)); - emit(__movt(__AL, __r8, ph2_ir->src1)); - emit(__add_r(__AL, __r8, __r12, __r8)); - emit(__sw(__AL, rn, __r8, 0)); - } else - emit(__sw(__AL, rn, __r12, ph2_ir->src1)); - break; - default: - printf("Unknown opcode\n"); - abort(); - } - } /* prepare `argc` and `argv`, then proceed to `main` function */ emit(__movw(__AL, __r8, GLOBAL_FUNC.stack_size)); emit(__movt(__AL, __r8, GLOBAL_FUNC.stack_size)); @@ -296,204 +420,7 @@ void code_generate() int i; for (i = 0; i < ph2_ir_idx; i++) { - ph2_ir_t *ph2_ir = &PH2_IR[i]; - int rd = ph2_ir->dest; - int rn = ph2_ir->src0; - int rm = ph2_ir->src1; - int ofs; - - switch (ph2_ir->op) { - case OP_define: - emit(__sw(__AL, __lr, __sp, -4)); - emit(__movw(__AL, __r8, ph2_ir->src0 + 4)); - emit(__movt(__AL, __r8, ph2_ir->src0 + 4)); - emit(__sub_r(__AL, __sp, __sp, __r8)); - break; - case OP_load_constant: - if (ph2_ir->src0 < 0) { - emit(__movw(__AL, __r8, -ph2_ir->src0)); - emit(__movt(__AL, __r8, -ph2_ir->src0)); - emit(__rsb_i(__AL, rd, 0, __r8)); - } else if (ph2_ir->src0 > 255) { - emit(__movw(__AL, rd, ph2_ir->src0)); - emit(__movt(__AL, rd, ph2_ir->src0)); - } else - emit(__mov_i(__AL, rd, ph2_ir->src0)); - break; - case OP_load_data_address: - emit(__movw(__AL, rd, ph2_ir->src0 + elf_data_start)); - emit(__movt(__AL, rd, ph2_ir->src0 + elf_data_start)); - break; - case OP_address_of: - if (ph2_ir->src0 > 255) { - emit(__movw(__AL, __r8, ph2_ir->src0)); - emit(__movt(__AL, __r8, ph2_ir->src0)); - emit(__add_r(__AL, rd, __sp, __r8)); - } else - emit(__add_i(__AL, rd, __sp, ph2_ir->src0)); - break; - case OP_assign: - emit(__mov_r(__AL, rd, rn)); - break; - case OP_load: - if (ph2_ir->src0 > 4095) { - emit(__movw(__AL, __r8, ph2_ir->src0)); - emit(__movt(__AL, __r8, ph2_ir->src0)); - emit(__add_r(__AL, __r8, __sp, __r8)); - emit(__lw(__AL, rd, __r8, 0)); - } else - emit(__lw(__AL, rd, __sp, ph2_ir->src0)); - break; - case OP_store: - if (ph2_ir->src1 > 4095) { - emit(__movw(__AL, __r8, ph2_ir->src1)); - emit(__movt(__AL, __r8, ph2_ir->src1)); - emit(__add_r(__AL, __r8, __sp, __r8)); - emit(__sw(__AL, rn, __r8, 0)); - } else - emit(__sw(__AL, rn, __sp, ph2_ir->src1)); - break; - case OP_global_load: - if (ph2_ir->src0 > 4095) { - emit(__movw(__AL, __r8, ph2_ir->src0)); - emit(__movt(__AL, __r8, ph2_ir->src0)); - emit(__add_r(__AL, __r8, __r12, __r8)); - emit(__lw(__AL, rd, __r8, 0)); - } else - emit(__lw(__AL, rd, __r12, ph2_ir->src0)); - break; - case OP_global_store: - if (ph2_ir->src1 > 4095) { - emit(__movw(__AL, __r8, ph2_ir->src1)); - emit(__movt(__AL, __r8, ph2_ir->src1)); - emit(__add_r(__AL, __r8, __r12, __r8)); - emit(__sw(__AL, rn, __r8, 0)); - } else - emit(__sw(__AL, rn, __r12, ph2_ir->src1)); - break; - case OP_read: - if (ph2_ir->src1 == 1) - emit(__lb(__AL, rd, rn, 0)); - else if (ph2_ir->src1 == 4) - emit(__lw(__AL, rd, rn, 0)); - else - abort(); - break; - case OP_write: - if (ph2_ir->dest == 1) - emit(__sb(__AL, rm, rn, 0)); - else if (ph2_ir->dest == 4) - emit(__sw(__AL, rm, rn, 0)); - else - abort(); - break; - case OP_branch: - ofs = ph2_ir->else_bb->elf_offset; - emit(__movw(__AL, __r8, ofs + elf_code_start)); - emit(__movt(__AL, __r8, ofs + elf_code_start)); - emit(__teq(rn)); - emit(__b(__NE, 8)); - emit(__blx(__AL, __r8)); - - ofs = ph2_ir->then_bb->elf_offset; - emit(__b(__AL, ofs - elf_code_idx)); - break; - case OP_jump: - emit(__b(__AL, ph2_ir->next_bb->elf_offset - elf_code_idx)); - break; - case OP_call: - emit(__bl(__AL, find_func(ph2_ir->func_name)->fn->bbs->elf_offset - - elf_code_idx)); - break; - case OP_address_of_func: - ofs = elf_code_start + - find_func(ph2_ir->func_name)->fn->bbs->elf_offset; - emit(__movw(__AL, __r8, ofs)); - emit(__movt(__AL, __r8, ofs)); - emit(__sw(__AL, __r8, rn, 0)); - break; - case OP_load_func: - emit(__mov_r(__AL, __r8, rn)); - break; - case OP_indirect: - emit(__blx(__AL, __r8)); - break; - case OP_return: - if (ph2_ir->src0 == -1) - emit(__mov_r(__AL, __r0, __r0)); - else - emit(__mov_r(__AL, __r0, rn)); - emit(__movw(__AL, __r8, ph2_ir->src1 + 4)); - emit(__movt(__AL, __r8, ph2_ir->src1 + 4)); - emit(__add_r(__AL, __sp, __sp, __r8)); - emit(__lw(__AL, __lr, __sp, -4)); - emit(__mov_r(__AL, __pc, __lr)); - break; - case OP_add: - emit(__add_r(__AL, rd, rn, rm)); - break; - case OP_sub: - emit(__sub_r(__AL, rd, rn, rm)); - break; - case OP_mul: - emit(__mul(__AL, rd, rn, rm)); - break; - case OP_div: - emit(__div(__AL, rd, rm, rn)); - break; - case OP_mod: - emit(__div(__AL, __r8, rm, rn)); - emit(__mul(__AL, __r8, rm, __r8)); - emit(__sub_r(__AL, rd, rn, __r8)); - break; - case OP_lshift: - emit(__sll(__AL, rd, rn, rm)); - break; - case OP_rshift: - emit(__srl(__AL, rd, rn, rm)); - break; - case OP_eq: - case OP_neq: - case OP_gt: - case OP_lt: - case OP_geq: - case OP_leq: - emit(__cmp_r(__AL, rn, rm)); - emit(__zero(rd)); - emit(__mov_i(arm_get_cond(ph2_ir->op), rd, 1)); - break; - case OP_negate: - emit(__rsb_i(__AL, rd, 0, rn)); - break; - case OP_bit_not: - emit(__mvn_r(__AL, rd, rn)); - break; - case OP_bit_and: - emit(__and_r(__AL, rd, rn, rm)); - break; - case OP_bit_or: - emit(__or_r(__AL, rd, rn, rm)); - break; - case OP_bit_xor: - emit(__eor_r(__AL, rd, rn, rm)); - break; - case OP_log_not: - emit(__teq(rn)); - emit(__mov_i(__NE, rd, 0)); - emit(__mov_i(__EQ, rd, 1)); - break; - case OP_log_and: - /* FIXME: bad logical-and instruction */ - emit(__and_r(__AL, rd, rn, rm)); - break; - case OP_log_or: - emit(__or_r(__AL, rd, rn, rm)); - emit(__teq(rd)); - emit(__mov_i(__NE, rd, 1)); - break; - default: - printf("Unknown opcode\n"); - abort(); - } + ph2_ir = &PH2_IR[i]; + emit_from_ph2_ir(ph2_ir); } } diff --git a/src/globals.c b/src/globals.c index 84127b9f..69af625e 100644 --- a/src/globals.c +++ b/src/globals.c @@ -67,6 +67,7 @@ char *elf_header; int elf_header_idx = 0; int elf_header_len = 0x54; /* ELF fixed: 0x34 + 1 * 0x20 */ int elf_code_start; +int elf_data_start; char *elf_symtab; char *elf_strtab; char *elf_section; diff --git a/src/riscv-codegen.c b/src/riscv-codegen.c index c0cd6170..968b3aa6 100644 --- a/src/riscv-codegen.c +++ b/src/riscv-codegen.c @@ -9,9 +9,84 @@ #include "riscv.c" -void emit(int code) +void update_elf_offset_by_ph2_ir(ph2_ir_t *ph2_ir) { - elf_write_code_int(code); + switch (ph2_ir->op) { + case OP_load_constant: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) + elf_offset += 8; + else + elf_offset += 4; + return; + case OP_address_of: + case OP_global_address_of: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) + elf_offset += 12; + else + elf_offset += 4; + return; + case OP_assign: + elf_offset += 4; + return; + case OP_load: + case OP_global_load: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) + elf_offset += 16; + else + elf_offset += 4; + return; + case OP_store: + case OP_global_store: + if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) + elf_offset += 16; + else + elf_offset += 4; + return; + case OP_read: + case OP_write: + case OP_jump: + case OP_call: + case OP_load_func: + case OP_indirect: + case OP_add: + case OP_sub: + case OP_mul: + case OP_div: + case OP_mod: + case OP_lshift: + case OP_rshift: + case OP_gt: + case OP_lt: + case OP_bit_and: + case OP_bit_or: + case OP_bit_xor: + case OP_negate: + case OP_log_and: + case OP_bit_not: + elf_offset += 4; + return; + case OP_load_data_address: + case OP_neq: + case OP_geq: + case OP_leq: + case OP_log_not: + case OP_log_or: + elf_offset += 8; + return; + case OP_address_of_func: + case OP_eq: + elf_offset += 12; + return; + case OP_branch: + elf_offset += 20; + return; + case OP_return: + elf_offset += 24; + return; + default: + printf("Unknown opcode\n"); + abort(); + } } void cfg_flatten() @@ -24,34 +99,9 @@ void cfg_flatten() ph2_ir_t *ph2_ir; for (ph2_ir = GLOBAL_FUNC.fn->bbs->ph2_ir_list.head; ph2_ir; - ph2_ir = ph2_ir->next) { - switch (ph2_ir->op) { - case OP_load_constant: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) - elf_offset += 8; - else - elf_offset += 4; - break; - case OP_global_address_of: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) - elf_offset += 12; - else - elf_offset += 4; - break; - case OP_assign: - elf_offset += 4; - break; - case OP_global_store: - if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) - elf_offset += 16; - else - elf_offset += 4; - break; - default: - printf("Unknown opcode\n"); - abort(); - } - } + ph2_ir = ph2_ir->next) + update_elf_offset_by_ph2_ir(ph2_ir); + /* prepare `argc` and `argv`, then proceed to `main` function */ elf_offset += 24; @@ -73,120 +123,243 @@ void cfg_flatten() ph2_ir_t *insn; for (insn = bb->ph2_ir_list.head; insn; insn = insn->next) { - switch (insn->op) { - case OP_load_constant: - flatten_ir = add_ph2_ir(OP_load_constant); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); + if (insn->op == OP_assign && insn->dest == insn->src0) + continue; - /* RISC-V uses 12 bits to encode immediate value */ - if (flatten_ir->src0 < 2048 && flatten_ir->src0 > -2047) - elf_offset += 4; - else - elf_offset += 8; + flatten_ir = add_ph2_ir(OP_generic); + memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - break; - case OP_assign: - if (insn->dest != insn->src0) { - flatten_ir = add_ph2_ir(OP_assign); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 4; - } - break; - case OP_address_of: - case OP_global_address_of: - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - if (flatten_ir->src0 < -2048 || flatten_ir->src0 > 2047) - elf_offset += 12; - else - elf_offset += 4; - break; - case OP_load: - case OP_global_load: - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - if (flatten_ir->src0 < -2048 || flatten_ir->src0 > 2047) - elf_offset += 16; - else - elf_offset += 4; - break; - case OP_store: - case OP_global_store: - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - if (flatten_ir->src1 < -2048 || flatten_ir->src1 > 2047) - elf_offset += 16; - else - elf_offset += 4; - break; - case OP_read: - case OP_write: - case OP_jump: - case OP_call: - case OP_load_func: - case OP_indirect: - case OP_add: - case OP_sub: - case OP_mul: - case OP_div: - case OP_mod: - case OP_lshift: - case OP_rshift: - case OP_gt: - case OP_lt: - case OP_bit_and: - case OP_bit_or: - case OP_bit_xor: - case OP_negate: - case OP_log_and: - case OP_bit_not: - /* TODO: if the offset of store/load is more than 12 bits, - * use compounded instructions. - */ - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 4; - break; - case OP_branch: - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 20; - break; - case OP_load_data_address: - case OP_neq: - case OP_geq: - case OP_leq: - case OP_log_not: - case OP_log_or: - flatten_ir = add_ph2_ir(insn->op); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 8; - break; - case OP_address_of_func: - case OP_eq: - flatten_ir = add_ph2_ir(OP_eq); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); - elf_offset += 12; - break; - case OP_return: - flatten_ir = add_ph2_ir(OP_return); - memcpy(flatten_ir, insn, sizeof(ph2_ir_t)); + if (insn->op == OP_return) /* restore sp */ flatten_ir->src1 = bb->belong_to->func->stack_size; - elf_offset += 24; - break; - default: - printf("Unknown opcode\n"); - abort(); - } + + update_elf_offset_by_ph2_ir(flatten_ir); } } } } +void emit(int code) +{ + elf_write_code_int(code); +} + +void emit_from_ph2_ir(ph2_ir_t *ph2_ir) +{ + int rd = ph2_ir->dest + 10; + int rs1 = ph2_ir->src0 + 10; + int rs2 = ph2_ir->src1 + 10; + int ofs; + + switch (ph2_ir->op) { + case OP_define: + emit(__lui(__t0, rv_hi(ph2_ir->src0 + 4))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0 + 4))); + emit(__sub(__sp, __sp, __t0)); + emit(__sw(__ra, __sp, 0)); + return; + case OP_load_constant: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { + emit(__lui(rd, rv_hi(ph2_ir->src0))); + emit(__addi(rd, rd, rv_lo(ph2_ir->src0))); + + } else + emit(__addi(rd, __zero, ph2_ir->src0)); + return; + case OP_global_address_of: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { + emit(__lui(__t0, rv_hi(ph2_ir->src0))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); + emit(__add(rd, __gp, __t0)); + } else + emit(__addi(rd, __gp, ph2_ir->src0)); + return; + case OP_address_of: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { + emit(__lui(__t0, rv_hi(ph2_ir->src0))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); + emit(__add(rd, __sp, __t0)); + } else + emit(__addi(rd, __sp, ph2_ir->src0)); + return; + case OP_assign: + emit(__addi(rd, rs1, 0)); + return; + case OP_load: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { + emit(__lui(__t0, rv_hi(ph2_ir->src0))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); + emit(__add(__t0, __sp, __t0)); + emit(__lw(rd, __t0, 0)); + } else + emit(__lw(rd, __sp, ph2_ir->src0)); + return; + case OP_store: + if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) { + emit(__lui(__t0, rv_hi(ph2_ir->src1))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1))); + emit(__add(__t0, __sp, __t0)); + emit(__sw(rs1, __t0, 0)); + } else + emit(__sw(rs1, __sp, ph2_ir->src1)); + return; + case OP_global_load: + if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { + emit(__lui(__t0, rv_hi(ph2_ir->src0))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); + emit(__add(__t0, __gp, __t0)); + emit(__lw(rd, __t0, 0)); + } else + emit(__lw(rd, __gp, ph2_ir->src0)); + return; + case OP_global_store: + if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) { + emit(__lui(__t0, rv_hi(ph2_ir->src1))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1))); + emit(__add(__t0, __gp, __t0)); + emit(__sw(rs1, __t0, 0)); + } else + emit(__sw(rs1, __gp, ph2_ir->src1)); + return; + case OP_read: + if (ph2_ir->src1 == 1) + emit(__lb(rd, rs1, 0)); + else if (ph2_ir->src1 == 4) + emit(__lw(rd, rs1, 0)); + else + abort(); + return; + case OP_write: + if (ph2_ir->dest == 1) + emit(__sb(rs2, rs1, 0)); + else if (ph2_ir->dest == 4) + emit(__sw(rs2, rs1, 0)); + else + abort(); + return; + case OP_branch: + ofs = elf_code_start + ph2_ir->then_bb->elf_offset; + emit(__lui(__t0, rv_hi(ofs))); + emit(__addi(__t0, __t0, rv_lo(ofs))); + emit(__beq(rs1, __zero, 8)); + emit(__jalr(__zero, __t0, 0)); + emit(__jal(__zero, ph2_ir->else_bb->elf_offset - elf_code_idx)); + return; + case OP_jump: + emit(__jal(__zero, ph2_ir->next_bb->elf_offset - elf_code_idx)); + return; + case OP_call: + emit(__jal(__ra, find_func(ph2_ir->func_name)->fn->bbs->elf_offset - + elf_code_idx)); + return; + case OP_load_data_address: + emit(__lui(rd, rv_hi(elf_data_start + ph2_ir->src0))); + emit(__addi(rd, rd, rv_lo(elf_data_start + ph2_ir->src0))); + return; + case OP_address_of_func: + ofs = + elf_code_start + find_func(ph2_ir->func_name)->fn->bbs->elf_offset; + emit(__lui(__t0, rv_hi(ofs))); + emit(__addi(__t0, __t0, rv_lo(ofs))); + emit(__sw(__t0, rs1, 0)); + return; + case OP_load_func: + emit(__addi(__t0, rs1, 0)); + return; + case OP_indirect: + emit(__jalr(__ra, __t0, 0)); + return; + case OP_return: + if (ph2_ir->src0 == -1) + emit(__addi(__zero, __zero, 0)); + else + emit(__addi(__a0, rs1, 0)); + emit(__lw(__ra, __sp, 0)); + emit(__lui(__t0, rv_hi(ph2_ir->src1 + 4))); + emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1 + 4))); + emit(__add(__sp, __sp, __t0)); + emit(__jalr(__zero, __ra, 0)); + return; + case OP_add: + emit(__add(rd, rs1, rs2)); + return; + case OP_sub: + emit(__sub(rd, rs1, rs2)); + return; + case OP_mul: + emit(__mul(rd, rs1, rs2)); + return; + case OP_div: + emit(__div(rd, rs1, rs2)); + return; + case OP_mod: + emit(__mod(rd, rs1, rs2)); + return; + case OP_lshift: + emit(__sll(rd, rs1, rs2)); + return; + case OP_rshift: + emit(__sra(rd, rs1, rs2)); + return; + case OP_eq: + emit(__sub(rd, rs1, rs2)); + emit(__sltu(rd, __zero, rd)); + emit(__xori(rd, rd, 1)); + return; + case OP_neq: + emit(__sub(rd, rs1, rs2)); + emit(__sltu(rd, __zero, rd)); + return; + case OP_gt: + emit(__slt(rd, rs2, rs1)); + return; + case OP_geq: + emit(__slt(rd, rs1, rs2)); + emit(__xori(rd, rd, 1)); + return; + case OP_lt: + emit(__slt(rd, rs1, rs2)); + return; + case OP_leq: + emit(__slt(rd, rs2, rs1)); + emit(__xori(rd, rd, 1)); + return; + case OP_negate: + emit(__sub(rd, __zero, rs1)); + return; + case OP_bit_not: + emit(__xori(rd, rs1, -1)); + return; + case OP_bit_and: + emit(__and(rd, rs1, rs2)); + return; + case OP_bit_or: + emit(__or(rd, rs1, rs2)); + return; + case OP_bit_xor: + emit(__xor(rd, rs1, rs2)); + return; + case OP_log_not: + emit(__sltu(rd, __zero, rs1)); + emit(__xori(rd, rd, 1)); + return; + case OP_log_and: + /* FIXME: bad logical-and instruction */ + emit(__and(rd, rs1, rs2)); + return; + case OP_log_or: + emit(__or(rd, rs1, rs2)); + emit(__sltu(rd, __zero, rd)); + return; + default: + printf("Unknown opcode\n"); + abort(); + } +} + void code_generate() { - int elf_data_start = elf_code_start + elf_offset; + elf_data_start = elf_code_start + elf_offset; /* start */ emit(__lui(__t0, rv_hi(GLOBAL_FUNC.stack_size))); @@ -217,44 +390,9 @@ void code_generate() ph2_ir_t *ph2_ir; for (ph2_ir = GLOBAL_FUNC.fn->bbs->ph2_ir_list.head; ph2_ir; - ph2_ir = ph2_ir->next) { - int rd = ph2_ir->dest + 10; - int rs1 = ph2_ir->src0 + 10; - int rs2 = ph2_ir->src1 + 10; + ph2_ir = ph2_ir->next) + emit_from_ph2_ir(ph2_ir); - switch (ph2_ir->op) { - case OP_load_constant: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { - emit(__lui(rd, rv_hi(ph2_ir->src0))); - emit(__addi(rd, rd, rv_lo(ph2_ir->src0))); - } else - emit(__addi(rd, __zero, ph2_ir->src0)); - break; - case OP_global_address_of: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src0))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); - emit(__add(rd, __gp, __t0)); - } else - emit(__addi(rd, __gp, ph2_ir->src0)); - break; - case OP_assign: - emit(__addi(rd, rs1, 0)); - break; - case OP_global_store: - if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src1))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1))); - emit(__add(__t0, __gp, __t0)); - emit(__sw(rs1, __t0, 0)); - } else - emit(__sw(rs1, __gp, ph2_ir->src1)); - break; - default: - printf("Unknown opcode\n"); - abort(); - } - } /* prepare `argc` and `argv`, then proceed to `main` function */ emit(__lui(__t0, rv_hi(GLOBAL_FUNC.stack_size))); emit(__addi(__t0, __t0, rv_lo(GLOBAL_FUNC.stack_size))); @@ -265,207 +403,7 @@ void code_generate() int i; for (i = 0; i < ph2_ir_idx; i++) { - ph2_ir_t *ph2_ir = &PH2_IR[i]; - int rd = ph2_ir->dest + 10; - int rs1 = ph2_ir->src0 + 10; - int rs2 = ph2_ir->src1 + 10; - int ofs; - - switch (ph2_ir->op) { - case OP_define: - emit(__lui(__t0, rv_hi(ph2_ir->src0 + 4))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0 + 4))); - emit(__sub(__sp, __sp, __t0)); - emit(__sw(__ra, __sp, 0)); - break; - case OP_load_constant: - if (ph2_ir->src0 < 2048 && ph2_ir->src0 > -2047) - emit(__addi(rd, __zero, ph2_ir->src0)); - else { - emit(__lui(rd, rv_hi(ph2_ir->src0))); - emit(__addi(rd, rd, rv_lo(ph2_ir->src0))); - } - break; - case OP_load_data_address: - emit(__lui(rd, rv_hi(elf_data_start + ph2_ir->src0))); - emit(__addi(rd, rd, rv_lo(elf_data_start + ph2_ir->src0))); - break; - case OP_address_of: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src0))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); - emit(__add(rd, __sp, __t0)); - } else - emit(__addi(rd, __sp, ph2_ir->src0)); - break; - case OP_assign: - emit(__addi(rd, rs1, 0)); - break; - case OP_load: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src0))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); - emit(__add(__t0, __sp, __t0)); - emit(__lw(rd, __t0, 0)); - } else - emit(__lw(rd, __sp, ph2_ir->src0)); - break; - case OP_store: - if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src1))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1))); - emit(__add(__t0, __sp, __t0)); - emit(__sw(rs1, __t0, 0)); - } else - emit(__sw(rs1, __sp, ph2_ir->src1)); - break; - case OP_global_load: - if (ph2_ir->src0 < -2048 || ph2_ir->src0 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src0))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src0))); - emit(__add(__t0, __gp, __t0)); - emit(__lw(rd, __t0, 0)); - } else - emit(__lw(rd, __gp, ph2_ir->src0)); - break; - case OP_global_store: - if (ph2_ir->src1 < -2048 || ph2_ir->src1 > 2047) { - emit(__lui(__t0, rv_hi(ph2_ir->src1))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1))); - emit(__add(__t0, __gp, __t0)); - emit(__sw(rs1, __t0, 0)); - } else - emit(__sw(rs1, __gp, ph2_ir->src1)); - break; - case OP_read: - if (ph2_ir->src1 == 1) - emit(__lb(rd, rs1, 0)); - else if (ph2_ir->src1 == 4) - emit(__lw(rd, rs1, 0)); - else - abort(); - break; - case OP_write: - if (ph2_ir->dest == 1) - emit(__sb(rs2, rs1, 0)); - else if (ph2_ir->dest == 4) - emit(__sw(rs2, rs1, 0)); - else - abort(); - break; - case OP_branch: - ofs = elf_code_start + ph2_ir->then_bb->elf_offset; - emit(__lui(__t0, rv_hi(ofs))); - emit(__addi(__t0, __t0, rv_lo(ofs))); - emit(__beq(rs1, __zero, 8)); - emit(__jalr(__zero, __t0, 0)); - emit(__jal(__zero, ph2_ir->else_bb->elf_offset - elf_code_idx)); - break; - case OP_jump: - emit(__jal(__zero, ph2_ir->next_bb->elf_offset - elf_code_idx)); - break; - case OP_call: - emit(__jal(__ra, find_func(ph2_ir->func_name)->fn->bbs->elf_offset - - elf_code_idx)); - break; - case OP_address_of_func: - ofs = elf_code_start + - find_func(ph2_ir->func_name)->fn->bbs->elf_offset; - emit(__lui(__t0, rv_hi(ofs))); - emit(__addi(__t0, __t0, rv_lo(ofs))); - emit(__sw(__t0, rs1, 0)); - break; - case OP_load_func: - emit(__addi(__t0, rs1, 0)); - break; - case OP_indirect: - emit(__jalr(__ra, __t0, 0)); - break; - case OP_return: - if (ph2_ir->src0 == -1) - emit(__addi(__zero, __zero, 0)); - else - emit(__addi(__a0, rs1, 0)); - emit(__lw(__ra, __sp, 0)); - emit(__lui(__t0, rv_hi(ph2_ir->src1 + 4))); - emit(__addi(__t0, __t0, rv_lo(ph2_ir->src1 + 4))); - emit(__add(__sp, __sp, __t0)); - emit(__jalr(__zero, __ra, 0)); - break; - case OP_add: - emit(__add(rd, rs1, rs2)); - break; - case OP_sub: - emit(__sub(rd, rs1, rs2)); - break; - case OP_mul: - emit(__mul(rd, rs1, rs2)); - break; - case OP_div: - emit(__div(rd, rs1, rs2)); - break; - case OP_mod: - emit(__mod(rd, rs1, rs2)); - break; - case OP_lshift: - emit(__sll(rd, rs1, rs2)); - break; - case OP_rshift: - emit(__sra(rd, rs1, rs2)); - break; - case OP_eq: - emit(__sub(rd, rs1, rs2)); - emit(__sltu(rd, __zero, rd)); - emit(__xori(rd, rd, 1)); - break; - case OP_neq: - emit(__sub(rd, rs1, rs2)); - emit(__sltu(rd, __zero, rd)); - break; - case OP_gt: - emit(__slt(rd, rs2, rs1)); - break; - case OP_geq: - emit(__slt(rd, rs1, rs2)); - emit(__xori(rd, rd, 1)); - break; - case OP_lt: - emit(__slt(rd, rs1, rs2)); - break; - case OP_leq: - emit(__slt(rd, rs2, rs1)); - emit(__xori(rd, rd, 1)); - break; - case OP_negate: - emit(__sub(rd, __zero, rs1)); - break; - case OP_bit_not: - emit(__xori(rd, rs1, -1)); - break; - case OP_bit_and: - emit(__and(rd, rs1, rs2)); - break; - case OP_bit_or: - emit(__or(rd, rs1, rs2)); - break; - case OP_bit_xor: - emit(__xor(rd, rs1, rs2)); - break; - case OP_log_not: - emit(__sltu(rd, __zero, rs1)); - emit(__xori(rd, rd, 1)); - break; - case OP_log_and: - /* FIXME: bad logical-and instruction */ - emit(__and(rd, rs1, rs2)); - break; - case OP_log_or: - emit(__or(rd, rs1, rs2)); - emit(__sltu(rd, __zero, rd)); - break; - default: - printf("Unknown opcode\n"); - abort(); - } + ph2_ir = &PH2_IR[i]; + emit_from_ph2_ir(ph2_ir); } }