refactor mv
This commit is contained in:
parent
66505c1389
commit
487704cd44
170
boot.c
170
boot.c
@ -653,19 +653,6 @@ void asm_addi(const char* rd, const char* rs, int imm) {
|
|||||||
|
|
||||||
// assembly helpers
|
// assembly helpers
|
||||||
|
|
||||||
// address loaders
|
|
||||||
// rd must be one of t0, t1, t2
|
|
||||||
void load_local_address(int rd, int slot_id) {
|
|
||||||
int offset = slot_id * 8 - 8;
|
|
||||||
const char* rd_name = reg_name(rd);
|
|
||||||
if (check_itype_immediate(offset)) {
|
|
||||||
printf(" addi %s, sp, %d\n", rd_name, offset);
|
|
||||||
} else {
|
|
||||||
printf(" li %s, %d\n", rd_name, offset);
|
|
||||||
printf(" add %s, sp, %s\n", rd_name, rd_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* load_op_of_type(int type) {
|
const char* load_op_of_type(int type) {
|
||||||
if (type & TYPE_PTR_MASK) {
|
if (type & TYPE_PTR_MASK) {
|
||||||
return "ld";
|
return "ld";
|
||||||
@ -686,23 +673,28 @@ const char* store_op_of_type(int type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load a non-trivial register into t0, t1 or t2
|
// address loaders
|
||||||
// rd must be one of t0, t1, t2
|
// rd must be one of t0, t1, t2
|
||||||
void load(int rd, int reg) {
|
void load_local_address(int rd, int slot_id) {
|
||||||
const char* op = load_op_of_type(reg_type[reg]);
|
asm_addi(reg_name(rd), "sp", slot_id * 8 - 8);
|
||||||
const char* rd_name = reg_name(rd);
|
|
||||||
if (is_overflow(reg)) {
|
|
||||||
load_local_address(rd, overflow[reg]);
|
|
||||||
if (indirection[reg]) {
|
|
||||||
printf(" ld %s, 0(%s)\n", rd_name, rd_name);
|
|
||||||
}
|
|
||||||
reg = rd;
|
|
||||||
}
|
|
||||||
printf(" %s %s, 0(%s) # load non-trivial register\n", op, rd_name, reg_name(reg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// store t0 into a non-trivial register
|
// load a non-trivial register into trivial one
|
||||||
void store_t0(int reg) {
|
void load(int rd, int rs) {
|
||||||
|
const char* op = load_op_of_type(reg_type[rs]);
|
||||||
|
const char* rd_name = reg_name(rd);
|
||||||
|
if (is_overflow(rs)) {
|
||||||
|
load_local_address(rd, overflow[rs]);
|
||||||
|
if (indirection[rs]) {
|
||||||
|
printf(" ld %s, 0(%s)\n", rd_name, rd_name);
|
||||||
|
}
|
||||||
|
rs = rd;
|
||||||
|
}
|
||||||
|
printf(" %s %s, 0(%s) # load non-trivial register\n", op, rd_name, reg_name(rs));
|
||||||
|
}
|
||||||
|
|
||||||
|
// store a trivial register into a non-trivial one
|
||||||
|
void store(const char* rs, int reg) {
|
||||||
const char* op = store_op_of_type(reg_type[reg]);
|
const char* op = store_op_of_type(reg_type[reg]);
|
||||||
if (is_overflow(reg)) {
|
if (is_overflow(reg)) {
|
||||||
load_local_address(REG_T2, overflow[reg]);
|
load_local_address(REG_T2, overflow[reg]);
|
||||||
@ -711,67 +703,65 @@ void store_t0(int reg) {
|
|||||||
}
|
}
|
||||||
reg = REG_T2;
|
reg = REG_T2;
|
||||||
}
|
}
|
||||||
printf(" %s t0, 0(%s) # store non-trivial register\n", op, reg_name(reg));
|
printf(" %s %s, 0(%s) # store non-trivial register\n", op, rs, reg_name(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_nontrivial(int reg) {
|
int is_nontrivial(int reg) {
|
||||||
return is_overflow(reg) || indirection[reg];
|
return is_overflow(reg) || indirection[reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* trivialize(int rs, int t) {
|
||||||
|
if (is_nontrivial(rs)) {
|
||||||
|
load(t, rs);
|
||||||
|
return reg_name(t);
|
||||||
|
}
|
||||||
|
return reg_name(rs);
|
||||||
|
}
|
||||||
|
|
||||||
void _asm_r(const char* op, int rd, int rs1) {
|
void _asm_r(const char* op, int rd, int rs1) {
|
||||||
const char* rd_name = reg_name(rd);
|
const char* rd_name = reg_name(rd);
|
||||||
const char* rs1_name = reg_name(rs1);
|
|
||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
if (is_nontrivial(rs1)) {
|
const char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
rs1_name = "t0";
|
|
||||||
load(REG_T0, rs1);
|
|
||||||
}
|
|
||||||
if (!(streq(op, "mv") && streq(rd_name, rs1_name)))
|
|
||||||
printf(" %s %s, %s\n", op, rd_name, rs1_name);
|
printf(" %s %s, %s\n", op, rd_name, rs1_name);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
store_t0(rd);
|
store("t0", rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void asm_mv(int rd, int rs1) {
|
||||||
|
const char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
|
if (is_nontrivial(rd)) {
|
||||||
|
store(rs1_name, rd);
|
||||||
|
} else {
|
||||||
|
const char* rd_name = reg_name(rd);
|
||||||
|
if (!streq(rd_name, rs1_name))
|
||||||
|
printf(" mv %s, %s\n", rd_name, rs1_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _asm_rr(const char* op, int rd, int rs1, int rs2) {
|
void _asm_rr(const char* op, int rd, int rs1, int rs2) {
|
||||||
const char* rd_name = reg_name(rd);
|
const char* rd_name = reg_name(rd);
|
||||||
const char* rs1_name = reg_name(rs1);
|
const char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
const char* rs2_name = reg_name(rs2);
|
const char* rs2_name = trivialize(rs2, REG_T1);
|
||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
if (is_nontrivial(rs1)) {
|
|
||||||
rs1_name = "t0";
|
|
||||||
load(REG_T0, rs1);
|
|
||||||
}
|
|
||||||
if (is_nontrivial(rs2)) {
|
|
||||||
rs2_name = "t1";
|
|
||||||
load(REG_T1, rs2);
|
|
||||||
}
|
|
||||||
printf(" %s %s, %s, %s\n", op, rd_name, rs1_name, rs2_name);
|
printf(" %s %s, %s, %s\n", op, rd_name, rs1_name, rs2_name);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
store_t0(rd);
|
store("t0", rd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _asm_ri(const char* op, int rd, int rs1, int imm) {
|
void _asm_ri(const char* op, int rd, int rs1, int imm) {
|
||||||
const char* rd_name = reg_name(rd);
|
const char* rd_name = reg_name(rd);
|
||||||
const char* rs1_name = reg_name(rs1);
|
|
||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
if (is_nontrivial(rs1)) {
|
const char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
rs1_name = "t0";
|
|
||||||
load(REG_T0, rs1);
|
|
||||||
}
|
|
||||||
printf(" %s %s, %s, %d\n", op, rd_name, rs1_name, imm);
|
printf(" %s %s, %s, %d\n", op, rd_name, rs1_name, imm);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
store_t0(rd);
|
store("t0", rd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _asm_branch(const char* op, int rs1, int label) {
|
void _asm_branch(const char* op, int rs1, int label) {
|
||||||
const char* rs1_name = reg_name(rs1);
|
const char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
if (is_nontrivial(rs1)) {
|
|
||||||
rs1_name = "t0";
|
|
||||||
load(REG_T0, rs1);
|
|
||||||
}
|
|
||||||
printf(" %s %s, L%d\n", op, rs1_name, label);
|
printf(" %s %s, L%d\n", op, rs1_name, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,7 +770,7 @@ void _asm_i(const char* op, int rd, const char* prefix1, const char* prefix2, in
|
|||||||
if (is_nontrivial(rd)) rd_name = "t0";
|
if (is_nontrivial(rd)) rd_name = "t0";
|
||||||
printf(" %s %s, %s%s%d\n", op, rd_name, prefix1, prefix2, imm);
|
printf(" %s %s, %s%s%d\n", op, rd_name, prefix1, prefix2, imm);
|
||||||
if (is_nontrivial(rd)) {
|
if (is_nontrivial(rd)) {
|
||||||
store_t0(rd);
|
store("t0", rd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,16 +793,8 @@ int asm_rr(int type, const char* op, int rs1, int rs2) {
|
|||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void asm_mv(int rd, int rs1) {
|
|
||||||
_asm_r("mv", rd, rs1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void store_into_local(int rs1, int slot) {
|
void store_into_local(int rs1, int slot) {
|
||||||
const char* rs1_name = reg_name(rs1);
|
const char* rs1_name = trivialize(rs1, REG_T0);
|
||||||
if (is_nontrivial(rs1)) {
|
|
||||||
rs1_name = "t0";
|
|
||||||
load(REG_T0, rs1);
|
|
||||||
}
|
|
||||||
load_local_address(REG_T2, slot);
|
load_local_address(REG_T2, slot);
|
||||||
printf(" %s %s, 0(t2)\n", store_op_of_type(local_type[slot]), rs1_name);
|
printf(" %s %s, 0(t2)\n", store_op_of_type(local_type[slot]), rs1_name);
|
||||||
}
|
}
|
||||||
@ -827,14 +809,14 @@ int materialize_address(int rd, int type, int marker) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lookup_from_slot(int slot) {
|
int lookup_from_slot(int slot) {
|
||||||
int reg = next_reg(TYPE_VOID_PTR);
|
int rd = next_reg(TYPE_VOID_PTR);
|
||||||
if (is_nontrivial(reg)) {
|
if (is_nontrivial(rd)) {
|
||||||
load_local_address(REG_T0, slot);
|
load_local_address(REG_T0, slot);
|
||||||
asm_mv(reg, REG_T0);
|
asm_mv(rd, REG_T0);
|
||||||
} else {
|
} else {
|
||||||
load_local_address(reg, slot);
|
load_local_address(rd, slot);
|
||||||
}
|
}
|
||||||
return materialize_address(reg, local_type[slot], local_marker[slot]);
|
return materialize_address(rd, local_type[slot], local_marker[slot]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_imm(int imm) {
|
int load_imm(int imm) {
|
||||||
@ -857,25 +839,14 @@ int lookup(int id) {
|
|||||||
eprintf("function name must not appear outside function call: %s\n", name);
|
eprintf("function name must not appear outside function call: %s\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int reg = next_reg(TYPE_VOID_PTR);
|
int rd = next_reg(TYPE_VOID_PTR);
|
||||||
_asm_i("la", reg, name, " # id: ", id);
|
_asm_i("la", rd, name, " # id: ", id);
|
||||||
return materialize_address(reg, global_type[id], global_marker[id]);
|
return materialize_address(rd, global_type[id], global_marker[id]);
|
||||||
}
|
}
|
||||||
eprintf("unresolved identifier: %s\n", name);
|
eprintf("unresolved identifier: %s\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int next_label_id = 0;
|
|
||||||
int next_label() {
|
|
||||||
return next_label_id++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int asm_label(int label) {
|
|
||||||
printf("L%d:\n", label);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
int asm_r_arith(const char* op, int rs1) {
|
int asm_r_arith(const char* op, int rs1) {
|
||||||
if (reg_type[rs1] & TYPE_PTR_MASK) {
|
if (reg_type[rs1] & TYPE_PTR_MASK) {
|
||||||
eprintf("pointer cannot be arithmetically operated by %s\n", op);
|
eprintf("pointer cannot be arithmetically operated by %s\n", op);
|
||||||
@ -909,6 +880,16 @@ void asm_j(int label) {
|
|||||||
printf(" j L%d\n", label);
|
printf(" j L%d\n", label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int next_label_id = 0;
|
||||||
|
int next_label() {
|
||||||
|
return next_label_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int asm_label(int label) {
|
||||||
|
printf("L%d:\n", label);
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
int break_label_stack[4096];
|
int break_label_stack[4096];
|
||||||
int cont_label_stack[4096];
|
int cont_label_stack[4096];
|
||||||
int break_label_stack_size;
|
int break_label_stack_size;
|
||||||
@ -932,11 +913,12 @@ void asm_pop_label() {
|
|||||||
--cont_label_stack_size;
|
--cont_label_stack_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int log_step_of(int type) {
|
||||||
|
return 2 * (type == TYPE_INT_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
int step_of(int type) {
|
int step_of(int type) {
|
||||||
if (type == TYPE_INT_PTR) {
|
return 1 << log_step_of(type);
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int asm_add(int lhs, int rhs) {
|
int asm_add(int lhs, int rhs) {
|
||||||
@ -958,8 +940,7 @@ int asm_add(int lhs, int rhs) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int offset = next_reg(TYPE_INT);
|
int offset = next_reg(TYPE_INT);
|
||||||
int shift = 2 * (ptr_type == TYPE_INT_PTR);
|
_asm_ri("slli", offset, idx, log_step_of(ptr_type));
|
||||||
_asm_ri("slli", offset, idx, shift);
|
|
||||||
return asm_rr(ptr_type, "add", ptr, offset);
|
return asm_rr(ptr_type, "add", ptr, offset);
|
||||||
}
|
}
|
||||||
if (type1 && type2) {
|
if (type1 && type2) {
|
||||||
@ -984,8 +965,7 @@ int asm_sub(int lhs, int rhs) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int difference = asm_rr(TYPE_INT, "sub", lhs, rhs);
|
int difference = asm_rr(TYPE_INT, "sub", lhs, rhs);
|
||||||
int shift = 2 * (lhs_type == TYPE_INT_PTR);
|
_asm_ri("slli", difference, difference, log_step_of(lhs_type));
|
||||||
_asm_ri("slli", difference, difference, shift);
|
|
||||||
return difference;
|
return difference;
|
||||||
}
|
}
|
||||||
if (type1) {
|
if (type1) {
|
||||||
@ -1582,7 +1562,7 @@ void parse_function(const char* name) {
|
|||||||
}
|
}
|
||||||
int arg_type = parse_type();
|
int arg_type = parse_type();
|
||||||
if (arg_type < 0 || arg_type == TYPE_VOID) {
|
if (arg_type < 0 || arg_type == TYPE_VOID) {
|
||||||
eprintf("unexpected a non-void argument type: %d\n", arg_type);
|
eprintf("expecting a non-void argument type: %d\n", arg_type);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
expect_token(TOKEN_ID);
|
expect_token(TOKEN_ID);
|
||||||
|
Loading…
Reference in New Issue
Block a user