]> gitweb.factorcode.org Git - factor.git/blob - vm/instruction_operands.cpp
git: fix tests
[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.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 preshift,
33                                               cell bits, cell postshift) {
34   int32_t* ptr = (int32_t*)(pointer - sizeof(uint32_t));
35
36   return ((((*ptr & (int32_t)mask) >> preshift ) << bits) >> bits) << postshift;
37 }
38
39 fixnum instruction_operand::load_value(cell relative_to) {
40   switch (rel.klass()) {
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, 0, 16, 0);
51     case RC_RELATIVE_PPC_2_PC:
52       return load_value_masked(rel_relative_ppc_2_mask, 0, 16, 0) +
53              relative_to - 4;
54     case RC_RELATIVE_PPC_3_PC:
55       return load_value_masked(rel_relative_ppc_3_mask, 0, 6, 0) +
56              relative_to - 4;
57     case RC_RELATIVE_ARM_3:
58       return load_value_masked(rel_relative_arm_3_mask, 0, 6, 2) + relative_to +
59              sizeof(cell);
60     case RC_INDIRECT_ARM:
61       return load_value_masked(rel_indirect_arm_mask, 0, 20, 0) + relative_to;
62     case RC_INDIRECT_ARM_PC:
63       return load_value_masked(rel_indirect_arm_mask, 0, 20, 0) + relative_to +
64              sizeof(cell);
65     case RC_ABSOLUTE_2:
66       return *(uint16_t*)(pointer - sizeof(uint16_t));
67     case RC_ABSOLUTE_1:
68       return *(uint8_t*)(pointer - sizeof(uint8_t));
69     case RC_ABSOLUTE_PPC_2_2_2_2:
70       return load_value_2_2_2_2();
71     case RC_RELATIVE_ARM64_BRANCH:
72       return load_value_masked(rel_relative_arm64_branch_mask, 0, 4, 2) +
73              relative_to;
74     case RC_RELATIVE_ARM64_BCOND:
75       return load_value_masked(rel_relative_arm64_bcond_mask, 3, 11, 0) +
76              relative_to;
77     default:
78       critical_error("Bad rel class", rel.klass());
79       return 0;
80   }
81 }
82
83 code_block* instruction_operand::load_code_block() {
84   return ((code_block*)load_value(pointer) - 1);
85 }
86
87 // Store a 32-bit value into a PowerPC LIS/ORI sequence
88 void instruction_operand::store_value_2_2(fixnum value) {
89   uint32_t* ptr = (uint32_t*)pointer;
90   ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
91   ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
92 }
93
94 // Store a 64-bit value into a PowerPC LIS/ORI/SLDI/ORIS/ORI sequence
95 void instruction_operand::store_value_2_2_2_2(fixnum value) {
96   uint64_t val = value;
97   uint32_t* ptr = (uint32_t*)pointer;
98   ptr[-5] = ((ptr[-5] & ~0xffff) | ((val >> 48) & 0xffff));
99   ptr[-4] = ((ptr[-4] & ~0xffff) | ((val >> 32) & 0xffff));
100   ptr[-2] = ((ptr[-2] & ~0xffff) | ((val >> 16) & 0xffff));
101   ptr[-1] = ((ptr[-1] & ~0xffff) | ((val >> 0) & 0xffff));
102 }
103
104 // Store a value into a bitfield of a PowerPC instruction
105 void instruction_operand::store_value_masked(fixnum value, cell mask,
106                                              cell shift1, cell shift2) {
107   uint32_t* ptr = (uint32_t*)(pointer - sizeof(uint32_t));
108   *ptr = (uint32_t)((*ptr & ~mask) | ((value >> shift1 << shift2) & mask));
109 }
110
111 void instruction_operand::store_value(fixnum absolute_value) {
112   fixnum relative_value = absolute_value - pointer;
113
114   switch (rel.klass()) {
115     case RC_ABSOLUTE_CELL:
116       *(cell*)(pointer - sizeof(cell)) = absolute_value;
117       break;
118     case RC_ABSOLUTE:
119       *(uint32_t*)(pointer - sizeof(uint32_t)) = (uint32_t)absolute_value;
120       break;
121     case RC_RELATIVE:
122       *(int32_t*)(pointer - sizeof(int32_t)) = (int32_t)relative_value;
123       break;
124     case RC_ABSOLUTE_PPC_2_2:
125       store_value_2_2(absolute_value);
126       break;
127     case RC_ABSOLUTE_PPC_2:
128       store_value_masked(absolute_value, rel_absolute_ppc_2_mask, 0, 0);
129       break;
130     case RC_RELATIVE_PPC_2_PC:
131       store_value_masked(relative_value + 4, rel_relative_ppc_2_mask, 0, 0);
132       break;
133     case RC_RELATIVE_PPC_3_PC:
134       store_value_masked(relative_value + 4, rel_relative_ppc_3_mask, 0, 0);
135       break;
136     case RC_RELATIVE_ARM_3:
137       store_value_masked(relative_value - sizeof(cell), rel_relative_arm_3_mask,
138                          2, 0);
139       break;
140     case RC_INDIRECT_ARM:
141       store_value_masked(relative_value, rel_indirect_arm_mask, 0, 0);
142       break;
143     case RC_INDIRECT_ARM_PC:
144       store_value_masked(relative_value - sizeof(cell), rel_indirect_arm_mask,
145                          0, 0);
146       break;
147     case RC_ABSOLUTE_2:
148       *(uint16_t*)(pointer - sizeof(uint16_t)) = (uint16_t)absolute_value;
149       break;
150     case RC_ABSOLUTE_1:
151       *(uint8_t*)(pointer - sizeof(uint8_t)) = (uint8_t)absolute_value;
152       break;
153     case RC_ABSOLUTE_PPC_2_2_2_2:
154       store_value_2_2_2_2(absolute_value);
155       break;
156     case RC_RELATIVE_ARM64_BRANCH:
157       store_value_masked(relative_value, rel_relative_arm64_branch_mask, 2, 0);
158       break;
159     case RC_RELATIVE_ARM64_BCOND:
160       store_value_masked(relative_value, rel_relative_arm64_bcond_mask, 2, 5);
161       break;
162     default:
163       critical_error("Bad rel class", rel.klass());
164       break;
165   }
166 }
167
168 }