| ... | ... | @@ -107,6 +107,7 @@ pub fn emit( |
| 107 | 107 | mir.body[nav_reloc.reloc.label], |
| 108 | 108 | body_end - Instruction.size * (1 + nav_reloc.reloc.label), |
| 109 | 109 | nav_reloc.reloc.addend, |
| 110 | if (ip.getNav(nav_reloc.nav).getExtern(ip)) |_| .got_load else .direct, |
| 110 | 111 | ); |
| 111 | 112 | for (mir.uav_relocs) |uav_reloc| try emitReloc( |
| 112 | 113 | lf, |
| ... | ... | @@ -124,6 +125,7 @@ pub fn emit( |
| 124 | 125 | mir.body[uav_reloc.reloc.label], |
| 125 | 126 | body_end - Instruction.size * (1 + uav_reloc.reloc.label), |
| 126 | 127 | uav_reloc.reloc.addend, |
| 128 | .direct, |
| 127 | 129 | ); |
| 128 | 130 | for (mir.lazy_relocs) |lazy_reloc| try emitReloc( |
| 129 | 131 | lf, |
| ... | ... | @@ -140,6 +142,7 @@ pub fn emit( |
| 140 | 142 | mir.body[lazy_reloc.reloc.label], |
| 141 | 143 | body_end - Instruction.size * (1 + lazy_reloc.reloc.label), |
| 142 | 144 | lazy_reloc.reloc.addend, |
| 145 | .direct, |
| 143 | 146 | ); |
| 144 | 147 | for (mir.global_relocs) |global_reloc| try emitReloc( |
| 145 | 148 | lf, |
| ... | ... | @@ -154,6 +157,7 @@ pub fn emit( |
| 154 | 157 | mir.body[global_reloc.reloc.label], |
| 155 | 158 | body_end - Instruction.size * (1 + global_reloc.reloc.label), |
| 156 | 159 | global_reloc.reloc.addend, |
| 160 | .direct, |
| 157 | 161 | ); |
| 158 | 162 | const literal_reloc_offset: i19 = @intCast(mir.epilogue.len + literals_align_gap); |
| 159 | 163 | for (mir.literal_relocs) |literal_reloc| { |
| ... | ... | @@ -188,6 +192,7 @@ fn emitReloc( |
| 188 | 192 | instruction: Instruction, |
| 189 | 193 | offset: u32, |
| 190 | 194 | addend: u64, |
| 195 | kind: enum { direct, got_load }, |
| 191 | 196 | ) !void { |
| 192 | 197 | const gpa = zcu.gpa; |
| 193 | 198 | switch (instruction.decode()) { |
| ... | ... | @@ -198,11 +203,20 @@ fn emitReloc( |
| 198 | 203 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode()) { |
| 199 | 204 | else => unreachable, |
| 200 | 205 | .pc_relative_addressing => |pc_relative_addressing| switch (pc_relative_addressing.group.op) { |
| 201 | | .adr => .ADR_PREL_LO21, |
| 202 | | .adrp => .ADR_PREL_PG_HI21, |
| 206 | .adr => switch (kind) { |
| 207 | .direct => .ADR_PREL_LO21, |
| 208 | .got_load => unreachable, |
| 209 | }, |
| 210 | .adrp => switch (kind) { |
| 211 | .direct => .ADR_PREL_PG_HI21, |
| 212 | .got_load => .ADR_GOT_PAGE, |
| 213 | }, |
| 203 | 214 | }, |
| 204 | 215 | .add_subtract_immediate => |add_subtract_immediate| switch (add_subtract_immediate.group.op) { |
| 205 | | .add => .ADD_ABS_LO12_NC, |
| 216 | .add => switch (kind) { |
| 217 | .direct => .ADD_ABS_LO12_NC, |
| 218 | .got_load => unreachable, |
| 219 | }, |
| 206 | 220 | .sub => unreachable, |
| 207 | 221 | }, |
| 208 | 222 | }; |
| ... | ... | @@ -223,7 +237,10 @@ fn emitReloc( |
| 223 | 237 | .offset = offset, |
| 224 | 238 | .target = sym_index, |
| 225 | 239 | .addend = @bitCast(addend), |
| 226 | | .type = .page, |
| 240 | .type = switch (kind) { |
| 241 | .direct => .page, |
| 242 | .got_load => .got_load_page, |
| 243 | }, |
| 227 | 244 | .meta = .{ |
| 228 | 245 | .pcrel = true, |
| 229 | 246 | .has_subtractor = false, |
| ... | ... | @@ -238,7 +255,10 @@ fn emitReloc( |
| 238 | 255 | .offset = offset, |
| 239 | 256 | .target = sym_index, |
| 240 | 257 | .addend = @bitCast(addend), |
| 241 | | .type = .pageoff, |
| 258 | .type = switch (kind) { |
| 259 | .direct => .pageoff, |
| 260 | .got_load => .got_load_pageoff, |
| 261 | }, |
| 242 | 262 | .meta = .{ |
| 243 | 263 | .pcrel = false, |
| 244 | 264 | .has_subtractor = false, |
| ... | ... | @@ -285,20 +305,39 @@ fn emitReloc( |
| 285 | 305 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode().register_unsigned_immediate.decode()) { |
| 286 | 306 | .integer => |integer| switch (integer.decode()) { |
| 287 | 307 | .unallocated, .prfm => unreachable, |
| 288 | | .strb, .ldrb, .ldrsb => .LDST8_ABS_LO12_NC, |
| 289 | | .strh, .ldrh, .ldrsh => .LDST16_ABS_LO12_NC, |
| 290 | | .ldrsw => .LDST32_ABS_LO12_NC, |
| 291 | | inline .str, .ldr => |encoded| switch (encoded.sf) { |
| 308 | .strb, .ldrb, .ldrsb => switch (kind) { |
| 309 | .direct => .LDST8_ABS_LO12_NC, |
| 310 | .got_load => unreachable, |
| 311 | }, |
| 312 | .strh, .ldrh, .ldrsh => switch (kind) { |
| 313 | .direct => .LDST16_ABS_LO12_NC, |
| 314 | .got_load => unreachable, |
| 315 | }, |
| 316 | .ldrsw => switch (kind) { |
| 317 | .direct => .LDST32_ABS_LO12_NC, |
| 318 | .got_load => unreachable, |
| 319 | }, |
| 320 | inline .str, .ldr => |encoded, mnemonic| switch (encoded.sf) { |
| 292 | 321 | .word => .LDST32_ABS_LO12_NC, |
| 293 | | .doubleword => .LDST64_ABS_LO12_NC, |
| 322 | .doubleword => switch (kind) { |
| 323 | .direct => .LDST64_ABS_LO12_NC, |
| 324 | .got_load => switch (mnemonic) { |
| 325 | else => comptime unreachable, |
| 326 | .str => unreachable, |
| 327 | .ldr => .LD64_GOT_LO12_NC, |
| 328 | }, |
| 329 | }, |
| 294 | 330 | }, |
| 295 | 331 | }, |
| 296 | | .vector => |vector| switch (vector.group.opc1.decode(vector.group.size)) { |
| 297 | | .byte => .LDST8_ABS_LO12_NC, |
| 298 | | .half => .LDST16_ABS_LO12_NC, |
| 299 | | .single => .LDST32_ABS_LO12_NC, |
| 300 | | .double => .LDST64_ABS_LO12_NC, |
| 301 | | .quad => .LDST128_ABS_LO12_NC, |
| 332 | .vector => |vector| switch (kind) { |
| 333 | .direct => switch (vector.group.opc1.decode(vector.group.size)) { |
| 334 | .byte => .LDST8_ABS_LO12_NC, |
| 335 | .half => .LDST16_ABS_LO12_NC, |
| 336 | .single => .LDST32_ABS_LO12_NC, |
| 337 | .double => .LDST64_ABS_LO12_NC, |
| 338 | .quad => .LDST128_ABS_LO12_NC, |
| 339 | }, |
| 340 | .got_load => unreachable, |
| 302 | 341 | }, |
| 303 | 342 | }; |
| 304 | 343 | try atom.addReloc(gpa, .{ |
| ... | ... | @@ -314,7 +353,10 @@ fn emitReloc( |
| 314 | 353 | .offset = offset, |
| 315 | 354 | .target = sym_index, |
| 316 | 355 | .addend = @bitCast(addend), |
| 317 | | .type = .pageoff, |
| 356 | .type = switch (kind) { |
| 357 | .direct => .pageoff, |
| 358 | .got_load => .got_load_pageoff, |
| 359 | }, |
| 318 | 360 | .meta = .{ |
| 319 | 361 | .pcrel = false, |
| 320 | 362 | .has_subtractor = false, |