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