loads and stores to global symbols need to go via the GOT (at least for weaks), otherwise -run doesn't work. Ideally we'd generate GOT relocs (and loads) always and replace them with PCREL relocs and adds during linking.
Unified · Split
| @@ -145,7 +145,7 @@ ST_FUNC void load(int r, SValue *sv) · 144 unmodified lines | |||
| 145 | int bt = sv->type.t & VT_BTYPE; | 145 | int bt = sv->type.t & VT_BTYPE; |
| 146 | int align, size = type_size(&sv->type, &align); | 146 | int align, size = type_size(&sv->type, &align); |
| 147 | if (fr & VT_LVAL) { | 147 | if (fr & VT_LVAL) { |
| 148 | int func3, opcode = 0x03; | 148 | int func3, opcode = 0x03, doload = 0; |
| 149 | if (is_freg(r)) { | 149 | if (is_freg(r)) { |
| 150 | assert(bt == VT_DOUBLE || bt == VT_FLOAT); | 150 | assert(bt == VT_DOUBLE || bt == VT_FLOAT); |
| 151 | opcode = 0x07; | 151 | opcode = 0x07; |
| @@ -176,12 +176,19 @@ ST_FUNC void load(int r, SValue *sv) · 24 unmodified lines | |||
| 176 | EI(opcode, func3, rr, ireg(v), fc); // l[bhwd][u] RR, 0(V) | 176 | EI(opcode, func3, rr, ireg(v), fc); // l[bhwd][u] RR, 0(V) |
| 177 | } else if (v == VT_CONST && (fr & VT_SYM)) { | 177 | } else if (v == VT_CONST && (fr & VT_SYM)) { |
| 178 | static Sym label; | 178 | static Sym label; |
| 179 | int addend = 0, tempr; | 179 | int tempr; |
| 180 | if (1 || ((unsigned)fc + (1 << 11)) >> 12) | 180 | if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax |
| 181 | addend = fc, fc = 0; | 181 | greloca(cur_text_section, sv->sym, ind, |
| 182 | 182 | R_RISCV_PCREL_HI20, sv->c.i); | |
| 183 | greloca(cur_text_section, sv->sym, ind, | 183 | fc = 0; |
| 184 | R_RISCV_PCREL_HI20, addend); | 184 | sv->c.i = 0; |
| 185 | } else { | ||
| 186 | if (((unsigned)fc + (1 << 11)) >> 12) | ||
| 187 | tcc_error("unimp: large addend for global address"); | ||
| 188 | greloca(cur_text_section, sv->sym, ind, | ||
| 189 | R_RISCV_GOT_HI20, 0); | ||
| 190 | doload = 1; | ||
| 191 | } | ||
| 185 | if (!label.v) { | 192 | if (!label.v) { |
| 186 | label.v = tok_alloc(".L0 ", 4)->tok; | 193 | label.v = tok_alloc(".L0 ", 4)->tok; |
| 187 | label.type.t = VT_VOID | VT_STATIC; | 194 | label.type.t = VT_VOID | VT_STATIC; |
| @@ -192,6 +199,12 @@ ST_FUNC void load(int r, SValue *sv) · 4 unmodified lines | |||
| 192 | o(0x17 | (tempr << 7)); // auipc TR, 0 %pcrel_hi(sym)+addend | 199 | o(0x17 | (tempr << 7)); // auipc TR, 0 %pcrel_hi(sym)+addend |
| 193 | greloca(cur_text_section, &label, ind, | 200 | greloca(cur_text_section, &label, ind, |
| 194 | R_RISCV_PCREL_LO12_I, 0); | 201 | R_RISCV_PCREL_LO12_I, 0); |
| 202 | if (doload) { | ||
| 203 | EI(0x03, 3, tempr, tempr, 0); // ld TR, 0(TR) | ||
| 204 | if (fc) | ||
| 205 | EI(0x13, 0, tempr, tempr, fc << 20 >> 20); // addi TR, TR, FC | ||
| 206 | fc = 0; | ||
| 207 | } | ||
| 195 | EI(opcode, func3, rr, tempr, fc); // l[bhwd][u] RR, fc(TR) | 208 | EI(opcode, func3, rr, tempr, fc); // l[bhwd][u] RR, fc(TR) |
| 196 | } else if (v == VT_LLOCAL) { | 209 | } else if (v == VT_LLOCAL) { |
| 197 | int br = 8, tempr = is_ireg(r) ? rr : 5; | 210 | int br = 8, tempr = is_ireg(r) ? rr : 5; |
| @@ -361,13 +374,20 @@ ST_FUNC void store(int r, SValue *sv) · 163 unmodified lines | |||
| 361 | ptrreg, rr, fc); // s[bhwd] RR, fc(PTRREG) | 374 | ptrreg, rr, fc); // s[bhwd] RR, fc(PTRREG) |
| 362 | } else if ((sv->r & ~VT_LVAL_TYPE) == (VT_CONST | VT_SYM | VT_LVAL)) { | 375 | } else if ((sv->r & ~VT_LVAL_TYPE) == (VT_CONST | VT_SYM | VT_LVAL)) { |
| 363 | static Sym label; | 376 | static Sym label; |
| 364 | int tempr, addend = 0; | 377 | int tempr, doload = 0; |
| 365 | if (1 || ((unsigned)fc + (1 << 11)) >> 12) | ||
| 366 | addend = fc, fc = 0; | ||
| 367 | |||
| 368 | tempr = 5; // t0 | 378 | tempr = 5; // t0 |
| 369 | greloca(cur_text_section, sv->sym, ind, | 379 | if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax |
| 370 | R_RISCV_PCREL_HI20, addend); | 380 | greloca(cur_text_section, sv->sym, ind, |
| 381 | R_RISCV_PCREL_HI20, sv->c.i); | ||
| 382 | fc = 0; | ||
| 383 | sv->c.i = 0; | ||
| 384 | } else { | ||
| 385 | if (((unsigned)fc + (1 << 11)) >> 12) | ||
| 386 | tcc_error("unimp: large addend for global address"); | ||
| 387 | greloca(cur_text_section, sv->sym, ind, | ||
| 388 | R_RISCV_GOT_HI20, 0); | ||
| 389 | doload = 1; | ||
| 390 | } | ||
| 371 | if (!label.v) { | 391 | if (!label.v) { |
| 372 | label.v = tok_alloc(".L0 ", 4)->tok; | 392 | label.v = tok_alloc(".L0 ", 4)->tok; |
| 373 | label.type.t = VT_VOID | VT_STATIC; | 393 | label.type.t = VT_VOID | VT_STATIC; |
| @@ -376,7 +396,13 @@ ST_FUNC void store(int r, SValue *sv) · 2 unmodified lines | |||
| 376 | put_extern_sym(&label, cur_text_section, ind, 0); | 396 | put_extern_sym(&label, cur_text_section, ind, 0); |
| 377 | o(0x17 | (tempr << 7)); // auipc TEMPR, 0 %pcrel_hi(sym)+addend | 397 | o(0x17 | (tempr << 7)); // auipc TEMPR, 0 %pcrel_hi(sym)+addend |
| 378 | greloca(cur_text_section, &label, ind, | 398 | greloca(cur_text_section, &label, ind, |
| 379 | R_RISCV_PCREL_LO12_S, 0); | 399 | doload ? R_RISCV_PCREL_LO12_I : R_RISCV_PCREL_LO12_S, 0); |
| 400 | if (doload) { | ||
| 401 | EI(0x03, 3, tempr, tempr, 0); // ld TR, 0(TR) | ||
| 402 | if (fc) | ||
| 403 | EI(0x13, 0, tempr, tempr, fc << 20 >> 20); // addi TR, TR, FC | ||
| 404 | fc = 0; | ||
| 405 | } | ||
| 380 | if (is_freg(r)) | 406 | if (is_freg(r)) |
| 381 | ES(0x27, size == 4 ? 2 : 3, tempr, rr, fc); // fs[wd] RR, fc(TEMPR) | 407 | ES(0x27, size == 4 ? 2 : 3, tempr, rr, fc); // fs[wd] RR, fc(TEMPR) |
| 382 | else | 408 | else |