so that a hello world works.
Unified · Split
| @@ -107,16 +107,38 @@ ST_FUNC void load(int r, SValue *sv) · 106 unmodified lines | |||
| 107 | int v = fr & VT_VALMASK; | 107 | int v = fr & VT_VALMASK; |
| 108 | int rr = ireg(r); | 108 | int rr = ireg(r); |
| 109 | int fc = sv->c.i; | 109 | int fc = sv->c.i; |
| 110 | if (v == VT_CONST) { | 110 | if (fr & VT_LVAL) { |
| 111 | if (fr & VT_SYM) | 111 | if (v == VT_LOCAL) { |
| 112 | tcc_error("unimp: load(sym)"); | 112 | if (((unsigned)fc + (1 << 11)) >> 12) |
| 113 | if (is_float(sv->type.t)) | 113 | tcc_error("unimp: load(large local ofs) (0x%x)", fc); |
| 114 | tcc_error("unimp: load(float)"); | 114 | EI(0x03, 3, rr, 8, fc); // ld RR, fc(s0) |
| 115 | } else { | ||
| 116 | tcc_error("unimp: load(non-local lval)"); | ||
| 117 | } | ||
| 118 | } else if (v == VT_CONST) { | ||
| 119 | int rb = 0; | ||
| 115 | if (fc != sv->c.i) | 120 | if (fc != sv->c.i) |
| 116 | tcc_error("unimp: load(very large const)"); | 121 | tcc_error("unimp: load(very large const)"); |
| 117 | if (((unsigned)fc + (1 << 11)) >> 12) | 122 | if (((unsigned)fc + (1 << 11)) >> 12) |
| 118 | tcc_error("unimp: load(large const) (0x%x)", fc); | 123 | tcc_error("unimp: load(large const) (0x%x)", fc); |
| 119 | EI(0x13, 0, rr, 0, fc); // addi R, x0, FC | 124 | if (fr & VT_SYM) { |
| 125 | static Sym label; | ||
| 126 | greloca(cur_text_section, vtop->sym, ind, | ||
| 127 | R_RISCV_PCREL_HI20, fc); | ||
| 128 | if (!label.v) { | ||
| 129 | label.v = tok_alloc(".L0 ", 4)->tok; | ||
| 130 | label.type.t = VT_VOID | VT_STATIC; | ||
| 131 | } | ||
| 132 | label.c = 0; /* force new local ELF symbol */ | ||
| 133 | put_extern_sym(&label, cur_text_section, ind, 0); | ||
| 134 | o(0x17 | (rr << 7)); // auipc RR, 0 %call(func) | ||
| 135 | greloca(cur_text_section, &label, ind, | ||
| 136 | R_RISCV_PCREL_LO12_I, 0); | ||
| 137 | rb = rr; | ||
| 138 | } | ||
| 139 | if (is_float(sv->type.t)) | ||
| 140 | tcc_error("unimp: load(float)"); | ||
| 141 | EI(0x13, 0, rr, rb, fc); // addi R, x0|R, FC | ||
| 120 | } else | 142 | } else |
| 121 | tcc_error("unimp: load(non-const)"); | 143 | tcc_error("unimp: load(non-const)"); |
| 122 | } | 144 | } |
| @@ -126,9 +148,39 @@ ST_FUNC void store(int r, SValue *sv) · 3 unmodified lines | |||
| 126 | tcc_error("implement me: %s", __FUNCTION__); | 148 | tcc_error("implement me: %s", __FUNCTION__); |
| 127 | } | 149 | } |
| 128 | 150 | ||
| 151 | static void gcall(void) | ||
| 152 | { | ||
| 153 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && | ||
| 154 | ((vtop->r & VT_SYM) && vtop->c.i == (int)vtop->c.i)) { | ||
| 155 | /* constant symbolic case -> simple relocation */ | ||
| 156 | greloca(cur_text_section, vtop->sym, ind, | ||
| 157 | R_RISCV_CALL_PLT, (int)vtop->c.i); | ||
| 158 | o(0x17 | (1 << 7)); // auipc ra, 0 %call(func) | ||
| 159 | o(0x80e7); // jalr ra, 0 %call(func) | ||
| 160 | } else { | ||
| 161 | tcc_error("unimp: indirect call"); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 129 | ST_FUNC void gfunc_call(int nb_args) | 165 | ST_FUNC void gfunc_call(int nb_args) |
| 130 | { | 166 | { |
| 131 | tcc_error("implement me: %s", __FUNCTION__); | 167 | int i, align, size, aireg; |
| 168 | aireg = 0; | ||
| 169 | for (i = 0; i < nb_args; i++) { | ||
| 170 | size = type_size(&vtop[-i].type, &align); | ||
| 171 | if (size > 8 || ((vtop[-i].type.t & VT_BTYPE) == VT_STRUCT) | ||
| 172 | || is_float(vtop[-i].type.t)) | ||
| 173 | tcc_error("unimp: call arg %d wrong type", nb_args - i); | ||
| 174 | if (aireg >= 8) | ||
| 175 | tcc_error("unimp: too many register args"); | ||
| 176 | vrotb(i+1); | ||
| 177 | gv(RC_R(aireg)); | ||
| 178 | vrott(i+1); | ||
| 179 | aireg++; | ||
| 180 | } | ||
| 181 | vrotb(nb_args + 1); | ||
| 182 | gcall(); | ||
| 183 | vtop -= nb_args + 1; | ||
| 132 | } | 184 | } |
| 133 | 185 | ||
| 134 | static int func_sub_sp_offset; | 186 | static int func_sub_sp_offset; |
| @@ -143,9 +195,9 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 8 unmodified lines | |||
| 143 | 195 | ||
| 144 | sym = func_type->ref; | 196 | sym = func_type->ref; |
| 145 | func_vt = sym->type; | 197 | func_vt = sym->type; |
| 146 | loc = -16; /* for saved ra, and s0 */ | 198 | loc = -16; // for ra and s0 |
| 147 | func_sub_sp_offset = ind; | 199 | func_sub_sp_offset = ind; |
| 148 | ind += 3 * 4; | 200 | ind += 4 * 4; |
| 149 | if (sym->f.func_type == FUNC_ELLIPSIS) { | 201 | if (sym->f.func_type == FUNC_ELLIPSIS) { |
| 150 | tcc_error("unimp: vararg prologue"); | 202 | tcc_error("unimp: vararg prologue"); |
| 151 | } | 203 | } |
| @@ -180,7 +232,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 28 unmodified lines | |||
| 180 | if (is_float(type->t)) { | 232 | if (is_float(type->t)) { |
| 181 | tcc_error("unimp: float args"); | 233 | tcc_error("unimp: float args"); |
| 182 | } else { | 234 | } else { |
| 183 | ES(0x23, 3, 2, 10 + aireg, -loc + i*8); // sd aX, loc(sp) // XXX | 235 | ES(0x23, 3, 8, 10 + aireg, loc + i*8); // sd aX, loc(s0) // XXX |
| 184 | } | 236 | } |
| 185 | } | 237 | } |
| 186 | } | 238 | } |
| @@ -227,6 +279,7 @@ ST_FUNC void gfunc_epilog(void) · 40 unmodified lines | |||
| 227 | EI(0x13, 0, 2, 2, -v); // addi sp, sp, -v | 279 | EI(0x13, 0, 2, 2, -v); // addi sp, sp, -v |
| 228 | ES(0x23, 3, 2, 1, v - 8); // sd ra, v-8(sp) | 280 | ES(0x23, 3, 2, 1, v - 8); // sd ra, v-8(sp) |
| 229 | ES(0x23, 3, 2, 8, v - 16); // sd s0, v-16(sp) | 281 | ES(0x23, 3, 2, 8, v - 16); // sd s0, v-16(sp) |
| 282 | EI(0x13, 0, 8, 2, v); // addi s0, sp, v | ||
| 230 | ind = saved_ind; | 283 | ind = saved_ind; |
| 231 | } | 284 | } |
| 232 | 285 | ||