Fixed stoopid bug in chimara_if_set_preferred_interpreter()
[rodin/chimara.git] / interpreters / git / operands.c
1 // $Id: operands.c,v 1.11 2004/02/02 00:13:46 iain Exp $
2
3 #include "git.h"
4 #include <assert.h>
5
6 git_uint32 parseLoad (git_uint32 * pc, LoadReg reg, int mode, TransferSize size, git_sint32 * constVal)
7 {
8     git_uint32 value;
9
10     switch (mode)
11     {
12         case 0x0: // Constant zero. (Zero bytes)
13             value = 0;
14             goto load_const;
15
16         case 0x1: // Constant, -80 to 7F. (One byte)
17             value = (git_sint32) ((git_sint8) memRead8(*pc));
18             *pc += 1;
19             goto load_const;
20
21         case 0x2: // Constant, -8000 to 7FFF. (Two bytes)
22             value = (git_sint32) ((git_sint16) memRead16(*pc));
23             *pc += 2;
24             goto load_const;
25
26         case 0x3: // Constant, any value. (Four bytes)
27             value = memRead32(*pc);
28             *pc += 4;
29             goto load_const;
30
31         case 0x5: // Contents of address 00 to FF. (One byte)
32             value = memRead8(*pc);
33             *pc += 1;
34             goto load_addr;
35
36         case 0x6: // Contents of address 0000 to FFFF. (Two bytes)
37             value = memRead16(*pc);
38             *pc += 2;
39             goto load_addr;
40
41         case 0x7: // Contents of any address. (Four bytes)
42             value = memRead32(*pc);
43             *pc += 4;
44             goto load_addr;
45
46         case 0x8: // Value popped off stack. (Zero bytes)
47             goto load_stack;
48
49         case 0x9: // Call frame local at address 00 to FF. (One byte)
50             value = memRead8(*pc);
51             *pc += 1;
52             goto load_local;
53
54         case 0xA: // Call frame local at address 0000 to FFFF. (Two bytes)
55             value = memRead16(*pc);
56             *pc += 2;
57             goto load_local;
58
59         case 0xB: // Call frame local at any address. (Four bytes)
60             value = memRead32(*pc);
61             *pc += 4;
62             goto load_local;
63
64         case 0xD: // Contents of RAM address 00 to FF. (One byte)
65             value = memRead8(*pc) + gRamStart;
66             *pc += 1;
67             goto load_addr;
68
69         case 0xE: // Contents of RAM address 0000 to FFFF. (Two bytes)
70             value = memRead16(*pc) + gRamStart;
71             *pc += 2;
72             goto load_addr;
73
74         case 0xF: // Contents of RAM, any address. (Four bytes)
75             value = memRead32(*pc) + gRamStart;
76             *pc += 4;
77             goto load_addr;
78
79         default: // Illegal addressing mode
80             abortCompilation();
81             break;
82
83         // ------------------------------------------------------
84
85         load_const:
86             if (constVal)
87             {
88                 *constVal = value;
89                 return 1;
90             }
91             else
92             {
93                 emitCode (label_L1_const + reg);
94                 emitData (value);
95             }
96             break;
97
98         load_stack:
99                         emitCode (label_L1_stack + reg);
100                         break;
101
102         load_addr:
103             if (value < gRamStart)
104             {
105                 if (size == size32)
106                     value = memRead32(value);
107                 else if (size == size16)
108                     value = memRead16(value);
109                 else
110                     value = memRead8(value);
111                                 goto load_const;
112             }
113                         switch (size)
114                         {
115                                 case size8:
116                                         assert (reg == reg_L1);
117                                         emitCode (label_L1_addr8);
118                                         break;
119
120                                 case size16:
121                                         assert (reg == reg_L1);
122                                         emitCode (label_L1_addr16);
123                                         break;
124
125                                 case size32:
126                                         emitCode (label_L1_addr + reg);
127                                         break;
128                         }
129                         emitData (value);
130                         break;
131
132         load_local:
133             emitCode (label_L1_local + reg);
134             emitData (value / 4); // Convert byte offset to word offset.
135             break;
136     }
137
138     return 0;
139 }
140
141 void parseStore (git_uint32 * pc, StoreReg reg, int mode, TransferSize size)
142 {
143     git_uint32 value;
144
145     switch (mode)
146     {
147         case 0x0: // Discard
148             break;
149
150         case 0x5: // Contents of address 00 to FF. (One byte)
151             value = memRead8(*pc);
152             *pc += 1;
153             goto store_addr;
154
155         case 0x6: // Contents of address 0000 to FFFF. (Two bytes)
156             value = memRead16(*pc);
157             *pc += 2;
158             goto store_addr;
159
160         case 0x7: // Contents of any address. (Four bytes)
161             value = memRead32(*pc);
162             *pc += 4;
163             goto store_addr;
164
165         case 0x8: // Value popped off stack. (Zero bytes)
166             goto store_stack;
167
168         case 0x9: // Call frame local at store_address 00 to FF. (One byte)
169             value = memRead8(*pc);
170             *pc += 1;
171             goto store_local;
172
173         case 0xA: // Call frame local at store_address 0000 to FFFF. (Two bytes)
174             value = memRead16(*pc);
175             *pc += 2;
176             goto store_local;
177
178         case 0xB: // Call frame local at any store_address. (Four bytes)
179             value = memRead32(*pc);
180             *pc += 4;
181             goto store_local;
182
183         case 0xD: // Contents of RAM address 00 to FF. (One byte)
184             value = memRead8(*pc) + gRamStart;
185             *pc += 1;
186             goto store_addr;
187
188         case 0xE: // Contents of RAM address 0000 to FFFF. (Two bytes)
189             value = memRead16(*pc) + gRamStart;
190             *pc += 2;
191             goto store_addr;
192
193         case 0xF: // Contents of RAM, any address. (Four bytes)
194             value = memRead32(*pc) + gRamStart;
195             *pc += 4;
196             goto store_addr;
197
198         // ------------------------------------------------------
199
200         store_stack:
201             emitCode (reg == reg_S1 ? label_S1_stack : label_S2_stack);
202             break;
203
204         store_addr:
205             if (size == size32)
206                         {
207                 emitCode (reg == reg_S1 ? label_S1_addr : label_S2_addr);
208             }
209                         else
210                         {
211                                 assert (reg == reg_S1);
212                                 emitCode (size == size16 ? label_S1_addr16 : label_S1_addr8);
213                         }
214             emitData (value);
215             break;
216
217         store_local:
218             emitCode (reg == reg_S1 ? label_S1_local : label_S2_local);
219             emitData (value / 4); // Convert byte offset to word offset.
220             break;
221     }
222 }
223
224 static void parseStub (git_uint32 * pc, int mode, Label discardOp)
225 {
226     git_uint32 value;
227     switch (mode)
228     {
229         case 0x0: // Discard
230             goto store_discard;
231         case 0x5: // Contents of address 00 to FF. (One byte)
232             value = memRead8(*pc);
233             *pc += 1;
234             goto store_addr;
235         case 0x6: // Contents of address 0000 to FFFF. (Two bytes)
236             value = memRead16(*pc);
237             *pc += 2;
238             goto store_addr;
239         case 0x7: // Contents of any address. (Four bytes)
240             value = memRead32(*pc);
241             *pc += 4;
242             goto store_addr;
243         case 0x8: // Value popped off stack. (Zero bytes)
244             goto store_stack;
245         case 0x9: // Call frame local at store_address 00 to FF. (One byte)
246             value = memRead8(*pc);
247             *pc += 1;
248             goto store_local;
249         case 0xA: // Call frame local at store_address 0000 to FFFF. (Two bytes)
250             value = memRead16(*pc);
251             *pc += 2;
252             goto store_local;
253         case 0xB: // Call frame local at any store_address. (Four bytes)
254             value = memRead32(*pc);
255             *pc += 4;
256             goto store_local;
257         case 0xD: // Contents of RAM address 00 to FF. (One byte)
258             value = memRead8(*pc) + gRamStart;
259             *pc += 1;
260             goto store_addr;
261         case 0xE: // Contents of RAM address 0000 to FFFF. (Two bytes)
262             value = memRead16(*pc) + gRamStart;
263             *pc += 2;
264             goto store_addr;
265         case 0xF: // Contents of RAM, any address. (Four bytes)
266             value = memRead32(*pc) + gRamStart;
267             *pc += 4;
268             goto store_addr;
269         // ------------------------------------------------------
270         store_discard:
271             emitCode (discardOp);
272             break;
273         store_stack:
274             emitCode (discardOp + (label_call_stub_stack - label_call_stub_discard));
275             break;
276         store_addr:
277             emitCode (discardOp + (label_call_stub_addr - label_call_stub_discard));
278             emitData (value);
279             break;
280         store_local:
281             emitCode (discardOp + (label_call_stub_local - label_call_stub_discard));
282             emitData (value); // Convert byte offset to word offset.
283             break;
284     }
285     
286     // Every call stub ends with the glulx return address.
287     emitData (*pc);
288
289     // ...which means that every call stub references the next instruction.
290     nextInstructionIsReferenced ();
291 }
292 void parseCallStub (git_uint32 * pc, int mode)
293 {
294     parseStub (pc, mode, label_call_stub_discard);
295 }
296 void parseCatchStub (git_uint32 * pc, int mode)
297 {
298     parseStub (pc, mode, label_catch_stub_discard);
299 }
300 void parseSaveStub (git_uint32 * pc, int mode)
301 {
302     parseStub (pc, mode, label_save_stub_discard);
303 }
304 void parseUndoStub (git_uint32 * pc, int mode)
305 {
306     parseStub (pc, mode, label_undo_stub_discard);
307 }