RPA Toolkit
merge the work on extended ops
[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 "rvmcpu.h"
26 #include "rvmoperator.h"
27 #include "rvmoperatorcast.h"
28 #include "rmem.h"
29 #include "rstring.h"
30 #include "rvmreg.h"
31
32
33 static const char *stropcalls[] = {
34         "RVM_EXT",
35         "RVM_ASR",
36         "RVM_SWI",
37         "RVM_MOV",
38         "RVM_ADD",
39         "RVM_ADDS",
40         "RVM_ADC",
41         "RVM_AND",
42         "RVM_BIC",
43         "RVM_CLZ",
44         "RVM_CMN",
45         "RVM_EOR",
46         "RVM_SUB",
47         "RVM_SUBS",
48         "RVM_SBC",
49         "RVM_MUL",
50         "RVM_MLS",
51         "RVM_MULS",
52         "RVM_NOT",
53         "RVM_DIV",
54         "RVM_DVS",
55         "RVM_DIVS",
56         "RVM_BL",
57         "RVM_B",
58         "RVM_STR",
59         "RVM_STRP",
60         "RVM_STRB",
61         "RVM_STRH",
62         "RVM_STRW",
63         "RVM_STRR",
64         "RVM_LDR",
65         "RVM_LDRP",
66         "RVM_LDRB",
67         "RVM_LDRH",
68         "RVM_LDRW",
69         "RVM_LDRR",
70         "RVM_LSL",
71         "RVM_LSR",
72         "RVM_STM",
73         "RVM_LDM",
74         "RVM_STS",
75         "RVM_LDS",
76         "RVM_ORR",
77         "RVM_PUSH",
78         "RVM_POP",
79         "RVM_CMP",
80         "RVM_NOP",
81         "RVM_BEQ",
82         "RVM_BNEQ",
83         "RVM_BLEQ",
84         "RVM_BGEQ",
85         "RVM_BLES",
86         "RVM_BGRE",
87         "RVM_RET",
88         "RVM_ROR",
89         "RVM_PUSHM",
90         "RVM_POPM",     
91         "RVM_TST",      
92         "RVM_TEQ",
93         "ERVM_CAST",            /* Cast: op1 = (op3)op2 */
94         "ERVM_TYPE",            /* Type: op1 = typeof(op2) */
95         "ERVM_MOV",
96 };
97
98
99 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
100 {
101         RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
102 }
103
104
105 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
106 {
107         if ((cpu->status & RVM_STATUS_Z))
108                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
109 }
110
111
112 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
113 {
114         if ((cpu->status & RVM_STATUS_Z) == 0)
115                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
116 }
117
118
119 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
120 {
121         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z))
122                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
123 }
124
125 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
126 {
127         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1)
128                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
129 }
130
131
132 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
133 {
134         if ((cpu->status & RVM_STATUS_N))
135                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
136 }
137
138
139 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
140 {
141         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0)
142                 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETU(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
143 }
144
145
146 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
147 {
148         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
149         RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
150 }
151
152
153 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
154 {
155
156 }
157
158
159 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
160 {
161         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
162 }
163
164
165 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
166 {
167         RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
168         
169 }
170
171
172 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
173 {
174         RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
175 }
176
177
178 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
179 {
180         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
181 }
182
183
184 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
185 {
186         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
187 }
188
189
190 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
191 {
192         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
193 }
194
195
196 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
197 {
198         RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
199 }
200
201
202 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
203 {
204         *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
205 }
206
207
208 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
209 {
210         *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
211 }
212
213
214 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
215 {
216         *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
217 }
218
219
220 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
221 {
222         *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
223         
224 }
225
226
227 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
228 {
229         *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
230
231 }
232
233
234 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
235 {
236         *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)) = RVM_CPUREG_GET(cpu, ins->op1);
237 }
238
239
240 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
241 {
242         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
243         
244         res = op2 + op3;
245         RVM_CPUREG_SETU(cpu, ins->op1, res);
246         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
247         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
248         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
249         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
250                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
251 }
252
253
254 static void rvm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
255 {
256         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
257         
258         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
259         RVM_CPUREG_SETU(cpu, ins->op1, res);
260         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
261         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
262         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
263         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
264                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
265 }
266
267
268 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
269 {
270         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
271         
272         res = op2 & op3;
273         RVM_CPUREG_SETU(cpu, ins->op1, res);
274         RVM_STATUS_CLRALL(cpu);
275         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
276         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
277 }
278
279
280 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
281 {
282         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
283         
284         res = op2 | op3;
285         RVM_CPUREG_SETU(cpu, ins->op1, res);
286         RVM_STATUS_CLRALL(cpu);
287         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
288         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
289 }
290
291
292 static void rvm_op_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
293 {
294         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
295         
296         res = op2 << op3;
297         RVM_CPUREG_SETU(cpu, ins->op1, res);
298         RVM_STATUS_CLRALL(cpu);
299         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
300         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
301 }
302
303
304 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
305 {
306         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
307         
308         res = op2 >> op3;
309         RVM_CPUREG_SETU(cpu, ins->op1, res);
310         RVM_STATUS_CLRALL(cpu);
311         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
312 }
313
314
315 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
316 {
317         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
318         
319         res = op2 >> op3;
320         res |= op2 & RVM_SIGN_BIT;
321         RVM_CPUREG_SETU(cpu, ins->op1, res);
322         RVM_STATUS_CLRALL(cpu);
323         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
324         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
325 }
326
327
328 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
329 {
330         ruint i;
331         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
332         
333         res = op2;
334         for (i = 0; i < op3; i++) {
335                 if (res & 1) {
336                         res >>= 1;
337                         res |= RVM_SIGN_BIT;
338                 } else {
339                         res >>= 1;
340                 }
341         }
342         RVM_CPUREG_SETU(cpu, ins->op1, res);
343         RVM_STATUS_CLRALL(cpu);
344         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
345         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
346         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
347 }
348
349
350 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
351 {
352         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
353         
354         res = op2 & op3;
355         RVM_STATUS_CLRALL(cpu);
356         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
357         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
358 }
359
360
361 static void rvm_op_eor(rvmcpu_t *cpu, rvm_asmins_t *ins)
362 {
363         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
364         
365         res = op2 ^ op3;
366         RVM_CPUREG_SETU(cpu, ins->op1, res);
367         RVM_STATUS_CLRALL(cpu);
368         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
369         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
370 }
371
372
373 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
374 {
375         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
376         
377         res = ~op2;
378         RVM_CPUREG_SETU(cpu, ins->op1, res);
379         RVM_STATUS_CLRALL(cpu);
380         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
381         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
382 }
383
384
385 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
386 {
387         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
388         
389         res = op2 ^ op3;
390         RVM_STATUS_CLRALL(cpu);
391         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
392         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
393 }
394
395
396 static void rvm_op_bic(rvmcpu_t *cpu, rvm_asmins_t *ins)
397 {
398         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
399         
400         res = op2 & ~op3;
401         RVM_CPUREG_SETU(cpu, ins->op1, res);
402         RVM_STATUS_CLRALL(cpu);
403         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
404         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
405 }
406
407
408 static void rvm_op_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
409 {
410         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
411         
412         for (res = RVM_REGISTER_BITS; op2; ) {
413                 op2 >>= 1;
414                 res -= 1;
415         }
416         RVM_CPUREG_SETU(cpu, ins->op1, res);
417 }
418
419
420 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
421 {
422         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
423 }
424
425
426 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
427 {
428 //      rvmcpu_swi *cbt = cpu->switable[RVM_CB_TABLE(RVM_CPUREG_GETU(cpu, ins->op1))];
429 //      cbt[RVM_CB_OFFSET(RVM_CPUREG_GETU(cpu, ins->op1))](cpu);
430
431         rvmcpu_swi swi;
432         rvm_switable_t *switable;
433         ruint ntable = (ruint) RVM_SWI_TABLE(RVM_CPUREG_GETU(cpu, ins->op1));
434         ruint nswi = (ruint) RVM_SWI_NUM(RVM_CPUREG_GETU(cpu, ins->op1));
435
436         if (r_array_size(cpu->switables) <= ntable)
437                 RVM_ABORT(cpu, RVM_E_SWITABLE);
438         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
439         swi = switable[nswi].op;
440         swi(cpu, ins);
441 }
442
443
444 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
445 {
446         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
447 }
448
449
450 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
451 {
452         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
453         
454         res = op2 - op3;
455         RVM_CPUREG_SETU(cpu, ins->op1, res);
456         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
457         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
458         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
459         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
460                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
461 }
462
463
464 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
465 {
466         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
467
468         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
469         RVM_CPUREG_SETU(cpu, ins->op1, res);
470         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
471         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
472         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
473         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
474                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
475 }
476
477
478 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
479 {
480         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
481 }
482
483
484 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
485 {
486         rsword res;
487         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
488
489         res = (rsword)(op2 * op3);
490         RVM_CPUREG_SETU(cpu, ins->op1, res);
491         /* TBD: Not sure how to update the RVM_STATUS_C */
492         RVM_STATUS_CLRALL(cpu);
493         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
494         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
495 }
496
497
498 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
499 {
500         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
501         
502         res = op2 * op3;
503         RVM_CPUREG_SETU(cpu, ins->op1, res);
504         RVM_STATUS_CLRALL(cpu);
505         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
506         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
507         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
508 }
509
510
511 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
512 {
513         if (!RVM_CPUREG_GETU(cpu, ins->op3))
514                 RVM_ABORT(cpu, RVM_E_DIVZERO);
515
516         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
517 }
518
519
520 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
521 {
522         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
523
524         if (!op3)
525                 RVM_ABORT(cpu, RVM_E_DIVZERO);
526         res = op2 / op3;
527         RVM_CPUREG_SETU(cpu, ins->op1, res);
528         RVM_STATUS_CLRALL(cpu);
529         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
530         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
531 }
532
533
534 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
535 {
536         rsword res;
537         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
538
539         if (!op3)
540                 RVM_ABORT(cpu, RVM_E_DIVZERO);
541         res = (rsword)(op2 / op3);
542         RVM_CPUREG_SETU(cpu, ins->op1, res);
543         RVM_STATUS_CLRALL(cpu);
544         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
545         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
546 }
547
548
549 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
550 {
551         rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
552
553         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
554         RVM_CPUREG_SETU(cpu, SP, sp);
555 }
556
557
558 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
559 {
560         rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
561
562         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
563 }
564
565
566 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
567 {
568         int n, i;
569         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
570         rword sp = RVM_CPUREG_GETU(cpu, SP);
571
572         for (i = 0, n = 0; bits && n < RLST; n++) {
573                 if (((rword)(1 << n)) & bits) {
574                         i += 1;
575                         sp += 1;
576                         r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, n));
577                         bits &= ~(1<<n);
578                 }
579         }
580         RVM_CPUREG_SETU(cpu, SP, RVM_CPUREG_GETU(cpu, SP) + i);
581 }
582
583
584 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
585 {
586         rword sp = RVM_CPUREG_GETU(cpu, SP);
587
588         RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
589         if (ins->op1 != SP)
590                 RVM_CPUREG_SETU(cpu, SP, sp - 1);
591 }
592
593
594 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
595 {
596         int n;
597         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
598         rword sp = RVM_CPUREG_GETU(cpu, SP);
599
600         for (n = RLST - 1; bits && n >= 0; n--) {
601                 if (((rword)(1 << n)) & bits) {
602                         RVM_CPUREG_SET(cpu, n, r_array_index(cpu->stack, sp, rvmreg_t));
603                         sp -= 1;
604                         bits &= ~(1<<n);
605                 }
606         }
607         if (!(((rword)(1 << SP)) & bits))
608                 RVM_CPUREG_SETU(cpu, SP, sp);
609 }
610
611
612 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
613 {
614         rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
615
616         RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
617 }
618
619
620 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
621 {
622         int n;
623         rword *dst = (rword*)   RVM_CPUREG_GETU(cpu, ins->op1);
624         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
625         
626         for (n = 0; bits && n < RLST; n++) {
627                 if (((rword)(1 << n)) & bits) {
628                         *dst = RVM_CPUREG_GETU(cpu, n);
629                         dst += 1;
630                         bits &= ~(1<<n);
631                 }
632         }
633 }
634
635
636 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
637 {
638         int n;
639         rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
640         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
641
642         for (n = 0; bits && n < RLST; n++) {
643                 if (((rword)(1 << n)) & bits) {
644                         RVM_CPUREG_SETU(cpu, n, *src);
645                         src += 1;
646                         bits &= ~(1<<n);
647                 }
648         }
649 }
650
651
652 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
653 {
654         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
655         rword res = (rword)(op1 - op2);
656         
657         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
658         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
659         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
660         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
661                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
662 }
663
664
665 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
666 {
667         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
668         rword res = (rword)(op1 + op2);
669         
670         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
671         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
672         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
673         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
674                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
675
676 }
677
678
679 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
680 {
681 //      fprintf(stdout, "nop\n");
682 }
683
684
685 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
686 {
687         RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));     
688 }
689
690
691
692 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
693 {
694         return vsnprintf(str, size, format, ap);
695 }
696
697
698 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
699 {
700         va_list ap;
701         int ret;
702
703         va_start(ap, format);
704         ret = rvm_vsnprintf(str, size, format, ap);
705         va_end(ap);
706         return ret;
707 }
708
709
710 static int rvm_printf(const char *format, ...)
711 {
712         va_list ap;
713         int ret;
714
715         va_start(ap, format);
716         ret = vfprintf(stdout, format, ap);
717         va_end(ap);
718         return ret;
719 }
720
721
722 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
723 {
724         int ret = 0;
725
726         if (reg == XX)
727                 ret = rvm_snprintf(str, size, "XX ");
728         else if (reg == FP)
729                 ret = rvm_snprintf(str, size, "FP ");
730         else if (reg == SP)
731                 ret = rvm_snprintf(str, size, "SP ");
732         else if (reg == LR)
733                 ret = rvm_snprintf(str, size, "LR ");
734         else if (reg == PC)
735                 ret = rvm_snprintf(str, size, "PC ");
736         else if (reg == DA)
737                 ret = rvm_snprintf(str, size, "DA ");
738         else if (reg >= 0 && reg < 10)
739                 ret = rvm_snprintf(str, size, "R%d ",  reg);
740         else if (reg >= 10)
741                 ret = rvm_snprintf(str, size, "R%d",  reg);
742
743         return ret;
744 }
745
746
747 int rvm_asm_dump_pi_to_str(rvm_asmins_t *pi, char *str, ruint size)
748 {
749         int ret = 0, sz = size;
750
751         if ((ret = rvm_snprintf(str, sz, "%10s   ", stropcalls[pi->opcode])) < 0)
752                 return ret;
753         str += ret;
754         sz -= ret;
755         
756         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
757                 return ret;
758         str += ret;
759         sz -= ret;
760                 
761         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
762                 return ret;
763         str += ret;
764         sz -= ret;
765
766         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
767                 return ret;
768         str += ret;
769         sz -= ret;
770                 
771         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
772                 return ret;
773         str += ret;
774         sz -= ret;
775
776         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
777                 return ret;
778         str += ret;
779         sz -= ret;
780                 
781         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
782                 return ret;
783         str += ret;
784         sz -= ret;
785
786 //      if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)RVM_REG_GETU(&pi->data))) < 0)
787 //              return ret;
788         if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)pi->data)) < 0)
789                 return ret;
790
791
792         str += ret;
793         sz -= ret;
794
795         return size - sz;
796 }
797
798
799 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
800 {
801         char buffer[256];
802         while (count) {
803                 rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
804                 rvm_printf("%s\n", buffer);
805                 ++pi;
806                 --count;
807         }
808 }
809
810
811 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
812 {
813     int ret;
814         char buffer[1024];
815         
816         ret = rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
817         if (ret < 0)
818                 return;
819     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
820         buffer[50] = '\0';
821         rvm_printf("%s", buffer);
822
823         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 )",
824                 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
825                 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
826                 RVM_CPUREG_GETU(vm, 8), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
827                 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
828                 vm->status & RVM_STATUS_V ? 'V' : '_',
829                 vm->status & RVM_STATUS_C ? 'C' : '_',
830                 vm->status & RVM_STATUS_N ? 'N' : '_',
831                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
832         rvm_printf("\n");
833 }
834
835
836 static void ervm_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
837 {
838         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
839         rvmreg_t tmp;
840
841         RVM_REG_CLEAR(&tmp);
842         RVM_REG_SETTYPE(&tmp, type);
843         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
844 }
845
846
847 static void ervm_op_type(rvmcpu_t *cpu, rvm_asmins_t *ins)
848 {
849         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETTYPE(cpu, ins->op2);
850
851         RVM_CPUREG_CLEAR(cpu, ins->op1);
852         RVM_CPUREG_SETU(cpu, ins->op1, type);
853 }
854
855
856 static void ervm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
857 {
858         rvm_op_mov(cpu, ins);
859 }
860
861
862 static void ervm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
863 {
864         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
865
866         res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
867         RVM_CPUREG_SETU(cpu, ins->op1, res);
868         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
869         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
870         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
871         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
872                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
873 }
874
875
876 static void ervm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
877 {
878         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
879
880         res = op2 + op3;
881         RVM_CPUREG_SETU(cpu, ins->op1, res);
882         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
883         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
884         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
885         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
886                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
887 }
888
889
890 static void ervm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
891 {
892         rvmreg_type_t type;
893         rvmreg_t *r2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
894         rvmreg_t *r3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
895
896         type = RVM_REG_GETTYPE(r2);
897
898
899         if (type != RVM_REG_GETTYPE(r3))
900                 RVM_ABORT(cpu, RVM_E_CAST);
901
902         switch (type) {
903         case RVM_DTYPE_UNSIGNED:
904                 RVM_CPUREG_SETU(cpu, ins->op1, RVM_REG_GETU(r2) + RVM_REG_GETU(r2));
905                 RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_NONE);
906                 RVM_CPUREG_CLRFLAG(cpu, ins->op1, RVM_INFOBIT_ROBJECT);
907                 break;
908         case RVM_DTYPE_LONG:
909                 RVM_CPUREG_SETU(cpu, ins->op1, RVM_REG_GETL(r2) + RVM_REG_GETL(r2));
910                 RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_LONG);
911                 RVM_CPUREG_CLRFLAG(cpu, ins->op1, RVM_INFOBIT_ROBJECT);
912                 break;
913         case RVM_DTYPE_DOUBLE:
914                 RVM_CPUREG_SETD(cpu, ins->op1, RVM_REG_GETD(r2) + RVM_REG_GETD(r2));
915                 RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_DOUBLE);
916                 RVM_CPUREG_CLRFLAG(cpu, ins->op1, RVM_INFOBIT_ROBJECT);
917                 break;
918         default:
919                 RVM_ABORT(cpu, RVM_E_CAST);
920         };
921 }
922
923
924 static void ervm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
925 {
926         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
927
928         res = op2 & op3;
929         RVM_CPUREG_SETU(cpu, ins->op1, res);
930         RVM_STATUS_CLRALL(cpu);
931         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
932         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
933 }
934
935
936 static void ervm_op_eor(rvmcpu_t *cpu, rvm_asmins_t *ins)
937 {
938         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
939
940         res = op2 ^ op3;
941         RVM_CPUREG_SETU(cpu, ins->op1, res);
942         RVM_STATUS_CLRALL(cpu);
943         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
944         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
945 }
946
947
948 static void ervm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
949 {
950         rsword res;
951         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
952
953         res = (rsword)(op2 * op3);
954         RVM_CPUREG_SETU(cpu, ins->op1, res);
955         /* TBD: Not sure how to update the RVM_STATUS_C */
956         RVM_STATUS_CLRALL(cpu);
957         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
958         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
959 }
960
961
962 static void ervm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
963 {
964         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
965 }
966
967
968 static void ervm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
969 {
970         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
971
972         res = op2 * op3;
973         RVM_CPUREG_SETU(cpu, ins->op1, res);
974         RVM_STATUS_CLRALL(cpu);
975         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
976         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
977         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
978 }
979
980
981 static void ervm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
982 {
983         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
984 }
985
986
987 static void ervm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
988 {
989         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
990
991         res = op2 - op3;
992         RVM_CPUREG_SETU(cpu, ins->op1, res);
993         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
994         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
995         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
996         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
997                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
998 }
999
1000
1001 static void ervm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
1002 {
1003         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
1004
1005         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
1006         RVM_CPUREG_SETU(cpu, ins->op1, res);
1007         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
1008         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
1009         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
1010         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
1011                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
1012 }
1013
1014
1015 static void ervm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
1016 {
1017         if (!RVM_CPUREG_GETU(cpu, ins->op3))
1018                 RVM_ABORT(cpu, RVM_E_DIVZERO);
1019
1020         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
1021 }
1022
1023
1024 static void ervm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
1025 {
1026         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
1027
1028         if (!op3)
1029                 RVM_ABORT(cpu, RVM_E_DIVZERO);
1030         res = op2 / op3;
1031         RVM_CPUREG_SETU(cpu, ins->op1, res);
1032         RVM_STATUS_CLRALL(cpu);
1033         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
1034         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
1035 }
1036
1037
1038 static void ervm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
1039 {
1040         rsword res;
1041         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
1042
1043         if (!op3)
1044                 RVM_ABORT(cpu, RVM_E_DIVZERO);
1045         res = (rsword)(op2 / op3);
1046         RVM_CPUREG_SETU(cpu, ins->op1, res);
1047         RVM_STATUS_CLRALL(cpu);
1048         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
1049         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
1050 }
1051
1052
1053 static rvm_cpu_op ops[] = {
1054         rvm_op_exit,            // RVM_EXT
1055         rvm_op_asr,                     // RVM_ASR
1056         rvm_op_swi,                     // RVM_swi
1057         rvm_op_mov,                     // RVM_MOV
1058         rvm_op_add,                     // RVM_ADD
1059         rvm_op_adds,            // RVM_ADDS
1060         rvm_op_adc,                     // RVM_ADC
1061         rvm_op_and,                     // RVM_AND
1062         rvm_op_bic,                     // RVM_BIC
1063         rvm_op_clz,                     // RVM_CLZ
1064         rvm_op_cmn,                     // RVM_CMN
1065         rvm_op_eor,                     // RVM_EOR
1066         rvm_op_sub,                     // RVM_SUB
1067         rvm_op_subs,            // RVM_SUBS
1068         rvm_op_sbc,                     // RVM_SBC
1069         rvm_op_mul,                     // RVM_MUL
1070         rvm_op_mls,                     // RVM_MLS
1071         rvm_op_muls,            // RVM_MULS
1072         rvm_op_not,                     // RVM_NOT
1073         rvm_op_div,                     // RVM_DIV
1074         rvm_op_dvs,                     // RVM_DVS
1075         rvm_op_divs,            // RVM_DIVS
1076         rvm_op_bl,                      // RVM_BL
1077         rvm_op_b,                       // RVM_B
1078         rvm_op_str,                     // RVM_STR
1079         rvm_op_strp,            // RVM_STRP
1080         rvm_op_strb,            // RVM_STRB
1081         rvm_op_strh,            // RVM_STRH
1082         rvm_op_strw,            // RVM_STRW
1083         rvm_op_strr,            // RVM_STRR
1084         rvm_op_ldr,                     // RVM_LDR
1085         rvm_op_ldrp,            // RVM_LDRP
1086         rvm_op_ldrb,            // RVM_LDRB
1087         rvm_op_ldrh,            // RVM_LDRH
1088         rvm_op_ldrw,            // RVM_LDRW
1089         rvm_op_ldrr,            // RVM_LDRR
1090         rvm_op_lsl,                     // RVM_LSL
1091         rvm_op_lsr,                     // RVM_LSR
1092         rvm_op_stm,                     // RVM_STM
1093         rvm_op_ldm,                     // RVM_LDS
1094         rvm_op_sts,                     // RVM_STS
1095         rvm_op_lds,                     // RVM_LDM
1096         rvm_op_orr,                     // RVM_ORR
1097         rvm_op_push,            // RVM_PUSH
1098         rvm_op_pop,                     // RVM_POP
1099         rvm_op_cmp,                     // RVM_CMP
1100         rvm_op_nop,                     // RVM_NOP
1101         rvm_op_beq,                     // RVM_BEQ
1102         rvm_op_bneq,            // RVM_BNEQ
1103         rvm_op_bleq,            // RVM_BLEQ
1104         rvm_op_bgeq,            // RVM_BGEQ
1105         rvm_op_bles,            // RVM_BLES
1106         rvm_op_bgre,            // RVM_BGRE
1107         rvm_op_ret,                     // RVM_RET
1108         rvm_op_ror,                     // RVM_ROR
1109         rvm_op_pushm,           // RVM_PUSHM
1110         rvm_op_popm,            // RVM_POPM
1111         rvm_op_tst,             // RVM_TST
1112         rvm_op_teq,             // RVM_TEQ
1113
1114 /* Extended VM instructions */
1115         ervm_op_cast,           // ERVM_CAST
1116         ervm_op_type,           // ERVM_TYPE
1117         ervm_op_mov,            // ERVM_MOV
1118         ervm_op_add,            // ERVM_ADD
1119         ervm_op_adds,           // ERVM_ADDS
1120         ervm_op_adc,            // ERVM_ADC
1121         ervm_op_and,            // ERVM_AND
1122         ervm_op_eor,            // ERVM_EOR
1123         ervm_op_sub,            // ERVM_SUB
1124         ervm_op_subs,           // ERVM_SUBS
1125         ervm_op_sbc,            // ERVM_SBC
1126         ervm_op_mul,            // ERVM_MUL
1127         ervm_op_mls,            // ERVM_MLS
1128         ervm_op_muls,           // ERVM_MULS
1129         ervm_op_div,            // RVM_DIV
1130         ervm_op_dvs,            // RVM_DVS
1131         ervm_op_divs,           // RVM_DIVS
1132         (void*) 0,
1133         (void*) 0,
1134         (void*) 0,
1135         (void*) 0,
1136         (void*) 0,
1137         (void*) 0,
1138         (void*) 0,
1139         (void*) 0,
1140         
1141 };
1142         
1143
1144 rvmcpu_t *rvm_cpu_create()
1145 {
1146         rvmcpu_t *cpu;
1147
1148         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1149         if (!cpu)
1150                 return ((void*)0);
1151         r_memset(cpu, 0, sizeof(*cpu));
1152         cpu->switables = r_array_create(sizeof(rvm_switable_t*));
1153         cpu->stack = r_array_create(sizeof(rvmreg_t));
1154         cpu->opmap = rvm_opmap_create();
1155         rvm_op_cast_init(cpu->opmap);
1156         return cpu;
1157 }
1158
1159
1160 void rvm_cpu_destroy(rvmcpu_t *cpu)
1161 {
1162 //      rvm_free(cpu->stack);
1163         r_array_destroy(cpu->switables);
1164         r_array_destroy(cpu->stack);
1165         rvm_opmap_destroy(cpu->opmap);
1166         r_free(cpu);
1167 }
1168
1169
1170 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1171 {
1172         rvm_asmins_t *pi;
1173
1174         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1175         cpu->abort = 0;
1176         cpu->error = 0;
1177         do {
1178                 pi = RVM_CPUREG_GETIP(cpu, PC);
1179                 RVM_CPUREG_SETU(cpu, DA, pi->data);
1180                 ops[pi->opcode](cpu, pi);
1181 #ifdef DEBUG
1182                 if (RVM_CPUREG_GETTYPE(cpu, DA) || RVM_CPUREG_TSTFLAG(cpu, DA, RVM_INFOBIT_ALL))
1183                         RVM_ABORT(cpu, RVM_E_ILLEGAL);
1184 #endif
1185                 if (cpu->abort)
1186                         return -1;
1187                 RVM_CPUREG_INCIP(cpu, PC, 1);
1188         } while (pi->opcode);
1189         return 0;
1190 }
1191
1192
1193 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1194 {
1195         rvm_asmins_t *pi;
1196
1197         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1198         cpu->abort = 0;
1199         cpu->error = 0;
1200         do {
1201                 pi = RVM_CPUREG_GETIP(cpu, PC);
1202                 RVM_CPUREG_CLEAR(cpu, DA);
1203                 RVM_CPUREG_SETU(cpu, DA, pi->data);
1204                 ops[pi->opcode](cpu, pi);
1205 #ifdef DEBUG
1206                 if (RVM_CPUREG_GETTYPE(cpu, DA) || RVM_CPUREG_TSTFLAG(cpu, DA, RVM_INFOBIT_ALL))
1207                         RVM_ABORT(cpu, RVM_E_ILLEGAL);
1208 #endif
1209                 if (cpu->abort)
1210                         return -1;
1211                 rvm_cpu_dumpregs(pi, cpu);              
1212                 RVM_CPUREG_INCIP(cpu, PC, 1);
1213         } while (pi->opcode);
1214         return 0;
1215 }
1216
1217
1218 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname)
1219 {
1220         rint ntable, nswi;
1221         rvm_switable_t *swientry;
1222
1223         for (ntable = 0; ntable < cpu->switables->len; ntable++) {
1224                 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
1225                 for (nswi = 0; swientry[nswi].name; nswi++) {
1226                         if (r_strcmp(swientry[nswi].name, swiname) == 0)
1227                                 return (rint)RVM_SWI_ID(ntable, nswi);
1228                 }
1229         }
1230
1231         return -1;
1232 }
1233
1234
1235 rint rvmcpu_switable_add(rvmcpu_t *cpu, rvm_switable_t *switable)
1236 {
1237         rint nswi;
1238
1239         for (nswi = 0; switable[nswi].name; nswi++) {
1240                 if (rvm_cpu_getswi(cpu, switable[nswi].name) >= 0)
1241                         return -1;
1242         }
1243
1244         return r_array_add(cpu->switables, &switable);
1245 }
1246
1247
1248 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
1249 {
1250         rvm_asmins_t a;
1251
1252         r_memset(&a, 0, sizeof(a));
1253         a.opcode = (unsigned char) opcode;
1254         a.op1 = (unsigned char)op1;
1255         a.op2 = (unsigned char)op2;
1256         a.op3 = (unsigned char)op3;
1257         a.data = (rword)data;
1258
1259 //      RVM_REG_GETP(&a.data) = data;
1260 //      RVM_REG_SETTYPE(&a.data, RVM_DTYPE_POINTER);
1261         return a;
1262 }
1263
1264
1265 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1266 {
1267         rvm_asmins_t a;
1268
1269         r_memset(&a, 0, sizeof(a));
1270         a.opcode = (unsigned char) opcode;
1271         a.op1 = (unsigned char)op1;
1272         a.op2 = (unsigned char)op2;
1273         a.op3 = (unsigned char)op3;
1274         a.data = (rword)data;
1275
1276 //      RVM_REG_GETU(&a.data) = data;
1277 //      RVM_REG_SETTYPE(&a.data, RVM_DTYPE_WORD);
1278         return a;
1279 }
1280
1281
1282 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1283 {
1284         rvm_asmins_t a;
1285
1286         r_memset(&a, 0, sizeof(a));
1287         a.opcode = (unsigned char) opcode;
1288         a.op1 = (unsigned char)op1;
1289         a.op2 = (unsigned char)op2;
1290         a.op3 = (unsigned char)op3;
1291         a.data = (rword)data;
1292
1293 //      RVM_REG_GETL(&a.data) = (rword)data;
1294 //      RVM_REG_SETTYPE(&a.data, RVM_DTYPE_LONG);
1295         return a;
1296 }
1297
1298
1299
1300 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1301 {
1302         rvm_asmins_t a;
1303
1304         r_memset(&a, 0, sizeof(a));
1305         a.opcode = (unsigned char) opcode;
1306         a.op1 = (unsigned char)op1;
1307         a.op2 = (unsigned char)op2;
1308         a.op3 = (unsigned char)op3;
1309         a.data = (rword)pReloc;
1310         a.flags = RVM_ASMINS_RELOC | RVM_ASMINS_RELOCPTR;
1311
1312 //      RVM_REG_GETP(&a.data) = pReloc;
1313 //      RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCPTR);
1314         return a;
1315 }
1316
1317
1318 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1319 {
1320         rvm_asmins_t a;
1321
1322         r_memset(&a, 0, sizeof(a));
1323         a.opcode = (unsigned char) opcode;
1324         a.op1 = (unsigned char)op1;
1325         a.op2 = (unsigned char)op2;
1326         a.op3 = (unsigned char)op3;
1327         a.data = (rword)pReloc;
1328         a.flags = RVM_ASMINS_RELOC;
1329
1330 //      RVM_REG_GETP(&a.data) = pReloc;
1331 //      RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCINDEX);
1332         return a;
1333 }
1334
1335
1336 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1337 {
1338         rvm_asmins_t *reloc;
1339         rulong relocindex;
1340         rulong off;
1341
1342         for (off = 0; off < size; off++, code++) {
1343                 if (code->flags & RVM_ASMINS_RELOC) {
1344                         if (code->flags & RVM_ASMINS_RELOCPTR) {
1345                                 reloc = *((rvm_asmins_t **)code->data);
1346                                 code->data = reloc - code;
1347                         } else {
1348                                 relocindex = *((rulong *)code->data);
1349                                 code->data = relocindex - off;
1350                         }
1351                         code->flags &= ~(RVM_ASMINS_RELOCPTR | RVM_ASMINS_RELOC);
1352                 }
1353         }
1354 }
1355