]> gitweb.factorcode.org Git - factor.git/blob - vm/instruction_operands.cpp
Merge branch 'master' of git://factorcode.org/git/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_->xt() + 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[-1] & 0xffff);
14         cell lo = (ptr[ 0] & 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         fixnum *ptr = (fixnum *)pointer;
22
23         return (((*ptr & 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;
32         case RC_ABSOLUTE:
33                 return *(u32*)pointer;
34         case RC_RELATIVE:
35                 return *(s32*)pointer + relative_to + sizeof(u32);
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,0,0);
40         case RC_RELATIVE_PPC_2:
41                 return load_value_masked(rel_relative_ppc_2_mask,16,0) + relative_to;
42         case RC_RELATIVE_PPC_3:
43                 return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to;
44         case RC_RELATIVE_ARM_3:
45                 return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell) * 2;
46         case RC_INDIRECT_ARM:
47                 return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell);
48         case RC_INDIRECT_ARM_PC:
49                 return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell) * 2;
50         default:
51                 critical_error("Bad rel class",rel.rel_class());
52                 return 0;
53         }
54 }
55
56 fixnum instruction_operand::load_value()
57 {
58         return load_value(pointer);
59 }
60
61 code_block *instruction_operand::load_code_block(cell relative_to)
62 {
63         return ((code_block *)load_value(relative_to) - 1);
64 }
65
66 code_block *instruction_operand::load_code_block()
67 {
68         return load_code_block(pointer);
69 }
70
71 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
72 void instruction_operand::store_value_2_2(fixnum value)
73 {
74         cell *ptr = (cell *)pointer;
75         ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
76         ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
77 }
78
79 /* Store a value into a bitfield of a PowerPC instruction */
80 void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift)
81 {
82         cell *ptr = (cell *)pointer;
83
84         /* This is unaccurate but good enough */
85         fixnum test = (fixnum)mask >> 1;
86         if(value <= -test || value >= test)
87                 critical_error("Value does not fit inside relocation",0);
88
89         *ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
90 }
91
92 void instruction_operand::store_value(fixnum absolute_value)
93 {
94         fixnum relative_value = absolute_value - pointer;
95
96         switch(rel.rel_class())
97         {
98         case RC_ABSOLUTE_CELL:
99                 *(cell *)pointer = absolute_value;
100                 break;
101         case RC_ABSOLUTE:
102                 *(u32*)pointer = absolute_value;
103                 break;
104         case RC_RELATIVE:
105                 *(s32*)pointer = relative_value - sizeof(u32);
106                 break;
107         case RC_ABSOLUTE_PPC_2_2:
108                 store_value_2_2(absolute_value);
109                 break;
110         case RC_ABSOLUTE_PPC_2:
111                 store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
112                 break;
113         case RC_RELATIVE_PPC_2:
114                 store_value_masked(relative_value,rel_relative_ppc_2_mask,0);
115                 break;
116         case RC_RELATIVE_PPC_3:
117                 store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
118                 break;
119         case RC_RELATIVE_ARM_3:
120                 store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
121                 break;
122         case RC_INDIRECT_ARM:
123                 store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
124                 break;
125         case RC_INDIRECT_ARM_PC:
126                 store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
127                 break;
128         default:
129                 critical_error("Bad rel class",rel.rel_class());
130                 break;
131         }
132 }
133
134 void instruction_operand::store_code_block(code_block *compiled)
135 {
136         store_value((cell)compiled->xt());
137 }
138
139 }