]> gitweb.factorcode.org Git - factor.git/blob - vm/instruction_operands.cpp
VM: change the definition of entry_point in word and quotation from void* to cell
[factor.git] / vm / instruction_operands.cpp
1 #include "master.hpp"
2
3 namespace factor {
4
5 instruction_operand::instruction_operand(relocation_entry rel,
6                                          code_block* compiled, cell index)
7     : rel(rel),
8       compiled(compiled),
9       index(index),
10       pointer(compiled->entry_point() + rel.rel_offset()) {}
11
12 /* Load a 32-bit value from a PowerPC LIS/ORI sequence */
13 fixnum instruction_operand::load_value_2_2() {
14   uint32_t* ptr = (uint32_t*)pointer;
15   cell hi = (ptr[-2] & 0xffff);
16   cell lo = (ptr[-1] & 0xffff);
17   return hi << 16 | lo;
18 }
19
20 /* Load a 64-bit value from a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
21 fixnum instruction_operand::load_value_2_2_2_2() {
22   uint32_t* ptr = (uint32_t*)pointer;
23   uint64_t hhi = (ptr[-5] & 0xffff);
24   uint64_t hlo = (ptr[-4] & 0xffff);
25   uint64_t lhi = (ptr[-2] & 0xffff);
26   uint64_t llo = (ptr[-1] & 0xffff);
27   uint64_t val = hhi << 48 | hlo << 32 | lhi << 16 | llo;
28   return (cell)val;
29 }
30
31 /* Load a value from a bitfield of a PowerPC instruction */
32 fixnum instruction_operand::load_value_masked(cell mask, cell bits,
33                                               cell shift) {
34   int32_t* ptr = (int32_t*)(pointer - sizeof(uint32_t));
35
36   return (((*ptr & (int32_t)mask) << bits) >> bits) << shift;
37 }
38
39 fixnum instruction_operand::load_value(cell relative_to) {
40   switch (rel.rel_class()) {
41     case RC_ABSOLUTE_CELL:
42       return *(cell*)(pointer - sizeof(cell));
43     case RC_ABSOLUTE:
44       return *(uint32_t*)(pointer - sizeof(uint32_t));
45     case RC_RELATIVE:
46       return *(int32_t*)(pointer - sizeof(uint32_t)) + relative_to;
47     case RC_ABSOLUTE_PPC_2_2:
48       return load_value_2_2();
49     case RC_ABSOLUTE_PPC_2:
50       return load_value_masked(rel_absolute_ppc_2_mask, 16, 0);
51     case RC_RELATIVE_PPC_2_PC:
52       return load_value_masked(rel_relative_ppc_2_mask, 16, 0) + relative_to -
53              4;
54     case RC_RELATIVE_PPC_3_PC:
55       return load_value_masked(rel_relative_ppc_3_mask, 6, 0) + relative_to - 4;
56     case RC_RELATIVE_ARM_3:
57       return load_value_masked(rel_relative_arm_3_mask, 6, 2) + relative_to +
58              sizeof(cell);
59     case RC_INDIRECT_ARM:
60       return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to;
61     case RC_INDIRECT_ARM_PC:
62       return load_value_masked(rel_indirect_arm_mask, 20, 0) + relative_to +
63              sizeof(cell);
64     case RC_ABSOLUTE_2:
65       return *(uint16_t*)(pointer - sizeof(uint16_t));
66     case RC_ABSOLUTE_1:
67       return *(uint8_t*)(pointer - sizeof(uint8_t));
68     case RC_ABSOLUTE_PPC_2_2_2_2:
69       return load_value_2_2_2_2();
70     default:
71       critical_error("Bad rel class", rel.rel_class());
72       return 0;
73   }
74 }
75
76 fixnum instruction_operand::load_value() { return load_value(pointer); }
77
78 code_block* instruction_operand::load_code_block(cell relative_to) {
79   return ((code_block*)load_value(relative_to) - 1);
80 }
81
82 code_block* instruction_operand::load_code_block() {
83   return load_code_block(pointer);
84 }
85
86 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
87 void instruction_operand::store_value_2_2(fixnum value) {
88   uint32_t* ptr = (uint32_t*)pointer;
89   ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
90   ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
91 }
92
93 /* Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence */
94 void instruction_operand::store_value_2_2_2_2(fixnum value) {
95   uint64_t val = value;
96   uint32_t* ptr = (uint32_t*)pointer;
97   ptr[-5] = ((ptr[-5] & ~0xffff) | ((val >> 48) & 0xffff));
98   ptr[-4] = ((ptr[-4] & ~0xffff) | ((val >> 32) & 0xffff));
99   ptr[-2] = ((ptr[-2] & ~0xffff) | ((val >> 16) & 0xffff));
100   ptr[-1] = ((ptr[-1] & ~0xffff) | ((val >> 0) & 0xffff));
101 }
102
103 /* Store a value into a bitfield of a PowerPC instruction */
104 void instruction_operand::store_value_masked(fixnum value, cell mask,
105                                              cell shift) {
106   uint32_t* ptr = (uint32_t*)(pointer - sizeof(uint32_t));
107   *ptr = (uint32_t)((*ptr & ~mask) | ((value >> shift) & mask));
108 }
109
110 void instruction_operand::store_value(fixnum absolute_value) {
111   fixnum relative_value = absolute_value - pointer;
112
113   switch (rel.rel_class()) {
114     case RC_ABSOLUTE_CELL:
115       *(cell*)(pointer - sizeof(cell)) = absolute_value;
116       break;
117     case RC_ABSOLUTE:
118       *(uint32_t*)(pointer - sizeof(uint32_t)) = (uint32_t)absolute_value;
119       break;
120     case RC_RELATIVE:
121       *(int32_t*)(pointer - sizeof(int32_t)) = (int32_t)relative_value;
122       break;
123     case RC_ABSOLUTE_PPC_2_2:
124       store_value_2_2(absolute_value);
125       break;
126     case RC_ABSOLUTE_PPC_2:
127       store_value_masked(absolute_value, rel_absolute_ppc_2_mask, 0);
128       break;
129     case RC_RELATIVE_PPC_2_PC:
130       store_value_masked(relative_value + 4, rel_relative_ppc_2_mask, 0);
131       break;
132     case RC_RELATIVE_PPC_3_PC:
133       store_value_masked(relative_value + 4, rel_relative_ppc_3_mask, 0);
134       break;
135     case RC_RELATIVE_ARM_3:
136       store_value_masked(relative_value - sizeof(cell), rel_relative_arm_3_mask,
137                          2);
138       break;
139     case RC_INDIRECT_ARM:
140       store_value_masked(relative_value, rel_indirect_arm_mask, 0);
141       break;
142     case RC_INDIRECT_ARM_PC:
143       store_value_masked(relative_value - sizeof(cell), rel_indirect_arm_mask,
144                          0);
145       break;
146     case RC_ABSOLUTE_2:
147       *(uint16_t*)(pointer - sizeof(uint16_t)) = (uint16_t)absolute_value;
148       break;
149     case RC_ABSOLUTE_1:
150       *(uint8_t*)(pointer - sizeof(uint8_t)) = (uint8_t)absolute_value;
151       break;
152     case RC_ABSOLUTE_PPC_2_2_2_2:
153       store_value_2_2_2_2(absolute_value);
154       break;
155     default:
156       critical_error("Bad rel class", rel.rel_class());
157       break;
158   }
159 }
160
161 void instruction_operand::store_code_block(code_block* compiled) {
162   store_value(compiled->entry_point());
163 }
164
165 }