Files
Odin/core/rexcode/ppc_vle/reloc.odin
2026-06-14 16:30:18 +01:00

88 lines
3.4 KiB
Odin

package rexcode_ppc_vle
// =============================================================================
// PowerPC VLE Relocations
// =============================================================================
//
// VLE-specific branch and immediate relocation forms.
//
// Branch displacements (from binutils):
// BD8 (16-bit): 8-bit signed << 1, PC-rel, ±256 bytes (se_b, se_bl)
// BD8IO (16-bit): same width, with BO/BI baked
// BD15 (32-bit): 15-bit signed << 1, PC-rel, ±32KB (e_bc, e_bcl)
// EBD15/EBD15BI (32-bit): same width, with BO/BI baked
// BD24 (32-bit): 24-bit signed << 1, PC-rel, ±16MB (e_b, e_bl)
//
// ELF relocation types (binutils elf/ppc.h R_PPC_VLE_*):
// REL8/REL15/REL24 PC-relative branches (matches BD8/BD15/BD24)
// LO16A/HI16A/HA16A 16-bit immediate halves, A-form (I16A imm position)
// LO16D/HI16D/HA16D 16-bit immediate halves, D-form (32-bit D-form)
// SDA21 21-bit small data area (e_add16i_sda variant)
// SDAREL_*16{A,D} SDA-relative variants of LO/HI/HA
// ADDR20 20-bit absolute address (LI20 form)
Relocation_Type :: enum u8 {
NONE = 0,
// Internal (encoder-resolved) branch relocations
BRANCH_BD8, // 8-bit signed << 1 at bits 7..0 of halfword
BRANCH_BD15, // 15-bit signed << 1 at bits 1..15 of low halfword
BRANCH_BD24, // 24-bit signed << 1 at bits 1..24 of word
// ELF-spec relocations (linker-bound — encoder emits them but doesn't
// resolve them locally)
R_PPC_VLE_REL8, // 216 — like BRANCH_BD8 but ELF-emitted
R_PPC_VLE_REL15, // 217
R_PPC_VLE_REL24, // 218
R_PPC_VLE_LO16A, // 219 — low 16 bits, A-form imm (I16A bit positions)
R_PPC_VLE_LO16D, // 220 — low 16 bits, D-form imm
R_PPC_VLE_HI16A, // 221 — high 16 bits, A-form
R_PPC_VLE_HI16D, // 222 — high 16 bits, D-form
R_PPC_VLE_HA16A, // 223 — high-adjusted 16 bits, A-form
R_PPC_VLE_HA16D, // 224 — high-adjusted 16 bits, D-form
R_PPC_VLE_SDA21, // 225 — 21-bit small-data-area
R_PPC_VLE_SDA21_LO, // 226 — like SDA21 but no overflow check
R_PPC_VLE_SDAREL_LO16A, // 227
R_PPC_VLE_SDAREL_LO16D, // 228
R_PPC_VLE_SDAREL_HI16A, // 229
R_PPC_VLE_SDAREL_HI16D, // 230
R_PPC_VLE_SDAREL_HA16A, // 231
R_PPC_VLE_SDAREL_HA16D, // 232
R_PPC_VLE_ADDR20, // 233 — 20-bit absolute (LI20)
}
// Mapping table — each VLE reloc's official ELF number.
elf_reloc_number :: proc(t: Relocation_Type) -> u32 {
#partial switch t {
case .R_PPC_VLE_REL8: return 216
case .R_PPC_VLE_REL15: return 217
case .R_PPC_VLE_REL24: return 218
case .R_PPC_VLE_LO16A: return 219
case .R_PPC_VLE_LO16D: return 220
case .R_PPC_VLE_HI16A: return 221
case .R_PPC_VLE_HI16D: return 222
case .R_PPC_VLE_HA16A: return 223
case .R_PPC_VLE_HA16D: return 224
case .R_PPC_VLE_SDA21: return 225
case .R_PPC_VLE_SDA21_LO: return 226
case .R_PPC_VLE_SDAREL_LO16A: return 227
case .R_PPC_VLE_SDAREL_LO16D: return 228
case .R_PPC_VLE_SDAREL_HI16A: return 229
case .R_PPC_VLE_SDAREL_HI16D: return 230
case .R_PPC_VLE_SDAREL_HA16A: return 231
case .R_PPC_VLE_SDAREL_HA16D: return 232
case .R_PPC_VLE_ADDR20: return 233
}
return 0
}
Relocation :: struct #packed {
offset: u32,
label_id: u32,
addend: i32,
type: Relocation_Type,
size: u8,
inst_idx: u16,
}
#assert(size_of(Relocation) == 16)