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