Unified · Split
| @@ -166,7 +166,7 @@ ST_FUNC void gsym_addr(int t_, int a_) · 165 unmodified lines | ||
| 166 | 166 | |
| 167 | 167 | static int load_symofs(int r, SValue *sv, int forstore) |
| 168 | 168 | { |
| 169 | − int rr, doload = 0; | |
| 169 | + int rr, doload = 0, large_addend = 0; | |
| 170 | 170 | int fc = sv->c.i, v = sv->r & VT_VALMASK; |
| 171 | 171 | if (sv->r & VT_SYM) { |
| 172 | 172 | Sym label = {0}; |
| @@ -176,8 +176,9 @@ static int load_symofs(int r, SValue *sv, int forstore) · 3 unmodified lines | ||
| 176 | 176 | R_RISCV_PCREL_HI20, sv->c.i); |
| 177 | 177 | sv->c.i = 0; |
| 178 | 178 | } else { |
| 179 | − if (((unsigned)fc + (1 << 11)) >> 12) | |
| 180 | − tcc_error("unimp: large addend for global address (0x%lx)", (long)sv->c.i); | |
| 179 | + if (((unsigned)fc + (1 << 11)) >> 12){ | |
| 180 | + large_addend = 1; | |
| 181 | + } | |
| 181 | 182 | greloca(cur_text_section, sv->sym, ind, |
| 182 | 183 | R_RISCV_GOT_HI20, 0); |
| 183 | 184 | doload = 1; |
| @@ -192,6 +193,11 @@ static int load_symofs(int r, SValue *sv, int forstore) · 8 unmodified lines | ||
| 192 | 193 | ? R_RISCV_PCREL_LO12_I : R_RISCV_PCREL_LO12_S, 0); |
| 193 | 194 | if (doload) { |
| 194 | 195 | EI(0x03, 3, rr, rr, 0); // ld RR, 0(RR) |
| 196 | + if (large_addend) { | |
| 197 | + o(0x37 | (5 << 7) | ((0x800 + fc) & 0xfffff000)); //lui t0, high(fc) | |
| 198 | + ER(0x33, 0, rr, rr, 5, 0); // add RR, RR, t0 | |
| 199 | + sv->c.i = fc << 20 >> 20; | |
| 200 | + } | |
| 195 | 201 | } |
| 196 | 202 | } else if (v == VT_LOCAL || v == VT_LLOCAL) { |
| 197 | 203 | rr = 8; // s0 |