this now allows to compile a simple working example: int main(void) { return 0; }
Unified · Split
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | #define NB_REGS 16 // x10-x17 aka a0-a7, f10-f17 aka fa0-fa7 |
| 5 | 5 | |
| 6 | 6 | #define TREG_R(x) (x) // x = 0..7 |
| 7 | −#define TREG_F(x) (x + 10) // x = 0..7 | |
| 7 | +#define TREG_F(x) (x + 8) // x = 0..7 | |
| 8 | 8 | |
| 9 | 9 | // Register classes sorted from more general to more precise: |
| 10 | 10 | #define RC_INT (1 << 0) |
| @@ -29,6 +29,9 @@ · 18 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #else |
| 31 | 31 | #include "tcc.h" |
| 32 | +#include <assert.h> | |
| 33 | + | |
| 34 | +#define XLEN 8 | |
| 32 | 35 | |
| 33 | 36 | ST_DATA const int reg_classes[NB_REGS] = { |
| 34 | 37 | RC_INT | RC_R(0), |
| @@ -49,15 +52,47 @@ ST_DATA const int reg_classes[NB_REGS] = { · 14 unmodified lines | ||
| 49 | 52 | RC_FLOAT | RC_F(7) |
| 50 | 53 | }; |
| 51 | 54 | |
| 55 | +static int ireg(int r) | |
| 56 | +{ | |
| 57 | + assert(r >= 0 && r < 8); | |
| 58 | + return r + 10; // tccrX --> aX == x(10+X) | |
| 59 | +} | |
| 60 | + | |
| 61 | +ST_FUNC void o(unsigned int c) | |
| 62 | +{ | |
| 63 | + int ind1 = ind + 4; | |
| 64 | + if (nocode_wanted) | |
| 65 | + return; | |
| 66 | + if (ind1 > cur_text_section->data_allocated) | |
| 67 | + section_realloc(cur_text_section, ind1); | |
| 68 | + write32le(cur_text_section->data + ind, c); | |
| 69 | + ind = ind1; | |
| 70 | +} | |
| 71 | + | |
| 72 | +static void EI(uint32_t opcode, uint32_t func3, | |
| 73 | + uint32_t rd, uint32_t rs1, uint32_t imm) | |
| 74 | +{ | |
| 75 | + assert(! ((imm + (1 << 11)) >> 12)); | |
| 76 | + o(opcode | (func3 << 12) | (rd << 7) | (rs1 << 15) | (imm << 20)); | |
| 77 | +} | |
| 78 | + | |
| 79 | +static void ES(uint32_t opcode, uint32_t func3, | |
| 80 | + uint32_t rs1, uint32_t rs2, uint32_t imm) | |
| 81 | +{ | |
| 82 | + assert(! ((imm + (1 << 11)) >> 12)); | |
| 83 | + o(opcode | (func3 << 12) | ((imm & 0x1f) << 7) | (rs1 << 15) | |
| 84 | + | (rs2 << 20) | ((imm >> 5) << 25)); | |
| 85 | +} | |
| 86 | + | |
| 52 | 87 | // Patch all branches in list pointed to by t to branch to a: |
| 53 | 88 | ST_FUNC void gsym_addr(int t_, int a_) |
| 54 | 89 | { |
| 55 | 90 | uint32_t t = t_; |
| 56 | 91 | uint32_t a = a_; |
| 57 | − tcc_error("implement me"); | |
| 58 | 92 | while (t) { |
| 59 | 93 | unsigned char *ptr = cur_text_section->data + t; |
| 60 | 94 | uint32_t next = read32le(ptr); |
| 95 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 61 | 96 | if (a - t + 0x8000000 >= 0x10000000) |
| 62 | 97 | tcc_error("branch out of range"); |
| 63 | 98 | write32le(ptr, (a - t == 4 ? 0xd503201f : // nop |
| @@ -68,46 +103,146 @@ ST_FUNC void gsym_addr(int t_, int a_) · 4 unmodified lines | ||
| 68 | 103 | |
| 69 | 104 | ST_FUNC void load(int r, SValue *sv) |
| 70 | 105 | { |
| 71 | − tcc_error("implement me"); | |
| 106 | + int fr = sv->r; | |
| 107 | + int v = fr & VT_VALMASK; | |
| 108 | + int rr = ireg(r); | |
| 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)"); | |
| 115 | + if (fc != sv->c.i) | |
| 116 | + tcc_error("unimp: load(very large const)"); | |
| 117 | + if (((unsigned)fc + (1 << 11)) >> 12) | |
| 118 | + tcc_error("unimp: load(large const) (0x%x)", fc); | |
| 119 | + EI(0x13, 0, rr, 0, fc); // addi R, x0, FC | |
| 120 | + } else | |
| 121 | + tcc_error("unimp: load(non-const)"); | |
| 72 | 122 | } |
| 73 | 123 | |
| 74 | 124 | ST_FUNC void store(int r, SValue *sv) |
| 75 | 125 | { |
| 76 | − tcc_error("implement me"); | |
| 126 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 77 | 127 | } |
| 78 | 128 | |
| 79 | 129 | ST_FUNC void gfunc_call(int nb_args) |
| 80 | 130 | { |
| 81 | − tcc_error("implement me"); | |
| 131 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 82 | 132 | } |
| 133 | + | |
| 134 | +static int func_sub_sp_offset; | |
| 135 | + | |
| 83 | 136 | ST_FUNC void gfunc_prolog(CType *func_type) |
| 84 | 137 | { |
| 85 | − tcc_error("implement me"); | |
| 138 | + int i, addr, align, size; | |
| 139 | + int param_addr = 0; | |
| 140 | + int aireg, afreg; | |
| 141 | + Sym *sym; | |
| 142 | + CType *type; | |
| 143 | + | |
| 144 | + sym = func_type->ref; | |
| 145 | + func_vt = sym->type; | |
| 146 | + loc = -16; /* for saved ra, and s0 */ | |
| 147 | + func_sub_sp_offset = ind; | |
| 148 | + ind += 3 * 4; | |
| 149 | + if (sym->f.func_type == FUNC_ELLIPSIS) { | |
| 150 | + tcc_error("unimp: vararg prologue"); | |
| 151 | + } | |
| 152 | + | |
| 153 | + aireg = afreg = 0; | |
| 154 | + addr = 0; // XXX not correct | |
| 155 | + /* if the function returns a structure, then add an | |
| 156 | + implicit pointer parameter */ | |
| 157 | + size = type_size(&func_vt, &align); | |
| 158 | + if (size > 2 * XLEN) { | |
| 159 | + tcc_error("unimp: struct return"); | |
| 160 | + func_vc = loc; | |
| 161 | + } | |
| 162 | + /* define parameters */ | |
| 163 | + while ((sym = sym->next) != NULL) { | |
| 164 | + type = &sym->type; | |
| 165 | + size = type_size(type, &align); | |
| 166 | + if (size > 2 * XLEN) { | |
| 167 | + from_stack: | |
| 168 | + addr = (addr + align - 1) & -align; | |
| 169 | + param_addr = addr; | |
| 170 | + addr += size; | |
| 171 | + } else { | |
| 172 | + int regcount = 1; | |
| 173 | + if (size > XLEN) | |
| 174 | + regcount++; | |
| 175 | + if (regcount + (is_float(type->t) ? afreg : aireg) >= 8) | |
| 176 | + goto from_stack; | |
| 177 | + loc -= regcount * 8; | |
| 178 | + param_addr = loc; | |
| 179 | + for (i = 0; i < regcount; i++) { | |
| 180 | + if (is_float(type->t)) { | |
| 181 | + tcc_error("unimp: float args"); | |
| 182 | + } else { | |
| 183 | + ES(0x23, 3, 2, 10 + aireg, -loc + i*8); // sd aX, loc(sp) // XXX | |
| 184 | + } | |
| 185 | + } | |
| 186 | + } | |
| 187 | + sym_push(sym->v & ~SYM_FIELD, type, | |
| 188 | + VT_LOCAL | lvalue_type(type->t), param_addr); | |
| 189 | + } | |
| 86 | 190 | } |
| 87 | −ST_FUNC void gen_va_start(void) | |
| 191 | + | |
| 192 | +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, | |
| 193 | + int *ret_align, int *regsize) | |
| 88 | 194 | { |
| 89 | − tcc_error("implement me"); | |
| 195 | + /* generic code can only deal with structs of pow(2) sizes | |
| 196 | + (it always deals with whole registers), so go through our own | |
| 197 | + code. */ | |
| 198 | + return 0; | |
| 90 | 199 | } |
| 91 | −ST_FUNC void gen_va_arg(CType *t) | |
| 200 | + | |
| 201 | +ST_FUNC void gfunc_return(CType *func_type) | |
| 92 | 202 | { |
| 93 | − tcc_error("implement me"); | |
| 203 | + int align, size = type_size(func_type, &align); | |
| 204 | + if ((func_type->t & VT_BTYPE) == VT_STRUCT | |
| 205 | + || size > 2 * XLEN) { | |
| 206 | + tcc_error("unimp: struct or large return"); | |
| 207 | + } | |
| 208 | + if (is_float(func_type->t)) | |
| 209 | + gv(RC_FRET); | |
| 210 | + else | |
| 211 | + gv(RC_IRET); | |
| 212 | + vtop--; | |
| 94 | 213 | } |
| 95 | −ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, | |
| 96 | − int *align, int *regsize) | |
| 214 | + | |
| 215 | +ST_FUNC void gfunc_epilog(void) | |
| 97 | 216 | { |
| 98 | − tcc_error("implement me"); | |
| 217 | + int v, saved_ind; | |
| 218 | + | |
| 219 | + v = (-loc + 15) & -16; | |
| 220 | + | |
| 221 | + EI(0x03, 3, 1, 2, v - 8); // ld ra, v-8(sp) | |
| 222 | + EI(0x03, 3, 8, 2, v - 16); // ld s0, v-16(sp) | |
| 223 | + EI(0x13, 0, 2, 2, v); // addi sp, sp, v | |
| 224 | + EI(0x67, 0, 0, 1, 0); // jalr x0, 0(x1), aka ret | |
| 225 | + saved_ind = ind; | |
| 226 | + ind = func_sub_sp_offset; | |
| 227 | + EI(0x13, 0, 2, 2, -v); // addi sp, sp, -v | |
| 228 | + 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) | |
| 230 | + ind = saved_ind; | |
| 99 | 231 | } |
| 100 | −ST_FUNC void gfunc_return(CType *func_type) | |
| 232 | + | |
| 233 | +ST_FUNC void gen_va_start(void) | |
| 101 | 234 | { |
| 102 | − tcc_error("implement me"); | |
| 235 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 103 | 236 | } |
| 104 | −ST_FUNC void gfunc_epilog(void) | |
| 237 | + | |
| 238 | +ST_FUNC void gen_va_arg(CType *t) | |
| 105 | 239 | { |
| 106 | − tcc_error("implement me"); | |
| 240 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 107 | 241 | } |
| 242 | + | |
| 108 | 243 | ST_FUNC void gen_fill_nops(int bytes) |
| 109 | 244 | { |
| 110 | − tcc_error("implement me"); | |
| 245 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 111 | 246 | if ((bytes & 3)) |
| 112 | 247 | tcc_error("alignment of code section not multiple of 4"); |
| 113 | 248 | } |
| @@ -115,79 +250,82 @@ ST_FUNC void gen_fill_nops(int bytes) · 1 unmodified line | ||
| 115 | 250 | // Generate forward branch to label: |
| 116 | 251 | ST_FUNC int gjmp(int t) |
| 117 | 252 | { |
| 118 | − tcc_error("implement me"); | |
| 253 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 119 | 254 | } |
| 120 | 255 | |
| 121 | 256 | // Generate branch to known address: |
| 122 | 257 | ST_FUNC void gjmp_addr(int a) |
| 123 | 258 | { |
| 124 | − tcc_error("implement me"); | |
| 259 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 125 | 260 | } |
| 126 | 261 | |
| 127 | 262 | ST_FUNC int gjmp_cond(int op, int t) |
| 128 | 263 | { |
| 129 | − tcc_error("implement me"); | |
| 264 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 130 | 265 | } |
| 131 | 266 | |
| 132 | 267 | ST_FUNC int gjmp_append(int n, int t) |
| 133 | 268 | { |
| 134 | − tcc_error("implement me"); | |
| 269 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 135 | 270 | } |
| 136 | 271 | |
| 137 | 272 | ST_FUNC int gtst(int inv, int t) |
| 138 | 273 | { |
| 139 | − tcc_error("implement me"); | |
| 274 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 140 | 275 | } |
| 276 | + | |
| 141 | 277 | ST_FUNC void gen_opi(int op) |
| 142 | 278 | { |
| 143 | − tcc_error("implement me"); | |
| 279 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 144 | 280 | } |
| 145 | 281 | |
| 146 | 282 | ST_FUNC void gen_opl(int op) |
| 147 | 283 | { |
| 148 | − tcc_error("implement me"); | |
| 284 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 149 | 285 | } |
| 150 | 286 | |
| 151 | 287 | ST_FUNC void gen_opf(int op) |
| 152 | 288 | { |
| 153 | − tcc_error("implement me"); | |
| 289 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 154 | 290 | } |
| 291 | + | |
| 155 | 292 | ST_FUNC void gen_cvt_sxtw(void) |
| 156 | 293 | { |
| 157 | − tcc_error("implement me"); | |
| 294 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 158 | 295 | } |
| 159 | 296 | |
| 160 | 297 | ST_FUNC void gen_cvt_itof(int t) |
| 161 | 298 | { |
| 162 | − tcc_error("implement me"); | |
| 299 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 163 | 300 | } |
| 164 | 301 | |
| 165 | 302 | ST_FUNC void gen_cvt_ftoi(int t) |
| 166 | 303 | { |
| 167 | − tcc_error("implement me"); | |
| 304 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 168 | 305 | } |
| 169 | 306 | |
| 170 | 307 | ST_FUNC void gen_cvt_ftof(int t) |
| 171 | 308 | { |
| 172 | − tcc_error("implement me"); | |
| 309 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 173 | 310 | } |
| 174 | 311 | |
| 175 | 312 | ST_FUNC void ggoto(void) |
| 176 | 313 | { |
| 177 | − tcc_error("implement me"); | |
| 314 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 178 | 315 | } |
| 316 | + | |
| 179 | 317 | ST_FUNC void gen_vla_sp_save(int addr) |
| 180 | 318 | { |
| 181 | − tcc_error("implement me"); | |
| 319 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 182 | 320 | } |
| 183 | 321 | |
| 184 | 322 | ST_FUNC void gen_vla_sp_restore(int addr) |
| 185 | 323 | { |
| 186 | − tcc_error("implement me"); | |
| 324 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 187 | 325 | } |
| 188 | 326 | |
| 189 | 327 | ST_FUNC void gen_vla_alloc(CType *type, int align) |
| 190 | 328 | { |
| 191 | − tcc_error("implement me"); | |
| 329 | + tcc_error("implement me: %s", __FUNCTION__); | |
| 192 | 330 | } |
| 193 | 331 | #endif |
| @@ -205,7 +205,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 204 unmodified lines | ||
| 205 | 205 | | (((val - addr) & 0xfff) << 20)); |
| 206 | 206 | return; |
| 207 | 207 | case R_RISCV_PCREL_HI20: |
| 208 | +#ifdef DEBUG_RELOC | |
| 208 | 209 | printf("PCREL_HI20: val=%lx addr=%lx\n", val, addr); |
| 210 | +#endif | |
| 209 | 211 | off64 = (int64_t)(val - addr + 0x800) >> 12; |
| 210 | 212 | if ((off64 + ((uint64_t)1 << 20)) >> 21) |
| 211 | 213 | tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx", |
| @@ -226,7 +228,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 14 unmodified lines | ||
| 226 | 228 | | ((off64 & 0xfffff) << 12)); |
| 227 | 229 | return; |
| 228 | 230 | case R_RISCV_PCREL_LO12_I: |
| 231 | +#ifdef DEBUG_RELOC | |
| 229 | 232 | printf("PCREL_LO12_I: val=%lx addr=%lx\n", val, addr); |
| 233 | +#endif | |
| 230 | 234 | if (val != last_hi.addr) |
| 231 | 235 | tcc_error("unsupported hi/lo pcrel reloc scheme"); |
| 232 | 236 | val = last_hi.val; |