this now allows to compile a simple working example: int main(void) { return 0; }
Unified · Split
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | #define NB_REGS 16 // x10-x17 aka a0-a7, f10-f17 aka fa0-fa7 | 4 | #define NB_REGS 16 // x10-x17 aka a0-a7, f10-f17 aka fa0-fa7 |
| 5 | 5 | ||
| 6 | #define TREG_R(x) (x) // x = 0..7 | 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 | // Register classes sorted from more general to more precise: | 9 | // Register classes sorted from more general to more precise: |
| 10 | #define RC_INT (1 << 0) | 10 | #define RC_INT (1 << 0) |
| @@ -29,6 +29,9 @@ · 18 unmodified lines | |||
| 29 | 29 | ||
| 30 | #else | 30 | #else |
| 31 | #include "tcc.h" | 31 | #include "tcc.h" |
| 32 | #include <assert.h> | ||
| 33 | |||
| 34 | #define XLEN 8 | ||
| 32 | 35 | ||
| 33 | ST_DATA const int reg_classes[NB_REGS] = { | 36 | ST_DATA const int reg_classes[NB_REGS] = { |
| 34 | RC_INT | RC_R(0), | 37 | RC_INT | RC_R(0), |
| @@ -49,15 +52,47 @@ ST_DATA const int reg_classes[NB_REGS] = { · 14 unmodified lines | |||
| 49 | RC_FLOAT | RC_F(7) | 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 | // Patch all branches in list pointed to by t to branch to a: | 87 | // Patch all branches in list pointed to by t to branch to a: |
| 53 | ST_FUNC void gsym_addr(int t_, int a_) | 88 | ST_FUNC void gsym_addr(int t_, int a_) |
| 54 | { | 89 | { |
| 55 | uint32_t t = t_; | 90 | uint32_t t = t_; |
| 56 | uint32_t a = a_; | 91 | uint32_t a = a_; |
| 57 | tcc_error("implement me"); | ||
| 58 | while (t) { | 92 | while (t) { |
| 59 | unsigned char *ptr = cur_text_section->data + t; | 93 | unsigned char *ptr = cur_text_section->data + t; |
| 60 | uint32_t next = read32le(ptr); | 94 | uint32_t next = read32le(ptr); |
| 95 | tcc_error("implement me: %s", __FUNCTION__); | ||
| 61 | if (a - t + 0x8000000 >= 0x10000000) | 96 | if (a - t + 0x8000000 >= 0x10000000) |
| 62 | tcc_error("branch out of range"); | 97 | tcc_error("branch out of range"); |
| 63 | write32le(ptr, (a - t == 4 ? 0xd503201f : // nop | 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 | ST_FUNC void load(int r, SValue *sv) | 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 | ST_FUNC void store(int r, SValue *sv) | 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 | ST_FUNC void gfunc_call(int nb_args) | 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 | ST_FUNC void gfunc_prolog(CType *func_type) | 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, | 214 | |
| 96 | int *align, int *regsize) | 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 | ST_FUNC void gen_fill_nops(int bytes) | 243 | ST_FUNC void gen_fill_nops(int bytes) |
| 109 | { | 244 | { |
| 110 | tcc_error("implement me"); | 245 | tcc_error("implement me: %s", __FUNCTION__); |
| 111 | if ((bytes & 3)) | 246 | if ((bytes & 3)) |
| 112 | tcc_error("alignment of code section not multiple of 4"); | 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 | // Generate forward branch to label: | 250 | // Generate forward branch to label: |
| 116 | ST_FUNC int gjmp(int t) | 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 | // Generate branch to known address: | 256 | // Generate branch to known address: |
| 122 | ST_FUNC void gjmp_addr(int a) | 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 | ST_FUNC int gjmp_cond(int op, int t) | 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 | ST_FUNC int gjmp_append(int n, int t) | 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 | ST_FUNC int gtst(int inv, int t) | 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 | ST_FUNC void gen_opi(int op) | 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 | ST_FUNC void gen_opl(int op) | 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 | ST_FUNC void gen_opf(int op) | 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 | ST_FUNC void gen_cvt_sxtw(void) | 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 | ST_FUNC void gen_cvt_itof(int t) | 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 | ST_FUNC void gen_cvt_ftoi(int t) | 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 | ST_FUNC void gen_cvt_ftof(int t) | 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 | ST_FUNC void ggoto(void) | 312 | ST_FUNC void ggoto(void) |
| 176 | { | 313 | { |
| 177 | tcc_error("implement me"); | 314 | tcc_error("implement me: %s", __FUNCTION__); |
| 178 | } | 315 | } |
| 316 | |||
| 179 | ST_FUNC void gen_vla_sp_save(int addr) | 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 | ST_FUNC void gen_vla_sp_restore(int addr) | 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 | ST_FUNC void gen_vla_alloc(CType *type, int align) | 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 | #endif | 331 | #endif |
| @@ -205,7 +205,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 204 unmodified lines | |||
| 205 | | (((val - addr) & 0xfff) << 20)); | 205 | | (((val - addr) & 0xfff) << 20)); |
| 206 | return; | 206 | return; |
| 207 | case R_RISCV_PCREL_HI20: | 207 | case R_RISCV_PCREL_HI20: |
| 208 | #ifdef DEBUG_RELOC | ||
| 208 | printf("PCREL_HI20: val=%lx addr=%lx\n", val, addr); | 209 | printf("PCREL_HI20: val=%lx addr=%lx\n", val, addr); |
| 210 | #endif | ||
| 209 | off64 = (int64_t)(val - addr + 0x800) >> 12; | 211 | off64 = (int64_t)(val - addr + 0x800) >> 12; |
| 210 | if ((off64 + ((uint64_t)1 << 20)) >> 21) | 212 | if ((off64 + ((uint64_t)1 << 20)) >> 21) |
| 211 | tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx", | 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 | | ((off64 & 0xfffff) << 12)); | 228 | | ((off64 & 0xfffff) << 12)); |
| 227 | return; | 229 | return; |
| 228 | case R_RISCV_PCREL_LO12_I: | 230 | case R_RISCV_PCREL_LO12_I: |
| 231 | #ifdef DEBUG_RELOC | ||
| 229 | printf("PCREL_LO12_I: val=%lx addr=%lx\n", val, addr); | 232 | printf("PCREL_LO12_I: val=%lx addr=%lx\n", val, addr); |
| 233 | #endif | ||
| 230 | if (val != last_hi.addr) | 234 | if (val != last_hi.addr) |
| 231 | tcc_error("unsupported hi/lo pcrel reloc scheme"); | 235 | tcc_error("unsupported hi/lo pcrel reloc scheme"); |
| 232 | val = last_hi.val; | 236 | val = last_hi.val; |