I’m currently compiling some rust code against the mipsel-sony-psx
target, which has 32-bit pointers. I have two statics that I need to emit with a specific size (4 bytes and 2 bytes, respectively):
use core::ptr;
static mut EXT_DATA_ALL: *const u8 = ptr::addr_of!(EXT_DATA);
static mut EXT_DATA_LO: u16 = ptr::addr_of!(EXT_DATA) as u16; // Doesn't work
extern "C" {
static mut EXT_DATA: u8;
}
The first static, EXT_DATA_ALL
, works as-is, and emits a relocation of type R_MIPS_32
. Ideally, I’d want it to be a u32
, but rust doesn’t let me cast at compile time despite the relocation not caring about the type of the variable, and the size and alignment of u32
and *const _
being the same, but I can live with that.
The second static, EXT_DATA_LO
, however, doesn’t work, and I’m not sure if I can make it work. I want it to contain the bottom 16 bits of the pointer. I believe the relocation R_MIPS_16
should work for this purpose, since it should truncate the address to 16 bits, but I have no clue how to get rust to emit it.
I’d also be fine with adding the relocations outside of the rust code (for e.g., by editing the elf file to add my relocation later on), but I’m afraid the compiler could perform optimizations based on the dummy value I place in the variable (since I’d have to initialize it with something). Is this a valid concern, or is that my only way forward?
I believe that using global_asm!
, I can define the relocation properly using .half %lo(EXT_DATA)
, but I need the data to reside in a rust static
, and I don’t think global_asm!
can be used to declare statics.