so that a hello world works.
Unified · Split
| @@ -107,16 +107,38 @@ ST_FUNC void load(int r, SValue *sv) · 106 unmodified lines | ||
| 107 | 107 | int v = fr & VT_VALMASK; |
| 108 | 108 | int rr = ireg(r); |
| 109 | 109 | int fc = sv->c.i; |
| 110 | − if (v == VT_CONST) { | |
| 111 | − if (fr & VT_SYM) | |
| 112 | − tcc_error("unimp: load(sym)"); | |
| 113 | − if (is_float(sv->type.t)) | |
| 114 | − tcc_error("unimp: load(float)"); | |
| 110 | + if (fr & VT_LVAL) { | |
| 111 | + if (v == VT_LOCAL) { | |
| 112 | + if (((unsigned)fc + (1 << 11)) >> 12) | |
| 113 | + tcc_error("unimp: load(large local ofs) (0x%x)", fc); | |
| 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 | 120 | if (fc != sv->c.i) |
| 116 | 121 | tcc_error("unimp: load(very large const)"); |
| 117 | 122 | if (((unsigned)fc + (1 << 11)) >> 12) |
| 118 | 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 | 142 | } else |
| 121 | 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 | 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 | 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 | 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 | 196 | sym = func_type->ref; |
| 145 | 197 | func_vt = sym->type; |
| 146 | − loc = -16; /* for saved ra, and s0 */ | |
| 198 | + loc = -16; // for ra and s0 | |
| 147 | 199 | func_sub_sp_offset = ind; |
| 148 | − ind += 3 * 4; | |
| 200 | + ind += 4 * 4; | |
| 149 | 201 | if (sym->f.func_type == FUNC_ELLIPSIS) { |
| 150 | 202 | tcc_error("unimp: vararg prologue"); |
| 151 | 203 | } |
| @@ -180,7 +232,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 28 unmodified lines | ||
| 180 | 232 | if (is_float(type->t)) { |
| 181 | 233 | tcc_error("unimp: float args"); |
| 182 | 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 | 279 | EI(0x13, 0, 2, 2, -v); // addi sp, sp, -v |
| 228 | 280 | ES(0x23, 3, 2, 1, v - 8); // sd ra, v-8(sp) |
| 229 | 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 | 283 | ind = saved_ind; |
| 231 | 284 | } |
| 232 | 285 | |