#include "master.hpp"
-namespace factor
-{
+namespace factor {
-/* Load a 32-bit value from a PowerPC LIS/ORI sequence */
-fixnum instruction_operand::load_value_2_2()
-{
- cell *ptr = (cell *)pointer;
- cell hi = (ptr[-1] & 0xffff);
- cell lo = (ptr[ 0] & 0xffff);
- return hi << 16 | lo;
-}
-
-/* Load a value from a bitfield of a PowerPC instruction */
-fixnum instruction_operand::load_value_masked(cell mask, fixnum shift)
-{
- cell *ptr = (cell *)pointer;
+instruction_operand::instruction_operand(relocation_entry rel,
+ code_block* compiled, cell index)
+ : rel(rel),
+ compiled(compiled),
+ index(index),
+ pointer(compiled->entry_point() + rel.offset()) {}
- return (*ptr & mask) << shift;
+// Load a 32-bit value from a PowerPC LIS/ORI sequence
+fixnum instruction_operand::load_value_2_2() {
+ uint32_t* ptr = (uint32_t*)pointer;
+ cell hi = (ptr[-2] & 0xffff);
+ cell lo = (ptr[-1] & 0xffff);
+ return hi << 16 | lo;
}
-fixnum instruction_operand::load_value(cell relative_to)
-{
- switch(rel_class)
- {
- case RC_ABSOLUTE_CELL:
- return *(cell *)pointer;
- case RC_ABSOLUTE:
- return *(u32*)pointer;
- case RC_RELATIVE:
- return *(s32*)pointer + relative_to + sizeof(u32);
- case RC_ABSOLUTE_PPC_2_2:
- return load_value_2_2();
- case RC_ABSOLUTE_PPC_2:
- return load_value_masked(rel_absolute_ppc_2_mask,0);
- case RC_RELATIVE_PPC_2:
- return load_value_masked(rel_relative_ppc_2_mask,0) + relative_to;
- case RC_RELATIVE_PPC_3:
- return load_value_masked(rel_relative_ppc_3_mask,0) + relative_to;
- case RC_RELATIVE_ARM_3:
- return load_value_masked(rel_relative_arm_3_mask,2) + relative_to + sizeof(cell) * 2;
- case RC_INDIRECT_ARM:
- return load_value_masked(rel_indirect_arm_mask,0) + relative_to + sizeof(cell);
- case RC_INDIRECT_ARM_PC:
- return load_value_masked(rel_indirect_arm_mask,0) + relative_to + sizeof(cell) * 2;
- default:
- critical_error("Bad rel class",rel_class);
- return 0;
- }
+// Load a 64-bit value from a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence
+fixnum instruction_operand::load_value_2_2_2_2() {
+ uint32_t* ptr = (uint32_t*)pointer;
+ uint64_t hhi = (ptr[-5] & 0xffff);
+ uint64_t hlo = (ptr[-4] & 0xffff);
+ uint64_t lhi = (ptr[-2] & 0xffff);
+ uint64_t llo = (ptr[-1] & 0xffff);
+ uint64_t val = hhi << 48 | hlo << 32 | lhi << 16 | llo;
+ return (cell)val;
}
-fixnum instruction_operand::load_value()
-{
- return load_value(pointer);
-}
+// Load a value from a bitfield of a PowerPC instruction
+fixnum instruction_operand::load_value_masked(cell mask, cell bits,
+ cell shift) {
+ int32_t* ptr = (int32_t*)(pointer - sizeof(uint32_t));
-code_block *instruction_operand::load_code_block()
-{
- return ((code_block *)load_value() - 1);
+ return (((*ptr & (int32_t)mask) << bits) >> bits) << shift;
}
-/* Store a 32-bit value into a PowerPC LIS/ORI sequence */
-void instruction_operand::store_value_2_2(fixnum value)
-{
- cell *ptr = (cell *)pointer;
- ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
- ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
+fixnum instruction_operand::load_value(cell relative_to) {
+ switch (rel.klass()) {
+ case RC_ABSOLUTE_CELL:
+ return *(cell*)(pointer - sizeof(cell));
+ case RC_ABSOLUTE:
+ return *(uint32_t*)(pointer - sizeof(uint32_t));
+ case RC_RELATIVE:
+ return *(int32_t*)(pointer - sizeof(uint32_t)) + relative_to;
+ case RC_ABSOLUTE_PPC_2_2:
+ return load_value_2_2();
+ case RC_ABSOLUTE_PPC_2:
+ return load_value_masked(rel_absolute_ppc_2_mask, 16, 0);
+ case RC_RELATIVE_PPC_2_PC:
+ return load_value_masked(rel_relative_ppc_2_mask, 16, 0) + relative_to -
+ 4;
+ case RC_RELATIVE_PPC_3_PC:
+ return load_value_masked(rel_relative_ppc_3_mask, 6, 0) + relative_to - 4;
+ case RC_RELATIVE_ARM_3:
+ return load_value_masked(rel_relative_arm_3_mask, 6, 2) + relative_to +
+ sizeof(cell);
+ case RC_INDIRECT_ARM:
+ return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to;
+ case RC_INDIRECT_ARM_PC:
+ return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to +
+ sizeof(cell);
+ case RC_ABSOLUTE_2:
+ return *(uint16_t*)(pointer - sizeof(uint16_t));
+ case RC_ABSOLUTE_1:
+ return *(uint8_t*)(pointer - sizeof(uint8_t));
+ case RC_ABSOLUTE_PPC_2_2_2_2:
+ return load_value_2_2_2_2();
+ default:
+ critical_error("Bad rel class", rel.klass());
+ return 0;
+ }
}
-/* Store a value into a bitfield of a PowerPC instruction */
-void instruction_operand::store_value_masked(fixnum value, cell mask, fixnum shift)
-{
- cell *ptr = (cell *)pointer;
-
- /* This is unaccurate but good enough */
- fixnum test = (fixnum)mask >> 1;
- if(value <= -test || value >= test)
- critical_error("Value does not fit inside relocation",0);
+code_block* instruction_operand::load_code_block() {
+ return ((code_block*)load_value(pointer) - 1);
+}
- *ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
+// Store a 32-bit value into a PowerPC LIS/ORI sequence
+void instruction_operand::store_value_2_2(fixnum value) {
+ uint32_t* ptr = (uint32_t*)pointer;
+ ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
+ ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
}
-void instruction_operand::store_value(fixnum absolute_value)
-{
- fixnum relative_value = absolute_value - pointer;
+// Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence
+void instruction_operand::store_value_2_2_2_2(fixnum value) {
+ uint64_t val = value;
+ uint32_t* ptr = (uint32_t*)pointer;
+ ptr[-5] = ((ptr[-5] & ~0xffff) | ((val >> 48) & 0xffff));
+ ptr[-4] = ((ptr[-4] & ~0xffff) | ((val >> 32) & 0xffff));
+ ptr[-2] = ((ptr[-2] & ~0xffff) | ((val >> 16) & 0xffff));
+ ptr[-1] = ((ptr[-1] & ~0xffff) | ((val >> 0) & 0xffff));
+}
- switch(rel_class)
- {
- case RC_ABSOLUTE_CELL:
- *(cell *)pointer = absolute_value;
- break;
- case RC_ABSOLUTE:
- *(u32*)pointer = absolute_value;
- break;
- case RC_RELATIVE:
- *(s32*)pointer = relative_value - sizeof(u32);
- break;
- case RC_ABSOLUTE_PPC_2_2:
- store_value_2_2(absolute_value);
- break;
- case RC_ABSOLUTE_PPC_2:
- store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
- break;
- case RC_RELATIVE_PPC_2:
- store_value_masked(relative_value,rel_relative_ppc_2_mask,0);
- break;
- case RC_RELATIVE_PPC_3:
- store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
- break;
- case RC_RELATIVE_ARM_3:
- store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
- break;
- case RC_INDIRECT_ARM:
- store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
- break;
- case RC_INDIRECT_ARM_PC:
- store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
- break;
- default:
- critical_error("Bad rel class",rel_class);
- break;
- }
+// Store a value into a bitfield of a PowerPC instruction
+void instruction_operand::store_value_masked(fixnum value, cell mask,
+ cell shift) {
+ uint32_t* ptr = (uint32_t*)(pointer - sizeof(uint32_t));
+ *ptr = (uint32_t)((*ptr & ~mask) | ((value >> shift) & mask));
}
-void instruction_operand::store_code_block(code_block *compiled)
-{
- store_value((cell)compiled->xt());
+void instruction_operand::store_value(fixnum absolute_value) {
+ fixnum relative_value = absolute_value - pointer;
+
+ switch (rel.klass()) {
+ case RC_ABSOLUTE_CELL:
+ *(cell*)(pointer - sizeof(cell)) = absolute_value;
+ break;
+ case RC_ABSOLUTE:
+ *(uint32_t*)(pointer - sizeof(uint32_t)) = (uint32_t)absolute_value;
+ break;
+ case RC_RELATIVE:
+ *(int32_t*)(pointer - sizeof(int32_t)) = (int32_t)relative_value;
+ break;
+ case RC_ABSOLUTE_PPC_2_2:
+ store_value_2_2(absolute_value);
+ break;
+ case RC_ABSOLUTE_PPC_2:
+ store_value_masked(absolute_value, rel_absolute_ppc_2_mask, 0);
+ break;
+ case RC_RELATIVE_PPC_2_PC:
+ store_value_masked(relative_value + 4, rel_relative_ppc_2_mask, 0);
+ break;
+ case RC_RELATIVE_PPC_3_PC:
+ store_value_masked(relative_value + 4, rel_relative_ppc_3_mask, 0);
+ break;
+ case RC_RELATIVE_ARM_3:
+ store_value_masked(relative_value - sizeof(cell), rel_relative_arm_3_mask,
+ 2);
+ break;
+ case RC_INDIRECT_ARM:
+ store_value_masked(relative_value, rel_indirect_arm_mask, 0);
+ break;
+ case RC_INDIRECT_ARM_PC:
+ store_value_masked(relative_value - sizeof(cell), rel_indirect_arm_mask,
+ 0);
+ break;
+ case RC_ABSOLUTE_2:
+ *(uint16_t*)(pointer - sizeof(uint16_t)) = (uint16_t)absolute_value;
+ break;
+ case RC_ABSOLUTE_1:
+ *(uint8_t*)(pointer - sizeof(uint8_t)) = (uint8_t)absolute_value;
+ break;
+ case RC_ABSOLUTE_PPC_2_2_2_2:
+ store_value_2_2_2_2(absolute_value);
+ break;
+ default:
+ critical_error("Bad rel class", rel.klass());
+ break;
+ }
}
}