RPA Toolkit
27bb0b2ce529350c9a9b3b4bc755cba46128d2dc
[rpatk.git] / rvm / rvmcpu.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include "rmem.h"
26 #include "rstring.h"
27 #include "rvmcpu.h"
28
29
30 static const char *stropcalls[] = {
31         "RVM_EXT",
32         "RVM_ASR",
33         "RVM_SWI",
34         "RVM_MOV",
35         "RVM_ADD",
36         "RVM_ADDS",
37         "RVM_ADC",
38         "RVM_AND",
39         "RVM_BIC",
40         "RVM_CLZ",
41         "RVM_CMN",
42         "RVM_EOR",
43         "RVM_SUB",
44         "RVM_SUBS",
45         "RVM_SBC",
46         "RVM_MUL",
47         "RVM_MLS",
48         "RVM_MULS",
49         "RVM_NOT",
50         "RVM_DIV",
51         "RVM_DVS",
52         "RVM_DIVS",
53         "RVM_BL",
54         "RVM_B",
55         "RVM_STR",
56         "RVM_STRP",
57         "RVM_STRB",
58         "RVM_STRH",
59         "RVM_STRW",
60         "RVM_STRR",
61         "RVM_LDR",
62         "RVM_LDRP",
63         "RVM_LDRB",
64         "RVM_LDRH",
65         "RVM_LDRW",
66         "RVM_LDRR",
67         "RVM_LSL",
68         "RVM_LSR",
69         "RVM_STM",
70         "RVM_LDM",
71         "RVM_STS",
72         "RVM_LDS",
73         "RVM_ORR",
74         "RVM_PUSH",
75         "RVM_POP",
76         "RVM_CMP",
77         "RVM_NOP",
78         "RVM_BEQ",
79         "RVM_BNEQ",
80         "RVM_BLEQ",
81         "RVM_BGEQ",
82         "RVM_BLES",
83         "RVM_BGRE",
84         "RVM_RET",
85         "RVM_ROR",
86         "RVM_PUSHM",
87         "RVM_POPM",     
88         "RVM_TST",      
89         "RVM_TEQ",      
90 };
91
92
93 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
94 {
95         RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
96 }
97
98
99 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
100 {
101         if ((cpu->status & RVM_STATUS_Z))
102                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
103 }
104
105
106 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
107 {
108         if ((cpu->status & RVM_STATUS_Z) == 0)
109                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
110 }
111
112
113 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
114 {
115         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z))
116                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
117 }
118
119 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
120 {
121         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1)
122                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
123 }
124
125
126 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
127 {
128         if ((cpu->status & RVM_STATUS_N))
129                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
130 }
131
132
133 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
134 {
135         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0)
136                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETU(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
137 }
138
139
140 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
141 {
142         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
143         RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
144 }
145
146
147 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
148 {
149
150 }
151
152
153 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
154 {
155         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
156 }
157
158
159 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
160 {
161         RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
162         
163 }
164
165
166 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
167 {
168         RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
169 }
170
171
172 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
173 {
174         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
175 }
176
177
178 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
179 {
180         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
181 }
182
183
184 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
185 {
186         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
187 }
188
189
190 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
191 {
192         RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
193 }
194
195
196 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
197 {
198         *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
199 }
200
201
202 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
203 {
204         *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
205 }
206
207
208 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
209 {
210         *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
211 }
212
213
214 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
215 {
216         *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
217         
218 }
219
220
221 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
222 {
223         *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
224
225 }
226
227
228 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
229 {
230         *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)) = RVM_CPUREG_GET(cpu, ins->op1);
231 }
232
233
234 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
235 {
236         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
237         
238         res = op2 + op3;
239         RVM_CPUREG_SETU(cpu, ins->op1, res);
240         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
241         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
242         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
243         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
244                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
245 }
246
247
248 static void rvm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
249 {
250         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
251         
252         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
253         RVM_CPUREG_SETU(cpu, ins->op1, res);
254         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
255         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
256         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
257         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
258                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
259 }
260
261
262 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
263 {
264         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
265         
266         res = op2 & op3;
267         RVM_CPUREG_SETU(cpu, ins->op1, res);
268         RVM_STATUS_CLRALL(cpu);
269         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
270         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
271 }
272
273
274 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
275 {
276         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
277         
278         res = op2 | op3;
279         RVM_CPUREG_SETU(cpu, ins->op1, res);
280         RVM_STATUS_CLRALL(cpu);
281         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
282         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
283 }
284
285
286 static void rvm_op_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
287 {
288         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
289         
290         res = op2 << op3;
291         RVM_CPUREG_SETU(cpu, ins->op1, res);
292         RVM_STATUS_CLRALL(cpu);
293         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
294         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
295 }
296
297
298 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
299 {
300         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
301         
302         res = op2 >> op3;
303         RVM_CPUREG_SETU(cpu, ins->op1, res);
304         RVM_STATUS_CLRALL(cpu);
305         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
306 }
307
308
309 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
310 {
311         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
312         
313         res = op2 >> op3;
314         res |= op2 & RVM_SIGN_BIT;
315         RVM_CPUREG_SETU(cpu, ins->op1, res);
316         RVM_STATUS_CLRALL(cpu);
317         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
318         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
319 }
320
321
322 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
323 {
324         ruint i;
325         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
326         
327         res = op2;
328         for (i = 0; i < op3; i++) {
329                 if (res & 1) {
330                         res >>= 1;
331                         res |= RVM_SIGN_BIT;
332                 } else {
333                         res >>= 1;
334                 }
335         }
336         RVM_CPUREG_SETU(cpu, ins->op1, res);
337         RVM_STATUS_CLRALL(cpu);
338         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
339         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
340         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
341 }
342
343
344 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
345 {
346         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
347         
348         res = op2 & op3;
349         RVM_STATUS_CLRALL(cpu);
350         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
351         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
352 }
353
354
355 static void rvm_op_eor(rvmcpu_t *cpu, rvm_asmins_t *ins)
356 {
357         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
358         
359         res = op2 ^ op3;
360         RVM_CPUREG_SETU(cpu, ins->op1, res);
361         RVM_STATUS_CLRALL(cpu);
362         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
363         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
364 }
365
366
367 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
368 {
369         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
370         
371         res = ~op2;
372         RVM_CPUREG_SETU(cpu, ins->op1, res);
373         RVM_STATUS_CLRALL(cpu);
374         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
375         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
376 }
377
378
379 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
380 {
381         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
382         
383         res = op2 ^ op3;
384         RVM_STATUS_CLRALL(cpu);
385         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
386         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
387 }
388
389
390 static void rvm_op_bic(rvmcpu_t *cpu, rvm_asmins_t *ins)
391 {
392         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
393         
394         res = op2 & ~op3;
395         RVM_CPUREG_SETU(cpu, ins->op1, res);
396         RVM_STATUS_CLRALL(cpu);
397         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
398         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
399 }
400
401
402 static void rvm_op_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
403 {
404         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
405         
406         for (res = RVM_REGISTER_BITS; op2; ) {
407                 op2 >>= 1;
408                 res -= 1;
409         }
410         RVM_CPUREG_SETU(cpu, ins->op1, res);
411 }
412
413
414 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
415 {
416         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
417 }
418
419
420 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
421 {
422 //      rvmcpu_swi *cbt = cpu->switable[RVM_CB_TABLE(RVM_CPUREG_GETU(cpu, ins->op1))];
423 //      cbt[RVM_CB_OFFSET(RVM_CPUREG_GETU(cpu, ins->op1))](cpu);
424
425         rvmcpu_swi swi;
426         rvm_switable_t *switable;
427         ruint ntable = (ruint) RVM_SWI_TABLE(RVM_CPUREG_GETU(cpu, ins->op1));
428         ruint nswi = (ruint) RVM_SWI_NUM(RVM_CPUREG_GETU(cpu, ins->op1));
429
430         if (r_array_size(cpu->switables) <= ntable)
431                 RVM_ABORT(cpu, RVM_E_SWITABLE);
432         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
433         swi = switable[nswi].op;
434         swi(cpu, ins);
435 }
436
437
438 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
439 {
440         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
441 }
442
443
444 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
445 {
446         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
447         
448         res = op2 - op3;
449         RVM_CPUREG_SETU(cpu, ins->op1, res);
450         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
451         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
452         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
453         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
454                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
455 }
456
457
458 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
459 {
460         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
461
462         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
463         RVM_CPUREG_SETU(cpu, ins->op1, res);
464         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
465         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
466         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
467         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
468                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
469 }
470
471
472 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
473 {
474         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
475 }
476
477
478 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
479 {
480         rsword res;
481         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
482
483         res = (rsword)(op2 * op3);
484         RVM_CPUREG_SETU(cpu, ins->op1, res);
485         /* TBD: Not sure how to update the RVM_STATUS_C */
486         RVM_STATUS_CLRALL(cpu);
487         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
488         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
489 }
490
491
492 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
493 {
494         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
495         
496         res = op2 * op3;
497         RVM_CPUREG_SETU(cpu, ins->op1, res);
498         RVM_STATUS_CLRALL(cpu);
499         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
500         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
501         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
502 }
503
504
505 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
506 {
507         if (!RVM_CPUREG_GETU(cpu, ins->op3))
508                 RVM_ABORT(cpu, RVM_E_DIVZERO);
509
510         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
511 }
512
513
514 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
515 {
516         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
517
518         if (!op3)
519                 RVM_ABORT(cpu, RVM_E_DIVZERO);
520         res = op2 / op3;
521         RVM_CPUREG_SETU(cpu, ins->op1, res);
522         RVM_STATUS_CLRALL(cpu);
523         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
524         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
525 }
526
527
528 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
529 {
530         rsword res;
531         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
532
533         if (!op3)
534                 RVM_ABORT(cpu, RVM_E_DIVZERO);
535         res = (rsword)(op2 / op3);
536         RVM_CPUREG_SETU(cpu, ins->op1, res);
537         RVM_STATUS_CLRALL(cpu);
538         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
539         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
540 }
541
542
543 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
544 {
545         rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
546
547         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
548         RVM_CPUREG_SETU(cpu, SP, sp);
549 }
550
551
552 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
553 {
554         rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
555
556         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
557 }
558
559
560 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
561 {
562         int n, i;
563         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
564         rword sp = RVM_CPUREG_GETU(cpu, SP);
565
566         for (i = 0, n = 0; bits && n < RLST; n++) {
567                 if (((rword)(1 << n)) & bits) {
568                         i += 1;
569                         sp += 1;
570                         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, n));
571                         bits &= ~(1<<n);
572                 }
573         }
574         RVM_CPUREG_SETU(cpu, SP, RVM_CPUREG_GETU(cpu, SP) + i);
575 }
576
577
578 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
579 {
580         rword sp = RVM_CPUREG_GETU(cpu, SP);
581
582         RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
583         if (ins->op1 != SP)
584                 RVM_CPUREG_SETU(cpu, SP, sp - 1);
585 }
586
587
588 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
589 {
590         int n;
591         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
592         rword sp = RVM_CPUREG_GETU(cpu, SP);
593
594         for (n = RLST - 1; bits && n >= 0; n--) {
595                 if (((rword)(1 << n)) & bits) {
596                         RVM_CPUREG_SET(cpu, n, r_array_index(cpu->stack, sp, rvmreg_t));
597                         sp -= 1;
598                         bits &= ~(1<<n);
599                 }
600         }
601         if (!(((rword)(1 << SP)) & bits))
602                 RVM_CPUREG_SETU(cpu, SP, sp);
603 }
604
605
606 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
607 {
608         rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
609
610         RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
611 }
612
613
614 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
615 {
616         int n;
617         rword *dst = (rword*)   RVM_CPUREG_GETU(cpu, ins->op1);
618         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
619         
620         for (n = 0; bits && n < RLST; n++) {
621                 if (((rword)(1 << n)) & bits) {
622                         *dst = RVM_CPUREG_GETU(cpu, n);
623                         dst += 1;
624                         bits &= ~(1<<n);
625                 }
626         }
627 }
628
629
630 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
631 {
632         int n;
633         rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
634         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
635
636         for (n = 0; bits && n < RLST; n++) {
637                 if (((rword)(1 << n)) & bits) {
638                         RVM_CPUREG_SETU(cpu, n, *src);
639                         src += 1;
640                         bits &= ~(1<<n);
641                 }
642         }
643 }
644
645
646 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
647 {
648         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
649         rword res = (rword)(op1 - op2);
650         
651         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
652         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
653         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
654         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
655                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
656 }
657
658
659 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
660 {
661         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
662         rword res = (rword)(op1 + op2);
663         
664         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
665         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
666         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
667         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
668                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
669
670 }
671
672
673 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
674 {
675 //      fprintf(stdout, "nop\n");
676 }
677
678
679 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
680 {
681         RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));     
682 }
683
684
685
686 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
687 {
688         return vsnprintf(str, size, format, ap);
689 }
690
691
692 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
693 {
694         va_list ap;
695         int ret;
696
697         va_start(ap, format);
698         ret = rvm_vsnprintf(str, size, format, ap);
699         va_end(ap);
700         return ret;
701 }
702
703
704 static int rvm_printf(const char *format, ...)
705 {
706         va_list ap;
707         int ret;
708
709         va_start(ap, format);
710         ret = vfprintf(stdout, format, ap);
711         va_end(ap);
712         return ret;
713 }
714
715
716 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
717 {
718         int ret = 0;
719
720         if (reg == XX)
721                 ret = rvm_snprintf(str, size, "XX ");
722         else if (reg == FP)
723                 ret = rvm_snprintf(str, size, "FP ");
724         else if (reg == SP)
725                 ret = rvm_snprintf(str, size, "SP ");
726         else if (reg == LR)
727                 ret = rvm_snprintf(str, size, "LR ");
728         else if (reg == PC)
729                 ret = rvm_snprintf(str, size, "PC ");
730         else if (reg == DA)
731                 ret = rvm_snprintf(str, size, "DA ");
732         else if (reg >= 0 && reg < 10)
733                 ret = rvm_snprintf(str, size, "R%d ",  reg);
734         else if (reg >= 10)
735                 ret = rvm_snprintf(str, size, "R%d",  reg);
736
737         return ret;
738 }
739
740
741 int rvm_asm_dump_pi_to_str(rvm_asmins_t *pi, char *str, ruint size)
742 {
743         int ret = 0, sz = size;
744
745         if ((ret = rvm_snprintf(str, sz, "%10s   ", stropcalls[pi->opcode])) < 0)
746                 return ret;
747         str += ret;
748         sz -= ret;
749         
750         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
751                 return ret;
752         str += ret;
753         sz -= ret;
754                 
755         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
756                 return ret;
757         str += ret;
758         sz -= ret;
759
760         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
761                 return ret;
762         str += ret;
763         sz -= ret;
764                 
765         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
766                 return ret;
767         str += ret;
768         sz -= ret;
769
770         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
771                 return ret;
772         str += ret;
773         sz -= ret;
774                 
775         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
776                 return ret;
777         str += ret;
778         sz -= ret;
779
780         if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)RVM_REG_GETU(&pi->data))) < 0)
781                 return ret;
782         str += ret;
783         sz -= ret;
784
785         return size - sz;
786 }
787
788
789 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
790 {
791         char buffer[256];
792         while (count) {
793                 rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
794                 rvm_printf("%s\n", buffer);
795                 ++pi;
796                 --count;
797         }
798 }
799
800
801 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
802 {
803     int ret;
804         char buffer[1024];
805         
806         ret = rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
807         if (ret < 0)
808                 return;
809     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
810         buffer[50] = '\0';
811         rvm_printf("%s", buffer);
812
813         rvm_printf("0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, FP=%ld, SP=%ld, LR=%ld, PC=%ld, DA=0x%lx, S( %c%c%c%c )",
814                 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
815                 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
816                 RVM_CPUREG_GETU(vm, 8), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
817                 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
818                 vm->status & RVM_STATUS_V ? 'V' : '_',
819                 vm->status & RVM_STATUS_C ? 'C' : '_',
820                 vm->status & RVM_STATUS_N ? 'N' : '_',
821                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
822         rvm_printf("\n");
823 }
824
825
826 static rvm_cpu_op ops[] = {
827         rvm_op_exit,            // RVM_EXT
828         rvm_op_asr,                     // RVM_ASR
829         rvm_op_swi,                     // RVM_swi
830         rvm_op_mov,                     // RVM_MOV
831         rvm_op_add,                     // RVM_ADD
832         rvm_op_adds,            // RVM_ADDS
833         rvm_op_adc,                     // RVM_ADC
834         rvm_op_and,                     // RVM_AND
835         rvm_op_bic,                     // RVM_BIC
836         rvm_op_clz,                     // RVM_CLZ
837         rvm_op_cmn,                     // RVM_CMN
838         rvm_op_eor,                     // RVM_EOR
839         rvm_op_sub,                     // RVM_SUB
840         rvm_op_subs,            // RVM_SUBS
841         rvm_op_sbc,                     // RVM_SBC
842         rvm_op_mul,                     // RVM_MUL
843         rvm_op_mls,                     // RVM_MLS
844         rvm_op_muls,            // RVM_MULS
845         rvm_op_not,                     // RVM_NOT
846         rvm_op_div,                     // RVM_DIV
847         rvm_op_dvs,                     // RVM_DVS
848         rvm_op_divs,            // RVM_DIVS
849         rvm_op_bl,                      // RVM_BL
850         rvm_op_b,                       // RVM_B
851         rvm_op_str,                     // RVM_STR
852         rvm_op_strp,            // RVM_STRP
853         rvm_op_strb,            // RVM_STRB
854         rvm_op_strh,            // RVM_STRH
855         rvm_op_strw,            // RVM_STRW
856         rvm_op_strr,            // RVM_STRR
857         rvm_op_ldr,                     // RVM_LDR
858         rvm_op_ldrp,            // RVM_LDRP
859         rvm_op_ldrb,            // RVM_LDRB
860         rvm_op_ldrh,            // RVM_LDRH
861         rvm_op_ldrw,            // RVM_LDRW
862         rvm_op_ldrr,            // RVM_LDRR
863         rvm_op_lsl,                     // RVM_LSL
864         rvm_op_lsr,                     // RVM_LSR
865         rvm_op_stm,                     // RVM_STM
866         rvm_op_ldm,                     // RVM_LDS
867         rvm_op_sts,                     // RVM_STS
868         rvm_op_lds,                     // RVM_LDM
869         rvm_op_orr,                     // RVM_ORR
870         rvm_op_push,            // RVM_PUSH
871         rvm_op_pop,                     // RVM_POP
872         rvm_op_cmp,                     // RVM_CMP
873         rvm_op_nop,                     // RVM_NOP
874         rvm_op_beq,                     // RVM_BEQ
875         rvm_op_bneq,            // RVM_BNEQ
876         rvm_op_bleq,            // RVM_BLEQ
877         rvm_op_bgeq,            // RVM_BGEQ
878         rvm_op_bles,            // RVM_BLES
879         rvm_op_bgre,            // RVM_BGRE
880         rvm_op_ret,                     // RVM_RET
881         rvm_op_ror,                     // RVM_ROR
882         rvm_op_pushm,           // RVM_PUSHM
883         rvm_op_popm,            // RVM_POPM
884         rvm_op_tst,             // RVM_TST
885         rvm_op_teq,             // RVM_TEQ
886         (void*) 0,
887         (void*) 0,
888         (void*) 0,
889         (void*) 0,
890         (void*) 0,
891         (void*) 0,
892         (void*) 0,
893         (void*) 0,
894         
895 };
896         
897
898 rvmcpu_t *rvm_cpu_create()
899 {
900         rvmcpu_t *cpu;
901
902         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
903         if (!cpu)
904                 return ((void*)0);
905         r_memset(cpu, 0, sizeof(*cpu));
906         cpu->switables = r_array_create(sizeof(rvm_switable_t*));
907         cpu->stack = r_array_create(sizeof(rvmreg_t));
908         return cpu;
909 }
910
911
912 void rvm_cpu_destroy(rvmcpu_t *cpu)
913 {
914 //      rvm_free(cpu->stack);
915         r_array_destroy(cpu->switables);
916         r_array_destroy(cpu->stack);
917         r_free(cpu);
918 }
919
920
921 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
922 {
923         rvm_asmins_t *pi;
924
925         RVM_CPUREG_SETIP(cpu, PC, prog + off);
926         cpu->abort = 0;
927         cpu->error = 0;
928         do {
929                 pi = RVM_CPUREG_GETIP(cpu, PC);
930                 cpu->r[DA] = pi->data;
931                 ops[pi->opcode](cpu, pi);
932                 if (cpu->abort)
933                         return -1;
934                 RVM_CPUREG_INCIP(cpu, PC, 1);
935         } while (pi->opcode);
936         return 0;
937 }
938
939
940 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
941 {
942         rvm_asmins_t *pi;
943
944         RVM_CPUREG_SETIP(cpu, PC, prog + off);
945         cpu->abort = 0;
946         cpu->error = 0;
947         do {
948                 pi = RVM_CPUREG_GETIP(cpu, PC);
949                 cpu->r[DA] = pi->data;
950                 ops[pi->opcode](cpu, pi);
951                 if (cpu->abort)
952                         return -1;
953                 rvm_cpu_dumpregs(pi, cpu);              
954                 RVM_CPUREG_INCIP(cpu, PC, 1);
955         } while (pi->opcode);
956         return 0;
957 }
958
959
960 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname)
961 {
962         rint ntable, nswi;
963         rvm_switable_t *swientry;
964
965         for (ntable = 0; ntable < cpu->switables->len; ntable++) {
966                 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
967                 for (nswi = 0; swientry[nswi].name; nswi++) {
968                         if (r_strcmp(swientry[nswi].name, swiname) == 0)
969                                 return (rint)RVM_SWI_ID(ntable, nswi);
970                 }
971         }
972
973         return -1;
974 }
975
976
977 rint rvmcpu_switable_add(rvmcpu_t *cpu, rvm_switable_t *switable)
978 {
979         rint nswi;
980
981         for (nswi = 0; switable[nswi].name; nswi++) {
982                 if (rvm_cpu_getswi(cpu, switable[nswi].name) >= 0)
983                         return -1;
984         }
985
986         return r_array_add(cpu->switables, &switable);
987 }
988
989
990 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
991 {
992         rvm_asmins_t a;
993
994         r_memset(&a, 0, sizeof(a));
995         a.opcode = (unsigned char) opcode;
996         a.op1 = (unsigned char)op1;
997         a.op2 = (unsigned char)op2;
998         a.op3 = (unsigned char)op3;
999         RVM_REG_GETD(&a.data) = data;
1000         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_DOUBLE);
1001         return a;
1002 }
1003
1004
1005 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
1006 {
1007         rvm_asmins_t a;
1008
1009         r_memset(&a, 0, sizeof(a));
1010         a.opcode = (unsigned char) opcode;
1011         a.op1 = (unsigned char)op1;
1012         a.op2 = (unsigned char)op2;
1013         a.op3 = (unsigned char)op3;
1014         RVM_REG_GETP(&a.data) = data;
1015         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_POINTER);
1016         return a;
1017 }
1018
1019
1020 rvm_asmins_t rvm_asmu(rword opcode, rword op1, rword op2, rword op3, rword data)
1021 {
1022         rvm_asmins_t a;
1023
1024         r_memset(&a, 0, sizeof(a));
1025         a.opcode = (unsigned char) opcode;
1026         a.op1 = (unsigned char)op1;
1027         a.op2 = (unsigned char)op2;
1028         a.op3 = (unsigned char)op3;
1029         RVM_REG_GETU(&a.data) = data;
1030         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_WORD);
1031         return a;
1032 }
1033
1034
1035 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1036 {
1037         rvm_asmins_t a;
1038
1039         r_memset(&a, 0, sizeof(a));
1040         a.opcode = (unsigned char) opcode;
1041         a.op1 = (unsigned char)op1;
1042         a.op2 = (unsigned char)op2;
1043         a.op3 = (unsigned char)op3;
1044         RVM_REG_GETL(&a.data) = (rword)data;
1045         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_LONG);
1046         return a;
1047 }
1048
1049
1050 rvm_asmins_t rvm_asmi(rword opcode, rword op1, rword op2, rword op3, rint data)
1051 {
1052         return rvm_asml(opcode, op1, op2, op3, data);
1053 }
1054
1055
1056 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1057 {
1058         rvm_asmins_t a;
1059
1060         r_memset(&a, 0, sizeof(a));
1061         a.opcode = (unsigned char) opcode;
1062         a.op1 = (unsigned char)op1;
1063         a.op2 = (unsigned char)op2;
1064         a.op3 = (unsigned char)op3;
1065         RVM_REG_GETP(&a.data) = pReloc;
1066         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCPTR);
1067         return a;
1068 }
1069
1070
1071 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1072 {
1073         rvm_asmins_t a;
1074
1075         r_memset(&a, 0, sizeof(a));
1076         a.opcode = (unsigned char) opcode;
1077         a.op1 = (unsigned char)op1;
1078         a.op2 = (unsigned char)op2;
1079         a.op3 = (unsigned char)op3;
1080         RVM_REG_GETP(&a.data) = pReloc;
1081         RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCINDEX);
1082         return a;
1083 }
1084
1085
1086 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1087 {
1088         return rvm_asmu(opcode, op1, op2, op3, data);
1089 }
1090
1091
1092 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1093 {
1094         rvm_asmins_t *reloc;
1095         rulong relocindex;
1096         rulong off;
1097
1098         for (off = 0; off < size; off++, code++) {
1099                 if (RVM_REG_GETTYPE(&code->data) == RVM_DTYPE_RELOCPTR) {
1100                         RVM_REG_SETTYPE(&code->data, RVM_DTYPE_NONE);
1101                         reloc = *((rvm_asmins_t **)RVM_REG_GETP(&code->data));
1102                         RVM_REG_GETU(&code->data) = reloc - code;
1103                 } else if (RVM_REG_GETTYPE(&code->data) == RVM_DTYPE_RELOCINDEX) {
1104                         RVM_REG_SETTYPE(&code->data, RVM_DTYPE_NONE);
1105                         relocindex = *((rulong *)RVM_REG_GETP(&code->data));
1106                         RVM_REG_GETU(&code->data) = relocindex - off;
1107                 }
1108         }
1109 }