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