]> gitweb.factorcode.org Git - factor.git/blob - vm/instruction_operands.cpp
Merge git://github.com/erikcharlebois/factor
[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 code_block *instruction_operand::load_code_block(cell relative_to)
66 {
67         return ((code_block *)load_value(relative_to) - 1);
68 }
69
70 code_block *instruction_operand::load_code_block()
71 {
72         return load_code_block(pointer);
73 }
74
75 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
76 void instruction_operand::store_value_2_2(fixnum value)
77 {
78         cell *ptr = (cell *)pointer;
79         ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
80         ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
81 }
82
83 /* Store a value into a bitfield of a PowerPC instruction */
84 void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift)
85 {
86         u32 *ptr = (u32 *)(pointer - sizeof(u32));
87         *ptr = (u32)((*ptr & ~mask) | ((value >> shift) & mask));
88 }
89
90 void instruction_operand::store_value(fixnum absolute_value)
91 {
92         fixnum relative_value = absolute_value - pointer;
93
94         switch(rel.rel_class())
95         {
96         case RC_ABSOLUTE_CELL:
97                 *(cell *)(pointer - sizeof(cell)) = absolute_value;
98                 break;
99         case RC_ABSOLUTE:
100                 *(u32 *)(pointer - sizeof(u32)) = (u32)absolute_value;
101                 break;
102         case RC_RELATIVE:
103                 *(s32 *)(pointer - sizeof(s32)) = (s32)relative_value;
104                 break;
105         case RC_ABSOLUTE_PPC_2_2:
106                 store_value_2_2(absolute_value);
107                 break;
108         case RC_ABSOLUTE_PPC_2:
109                 store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
110                 break;
111         case RC_RELATIVE_PPC_2:
112                 store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_2_mask,0);
113                 break;
114         case RC_RELATIVE_PPC_3:
115                 store_value_masked(relative_value + sizeof(cell),rel_relative_ppc_3_mask,0);
116                 break;
117         case RC_RELATIVE_ARM_3:
118                 store_value_masked(relative_value - sizeof(cell),rel_relative_arm_3_mask,2);
119                 break;
120         case RC_INDIRECT_ARM:
121                 store_value_masked(relative_value,rel_indirect_arm_mask,0);
122                 break;
123         case RC_INDIRECT_ARM_PC:
124                 store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
125                 break;
126         case RC_ABSOLUTE_2:
127                 *(u16 *)(pointer - sizeof(u16)) = (u16)absolute_value;
128                 break;
129         case RC_ABSOLUTE_1:
130                 *(u8 *)(pointer - sizeof(u8)) = (u8)absolute_value;
131                 break;
132         default:
133                 critical_error("Bad rel class",rel.rel_class());
134                 break;
135         }
136 }
137
138 void instruction_operand::store_code_block(code_block *compiled)
139 {
140         store_value((cell)compiled->entry_point());
141 }
142
143 }