| @@ -35,6 +35,10 @@ · 34 unmodified lines |
| 35 | 35 | #include "tcc.h" |
| 36 | 36 | #include <assert.h> |
| 37 | 37 | |
| 38 | +#define UPPER(x) (((unsigned)(x) + 0x800u) & 0xfffff000) |
| 39 | +#define SIGN7(x) ((((x) & 0xff) ^ 0x80) - 0x80) |
| 40 | +#define SIGN11(x) ((((x) & 0xfff) ^ 0x800) - 0x800) |
| 41 | + |
| 38 | 42 | ST_DATA const char * const target_machine_defs = |
| 39 | 43 | "__riscv\0" |
| 40 | 44 | "__riscv_xlen 64\0" |
| @@ -163,7 +167,7 @@ ST_FUNC void gsym_addr(int t_, int a_) · 122 unmodified lines |
| 163 | 167 | } |
| 164 | 168 | } |
| 165 | 169 | |
| 166 | | −static int load_symofs(int r, SValue *sv, int forstore) |
| 170 | +static int load_symofs(int r, SValue *sv, int forstore, int *new_fc) |
| 167 | 171 | { |
| 168 | 172 | int rr, doload = 0, large_addend = 0; |
| 169 | 173 | int fc = sv->c.i, v = sv->r & VT_VALMASK; |
| @@ -173,7 +177,7 @@ static int load_symofs(int r, SValue *sv, int forstore) · 3 unmodified lines |
| 173 | 177 | if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax |
| 174 | 178 | greloca(cur_text_section, sv->sym, ind, |
| 175 | 179 | R_RISCV_PCREL_HI20, sv->c.i); |
| 176 | | − sv->c.i = 0; |
| 180 | + *new_fc = 0; |
| 177 | 181 | } else { |
| 178 | 182 | if (((unsigned)fc + (1 << 11)) >> 12){ |
| 179 | 183 | large_addend = 1; |
| @@ -193,9 +197,9 @@ static int load_symofs(int r, SValue *sv, int forstore) · 13 unmodified lines |
| 193 | 197 | if (doload) { |
| 194 | 198 | EI(0x03, 3, rr, rr, 0); // ld RR, 0(RR) |
| 195 | 199 | if (large_addend) { |
| 196 | | − o(0x37 | (6 << 7) | ((0x800 + fc) & 0xfffff000)); //lui t1, high(fc) |
| 200 | + o(0x37 | (6 << 7) | UPPER(fc)); //lui t1, high(fc) |
| 197 | 201 | ER(0x33, 0, rr, rr, 6, 0); // add RR, RR, t1 |
| 198 | | − sv->c.i = fc << 20 >> 20; |
| 202 | + *new_fc = SIGN11(fc); |
| 199 | 203 | } |
| 200 | 204 | } |
| 201 | 205 | } else if (v == VT_LOCAL || v == VT_LLOCAL) { |
| @@ -204,9 +208,9 @@ static int load_symofs(int r, SValue *sv, int forstore) · 2 unmodified lines |
| 204 | 208 | tcc_error("unimp: store(giant local off) (0x%lx)", (long)sv->c.i); |
| 205 | 209 | if (((unsigned)fc + (1 << 11)) >> 12) { |
| 206 | 210 | rr = is_ireg(r) ? ireg(r) : 5; // t0 |
| 207 | | − o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)); //lui RR, upper(fc) |
| 211 | + o(0x37 | (rr << 7) | UPPER(fc)); //lui RR, upper(fc) |
| 208 | 212 | ER(0x33, 0, rr, rr, 8, 0); // add RR, RR, s0 |
| 209 | | − sv->c.i = fc << 20 >> 20; |
| 213 | + *new_fc = SIGN11(fc); |
| 210 | 214 | } |
| 211 | 215 | } else |
| 212 | 216 | tcc_error("uhh"); |
| @@ -217,13 +221,12 @@ static void load_large_constant(int rr, int fc, uint32_t pi) · 4 unmodified lines |
| 217 | 221 | { |
| 218 | 222 | if (fc < 0) |
| 219 | 223 | pi++; |
| 220 | | − o(0x37 | (rr << 7) | (((pi + 0x800) & 0xfffff000))); // lui RR, up(up(fc)) |
| 221 | | − EI(0x13, 0, rr, rr, (int)pi << 20 >> 20); // addi RR, RR, lo(up(fc)) |
| 224 | + o(0x37 | (rr << 7) | UPPER(pi)); // lui RR, up(up(fc)) |
| 225 | + EI(0x13, 0, rr, rr, SIGN11(pi)); // addi RR, RR, lo(up(fc)) |
| 222 | 226 | EI(0x13, 1, rr, rr, 12); // slli RR, RR, 12 |
| 223 | | − EI(0x13, 0, rr, rr, (fc + (1 << 19)) >> 20); // addi RR, RR, up(lo(fc)) |
| 227 | + EI(0x13, 0, rr, rr, SIGN11(((unsigned)fc + (1 << 19)) >> 20)); // addi RR, RR, up(lo(fc)) |
| 224 | 228 | EI(0x13, 1, rr, rr, 12); // slli RR, RR, 12 |
| 225 | | − fc = (fc + (1 << 7)) << 12 >> 12; |
| 226 | | − EI(0x13, 0, rr, rr, fc >> 8); // addi RR, RR, lo1(lo(fc)) |
| 229 | + EI(0x13, 0, rr, rr, SIGN11(((unsigned)fc + (1 << 7)) >> 8)); // addi RR, RR, lo1(lo(fc)) |
| 227 | 230 | EI(0x13, 1, rr, rr, 8); // slli RR, RR, 8 |
| 228 | 231 | } |
| 229 | 232 | |
| @@ -233,7 +236,6 @@ ST_FUNC void load(int r, SValue *sv) · 3 unmodified lines |
| 233 | 236 | int v = fr & VT_VALMASK; |
| 234 | 237 | int rr = is_ireg(r) ? ireg(r) : freg(r); |
| 235 | 238 | int fc = sv->c.i; |
| 236 | | − uint64_t save_fc = sv->c.i; |
| 237 | 239 | int bt = sv->type.t & VT_BTYPE; |
| 238 | 240 | int align, size; |
| 239 | 241 | if (fr & VT_LVAL) { |
| @@ -246,16 +248,14 @@ ST_FUNC void load(int r, SValue *sv) · 6 unmodified lines |
| 246 | 248 | if (size < 4 && !is_float(sv->type.t) && (sv->type.t & VT_UNSIGNED)) |
| 247 | 249 | func3 |= 4; |
| 248 | 250 | if (v == VT_LOCAL || (fr & VT_SYM)) { |
| 249 | | − br = load_symofs(r, sv, 0); |
| 250 | | − fc = sv->c.i; |
| 251 | + br = load_symofs(r, sv, 0, &fc); |
| 251 | 252 | } else if (v < VT_CONST) { |
| 252 | 253 | br = ireg(v); |
| 253 | 254 | /*if (((unsigned)fc + (1 << 11)) >> 12) |
| 254 | 255 | tcc_error("unimp: load(large addend) (0x%x)", fc);*/ |
| 255 | 256 | fc = 0; // XXX store ofs in LVAL(reg) |
| 256 | 257 | } else if (v == VT_LLOCAL) { |
| 257 | | − br = load_symofs(r, sv, 0); |
| 258 | | − fc = sv->c.i; |
| 258 | + br = load_symofs(r, sv, 0, &fc); |
| 259 | 259 | EI(0x03, 3, rr, br, fc); // ld RR, fc(BR) |
| 260 | 260 | br = rr; |
| 261 | 261 | fc = 0; |
| @@ -264,10 +264,10 @@ ST_FUNC void load(int r, SValue *sv) · 2 unmodified lines |
| 264 | 264 | si >>= 32; |
| 265 | 265 | if (si != 0) { |
| 266 | 266 | load_large_constant(rr, fc, si); |
| 267 | | − fc = fc << 24 >> 24; |
| 267 | + fc = SIGN7(fc); |
| 268 | 268 | } else { |
| 269 | | − o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)); //lui RR, upper(fc) |
| 270 | | − fc = fc << 20 >> 20; |
| 269 | + o(0x37 | (rr << 7) | UPPER(fc)); //lui RR, upper(fc) |
| 270 | + fc = SIGN11(fc); |
| 271 | 271 | } |
| 272 | 272 | br = rr; |
| 273 | 273 | } else { |
| @@ -278,18 +278,17 @@ ST_FUNC void load(int r, SValue *sv) · 4 unmodified lines |
| 278 | 278 | int rb = 0, do32bit = 8, zext = 0; |
| 279 | 279 | assert((!is_float(sv->type.t) && is_ireg(r)) || bt == VT_LDOUBLE); |
| 280 | 280 | if (fr & VT_SYM) { |
| 281 | | − rb = load_symofs(r, sv, 0); |
| 282 | | − fc = sv->c.i; |
| 281 | + rb = load_symofs(r, sv, 0, &fc); |
| 283 | 282 | do32bit = 0; |
| 284 | 283 | } |
| 285 | 284 | if (is_float(sv->type.t) && bt != VT_LDOUBLE) |
| 286 | 285 | tcc_error("unimp: load(float)"); |
| 287 | | − if (fc != sv->c.i) { |
| 286 | + if (do32bit && fc != sv->c.i) { |
| 288 | 287 | int64_t si = sv->c.i; |
| 289 | 288 | si >>= 32; |
| 290 | 289 | if (si != 0) { |
| 291 | 290 | load_large_constant(rr, fc, si); |
| 292 | | − fc = fc << 24 >> 24; |
| 291 | + fc = SIGN7(fc); |
| 293 | 292 | rb = rr; |
| 294 | 293 | do32bit = 0; |
| 295 | 294 | } else if (bt == VT_LLONG) { |
| @@ -299,17 +298,16 @@ ST_FUNC void load(int r, SValue *sv) · 3 unmodified lines |
| 299 | 298 | } |
| 300 | 299 | } |
| 301 | 300 | if (((unsigned)fc + (1 << 11)) >> 12) |
| 302 | | − o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)), rb = rr; //lui RR, upper(fc) |
| 301 | + o(0x37 | (rr << 7) | UPPER(fc)), rb = rr; //lui RR, upper(fc) |
| 303 | 302 | if (fc || (rr != rb) || do32bit || (fr & VT_SYM)) |
| 304 | | − EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC |
| 303 | + EI(0x13 | do32bit, 0, rr, rb, SIGN11(fc)); // addi[w] R, x0|R, FC |
| 305 | 304 | if (zext) { |
| 306 | 305 | EI(0x13, 1, rr, rr, 32); // slli RR, RR, 32 |
| 307 | 306 | EI(0x13, 5, rr, rr, 32); // srli RR, RR, 32 |
| 308 | 307 | } |
| 309 | 308 | } else if (v == VT_LOCAL) { |
| 310 | | − int br = load_symofs(r, sv, 0); |
| 309 | + int br = load_symofs(r, sv, 0, &fc); |
| 311 | 310 | assert(is_ireg(r)); |
| 312 | | − fc = sv->c.i; |
| 313 | 311 | EI(0x13, 0, rr, br, fc); // addi R, s0, FC |
| 314 | 312 | } else if (v < VT_CONST) { /* reg-reg */ |
| 315 | 313 | //assert(!fc); XXX support offseted regs |
| @@ -324,7 +322,7 @@ ST_FUNC void load(int r, SValue *sv) · 8 unmodified lines |
| 324 | 322 | func7 |= 1; |
| 325 | 323 | assert(size == 4 || size == 8); |
| 326 | 324 | o(0x53 | (rr << 7) | ((is_freg(v) ? freg(v) : ireg(v)) << 15) |
| 327 | | − | (func7 << 25)); // fmv.{w.x, x.w, d.x, x.d} RR, VR |
| 325 | + | ((unsigned)func7 << 25)); // fmv.{w.x, x.w, d.x, x.d} RR, VR |
| 328 | 326 | } |
| 329 | 327 | } else if (v == VT_CMP) { |
| 330 | 328 | int op = vtop->cmp_op; |
| @@ -371,7 +369,6 @@ ST_FUNC void load(int r, SValue *sv) · 40 unmodified lines |
| 371 | 369 | EI(0x13, 0, rr, 0, t ^ 1); // addi RR, x0, !t |
| 372 | 370 | } else |
| 373 | 371 | tcc_error("unimp: load(non-const)"); |
| 374 | | − sv->c.i = save_fc; |
| 375 | 372 | } |
| 376 | 373 | |
| 377 | 374 | ST_FUNC void store(int r, SValue *sv) |
| @@ -379,7 +376,6 @@ ST_FUNC void store(int r, SValue *sv) · 1 unmodified line |
| 379 | 376 | int fr = sv->r & VT_VALMASK; |
| 380 | 377 | int rr = is_ireg(r) ? ireg(r) : freg(r), ptrreg; |
| 381 | 378 | int fc = sv->c.i; |
| 382 | | − uint64_t save_fc = sv->c.i; |
| 383 | 379 | int bt = sv->type.t & VT_BTYPE; |
| 384 | 380 | int align, size = type_size(&sv->type, &align); |
| 385 | 381 | assert(!is_float(bt) || is_freg(r) || bt == VT_LDOUBLE); |
| @@ -393,8 +389,7 @@ ST_FUNC void store(int r, SValue *sv) · 7 unmodified lines |
| 393 | 389 | tcc_error("unimp: large sized store"); |
| 394 | 390 | assert(sv->r & VT_LVAL); |
| 395 | 391 | if (fr == VT_LOCAL || (sv->r & VT_SYM)) { |
| 396 | | − ptrreg = load_symofs(-1, sv, 1); |
| 397 | | − fc = sv->c.i; |
| 392 | + ptrreg = load_symofs(-1, sv, 1, &fc); |
| 398 | 393 | } else if (fr < VT_CONST) { |
| 399 | 394 | ptrreg = ireg(fr); |
| 400 | 395 | /*if (((unsigned)fc + (1 << 11)) >> 12) |
| @@ -406,17 +401,16 @@ ST_FUNC void store(int r, SValue *sv) · 5 unmodified lines |
| 406 | 401 | si >>= 32; |
| 407 | 402 | if (si != 0) { |
| 408 | 403 | load_large_constant(ptrreg, fc, si); |
| 409 | | − fc = fc << 24 >> 24; |
| 404 | + fc = SIGN7(fc); |
| 410 | 405 | } else { |
| 411 | | − o(0x37 | (ptrreg << 7) | ((0x800 + fc) & 0xfffff000)); //lui RR, upper(fc) |
| 412 | | − fc = fc << 20 >> 20; |
| 406 | + o(0x37 | (ptrreg << 7) | UPPER(fc)); //lui RR, upper(fc) |
| 407 | + fc = SIGN11(fc); |
| 413 | 408 | } |
| 414 | 409 | } else |
| 415 | 410 | tcc_error("implement me: %s(!local)", __FUNCTION__); |
| 416 | 411 | ES(is_freg(r) ? 0x27 : 0x23, // fs... | s... |
| 417 | 412 | size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, // ... [wd] | [bhwd] |
| 418 | 413 | ptrreg, rr, fc); // RR, fc(base) |
| 419 | | − sv->c.i = save_fc; |
| 420 | 414 | } |
| 421 | 415 | |
| 422 | 416 | static void gcall_or_jmp(int docall) |
| @@ -634,11 +628,8 @@ ST_FUNC void gfunc_call(int nb_args) · 211 unmodified lines |
| 634 | 628 | |
| 635 | 629 | if (stack_add) { |
| 636 | 630 | if (stack_add >= 0x800) { |
| 637 | | − unsigned int bit11 = (((unsigned int)-stack_add) >> 11) & 1; |
| 638 | | − o(0x37 | (5 << 7) | |
| 639 | | − ((-stack_add + (bit11 << 12)) & 0xfffff000)); //lui t0, upper(v) |
| 640 | | − EI(0x13, 0, 5, 5, ((-stack_add & 0xfff) - bit11 * (1 << 12))); |
| 641 | | − // addi t0, t0, lo(v) |
| 631 | + o(0x37 | (5 << 7) | UPPER(-stack_add)); //lui t0, upper(v) |
| 632 | + EI(0x13, 0, 5, 5, SIGN11(-stack_add)); // addi t0, t0, lo(v) |
| 642 | 633 | ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0 |
| 643 | 634 | } |
| 644 | 635 | else |
| @@ -766,11 +757,8 @@ done: · 121 unmodified lines |
| 766 | 757 | vtop -= nb_args + 1; |
| 767 | 758 | if (stack_add) { |
| 768 | 759 | if (stack_add >= 0x800) { |
| 769 | | − unsigned int bit11 = ((unsigned int)stack_add >> 11) & 1; |
| 770 | | − o(0x37 | (5 << 7) | |
| 771 | | − ((stack_add + (bit11 << 12)) & 0xfffff000)); //lui t0, upper(v) |
| 772 | | − EI(0x13, 0, 5, 5, (stack_add & 0xfff) - bit11 * (1 << 12)); |
| 773 | | − // addi t0, t0, lo(v) |
| 760 | + o(0x37 | (5 << 7) | UPPER(stack_add)); //lui t0, upper(v) |
| 761 | + EI(0x13, 0, 5, 5, SIGN11(stack_add)); // addi t0, t0, lo(v) |
| 774 | 762 | ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0 |
| 775 | 763 | } |
| 776 | 764 | else |
| @@ -911,8 +899,8 @@ ST_FUNC void gfunc_epilog(void) · 134 unmodified lines |
| 911 | 899 | |
| 912 | 900 | if (v >= (1 << 11)) { |
| 913 | 901 | d = 16; |
| 914 | | − o(0x37 | (5 << 7) | ((0x800 + (v-16)) & 0xfffff000)); //lui t0, upper(v) |
| 915 | | − EI(0x13, 0, 5, 5, (v-16) << 20 >> 20); // addi t0, t0, lo(v) |
| 902 | + o(0x37 | (5 << 7) | UPPER(v-16)); //lui t0, upper(v) |
| 903 | + EI(0x13, 0, 5, 5, SIGN11(v-16)); // addi t0, t0, lo(v) |
| 916 | 904 | ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0 |
| 917 | 905 | } |
| 918 | 906 | EI(0x03, 3, 1, 2, d - 8 - num_va_regs * 8); // ld ra, v-8(sp) |
| @@ -922,8 +910,8 @@ ST_FUNC void gfunc_epilog(void) · 3 unmodified lines |
| 922 | 910 | large_ofs_ind = ind; |
| 923 | 911 | if (v >= (1 << 11)) { |
| 924 | 912 | EI(0x13, 0, 8, 2, d - num_va_regs * 8); // addi s0, sp, d |
| 925 | | − o(0x37 | (5 << 7) | ((0x800 + (v-16)) & 0xfffff000)); //lui t0, upper(v) |
| 926 | | − EI(0x13, 0, 5, 5, (v-16) << 20 >> 20); // addi t0, t0, lo(v) |
| 913 | + o(0x37 | (5 << 7) | UPPER(v-16)); //lui t0, upper(v) |
| 914 | + EI(0x13, 0, 5, 5, SIGN11(v-16)); // addi t0, t0, lo(v) |
| 927 | 915 | ER(0x33, 0, 2, 2, 5, 0x20); // sub sp, sp, t0 |
| 928 | 916 | gjmp_addr(func_sub_sp_offset + 5*4); |
| 929 | 917 | } |
| @@ -972,8 +960,8 @@ ST_FUNC void gjmp_addr(int a) · 42 unmodified lines |
| 972 | 960 | { |
| 973 | 961 | uint32_t r = a - ind, imm; |
| 974 | 962 | if ((r + (1 << 21)) & ~((1U << 22) - 2)) { |
| 975 | | − o(0x17 | (5 << 7) | (((r + 0x800) & 0xfffff000))); // lui RR, up(r) |
| 976 | | − r = (int)r << 20 >> 20; |
| 963 | + o(0x17 | (5 << 7) | UPPER(r)); // lui RR, up(r) |
| 964 | + r = SIGN11(r); |
| 977 | 965 | EI(0x67, 0, 0, 5, r); // jalr x0, r(t0) |
| 978 | 966 | } else { |
| 979 | 967 | imm = (((r >> 12) & 0xff) << 12) |
| @@ -1394,9 +1382,9 @@ ST_FUNC void ggoto(void) · 414 unmodified lines |
| 1394 | 1382 | ST_FUNC void gen_vla_sp_save(int addr) |
| 1395 | 1383 | { |
| 1396 | 1384 | if (((unsigned)addr + (1 << 11)) >> 12) { |
| 1397 | | − o(0x37 | (5 << 7) | ((0x800 + addr) & 0xfffff000)); //lui t0,upper(addr) |
| 1385 | + o(0x37 | (5 << 7) | UPPER(addr)); //lui t0,upper(addr) |
| 1398 | 1386 | ER(0x33, 0, 5, 5, 8, 0); // add t0, t0, s0 |
| 1399 | | − ES(0x23, 3, 5, 2, (int)addr << 20 >> 20); // sd sp, fc(t0) |
| 1387 | + ES(0x23, 3, 5, 2, SIGN11(addr)); // sd sp, fc(t0) |
| 1400 | 1388 | } |
| 1401 | 1389 | else |
| 1402 | 1390 | ES(0x23, 3, 8, 2, addr); // sd sp, fc(s0) |
| @@ -1405,9 +1393,9 @@ ST_FUNC void gen_vla_sp_save(int addr) · 2 unmodified lines |
| 1405 | 1393 | ST_FUNC void gen_vla_sp_restore(int addr) |
| 1406 | 1394 | { |
| 1407 | 1395 | if (((unsigned)addr + (1 << 11)) >> 12) { |
| 1408 | | − o(0x37 | (5 << 7) | ((0x800 + addr) & 0xfffff000)); //lui t0,upper(addr) |
| 1396 | + o(0x37 | (5 << 7) | UPPER(addr)); //lui t0,upper(addr) |
| 1409 | 1397 | ER(0x33, 0, 5, 5, 8, 0); // add t0, t0, s0 |
| 1410 | | − EI(0x03, 3, 2, 5, (int)addr << 20 >> 20); // ld sp, fc(t0) |
| 1398 | + EI(0x03, 3, 2, 5, SIGN11(addr)); // ld sp, fc(t0) |
| 1411 | 1399 | } |
| 1412 | 1400 | else |
| 1413 | 1401 | EI(0x03, 3, 2, 8, addr); // ld sp, fc(s0) |