diff --git a/boot.c b/boot.c index c35e623..4099852 100644 --- a/boot.c +++ b/boot.c @@ -466,22 +466,60 @@ void declare_global(int id, int marker) { global_marker[id] = marker; } +int check_itype_immediate(int value) { + return value >= -2048 && value <= 2047; +} + +void asm_ld(const char* rd, int imm, const char* rs) { + if (check_itype_immediate(imm)) { + printf(" ld %s, %d(%s)\n", rd, imm, rs); + } else { + printf(" li t0, %d\n", imm); + printf(" add t0, %s, t0\n", rs); + printf(" ld %s, 0(t0)\n", rd); + } +} + +void asm_sd(const char* rs1, int imm, const char* rs2) { + if (check_itype_immediate(imm)) { + printf(" sd %s, %d(%s)\n", rs1, imm, rs2); + } else { + printf(" li t0, %d\n", imm); + printf(" add t0, %s, t0\n", rs2); + printf(" sd %s, 0(t0)\n", rs1); + } + +} + +void asm_addi(const char* rd, const char* rs, int imm) { + if (check_itype_immediate(imm)) { + printf(" addi %s, %s, %d\n", rd, rs, imm); + } else { + printf(" li t0, %d\n", imm); + printf(" add %s, %s, t0\n", rd, rs); + } +} + const int INDIRECTION = 1048576; // 2**20 -const int GLOBAL = 2097152; // 2**21 void load_address(int rd, int id) { - if (id & GLOBAL) { - id = id & ~GLOBAL; - const char* name = CA_offset(id_table, id_lut[id]); - printf(" la t%d, %s # id: %d\n", rd, name, id); - } else { - if (id & INDIRECTION) { - id = id & ~INDIRECTION; - int offset = -id * 8 - 8; + if (id & INDIRECTION) { + id = id & ~INDIRECTION; + int offset = -id * 8 - 8; + if (check_itype_immediate(offset)) { printf(" ld t%d, %d(fp) # indirection\n", rd, offset); } else { - int offset = -id * 8 - 8; + printf(" li t%d, %d\n", rd, offset); + printf(" add t%d, fp, t%d\n", rd, rd); + printf(" ld t%d, 0(t%d) # indirection\n", rd, rd); + } + } else { + int offset = -id * 8 - 8; + if (check_itype_immediate(offset)) { printf(" addi t%d, fp, %d\n", rd, offset); + } else { + printf(" li t%d, %d\n", rd, offset); + printf(" add t%d, fp, t%d\n", rd, rd); } } } @@ -495,27 +533,30 @@ void store(int rs1, int rs2) { printf(" sd t%d, 0(t%d)\n", rs1, rs2); } +int materialize_t0() { + int reg = next_reg(); + load_address(1, reg); + store(0, 1); + return reg; +} + int lookup(int id) { int local = local_table[id]; if (local) { if (local_marker[local] == ARRAY) { - int reg = next_reg(); load_address(0, local); - load_address(1, reg); - store(0, 1); - return reg; + return materialize_t0(); } return local; } if (global_marker[id]) { - if (global_marker[id] == ARRAY) { - int reg = next_reg(); - load_address(0, id | GLOBAL); - load_address(1, reg); - store(0, 1); - return reg; + const char* name = CA_offset(id_table, id_lut[id]); + printf(" la t0, %s # id: %d\n", name, id); + int reg = materialize_t0(); + if (global_marker[id] != ARRAY) { + reg = reg | INDIRECTION; } - return id | GLOBAL; + return reg; } const char* name = CA_offset(id_table, id_lut[id]); eprintf("unresolved identifier: %s\n", name); @@ -534,7 +575,7 @@ int asm_label(int label) { } int is_not_reusable(int rs1) { - return (rs1 & GLOBAL) || (rs1 & INDIRECTION) || local_marker[rs1]; + return (rs1 & INDIRECTION) || local_marker[rs1]; } int asm_r(const char* op, int rs1) { @@ -559,14 +600,6 @@ int asm_rr(const char* op, int rs1, int rs2) { return rd; } -int asm_li(int imm) { - printf(" li t0, %d\n", imm); - int rd = next_reg(); - load_address(1, rd); - store(0, 1); - return rd; -} - void asm_beqz(int rs1, int label) { load(0, rs1); printf(" beqz t0, L%d\n", label); @@ -612,15 +645,13 @@ int parse_primary_expr() { if (token_type == TOKEN_EOF) { exit(1); } else if (token_type == TOKEN_NUMBER) { - return asm_li(token_data); + printf(" li t0, %d\n", token_data); + return materialize_t0(); } else if (token_type == TOKEN_ID) { return lookup(token_data); } else if (token_type == TOKEN_STRING) { - int reg = next_reg(); printf(" la t0, .LC%d\n", token_data); - load_address(1, reg); - store(0, 1); - return reg; + return materialize_t0(); } else if (token_type == TOKEN_PAREN_LEFT) { int reg = parse_expr(); expect_token(TOKEN_PAREN_RIGHT); @@ -654,16 +685,13 @@ int parse_postfix_expr() { store(0, 1); return reg; } else if (token_type == TOKEN_BRACKET_LEFT) { - int reg = next_reg(); int rhs = parse_expr(); expect_token(TOKEN_BRACKET_RIGHT); load(0, rhs); load(1, lhs); printf(" slli t0, t0, 3\n"); printf(" add t0, t0, t1\n"); - load_address(1, reg); - store(0, 1); - return reg | INDIRECTION; + return materialize_t0() | INDIRECTION; } else if (token_type == TOKEN_PAREN_LEFT) { int arg = 0; int args[8]; @@ -695,10 +723,7 @@ int parse_postfix_expr() { load_address(0, lhs); printf(" jalr t0\n"); printf(" mv t0, a0\n"); - int reg = next_reg(); - load_address(1, reg); - store(0, 1); - return reg; + return materialize_t0(); } else { unget_token(); return lhs; @@ -710,11 +735,8 @@ int parse_prefix_expr() { next_token(); if (token_type == TOKEN_AND) { int id = parse_postfix_expr(); - int reg = next_reg(); load_address(0, id); - load_address(1, reg); - store(0, 1); - return reg; + return materialize_t0(); } else if (token_type == TOKEN_STAR) { int reg = parse_postfix_expr(); return reg | INDIRECTION; @@ -1143,10 +1165,10 @@ void parse_function(const char* name) { } // prolog asm_label(prolog_label); - printf(" addi sp, sp, %d\n", -shift); - printf(" sd ra, %d(sp)\n", shift - 8); - printf(" sd fp, %d(sp)\n", shift - 16); - printf(" addi fp, sp, %d\n", shift); + asm_addi("sp", "sp", -shift); + asm_sd("ra", shift - 8, "sp"); + asm_sd("fp", shift - 16, "sp"); + asm_addi("fp", "sp", shift); for (int i = 0; i < arg; ++i) { load_address(1, args[i]); printf(" mv t0, a%d\n", i); @@ -1155,9 +1177,9 @@ void parse_function(const char* name) { asm_j(label); // epilog asm_label(epilog_label); - printf(" ld fp, %d(sp)\n", shift - 16); - printf(" ld ra, %d(sp)\n", shift - 8); - printf(" addi sp, sp, %d\n", shift); + asm_ld("fp", shift - 16, "sp"); + asm_ld("ra", shift - 8, "sp"); + asm_addi("sp", "sp", shift); printf(" ret\n"); }