RPA Toolkit
implemented conditional expressions and fixes
[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 <stdarg.h>
23 #include "rvmcpu.h"
24 #include "rvmoperator.h"
25 #include "rvmoperatorbin.h"
26 #include "rvmoperatorcast.h"
27 #include "rvmoperatornot.h"
28 #include "rvmoperatorlogicnot.h"
29 #include "rmem.h"
30 #include "rstring.h"
31 #include "rvmreg.h"
32
33
34 static const char *stropcalls[] = {
35         "RVM_EXT",
36         "RVM_ABORT",
37         "RVM_PRN",
38         "RVM_ASR",
39         "RVM_SWI",
40         "RVM_SWIID",
41         "RVM_CALL",
42         "RVM_MOV",
43         "RVM_INC",
44         "RVM_DEC",
45         "RVM_ADD",
46         "RVM_ADDS",
47         "RVM_ADC",
48         "RVM_AND",
49         "RVM_BIC",
50         "RVM_CLZ",
51         "RVM_CMN",
52         "RVM_XOR",
53         "RVM_SUB",
54         "RVM_SUBS",
55         "RVM_SBC",
56         "RVM_MUL",
57         "RVM_MLS",
58         "RVM_MULS",
59         "RVM_NOT",
60         "RVM_DIV",
61         "RVM_DVS",
62         "RVM_DIVS",
63         "RVM_MOD",
64         "RVM_MODS",
65         "RVM_BX",
66         "RVM_BL",
67         "RVM_B",
68         "RVM_STR",
69         "RVM_STRP",
70         "RVM_STRB",
71         "RVM_STRH",
72         "RVM_STRW",
73         "RVM_STRR",
74         "RVM_LDR",
75         "RVM_LDRP",
76         "RVM_LDRB",
77         "RVM_LDRH",
78         "RVM_LDRW",
79         "RVM_LDRR",
80         "RVM_CLRR",
81         "RVM_LSL",
82         "RVM_LSR",
83         "RVM_LSRS",
84         "RVM_STM",
85         "RVM_LDM",
86         "RVM_STS",
87         "RVM_LDS",
88         "RVM_ORR",
89         "RVM_PUSH",
90         "RVM_POP",
91         "RVM_CMP",
92         "RVM_NOP",
93         "RVM_BEQ",
94         "RVM_BNEQ",
95         "RVM_BLEQ",
96         "RVM_BGEQ",
97         "RVM_BLES",
98         "RVM_BGRE",
99         "RVM_RET",
100         "RVM_ROR",
101         "RVM_PUSHM",
102         "RVM_POPM",     
103         "RVM_TST",
104         "RVM_TEQ",
105         "RVM_CLR",
106         "RVM_ADDRS",
107
108         "RVM_CAST",             /* Cast: op1 = (op3)op2 */
109         "RVM_TYPE",             /* Type: op1 = typeof(op2) */
110         "RVM_SETTYPE",  /* Type: op1.type = op2 */
111         "RVM_EMOV",
112         "RVM_EADD",
113         "RVM_ESUB",
114         "RVM_EMUL",
115         "RVM_EDIV",
116         "RVM_EMOD",
117         "RVM_ELSL",
118         "RVM_ELSR",
119         "RVM_ELSRU",
120         "RVM_EAND",
121         "RVM_EORR",
122         "RVM_EXOR",
123         "RVM_ENOT",
124         "RVM_ELAND",
125         "RVM_ELOR",
126         "RVM_ELNOT",
127         "RVM_EEQ",
128         "RVM_ENOTEQ",
129         "RVM_EGREAT",
130         "RVM_EGREATEQ",
131         "RVM_ELESS",
132         "RVM_ELESSEQ",
133         "RVM_ECMP",
134         "RVM_ECMN",
135         "RVM_ALLOCSTR",
136         "RVM_ALLOCARR",
137         "RVM_ADDRA",
138         "RVM_ELDA",
139         "RVM_ESTA",
140         "UNKNOWN",
141         "UNKNOWN",
142         "UNKNOWN",
143         "UNKNOWN",
144         "UNKNOWN",
145         "UNKNOWN",
146         "UNKNOWN",
147         "UNKNOWN",
148         "UNKNOWN",
149         "UNKNOWN",
150         "UNKNOWN",
151 };
152
153
154 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
155 {
156         rword pc = 0;
157
158         if (ins->op1 != XX)
159                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
160         if (ins->op2 != XX)
161                 pc += RVM_CPUREG_GETU(cpu, ins->op2);
162         if (ins->op3 != XX)
163                 pc += RVM_CPUREG_GETU(cpu, ins->op3);
164         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
165 }
166
167
168 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
169 {
170         rword pc = 0;
171
172         if ((cpu->status & RVM_STATUS_Z)) {
173                 if (ins->op1 != XX)
174                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
175                 if (ins->op2 != XX)
176                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
177                 if (ins->op3 != XX)
178                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
179                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
180         }
181 }
182
183
184 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
185 {
186         rword pc = 0;
187
188         if ((cpu->status & RVM_STATUS_Z) == 0) {
189                 if (ins->op1 != XX)
190                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
191                 if (ins->op2 != XX)
192                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
193                 if (ins->op3 != XX)
194                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
195                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
196         }
197 }
198
199
200 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
201 {
202         rword pc = 0;
203
204         if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)) {
205                 if (ins->op1 != XX)
206                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
207                 if (ins->op2 != XX)
208                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
209                 if (ins->op3 != XX)
210                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
211                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
212         }
213 }
214
215 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
216 {
217         rword pc = 0;
218
219         if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1){
220                 if (ins->op1 != XX)
221                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
222                 if (ins->op2 != XX)
223                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
224                 if (ins->op3 != XX)
225                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
226                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
227         }
228 }
229
230
231 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
232 {
233         rword pc = 0;
234
235
236         if ((cpu->status & RVM_STATUS_N)){
237                 if (ins->op1 != XX)
238                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
239                 if (ins->op2 != XX)
240                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
241                 if (ins->op3 != XX)
242                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
243                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
244         }
245 }
246
247
248 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
249 {
250         rword pc = 0;
251
252         if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0) {
253                 if (ins->op1 != XX)
254                         pc += RVM_CPUREG_GETU(cpu, ins->op1);
255                 if (ins->op2 != XX)
256                         pc += RVM_CPUREG_GETU(cpu, ins->op2);
257                 if (ins->op3 != XX)
258                         pc += RVM_CPUREG_GETU(cpu, ins->op3);
259                 RVM_CPUREG_INCIP(cpu, PC, pc - 1);
260         }
261 }
262
263
264 static void rvm_op_bx(rvmcpu_t *cpu, rvm_asmins_t *ins)
265 {
266         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
267 }
268
269
270 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
271 {
272         rword pc = 0;
273         if (ins->op1 != XX)
274                 pc += RVM_CPUREG_GETU(cpu, ins->op1);
275         if (ins->op2 != XX)
276                 pc += RVM_CPUREG_GETU(cpu, ins->op2);
277         if (ins->op3 != XX)
278                 pc += RVM_CPUREG_GETU(cpu, ins->op3);
279
280         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
281         RVM_CPUREG_INCIP(cpu, PC, pc - 1);
282 }
283
284
285 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
286 {
287         cpu->abort = 1;
288 }
289
290
291 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
292 {
293         RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
294 }
295
296
297 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
298 {
299         RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
300         
301 }
302
303
304 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
305 {
306         RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
307 }
308
309
310 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
311 {
312         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
313 }
314
315
316 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
317 {
318         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
319 }
320
321
322 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
323 {
324         RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
325 }
326
327
328 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
329 {
330         RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
331 }
332
333
334 static void rvm_op_clrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
335 {
336         rvm_reg_cleanup(((rvmreg_t*)RVM_CPUREG_GETP(cpu, ins->op1)));
337 }
338
339
340 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
341 {
342         *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
343 }
344
345
346 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
347 {
348         *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
349 }
350
351
352 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
353 {
354         *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
355 }
356
357
358 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
359 {
360         *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
361         
362 }
363
364
365 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
366 {
367         *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
368
369 }
370
371
372 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
373 {
374         rvmreg_t *dest = RVM_CPUREG_PTR(cpu, ins->op2);
375         if (RVM_REG_GETTYPE(dest) != RVM_DTYPE_POINTER)
376                 RVM_ABORT(cpu, RVM_E_LVALUE);
377         else
378                 *((rvmreg_t*)RVM_REG_GETP(dest)) = RVM_CPUREG_GET(cpu, ins->op1);
379 }
380
381
382 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
383 {
384         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
385
386         res = op2 + op3;
387         RVM_CPUREG_SETU(cpu, ins->op1, res);
388         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
389         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
390         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
391         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
392                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
393 }
394
395
396 static void rvm_op_adc(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 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
401         RVM_CPUREG_SETU(cpu, ins->op1, res);
402         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
403         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
404         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
405         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
406                                                         (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
407 }
408
409
410 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
411 {
412         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
413         
414         res = op2 & op3;
415         RVM_CPUREG_SETU(cpu, ins->op1, res);
416         RVM_STATUS_CLRALL(cpu);
417         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
418         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
419 }
420
421
422 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
423 {
424         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
425         
426         res = op2 | op3;
427         RVM_CPUREG_SETU(cpu, ins->op1, res);
428         RVM_STATUS_CLRALL(cpu);
429         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
430         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
431 }
432
433
434 static void rvm_op_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
435 {
436         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
437         
438         res = op2 << op3;
439         RVM_CPUREG_SETU(cpu, ins->op1, res);
440         RVM_STATUS_CLRALL(cpu);
441         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
442         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
443 }
444
445
446 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
447 {
448         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
449         
450         res = op2 >> op3;
451         RVM_CPUREG_SETU(cpu, ins->op1, res);
452         RVM_STATUS_CLRALL(cpu);
453         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
454 }
455
456
457 static void rvm_op_lsrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
458 {
459         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
460
461         res = ((rsword)op2) >> op3;
462         RVM_CPUREG_SETU(cpu, ins->op1, res);
463         RVM_STATUS_CLRALL(cpu);
464         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
465 }
466
467
468 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
469 {
470         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
471         
472         res = op2 >> op3;
473         res |= op2 & RVM_SIGN_BIT;
474         RVM_CPUREG_SETU(cpu, ins->op1, res);
475         RVM_STATUS_CLRALL(cpu);
476         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
477         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
478 }
479
480
481 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
482 {
483         ruint i;
484         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
485         
486         res = op2;
487         for (i = 0; i < op3; i++) {
488                 if (res & 1) {
489                         res >>= 1;
490                         res |= RVM_SIGN_BIT;
491                 } else {
492                         res >>= 1;
493                 }
494         }
495         RVM_CPUREG_SETU(cpu, ins->op1, res);
496         RVM_STATUS_CLRALL(cpu);
497         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
498         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
499         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
500 }
501
502
503 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
504 {
505         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
506         
507         res = op2 & op3;
508         RVM_STATUS_CLRALL(cpu);
509         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
510         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
511 }
512
513
514 static void rvm_op_xor(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         res = op2 ^ op3;
519         RVM_CPUREG_SETU(cpu, ins->op1, res);
520         RVM_STATUS_CLRALL(cpu);
521         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
522         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
523 }
524
525
526 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
527 {
528         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
529         
530         res = ~op2;
531         RVM_CPUREG_SETU(cpu, ins->op1, res);
532         RVM_STATUS_CLRALL(cpu);
533         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
534         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
535 }
536
537
538 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
539 {
540         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
541         
542         res = op2 ^ op3;
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_clr(rvmcpu_t *cpu, rvm_asmins_t *ins)
550 {
551         rvmreg_t *reg = RVM_CPUREG_PTR(cpu, ins->op1);
552         rvm_reg_cleanup(reg);
553 }
554
555
556 static void rvm_op_bic(rvmcpu_t *cpu, rvm_asmins_t *ins)
557 {
558         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
559         
560         res = op2 & ~op3;
561         RVM_CPUREG_SETU(cpu, ins->op1, res);
562         RVM_STATUS_CLRALL(cpu);
563         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
564         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
565 }
566
567
568 static void rvm_op_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
569 {
570         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
571         
572         for (res = RVM_REGISTER_BITS; op2; ) {
573                 op2 >>= 1;
574                 res -= 1;
575         }
576         RVM_CPUREG_SETU(cpu, ins->op1, res);
577 }
578
579
580 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
581 {
582         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
583 }
584
585
586 static void rvm_op_inc(rvmcpu_t *cpu, rvm_asmins_t *ins)
587 {
588         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) + 1);
589 }
590
591
592 static void rvm_op_dec(rvmcpu_t *cpu, rvm_asmins_t *ins)
593 {
594         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
595 }
596
597
598 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
599 {
600         rvmcpu_swi swi;
601         rvm_switable_t *switable;
602         ruint ntable = (ruint) RVM_SWI_TABLE(ins->swi);
603         ruint nswi = (ruint) RVM_SWI_NUM(ins->swi);
604
605         if (r_array_length(cpu->switables) <= ntable)
606                 RVM_ABORT(cpu, RVM_E_SWITABLE);
607         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
608         swi = switable[nswi].op;
609         swi(cpu, ins);
610 }
611
612
613 static void rvm_op_swiid(rvmcpu_t *cpu, rvm_asmins_t *ins)
614 {
615         rvmcpu_swi swi;
616         rvm_switable_t *switable;
617         ruint ntable = (ruint) RVM_SWI_TABLE(RVM_CPUREG_GETU(cpu, ins->op1));
618         ruint nswi = (ruint) RVM_SWI_NUM(RVM_CPUREG_GETU(cpu, ins->op1));
619
620         if (r_array_length(cpu->switables) <= ntable)
621                 RVM_ABORT(cpu, RVM_E_SWITABLE);
622         switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
623         swi = switable[nswi].op;
624         swi(cpu, ins);
625 }
626
627
628 static void rvm_op_call(rvmcpu_t *cpu, rvm_asmins_t *ins)
629 {
630         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
631
632         if (RVM_REG_GETTYPE(arg1) == RVM_DTYPE_SWIID) {
633                 RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
634                 rvm_op_swiid(cpu, ins);
635         } else {
636                 rvm_op_bl(cpu, ins);
637         }
638 }
639
640
641 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
642 {
643         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
644 }
645
646
647 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
648 {
649         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
650         
651         res = op2 - op3;
652         RVM_CPUREG_SETU(cpu, ins->op1, res);
653         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
654         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
655         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
656         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
657                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
658 }
659
660
661 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
662 {
663         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
664
665         res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
666         RVM_CPUREG_SETU(cpu, ins->op1, res);
667         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
668         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
669         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
670         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
671                                                         (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
672 }
673
674
675 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
676 {
677         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
678 }
679
680
681 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
682 {
683         rsword res;
684         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
685
686         res = (rsword)(op2 * op3);
687         RVM_CPUREG_SETU(cpu, ins->op1, res);
688         /* TBD: Not sure how to update the RVM_STATUS_C */
689         RVM_STATUS_CLRALL(cpu);
690         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
691         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
692 }
693
694
695 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
696 {
697         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
698         
699         res = op2 * op3;
700         RVM_CPUREG_SETU(cpu, ins->op1, res);
701         RVM_STATUS_CLRALL(cpu);
702         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
703         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
704         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
705 }
706
707
708 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
709 {
710         if (!RVM_CPUREG_GETU(cpu, ins->op3))
711                 RVM_ABORT(cpu, RVM_E_DIVZERO);
712
713         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
714 }
715
716
717 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
718 {
719         rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
720
721         if (!op3)
722                 RVM_ABORT(cpu, RVM_E_DIVZERO);
723         res = op2 / op3;
724         RVM_CPUREG_SETU(cpu, ins->op1, res);
725         RVM_STATUS_CLRALL(cpu);
726         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
727         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
728 }
729
730
731 static void rvm_op_mod(rvmcpu_t *cpu, rvm_asmins_t *ins)
732 {
733         if (!RVM_CPUREG_GETU(cpu, ins->op3))
734                 RVM_ABORT(cpu, RVM_E_DIVZERO);
735
736         RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) % RVM_CPUREG_GETU(cpu, ins->op3));
737 }
738
739
740 static void rvm_op_mods(rvmcpu_t *cpu, rvm_asmins_t *ins)
741 {
742         rsword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
743
744         if (!op3)
745                 RVM_ABORT(cpu, RVM_E_DIVZERO);
746         res = op2 % op3;
747         r_printf("mod RES: %ld\n", res);
748         RVM_CPUREG_SETU(cpu, ins->op1, res);
749         RVM_STATUS_CLRALL(cpu);
750         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
751         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
752 }
753
754
755 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
756 {
757         rsword res;
758         rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
759
760         if (!op3)
761                 RVM_ABORT(cpu, RVM_E_DIVZERO);
762         res = (rsword)(op2 / op3);
763         RVM_CPUREG_SETU(cpu, ins->op1, res);
764         RVM_STATUS_CLRALL(cpu);
765         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
766         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
767 }
768
769
770 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
771 {
772         rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
773
774         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, ins->op1));
775         RVM_CPUREG_SETU(cpu, SP, sp);
776 }
777
778
779 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
780 {
781         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
782
783         RVM_CPUREG_SET(cpu, ins->op1, RVM_STACK_READ(cpu->stack, sp));
784 }
785
786
787 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
788 {
789         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
790
791         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, ins->op1));
792 }
793
794
795 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
796 {
797         rword n, i = 0;
798         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
799         rword sp = RVM_CPUREG_GETU(cpu, SP);
800
801         if (!(bits & ((1<<(RVM_REGS_NUM / 2)) - 1)))
802                 i = RVM_REGS_NUM / 2;
803         for (;bits && i < RLST; i++) {
804                 n = 1 << i;
805                 if (n & bits) {
806                         sp += 1;
807                         RVM_STACK_WRITE(cpu->stack, sp, &RVM_CPUREG_GET(cpu, i));
808                         bits &= ~n;
809                 }
810         }
811         RVM_CPUREG_SETU(cpu, SP, sp);
812 }
813
814
815 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
816 {
817         int n, i = RLST - 1;
818         rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
819         rword savedbits = bits;
820         rword sp = RVM_CPUREG_GETU(cpu, SP);
821
822         if (!(bits & ~((1 << (RVM_REGS_NUM / 2)) - 1)))
823                 i = RVM_REGS_NUM / 2 - 1;
824         for (; bits && i >= 0; i--) {
825                 n = 1 << i;
826                 if (n & bits) {
827                         RVM_CPUREG_SET(cpu, i, RVM_STACK_READ(cpu->stack, sp));
828                         sp -= 1;
829                         bits &= ~n;
830                 }
831         }
832         if (!(((rword)(1 << SP)) & savedbits))
833                 RVM_CPUREG_SETU(cpu, SP, sp);
834 }
835
836
837 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
838 {
839         rword sp = RVM_CPUREG_GETU(cpu, SP);
840
841         RVM_CPUREG_SET(cpu, ins->op1, RVM_STACK_READ(cpu->stack, sp));
842         if (ins->op1 != SP)
843                 RVM_CPUREG_SETU(cpu, SP, sp - 1);
844 }
845
846
847 static void rvm_op_addrs(rvmcpu_t *cpu, rvm_asmins_t *ins)
848 {
849         rword sp = ((ins->op2 != XX) ? RVM_CPUREG_GETU(cpu, ins->op2) : 0) + ((ins->op3 != XX) ? RVM_CPUREG_GETU(cpu, ins->op3) : 0);
850
851         RVM_CPUREG_CLEAR(cpu, ins->op1);
852         RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_POINTER);
853         RVM_CPUREG_SETP(cpu, ins->op1, RVM_STACK_ADDR(cpu->stack, sp));
854 }
855
856
857 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
858 {
859         int n;
860         rword *dst = (rword*)   RVM_CPUREG_GETU(cpu, ins->op1);
861         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
862         
863         for (n = 0; bits && n < RLST; n++) {
864                 if (((rword)(1 << n)) & bits) {
865                         *dst = RVM_CPUREG_GETU(cpu, n);
866                         dst += 1;
867                         bits &= ~(1<<n);
868                 }
869         }
870 }
871
872
873 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
874 {
875         int n;
876         rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
877         rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
878
879         for (n = 0; bits && n < RLST; n++) {
880                 if (((rword)(1 << n)) & bits) {
881                         RVM_CPUREG_CLEAR(cpu, n);
882                         RVM_CPUREG_SETU(cpu, n, *src);
883                         src += 1;
884                         bits &= ~(1<<n);
885                 }
886         }
887 }
888
889
890 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
891 {
892         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
893         rword res = (rword)(op1 - op2);
894         
895         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
896         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
897         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
898         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
899                                                         (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
900 }
901
902
903 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
904 {
905         rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
906         rword res = (rword)(op1 + op2);
907         
908         RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
909         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
910         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
911         RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
912                                                         (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
913
914 }
915
916
917 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
918 {
919 //      fprintf(stdout, "nop\n");
920 }
921
922
923 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
924 {
925         RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));     
926 }
927
928
929 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
930 {
931         return vsnprintf(str, size, format, ap);
932 }
933
934
935 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
936 {
937         va_list ap;
938         int ret;
939
940         va_start(ap, format);
941         ret = rvm_vsnprintf(str, size, format, ap);
942         va_end(ap);
943         return ret;
944 }
945
946
947 static int rvm_printf(const char *format, ...)
948 {
949         va_list ap;
950         int ret;
951
952         va_start(ap, format);
953         ret = vfprintf(stdout, format, ap);
954         va_end(ap);
955         return ret;
956 }
957
958
959 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
960 {
961         int ret = 0;
962
963         if (reg == XX)
964                 ret = rvm_snprintf(str, size, "XX ");
965         else if (reg == FP)
966                 ret = rvm_snprintf(str, size, "FP ");
967         else if (reg == SP)
968                 ret = rvm_snprintf(str, size, "SP ");
969         else if (reg == LR)
970                 ret = rvm_snprintf(str, size, "LR ");
971         else if (reg == PC)
972                 ret = rvm_snprintf(str, size, "PC ");
973         else if (reg == DA)
974                 ret = rvm_snprintf(str, size, "DA ");
975         else if (reg >= 0 && reg < RVM_REGS_NUM/2)
976                 ret = rvm_snprintf(str, size, "R%d ",  reg);
977         else if (reg >= RVM_REGS_NUM/2)
978                 ret = rvm_snprintf(str, size, "S%d ",  reg & ((1 << (RVM_OPERAND_BITS-1))-1));
979
980         return ret;
981 }
982
983
984 static void rvm_op_prn(rvmcpu_t *cpu, rvm_asmins_t *ins)
985 {
986         rvmreg_t *r = RVM_CPUREG_PTR(cpu, ins->op1);
987
988         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
989                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
990         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
991                 rvm_printf("(UNSIGNED) R%d = %lu(0x%lx)\n", ins->op1, RVM_REG_GETU(r), RVM_REG_GETU(r));
992         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
993                 rvm_printf("(POINTER) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
994         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
995                 rvm_printf("(LONG) R%d = %ld\n", ins->op1, RVM_REG_GETL(r));
996         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
997                 rvm_printf("(DOUBLE) R%d = %0.2f\n", ins->op1, RVM_REG_GETD(r));
998         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
999                 rvm_printf("(STRING) R%d = %s\n", ins->op1, ((rstring_t*) RVM_REG_GETP(r))->s.str);
1000         else if (rvm_reg_gettype(r) == RVM_DTYPE_ARRAY)
1001                 rvm_printf("(ARRAY) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1002         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
1003                 rvm_printf("(SWI) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
1004         else
1005                 rvm_printf("(UNKNOWN) R%d = ?\n", ins->op1);
1006 }
1007
1008
1009 int rvm_asm_dump_pi_to_str(rvmcpu_t *vm, rvm_asmins_t *pi, char *str, ruint size)
1010 {
1011         int ret = 0, sz = size;
1012
1013         if (pi->opcode == RVM_SWI) {
1014                 rchar szSwi[64];
1015                 r_memset(szSwi, 0, sizeof(szSwi));
1016                 if (!vm) {
1017                         rvm_snprintf(szSwi, sizeof(szSwi) - 1, "%s(%x)", stropcalls[pi->opcode], (ruint32)pi->swi);
1018                 } else {
1019                         rvm_switable_t *switable;
1020                         ruint ntable = (ruint) RVM_SWI_TABLE(pi->swi);
1021                         ruint nswi = (ruint) RVM_SWI_NUM(pi->swi);
1022
1023                         if (ntable < r_array_length(vm->switables)) {
1024                                 switable = r_array_index(vm->switables, ntable, rvm_switable_t*);
1025                                 rvm_snprintf(szSwi, sizeof(szSwi) - 1, "(%s)",  switable[nswi].name ? switable[nswi].name : "unknown");
1026                         }
1027                 }
1028                 if ((ret = rvm_snprintf(str, sz, "%16s   ", szSwi)) < 0)
1029                         return ret;
1030         } else {
1031                 if ((ret = rvm_snprintf(str, sz, "%16s   ", stropcalls[pi->opcode])) < 0)
1032                         return ret;
1033         }
1034         str += ret;
1035         sz -= ret;
1036         
1037         if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
1038                 return ret;
1039         str += ret;
1040         sz -= ret;
1041                 
1042         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1043                 return ret;
1044         str += ret;
1045         sz -= ret;
1046
1047         if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
1048                 return ret;
1049         str += ret;
1050         sz -= ret;
1051                 
1052         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1053                 return ret;
1054         str += ret;
1055         sz -= ret;
1056
1057         if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
1058                 return ret;
1059         str += ret;
1060         sz -= ret;
1061                 
1062         if ((ret = rvm_snprintf(str, sz, " ")) < 0)
1063                 return ret;
1064         str += ret;
1065         sz -= ret;
1066
1067         if (pi->type == RVM_DTYPE_DOUBLE) {
1068                 if ((ret = rvm_snprintf(str, sz, "%f  ", pi->data.d)) < 0)
1069                         return ret;
1070         } else if (pi->type == RVM_DTYPE_LONG) {
1071                 if ((ret = rvm_snprintf(str, sz, "%ld  ", (long)pi->data.u)) < 0)
1072                         return ret;
1073         } else {
1074                 if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)pi->data.u)) < 0)
1075                         return ret;
1076         }
1077
1078         str += ret;
1079         sz -= ret;
1080
1081         return size - sz;
1082 }
1083
1084
1085 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
1086 {
1087         char buffer[256];
1088         while (count) {
1089                 rvm_asm_dump_pi_to_str(NULL, pi, buffer, sizeof(buffer));
1090                 rvm_printf("%s\n", buffer);
1091                 ++pi;
1092                 --count;
1093         }
1094 }
1095
1096
1097 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
1098 {
1099     int ret;
1100         char buffer[1024];
1101         
1102         ret = rvm_asm_dump_pi_to_str(vm, pi, buffer, sizeof(buffer));
1103         if (ret < 0)
1104                 return;
1105     ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, "                                                                                        ");
1106         buffer[50] = '\0';
1107         rvm_printf("%s", buffer);
1108
1109         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 )",
1110                 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
1111                 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
1112                 RVM_CPUREG_GETU(vm, 8), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
1113                 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
1114                 vm->status & RVM_STATUS_V ? 'V' : '_',
1115                 vm->status & RVM_STATUS_C ? 'C' : '_',
1116                 vm->status & RVM_STATUS_N ? 'N' : '_',
1117                 vm->status & RVM_STATUS_Z ? 'Z' : '_');
1118         rvm_printf("\n");
1119 }
1120
1121
1122 static void rvm_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
1123 {
1124         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
1125         rvmreg_t tmp;
1126
1127         RVM_REG_CLEAR(&tmp);
1128         RVM_REG_SETTYPE(&tmp, type);
1129         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
1130 }
1131
1132
1133 static void rvm_op_type(rvmcpu_t *cpu, rvm_asmins_t *ins)
1134 {
1135         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETTYPE(cpu, ins->op2);
1136
1137         RVM_CPUREG_SETU(cpu, ins->op1, type);
1138 }
1139
1140
1141 static void rvm_op_settype(rvmcpu_t *cpu, rvm_asmins_t *ins)
1142 {
1143         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op2);
1144
1145         RVM_CPUREG_SETTYPE(cpu, ins->op1, type);
1146 }
1147
1148
1149 static void rvm_op_emov(rvmcpu_t *cpu, rvm_asmins_t *ins)
1150 {
1151         rvm_op_mov(cpu, ins);
1152 }
1153
1154
1155 static void rvm_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
1156 {
1157         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1158         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1159
1160         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1161 }
1162
1163
1164 static void rvm_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
1165 {
1166         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1167         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1168
1169         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1170 }
1171
1172
1173 static void rvm_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
1174 {
1175         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1176         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1177
1178         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1179 }
1180
1181
1182 static void rvm_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
1183 {
1184         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1185         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1186
1187         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1188 }
1189
1190
1191 static void rvm_op_emod(rvmcpu_t *cpu, rvm_asmins_t *ins)
1192 {
1193         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1194         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1195
1196         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_MOD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1197 }
1198
1199
1200 static void rvm_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
1201 {
1202         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1203         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1204
1205         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1206 }
1207
1208
1209 static void rvm_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1210 {
1211         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1212         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1213
1214         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1215 }
1216
1217
1218 static void rvm_op_elsru(rvmcpu_t *cpu, rvm_asmins_t *ins)
1219 {
1220         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1221         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1222
1223         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LSRU, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1224 }
1225
1226
1227 static void rvm_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
1228 {
1229         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1230         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1231
1232         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1233 }
1234
1235
1236 static void rvm_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1237 {
1238         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1239         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1240
1241         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1242 }
1243
1244
1245 static void rvm_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1246 {
1247         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1248         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1249
1250         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1251 }
1252
1253
1254 static void rvm_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1255 {
1256         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1257
1258         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1259 }
1260
1261
1262 static void rvm_op_eland(rvmcpu_t *cpu, rvm_asmins_t *ins)
1263 {
1264         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1265         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1266
1267         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICAND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1268 }
1269
1270
1271 static void rvm_op_elor(rvmcpu_t *cpu, rvm_asmins_t *ins)
1272 {
1273         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1274         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1275
1276         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LOGICOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1277 }
1278
1279
1280 static void rvm_op_elnot(rvmcpu_t *cpu, rvm_asmins_t *ins)
1281 {
1282         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1283
1284         rvm_opmap_invoke_unary_handler(cpu->opmap, RVM_OPID_LOGICNOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
1285 }
1286
1287
1288 static void rvm_op_eeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1289 {
1290         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1291         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1292
1293         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_EQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1294 }
1295
1296
1297 static void rvm_op_enoteq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1298 {
1299         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1300         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1301
1302         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_NOTEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1303 }
1304
1305
1306 static void rvm_op_egreat(rvmcpu_t *cpu, rvm_asmins_t *ins)
1307 {
1308         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1309         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1310
1311         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_GREATER, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1312 }
1313
1314
1315 static void rvm_op_egreateq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1316 {
1317         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1318         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1319
1320         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_GREATEREQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1321 }
1322
1323
1324 static void rvm_op_elesseq(rvmcpu_t *cpu, rvm_asmins_t *ins)
1325 {
1326         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1327         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1328
1329         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LESSEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1330 }
1331
1332
1333 static void rvm_op_eless(rvmcpu_t *cpu, rvm_asmins_t *ins)
1334 {
1335         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1336         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
1337
1338         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_LESS, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
1339 }
1340
1341
1342 static void rvm_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
1343 {
1344         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1345         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1346
1347         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMP, cpu, NULL, arg1, arg2);
1348 }
1349
1350
1351 static void rvm_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
1352 {
1353         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1354         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1355
1356         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CMN, cpu, NULL, arg1, arg2);
1357 }
1358
1359
1360 static void rvm_op_allocstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1361 {
1362
1363         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1364         rstring_t *s = r_string_create_strsize((const rchar*)RVM_CPUREG_GETP(cpu, ins->op2), RVM_CPUREG_GETU(cpu, ins->op3));
1365         if (!s) {
1366                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1367         }
1368         rvm_gc_add(cpu->gc, (robject_t*)s);
1369         rvm_reg_setstring(arg1, s);
1370 }
1371
1372
1373 static void rvm_op_allocarr(rvmcpu_t *cpu, rvm_asmins_t *ins)
1374 {
1375         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1376         ruint size = RVM_CPUREG_GETU(cpu, ins->op2);
1377         rcarray_t *a = r_carray_create_rvmreg();
1378         if (!a) {
1379                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1380         }
1381         r_carray_setlength(a, size);
1382         rvm_gc_add(cpu->gc, (robject_t*)a);
1383         rvm_reg_setarray(arg1, (robject_t*)a);
1384 }
1385
1386
1387 static void rvm_op_addra(rvmcpu_t *cpu, rvm_asmins_t *ins)
1388 {
1389         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1390         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1391         rvmreg_t tmp = rvm_reg_create_long(0);
1392         rcarray_t *a = RVM_REG_GETP(arg2);
1393         rlong index;
1394
1395         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
1396         index = RVM_REG_GETL(&tmp);
1397
1398         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY || index < 0) {
1399                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1400         }
1401         RVM_REG_CLEAR(arg1);
1402         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
1403         RVM_REG_SETP(arg1, r_carray_slot_expand(a, index));
1404 }
1405
1406
1407 static void rvm_op_elda(rvmcpu_t *cpu, rvm_asmins_t *ins)
1408 {
1409         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1410         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1411         ruint index = RVM_CPUREG_GETU(cpu, ins->op3);
1412         rcarray_t *a = RVM_REG_GETP(arg2);
1413
1414         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1415                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1416         }
1417         *arg1 = *((rvmreg_t*)r_carray_slot_expand(a, index));
1418 }
1419
1420
1421 static void rvm_op_esta(rvmcpu_t *cpu, rvm_asmins_t *ins)
1422 {
1423         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
1424         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
1425         ruint index = RVM_CPUREG_GETU(cpu, ins->op3);
1426         rcarray_t *a = RVM_REG_GETP(arg2);
1427
1428         if (rvm_reg_gettype(arg2) != RVM_DTYPE_ARRAY) {
1429                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
1430         }
1431         r_carray_replace(a, index, arg1);
1432 }
1433
1434
1435 static void rvm_op_abort(rvmcpu_t *cpu, rvm_asmins_t *ins)
1436 {
1437         RVM_ABORT(cpu, RVM_CPUREG_GETU(cpu, ins->op1));
1438 }
1439
1440 #if 0
1441 static void rvm_op_elds(rvmcpu_t *cpu, rvm_asmins_t *ins)
1442 {
1443         ruint index = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
1444         RVM_CPUREG_SET(cpu, ins->op1, *RVM_STACK_ADDR(cpu, index));
1445 }
1446
1447
1448 static void rvm_op_ests(rvmcpu_t *cpu, rvm_asmins_t *ins)
1449 {
1450         ruint index = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
1451         *RVM_STACK_ADDR(cpu, index) = RVM_CPUREG_GET(cpu, ins->op1);
1452 }
1453 #endif
1454
1455 static rvm_cpu_op ops[] = {
1456         rvm_op_exit,            // RVM_EXT
1457         rvm_op_abort,           // RVM_ABORT
1458         rvm_op_prn,                     // RVM_PRN
1459         rvm_op_asr,                     // RVM_ASR
1460         rvm_op_swi,                     // RVM_SWI
1461         rvm_op_swiid,           // RVM_SWIID
1462         rvm_op_call,            // RVM_CALL
1463         rvm_op_mov,                     // RVM_MOV
1464         rvm_op_inc,                     // RVM_INC
1465         rvm_op_dec,                     // RVM_DEC
1466         rvm_op_add,                     // RVM_ADD
1467         rvm_op_adds,            // RVM_ADDS
1468         rvm_op_adc,                     // RVM_ADC
1469         rvm_op_and,                     // RVM_AND
1470         rvm_op_bic,                     // RVM_BIC
1471         rvm_op_clz,                     // RVM_CLZ
1472         rvm_op_cmn,                     // RVM_CMN
1473         rvm_op_xor,                     // RVM_XOR
1474         rvm_op_sub,                     // RVM_SUB
1475         rvm_op_subs,            // RVM_SUBS
1476         rvm_op_sbc,                     // RVM_SBC
1477         rvm_op_mul,                     // RVM_MUL
1478         rvm_op_mls,                     // RVM_MLS
1479         rvm_op_muls,            // RVM_MULS
1480         rvm_op_not,                     // RVM_NOT
1481         rvm_op_div,                     // RVM_DIV
1482         rvm_op_dvs,                     // RVM_DVS
1483         rvm_op_divs,            // RVM_DIVS
1484         rvm_op_mod,                     // RVM_MOD
1485         rvm_op_mods,            // RVM_MODS
1486         rvm_op_bx,                      // RVM_BX
1487         rvm_op_bl,                      // RVM_BL
1488         rvm_op_b,                       // RVM_B
1489         rvm_op_str,                     // RVM_STR
1490         rvm_op_strp,            // RVM_STRP
1491         rvm_op_strb,            // RVM_STRB
1492         rvm_op_strh,            // RVM_STRH
1493         rvm_op_strw,            // RVM_STRW
1494         rvm_op_strr,            // RVM_STRR
1495         rvm_op_ldr,                     // RVM_LDR
1496         rvm_op_ldrp,            // RVM_LDRP
1497         rvm_op_ldrb,            // RVM_LDRB
1498         rvm_op_ldrh,            // RVM_LDRH
1499         rvm_op_ldrw,            // RVM_LDRW
1500         rvm_op_ldrr,            // RVM_LDRR
1501         rvm_op_clrr,            // RVM_CLRR
1502         rvm_op_lsl,                     // RVM_LSL
1503         rvm_op_lsr,                     // RVM_LSR
1504         rvm_op_lsrs,            // RVM_LSRS
1505         rvm_op_stm,                     // RVM_STM
1506         rvm_op_ldm,                     // RVM_LDM
1507         rvm_op_sts,                     // RVM_STS
1508         rvm_op_lds,                     // RVM_LDS
1509         rvm_op_orr,                     // RVM_ORR
1510         rvm_op_push,            // RVM_PUSH
1511         rvm_op_pop,                     // RVM_POP
1512         rvm_op_cmp,                     // RVM_CMP
1513         rvm_op_nop,                     // RVM_NOP
1514         rvm_op_beq,                     // RVM_BEQ
1515         rvm_op_bneq,            // RVM_BNEQ
1516         rvm_op_bleq,            // RVM_BLEQ
1517         rvm_op_bgeq,            // RVM_BGEQ
1518         rvm_op_bles,            // RVM_BLES
1519         rvm_op_bgre,            // RVM_BGRE
1520         rvm_op_ret,                     // RVM_RET
1521         rvm_op_ror,                     // RVM_ROR
1522         rvm_op_pushm,           // RVM_PUSHM
1523         rvm_op_popm,            // RVM_POPM
1524         rvm_op_tst,             // RVM_TST
1525         rvm_op_teq,             // RVM_TEQ
1526         rvm_op_clr,             // RVM_CLR
1527         rvm_op_addrs,           // RVM_ADDRS
1528
1529 /* Extended VM instructions */
1530         rvm_op_cast,            // RVM_CAST
1531         rvm_op_type,            // RVM_TYPE
1532         rvm_op_settype,         // RVM_SETTYPE
1533         rvm_op_emov,            // RVM_EMOV
1534         rvm_op_eadd,            // RVM_EADD
1535         rvm_op_esub,            // RVM_ESUB
1536         rvm_op_emul,            // RVM_EMUL
1537         rvm_op_ediv,            // RVM_EDIV
1538         rvm_op_emod,            // RVM_MOD
1539         rvm_op_elsl,            // RVM_ELSL
1540         rvm_op_elsr,            // RVM_ELSR
1541         rvm_op_elsru,           // RVM_ELSRU
1542         rvm_op_eand,            // RVM_EAND
1543         rvm_op_eorr,            // RVM_EORR
1544         rvm_op_exor,            // RVM_EXOR
1545         rvm_op_enot,            // RVM_ENOT
1546
1547         rvm_op_eland,           // RVM_ELAND
1548         rvm_op_elor,            // RVM_ELOR
1549         rvm_op_elnot,           // RVM_ELNOT
1550         rvm_op_eeq,                     // RVM_EEQ
1551         rvm_op_enoteq,          // RVM_ENOTEQ
1552         rvm_op_egreat,          // RVM_EGREAT
1553         rvm_op_egreateq,        // RVM_EGREATEQ
1554         rvm_op_eless,           // RVM_ELESS
1555         rvm_op_elesseq,         // RVM_ELESSEQ
1556         rvm_op_ecmp,            // RVM_ECMP
1557         rvm_op_ecmn,            // RVM_ECMN
1558         rvm_op_allocstr,        // RVM_ALLOCSTR
1559         rvm_op_allocarr,        // RVM_ALLOCARR
1560         rvm_op_addra,           // RVM_ADDRA
1561         rvm_op_elda,            // RVM_ELDA
1562         rvm_op_esta,            // RVM_ESTA
1563         (void*) 0,
1564         (void*) 0,
1565         (void*) 0,
1566         (void*) 0,
1567         (void*) 0,
1568         (void*) 0,
1569         (void*) 0,
1570         (void*) 0,
1571         
1572 };
1573
1574
1575 rvmcpu_t *rvm_cpu_create()
1576 {
1577         rvmcpu_t *cpu;
1578
1579         cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
1580         if (!cpu)
1581                 return ((void*)0);
1582         r_memset(cpu, 0, sizeof(*cpu));
1583         cpu->switables = r_array_create(sizeof(rvm_switable_t*));
1584         cpu->stack = r_malloc(4 * 1024 *sizeof(rvmreg_t));
1585         cpu->data = r_carray_create(sizeof(rvmreg_t));
1586         cpu->opmap = rvm_opmap_create();
1587         cpu->gc = rvm_gc_create();
1588         rvm_op_binary_init(cpu->opmap);
1589         rvm_op_cast_init(cpu->opmap);
1590         rvm_op_not_init(cpu->opmap);
1591         rvm_op_logicnot_init(cpu->opmap);
1592
1593         return cpu;
1594 }
1595
1596
1597 void rvm_cpu_destroy(rvmcpu_t *cpu)
1598 {
1599         rvm_gc_deallocate_all(cpu->gc);
1600         rvm_gc_destroy(cpu->gc);
1601         r_object_destroy((robject_t*)cpu->switables);
1602 //      r_object_destroy((robject_t*)cpu->stack);
1603         r_free(cpu->stack);
1604         r_object_destroy((robject_t*)cpu->data);
1605         rvm_opmap_destroy(cpu->opmap);
1606         r_free(cpu);
1607 }
1608
1609
1610 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1611 {
1612         rvm_asmins_t *pi;
1613         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1614         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1615
1616         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1617         cpu->abort = 0;
1618         cpu->error = 0;
1619         do {
1620                 pi = RVM_REG_GETIP(regpc);
1621                 if (pi->da) {
1622                         if (pi->type == RVM_DTYPE_DOUBLE) {
1623                                 RVM_REG_SETD(regda, pi->data.d);
1624                         } else {
1625                                 RVM_REG_SETU(regda, pi->data.u);
1626                         }
1627                         RVM_REG_SETTYPE(regda, pi->type);
1628                         RVM_REG_ASSIGNFLAGS(regda, (pi->type >= RVM_DTYPE_STRING) ? RVM_INFOBIT_ROBJECT : 0);
1629                 }
1630                 ops[pi->opcode](cpu, pi);
1631                 RVM_REG_INCIP(regpc, 1);
1632         } while (!cpu->abort);
1633         if (cpu->error)
1634                 return -1;
1635         return 0;
1636 }
1637
1638
1639 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
1640 {
1641         rvm_asmins_t *pi;
1642         rvmreg_t *regda = RVM_CPUREG_PTR(cpu, DA);
1643         rvmreg_t *regpc = RVM_CPUREG_PTR(cpu, PC);
1644
1645         RVM_CPUREG_SETIP(cpu, PC, prog + off);
1646         cpu->abort = 0;
1647         cpu->error = 0;
1648         do {
1649                 pi = RVM_REG_GETIP(regpc);
1650                 if (pi->da) {
1651                         if (pi->type == RVM_DTYPE_DOUBLE) {
1652                                 RVM_REG_SETD(regda, pi->data.d);
1653                         } else {
1654                                 RVM_REG_SETU(regda, pi->data.u);
1655                         }
1656                         RVM_REG_SETTYPE(regda, pi->type);
1657                         RVM_REG_ASSIGNFLAGS(regda, (pi->type >= RVM_DTYPE_STRING) ? RVM_INFOBIT_ROBJECT : 0);
1658                 }
1659                 ops[pi->opcode](cpu, pi);
1660                 rvm_cpu_dumpregs(pi, cpu);
1661                 RVM_REG_INCIP(regpc, 1);
1662         } while (!cpu->abort);
1663         if (cpu->error)
1664                 return -1;
1665         return 0;
1666 }
1667
1668
1669 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname, rsize_t size)
1670 {
1671         rint ntable, nswi;
1672         rvm_switable_t *swientry;
1673
1674         for (ntable = 0; ntable < r_array_length(cpu->switables); ntable++) {
1675                 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
1676                 for (nswi = 0; swientry[nswi].name; nswi++) {
1677                         if (r_strncmp(swientry[nswi].name, swiname, size) == 0 && r_strlen(swientry[nswi].name) == size)
1678                                 return (rint)RVM_SWI_ID(ntable, nswi);
1679                 }
1680         }
1681
1682         return -1;
1683 }
1684
1685
1686 rint rvm_cpu_getswi_s(rvmcpu_t *cpu, const rchar *swiname)
1687 {
1688         return rvm_cpu_getswi(cpu, swiname, r_strlen(swiname));
1689 }
1690
1691
1692 rint rvm_cpu_addswitable(rvmcpu_t *cpu, rvm_switable_t *switable)
1693 {
1694         rint nswi;
1695
1696         for (nswi = 0; switable[nswi].name; nswi++) {
1697                 if (rvm_cpu_getswi_s(cpu, switable[nswi].name) >= 0)
1698                         return -1;
1699         }
1700
1701         return r_array_add(cpu->switables, &switable);
1702 }
1703
1704
1705 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
1706 {
1707         rvm_asmins_t a;
1708
1709         r_memset(&a, 0, sizeof(a));
1710         a.opcode = (ruint8) opcode;
1711         a.op1 = (ruint8)op1;
1712         a.op2 = (ruint8)op2;
1713         a.op3 = (ruint8)op3;
1714         a.data.u = (rword)data;
1715         a.type = RVM_DTYPE_POINTER;
1716         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1717                 a.da = 1;
1718         return a;
1719 }
1720
1721
1722 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1723 {
1724         rvm_asmins_t a;
1725
1726         r_memset(&a, 0, sizeof(a));
1727         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1728         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1729         a.op1 = (ruint8)op1;
1730         a.op2 = (ruint8)op2;
1731         a.op3 = (ruint8)op3;
1732         a.data.u = (rword)data;
1733         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1734                 a.da = 1;
1735         return a;
1736 }
1737
1738
1739 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1740 {
1741         rvm_asmins_t a;
1742
1743         r_memset(&a, 0, sizeof(a));
1744         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1745         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1746         a.op1 = (ruint8)op1;
1747         a.op2 = (ruint8)op2;
1748         a.op3 = (ruint8)op3;
1749         a.data.u = (rword)data;
1750         a.type = RVM_DTYPE_LONG;
1751         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1752                 a.da = 1;
1753         return a;
1754 }
1755
1756
1757 rvm_asmins_t rvm_asmb(rword opcode, rword op1, rword op2, rword op3, rword data)
1758 {
1759         rvm_asmins_t a;
1760
1761         r_memset(&a, 0, sizeof(a));
1762         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1763         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1764         a.op1 = (ruint8)op1;
1765         a.op2 = (ruint8)op2;
1766         a.op3 = (ruint8)op3;
1767         a.data.u = (rword)(data ? 1 : 0);
1768         a.type = RVM_DTYPE_BOOLEAN;
1769         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1770                 a.da = 1;
1771         return a;
1772 }
1773
1774
1775 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
1776 {
1777         rvm_asmins_t a;
1778
1779         r_memset(&a, 0, sizeof(a));
1780         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1781         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1782         a.op1 = (ruint8)op1;
1783         a.op2 = (ruint8)op2;
1784         a.op3 = (ruint8)op3;
1785         a.data.d = data;
1786         a.type = RVM_DTYPE_DOUBLE;
1787         if ((ruint8)op1 == DA || (ruint8)op2 == DA || (ruint8)op3 == DA)
1788                 a.da = 1;
1789
1790         return a;
1791 }
1792
1793
1794 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1795 {
1796         rvm_asmins_t a;
1797
1798         r_memset(&a, 0, sizeof(a));
1799         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1800         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1801         a.op1 = (ruint8)op1;
1802         a.op2 = (ruint8)op2;
1803         a.op3 = (ruint8)op3;
1804         a.data.u = (rword)pReloc;
1805         a.flags = RVM_ASMINS_RELOC | RVM_ASMINS_RELOCPTR;
1806         a.da = 1;
1807
1808         return a;
1809 }
1810
1811
1812 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1813 {
1814         rvm_asmins_t a;
1815
1816         r_memset(&a, 0, sizeof(a));
1817         a.opcode = (ruint32) RVM_ASMINS_OPCODE(opcode);
1818         a.swi = (ruint32) RVM_ASMINS_SWI(opcode);
1819         a.op1 = (ruint8)op1;
1820         a.op2 = (ruint8)op2;
1821         a.op3 = (ruint8)op3;
1822         a.data.u = (rword)pReloc;
1823         a.flags = RVM_ASMINS_RELOC;
1824         a.da = 1;
1825
1826         return a;
1827 }
1828
1829
1830 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1831 {
1832         rvm_asmins_t *reloc;
1833         rulong relocindex;
1834         rulong off;
1835
1836         for (off = 0; off < size; off++, code++) {
1837                 if (code->flags & RVM_ASMINS_RELOC) {
1838                         if (code->flags & RVM_ASMINS_RELOCPTR) {
1839                                 reloc = *((rvm_asmins_t **)code->data.u);
1840                                 code->data.u = reloc - code;
1841                         } else {
1842                                 relocindex = *((rulong *)code->data.u);
1843                                 code->data.u = relocindex - off;
1844                         }
1845                         code->flags &= ~(RVM_ASMINS_RELOCPTR | RVM_ASMINS_RELOC);
1846                 }
1847         }
1848 }
1849