| @@ -189,12 +189,22 @@ ST_FUNC void load(int r, SValue *sv) · 188 unmodified lines |
| 189 | 189 | tcc_error("unimp: load(non-local lval)"); |
| 190 | 190 | } |
| 191 | 191 | } else if (v == VT_CONST) { |
| 192 | | − int rb = 0, do32bit = 8; |
| 192 | + int rb = 0, do32bit = 8, doload = 0; |
| 193 | 193 | assert(!is_float(sv->type.t) && is_ireg(r)); |
| 194 | 194 | if (fr & VT_SYM) { |
| 195 | 195 | static Sym label; |
| 196 | | − greloca(cur_text_section, sv->sym, ind, |
| 197 | | − R_RISCV_PCREL_HI20, sv->c.i); |
| 196 | + if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax |
| 197 | + greloca(cur_text_section, sv->sym, ind, |
| 198 | + R_RISCV_PCREL_HI20, sv->c.i); |
| 199 | + fc = 0; |
| 200 | + sv->c.i = 0; |
| 201 | + } else { |
| 202 | + if (((unsigned)fc + (1 << 11)) >> 12) |
| 203 | + tcc_error("unimp: large addend for global address"); |
| 204 | + greloca(cur_text_section, sv->sym, ind, |
| 205 | + R_RISCV_GOT_HI20, 0); |
| 206 | + doload = 1; |
| 207 | + } |
| 198 | 208 | if (!label.v) { |
| 199 | 209 | label.v = tok_alloc(".L0 ", 4)->tok; |
| 200 | 210 | label.type.t = VT_VOID | VT_STATIC; |
| @@ -205,8 +215,6 @@ ST_FUNC void load(int r, SValue *sv) · 4 unmodified lines |
| 205 | 215 | greloca(cur_text_section, &label, ind, |
| 206 | 216 | R_RISCV_PCREL_LO12_I, 0); |
| 207 | 217 | rb = rr; |
| 208 | | − fc = 0; |
| 209 | | − sv->c.i = 0; |
| 210 | 218 | do32bit = 0; |
| 211 | 219 | } |
| 212 | 220 | if (is_float(sv->type.t)) |
| @@ -244,7 +252,12 @@ ST_FUNC void load(int r, SValue *sv) · 31 unmodified lines |
| 244 | 252 | } |
| 245 | 253 | if (((unsigned)fc + (1 << 11)) >> 12) |
| 246 | 254 | o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)), rb = rr; //lui RR, upper(fc) |
| 247 | | − EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC |
| 255 | + if (doload) { |
| 256 | + EI(0x03, 3, rr, rr, 0); // ld RR, 0(RR) |
| 257 | + if (fc) |
| 258 | + EI(0x13 | do32bit, 0, rr, rr, fc << 20 >> 20); // addi[w] R, x0|R, FC |
| 259 | + } else |
| 260 | + EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC |
| 248 | 261 | } else if (v == VT_LOCAL) { |
| 249 | 262 | assert(is_ireg(r)); |
| 250 | 263 | if (((unsigned)fc + (1 << 11)) >> 12) |
| @@ -636,7 +649,6 @@ static void gen_opil(int op, int ll) · 385 unmodified lines |
| 636 | 649 | d = ireg(d); |
| 637 | 650 | ll = ll ? 0 : 8; |
| 638 | 651 | switch (op) { |
| 639 | | − case '%': |
| 640 | 652 | case TOK_PDIV: |
| 641 | 653 | default: |
| 642 | 654 | tcc_error("implement me: %s(%s)", __FUNCTION__, get_tok_str(op, NULL)); |
| @@ -671,6 +683,9 @@ static void gen_opil(int op, int ll) · 28 unmodified lines |
| 671 | 683 | case '|': |
| 672 | 684 | o(0x33 | (d << 7) | (a << 15) | (b << 20) | (6 << 12)); // or d, a, b |
| 673 | 685 | break; |
| 686 | + case '%': |
| 687 | + o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25) | (6 << 12)); //rem d, a, b |
| 688 | + break; |
| 674 | 689 | case TOK_UMOD: |
| 675 | 690 | o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25) | (7 << 12)); //remu d, a, b |
| 676 | 691 | break; |