]> gitweb.factorcode.org Git - factor.git/blob - vm/instruction_operands.cpp
compiler: add ##load-vector instruction to avoid wasting a temporary register on...
[factor.git] / vm / instruction_operands.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 instruction_operand::instruction_operand(relocation_entry rel_, code_block *compiled_, cell index_) :
7         rel(rel_), compiled(compiled_), index(index_), pointer((cell)compiled_->entry_point() + rel_.rel_offset()) {}
8
9 /* Load a 32-bit value from a PowerPC LIS/ORI sequence */
10 fixnum instruction_operand::load_value_2_2()
11 {
12         cell *ptr = (cell *)pointer;
13         cell hi = (ptr[-2] & 0xffff);
14         cell lo = (ptr[-1] & 0xffff);
15         return hi << 16 | lo;
16 }
17
18 /* Load a value from a bitfield of a PowerPC instruction */
19 fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift)
20 {
21         s32 *ptr = (s32 *)(pointer - sizeof(u32));
22
23         return (((*ptr & (s32)mask) << bits) >> bits) << shift;
24 }
25
26 fixnum instruction_operand::load_value(cell relative_to)
27 {
28         switch(rel.rel_class())
29         {
30         case RC_ABSOLUTE_CELL:
31                 return *(cell *)(pointer - sizeof(cell));
32         case RC_ABSOLUTE:
33                 return *(u32 *)(pointer - sizeof(u32));
34         case RC_RELATIVE:
35                 return *(s32 *)(pointer - sizeof(u32)) + relative_to;
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,16,0);
40         case RC_RELATIVE_PPC_2:
41                 return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to - sizeof(cell);
42         case RC_RELATIVE_PPC_3:
43                 return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to - sizeof(cell);
44         case RC_RELATIVE_ARM_3:
45                 return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell);
46         case RC_INDIRECT_ARM:
47                 return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to;
48         case RC_INDIRECT_ARM_PC:
49                 return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell);
50         case RC_ABSOLUTE_2:
51                 return *(u16 *)(pointer - sizeof(u16));
52         case RC_ABSOLUTE_1:
53                 return *(u8 *)(pointer - sizeof(u8));
54         default:
55                 critical_error("Bad rel class",rel.rel_class());
56                 return 0;
57         }
58 }
59
60 fixnum instruction_operand::load_value()
61 {
62         return load_value(pointer);
63 }
64
65 cell instruction_operand::load_float()
66 {
67         return (cell)load_value() - boxed_float_offset;
68 }
69
70 cell instruction_operand::load_float(cell pointer)
71 {
72         return (cell)load_value(pointer) - boxed_float_offset;
73 }
74
75 cell instruction_operand::load_byte_array()
76 {
77         return (cell)load_value() - byte_array_offset;
78 }
79
80 cell instruction_operand::load_byte_array(cell pointer)
81 {
82         return (cell)load_value(pointer) - byte_array_offset;
83 }
84
85 code_block *instruction_operand::load_code_block(cell relative_to)
86 {
87         return ((code_block *)load_value(relative_to) - 1);
88 }
89
90 code_block *instruction_operand::load_code_block()
91 {
92         return load_code_block(pointer);
93 }
94
95 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
96 void instruction_operand::store_value_2_2(fixnum value)
97 {
98         cell *ptr = (cell *)pointer;
99         ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
100         ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 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, cell shift)
105 {
106         u32 *ptr = (u32 *)(pointer - sizeof(u32));
107         *ptr = (u32)((*ptr & ~mask) | ((value >> shift) & mask));
108 }
109
110 void instruction_operand::store_value(fixnum absolute_value)
111 {
112         fixnum relative_value = absolute_value - pointer;
113
114         switch(rel.rel_class())
115         {
116         case RC_ABSOLUTE_CELL:
117                 *(cell *)(pointer - sizeof(cell)) = absolute_value;
118                 break;
119         case RC_ABSOLUTE:
120                 *(u32 *)(pointer - sizeof(u32)) = (u32)absolute_value;
121                 break;
122         case RC_RELATIVE:
123                 *(s32 *)(pointer - sizeof(s32)) = (s32)relative_value;
124                 break;
125         case RC_ABSOLUTE_PPC_2_2:
126                 store_value_2_2(absolute_value);
127                 break;
128         case RC_ABSOLUTE_PPC_2:
129                 store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
130                 break;
131         case RC_RELATIVE_PPC_2:
132                 store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_2_mask,0);
133                 break;
134         case RC_RELATIVE_PPC_3:
135                 store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_3_mask,0);
136                 break;
137         case RC_RELATIVE_ARM_3:
138                 store_value_masked(relative_value - sizeof(cell),rel_relative_arm_3_mask,2);
139                 break;
140         case RC_INDIRECT_ARM:
141                 store_value_masked(relative_value,rel_indirect_arm_mask,0);
142                 break;
143         case RC_INDIRECT_ARM_PC:
144                 store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
145                 break;
146         case RC_ABSOLUTE_2:
147                 *(u16 *)(pointer - sizeof(u16)) = (u16)absolute_value;
148                 break;
149         case RC_ABSOLUTE_1:
150                 *(u8 *)(pointer - sizeof(u8)) = (u8)absolute_value;
151                 break;
152         default:
153                 critical_error("Bad rel class",rel.rel_class());
154                 break;
155         }
156 }
157
158 void instruction_operand::store_float(cell value)
159 {
160         store_value((fixnum)value + boxed_float_offset);
161 }
162
163 void instruction_operand::store_byte_array(cell value)
164 {
165         store_value((fixnum)value + byte_array_offset);
166 }
167
168 void instruction_operand::store_code_block(code_block *compiled)
169 {
170         store_value((cell)compiled->entry_point());
171 }
172
173 }