]> gitweb.factorcode.org Git - factor.git/blob - vm/instruction_operands.cpp
vm: mark sweep now traces code block references; rename embedded_pointer to instructi...
[factor.git] / vm / instruction_operands.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 /* Load a 32-bit value from a PowerPC LIS/ORI sequence */
7 fixnum instruction_operand::load_value_2_2()
8 {
9         cell *ptr = (cell *)pointer;
10         cell hi = (ptr[-1] & 0xffff);
11         cell lo = (ptr[ 0] & 0xffff);
12         return hi << 16 | lo;
13 }
14
15 /* Load a value from a bitfield of a PowerPC instruction */
16 fixnum instruction_operand::load_value_masked(cell mask, fixnum shift)
17 {
18         cell *ptr = (cell *)pointer;
19
20         return (*ptr & mask) << shift;
21 }
22
23 fixnum instruction_operand::load_value()
24 {
25         switch(rel_class)
26         {
27         case RC_ABSOLUTE_CELL:
28                 return *(cell *)pointer;
29         case RC_ABSOLUTE:
30                 return *(u32*)pointer;
31         case RC_RELATIVE:
32                 return *(s32*)pointer + pointer + sizeof(u32);
33         case RC_ABSOLUTE_PPC_2_2:
34                 return load_value_2_2();
35         case RC_ABSOLUTE_PPC_2:
36                 return load_value_masked(rel_absolute_ppc_2_mask,0);
37         case RC_RELATIVE_PPC_2:
38                 return load_value_masked(rel_relative_ppc_2_mask,0) + pointer;
39         case RC_RELATIVE_PPC_3:
40                 return load_value_masked(rel_relative_ppc_3_mask,0) + pointer;
41         case RC_RELATIVE_ARM_3:
42                 return load_value_masked(rel_relative_arm_3_mask,2) + pointer + sizeof(cell) * 2;
43         case RC_INDIRECT_ARM:
44                 return load_value_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell);
45         case RC_INDIRECT_ARM_PC:
46                 return load_value_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell) * 2;
47         default:
48                 critical_error("Bad rel class",rel_class);
49                 return 0;
50         }
51 }
52
53 /* Store a 32-bit value into a PowerPC LIS/ORI sequence */
54 void instruction_operand::store_value_2_2(fixnum value)
55 {
56         cell *ptr = (cell *)pointer;
57         ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
58         ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
59 }
60
61 /* Store a value into a bitfield of a PowerPC instruction */
62 void instruction_operand::store_value_masked(fixnum value, cell mask, fixnum shift)
63 {
64         cell *ptr = (cell *)pointer;
65
66         /* This is unaccurate but good enough */
67         fixnum test = (fixnum)mask >> 1;
68         if(value <= -test || value >= test)
69                 critical_error("Value does not fit inside relocation",0);
70
71         *ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
72 }
73
74 void instruction_operand::store_value(fixnum absolute_value)
75 {
76         fixnum relative_value = absolute_value - pointer;
77
78         switch(rel_class)
79         {
80         case RC_ABSOLUTE_CELL:
81                 *(cell *)pointer = absolute_value;
82                 break;
83         case RC_ABSOLUTE:
84                 *(u32*)pointer = absolute_value;
85                 break;
86         case RC_RELATIVE:
87                 *(s32*)pointer = relative_value - sizeof(u32);
88                 break;
89         case RC_ABSOLUTE_PPC_2_2:
90                 store_value_2_2(absolute_value);
91                 break;
92         case RC_ABSOLUTE_PPC_2:
93                 store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
94                 break;
95         case RC_RELATIVE_PPC_2:
96                 store_value_masked(relative_value,rel_relative_ppc_2_mask,0);
97                 break;
98         case RC_RELATIVE_PPC_3:
99                 store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
100                 break;
101         case RC_RELATIVE_ARM_3:
102                 store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
103                 break;
104         case RC_INDIRECT_ARM:
105                 store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
106                 break;
107         case RC_INDIRECT_ARM_PC:
108                 store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
109                 break;
110         default:
111                 critical_error("Bad rel class",rel_class);
112                 break;
113         }
114 }
115
116 }