]> gitweb.factorcode.org Git - factor.git/blob - vm/instruction_operands.cpp
vm: new image relocation that doesn't use literal table
[factor.git] / vm / instruction_operands.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 /* Load a 32-bit value from a PowerPC LIS/ORI sequence */
7 fixnum instruction_operand::load_value_2_2()
8 {
9         cell *ptr = (cell *)pointer;
10         cell hi = (ptr[-1] & 0xffff);
11         cell lo = (ptr[ 0] & 0xffff);
12         return hi << 16 | lo;
13 }
14
15 /* Load a value from a bitfield of a PowerPC instruction */
16 fixnum instruction_operand::load_value_masked(cell mask, fixnum shift)
17 {
18         cell *ptr = (cell *)pointer;
19
20         return (*ptr & mask) << shift;
21 }
22
23 fixnum instruction_operand::load_value(cell relative_to)
24 {
25         switch(rel_class)
26         {
27         case RC_ABSOLUTE_CELL:
28                 return *(cell *)pointer;
29         case RC_ABSOLUTE:
30                 return *(u32*)pointer;
31         case RC_RELATIVE:
32                 return *(s32*)pointer + relative_to + sizeof(u32);
33         case RC_ABSOLUTE_PPC_2_2:
34                 return load_value_2_2();
35         case RC_ABSOLUTE_PPC_2:
36                 return load_value_masked(rel_absolute_ppc_2_mask,0);
37         case RC_RELATIVE_PPC_2:
38                 return load_value_masked(rel_relative_ppc_2_mask,0) + relative_to;
39         case RC_RELATIVE_PPC_3:
40                 return load_value_masked(rel_relative_ppc_3_mask,0) + relative_to;
41         case RC_RELATIVE_ARM_3:
42                 return load_value_masked(rel_relative_arm_3_mask,2) + relative_to + sizeof(cell) * 2;
43         case RC_INDIRECT_ARM:
44                 return load_value_masked(rel_indirect_arm_mask,0) + relative_to + sizeof(cell);
45         case RC_INDIRECT_ARM_PC:
46                 return load_value_masked(rel_indirect_arm_mask,0) + relative_to + sizeof(cell) * 2;
47         default:
48                 critical_error("Bad rel class",rel_class);
49                 return 0;
50         }
51 }
52
53 fixnum instruction_operand::load_value()
54 {
55         return load_value(pointer);
56 }
57
58 code_block *instruction_operand::load_code_block(cell relative_to)
59 {
60         return ((code_block *)load_value(relative_to) - 1);
61 }
62
63 code_block *instruction_operand::load_code_block()
64 {
65         return load_code_block(pointer);
66 }
67
68 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
69 void instruction_operand::store_value_2_2(fixnum value)
70 {
71         cell *ptr = (cell *)pointer;
72         ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
73         ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
74 }
75
76 /* Store a value into a bitfield of a PowerPC instruction */
77 void instruction_operand::store_value_masked(fixnum value, cell mask, fixnum shift)
78 {
79         cell *ptr = (cell *)pointer;
80
81         /* This is unaccurate but good enough */
82         fixnum test = (fixnum)mask >> 1;
83         if(value <= -test || value >= test)
84                 critical_error("Value does not fit inside relocation",0);
85
86         *ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
87 }
88
89 void instruction_operand::store_value(fixnum absolute_value)
90 {
91         fixnum relative_value = absolute_value - pointer;
92
93         switch(rel_class)
94         {
95         case RC_ABSOLUTE_CELL:
96                 *(cell *)pointer = absolute_value;
97                 break;
98         case RC_ABSOLUTE:
99                 *(u32*)pointer = absolute_value;
100                 break;
101         case RC_RELATIVE:
102                 *(s32*)pointer = relative_value - sizeof(u32);
103                 break;
104         case RC_ABSOLUTE_PPC_2_2:
105                 store_value_2_2(absolute_value);
106                 break;
107         case RC_ABSOLUTE_PPC_2:
108                 store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
109                 break;
110         case RC_RELATIVE_PPC_2:
111                 store_value_masked(relative_value,rel_relative_ppc_2_mask,0);
112                 break;
113         case RC_RELATIVE_PPC_3:
114                 store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
115                 break;
116         case RC_RELATIVE_ARM_3:
117                 store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
118                 break;
119         case RC_INDIRECT_ARM:
120                 store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
121                 break;
122         case RC_INDIRECT_ARM_PC:
123                 store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
124                 break;
125         default:
126                 critical_error("Bad rel class",rel_class);
127                 break;
128         }
129 }
130
131 void instruction_operand::store_code_block(code_block *compiled)
132 {
133         store_value((cell)compiled->xt());
134 }
135
136 }