6 instruction_operand::instruction_operand(relocation_entry rel_, code_block *compiled_, cell index_) :
7 rel(rel_), compiled(compiled_), index(index_), pointer((cell)compiled_->xt() + rel_.rel_offset()) {}
9 /* Load a 32-bit value from a PowerPC LIS/ORI sequence */
10 fixnum instruction_operand::load_value_2_2()
12 cell *ptr = (cell *)pointer;
13 cell hi = (ptr[-1] & 0xffff);
14 cell lo = (ptr[ 0] & 0xffff);
18 /* Load a value from a bitfield of a PowerPC instruction */
19 fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift)
21 fixnum *ptr = (fixnum *)pointer;
23 return (((*ptr & mask) << bits) >> bits) << shift;
26 fixnum instruction_operand::load_value(cell relative_to)
28 switch(rel.rel_class())
30 case RC_ABSOLUTE_CELL:
31 return *(cell *)pointer;
33 return *(u32*)pointer;
35 return *(s32*)pointer + relative_to + sizeof(u32);
36 case RC_ABSOLUTE_PPC_2_2:
37 return load_value_2_2();
38 case RC_ABSOLUTE_PPC_2:
39 return load_value_masked(rel_absolute_ppc_2_mask,0,0);
40 case RC_RELATIVE_PPC_2:
41 return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to;
42 case RC_RELATIVE_PPC_3:
43 return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to;
44 case RC_RELATIVE_ARM_3:
45 return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell) * 2;
47 return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell);
48 case RC_INDIRECT_ARM_PC:
49 return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell) * 2;
51 critical_error("Bad rel class",rel.rel_class());
56 fixnum instruction_operand::load_value()
58 return load_value(pointer);
61 code_block *instruction_operand::load_code_block(cell relative_to)
63 return ((code_block *)load_value(relative_to) - 1);
66 code_block *instruction_operand::load_code_block()
68 return load_code_block(pointer);
71 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
72 void instruction_operand::store_value_2_2(fixnum value)
74 cell *ptr = (cell *)pointer;
75 ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
76 ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
79 /* Store a value into a bitfield of a PowerPC instruction */
80 void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift)
82 cell *ptr = (cell *)pointer;
84 /* This is unaccurate but good enough */
85 fixnum test = (fixnum)mask >> 1;
86 if(value <= -test || value >= test)
87 critical_error("Value does not fit inside relocation",0);
89 *ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
92 void instruction_operand::store_value(fixnum absolute_value)
94 fixnum relative_value = absolute_value - pointer;
96 switch(rel.rel_class())
98 case RC_ABSOLUTE_CELL:
99 *(cell *)pointer = absolute_value;
102 *(u32*)pointer = absolute_value;
105 *(s32*)pointer = relative_value - sizeof(u32);
107 case RC_ABSOLUTE_PPC_2_2:
108 store_value_2_2(absolute_value);
110 case RC_ABSOLUTE_PPC_2:
111 store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
113 case RC_RELATIVE_PPC_2:
114 store_value_masked(relative_value,rel_relative_ppc_2_mask,0);
116 case RC_RELATIVE_PPC_3:
117 store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
119 case RC_RELATIVE_ARM_3:
120 store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
122 case RC_INDIRECT_ARM:
123 store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
125 case RC_INDIRECT_ARM_PC:
126 store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
129 critical_error("Bad rel class",rel.rel_class());
134 void instruction_operand::store_code_block(code_block *compiled)
136 store_value((cell)compiled->xt());