2 * Regular Pattern Analyzer (RPA)
3 * Copyright (c) 2009-2010 Martin Stoilov
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.
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.
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/>.
18 * Martin Stoilov <martin@rpasearch.com>
30 static const char *stropcalls[] = {
93 static void rvm_op_b(rvmcpu_t *cpu, rvm_asmins_t *ins)
95 RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
99 static void rvm_op_beq(rvmcpu_t *cpu, rvm_asmins_t *ins)
101 if ((cpu->status & RVM_STATUS_Z))
102 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
106 static void rvm_op_bneq(rvmcpu_t *cpu, rvm_asmins_t *ins)
108 if ((cpu->status & RVM_STATUS_Z) == 0)
109 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
113 static void rvm_op_bleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
115 if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z))
116 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
119 static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
121 if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1)
122 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
126 static void rvm_op_bles(rvmcpu_t *cpu, rvm_asmins_t *ins)
128 if ((cpu->status & RVM_STATUS_N))
129 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
133 static void rvm_op_bgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
135 if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0)
136 RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETU(cpu, PC) + RVM_CPUREG_GETU(cpu, ins->op1) - 1);
140 static void rvm_op_bl(rvmcpu_t *cpu, rvm_asmins_t *ins)
142 RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
143 RVM_CPUREG_INCIP(cpu, PC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
147 static void rvm_op_exit(rvmcpu_t *cpu, rvm_asmins_t *ins)
153 static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
155 RVM_CPUREG_SET(cpu, ins->op1, RVM_CPUREG_GET(cpu, ins->op2));
159 static void rvm_op_ldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
161 RVM_CPUREG_SETU(cpu, ins->op1, *((rword*)RVM_CPUREG_GETU(cpu, ins->op2)));
166 static void rvm_op_ldrp(rvmcpu_t *cpu, rvm_asmins_t *ins)
168 RVM_CPUREG_SETU(cpu, ins->op1, *((rpointer*)RVM_CPUREG_GETU(cpu, ins->op2)));
172 static void rvm_op_ldrb(rvmcpu_t *cpu, rvm_asmins_t *ins)
174 RVM_CPUREG_SETU(cpu, ins->op1, *((ruint8*)RVM_CPUREG_GETU(cpu, ins->op2)));
178 static void rvm_op_ldrh(rvmcpu_t *cpu, rvm_asmins_t *ins)
180 RVM_CPUREG_SETU(cpu, ins->op1, *((ruint16*)RVM_CPUREG_GETU(cpu, ins->op2)));
184 static void rvm_op_ldrw(rvmcpu_t *cpu, rvm_asmins_t *ins)
186 RVM_CPUREG_SETU(cpu, ins->op1, *((ruint32*)RVM_CPUREG_GETU(cpu, ins->op2)));
190 static void rvm_op_ldrr(rvmcpu_t *cpu, rvm_asmins_t *ins)
192 RVM_CPUREG_SET(cpu, ins->op1, *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)));
196 static void rvm_op_str(rvmcpu_t *cpu, rvm_asmins_t *ins)
198 *((rword*)RVM_CPUREG_GETP(cpu, ins->op2)) = RVM_CPUREG_GETU(cpu, ins->op1);
202 static void rvm_op_strp(rvmcpu_t *cpu, rvm_asmins_t *ins)
204 *((rpointer*)RVM_CPUREG_GETP(cpu, ins->op2)) = (rpointer)RVM_CPUREG_GETP(cpu, ins->op1);
208 static void rvm_op_strb(rvmcpu_t *cpu, rvm_asmins_t *ins)
210 *((ruint8*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint8)RVM_CPUREG_GETU(cpu, ins->op1);
214 static void rvm_op_strh(rvmcpu_t *cpu, rvm_asmins_t *ins)
216 *((ruint16*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint16)RVM_CPUREG_GETU(cpu, ins->op1);
221 static void rvm_op_strw(rvmcpu_t *cpu, rvm_asmins_t *ins)
223 *((ruint32*)RVM_CPUREG_GETP(cpu, ins->op2)) = (ruint32)RVM_CPUREG_GETU(cpu, ins->op1);
228 static void rvm_op_strr(rvmcpu_t *cpu, rvm_asmins_t *ins)
230 *((rvmreg_t*)RVM_CPUREG_GETU(cpu, ins->op2)) = RVM_CPUREG_GET(cpu, ins->op1);
234 static void rvm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
236 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
239 RVM_CPUREG_SETU(cpu, ins->op1, res);
240 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
241 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
242 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
243 RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
244 (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
248 static void rvm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
250 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
252 res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
253 RVM_CPUREG_SETU(cpu, ins->op1, res);
254 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
255 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
256 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
257 RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
258 (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
262 static void rvm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
264 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
267 RVM_CPUREG_SETU(cpu, ins->op1, res);
268 RVM_STATUS_CLRALL(cpu);
269 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
270 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
274 static void rvm_op_orr(rvmcpu_t *cpu, rvm_asmins_t *ins)
276 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
279 RVM_CPUREG_SETU(cpu, ins->op1, res);
280 RVM_STATUS_CLRALL(cpu);
281 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
282 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
286 static void rvm_op_lsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
288 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
291 RVM_CPUREG_SETU(cpu, ins->op1, res);
292 RVM_STATUS_CLRALL(cpu);
293 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
294 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
298 static void rvm_op_lsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
300 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
303 RVM_CPUREG_SETU(cpu, ins->op1, res);
304 RVM_STATUS_CLRALL(cpu);
305 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
309 static void rvm_op_asr(rvmcpu_t *cpu, rvm_asmins_t *ins)
311 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
314 res |= op2 & RVM_SIGN_BIT;
315 RVM_CPUREG_SETU(cpu, ins->op1, res);
316 RVM_STATUS_CLRALL(cpu);
317 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
318 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
322 static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
325 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
328 for (i = 0; i < op3; i++) {
336 RVM_CPUREG_SETU(cpu, ins->op1, res);
337 RVM_STATUS_CLRALL(cpu);
338 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
339 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
340 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res & RVM_SIGN_BIT);
344 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
346 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
349 RVM_STATUS_CLRALL(cpu);
350 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
351 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
355 static void rvm_op_eor(rvmcpu_t *cpu, rvm_asmins_t *ins)
357 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
360 RVM_CPUREG_SETU(cpu, ins->op1, res);
361 RVM_STATUS_CLRALL(cpu);
362 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
363 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
367 static void rvm_op_not(rvmcpu_t *cpu, rvm_asmins_t *ins)
369 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
372 RVM_CPUREG_SETU(cpu, ins->op1, res);
373 RVM_STATUS_CLRALL(cpu);
374 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
375 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
379 static void rvm_op_teq(rvmcpu_t *cpu, rvm_asmins_t *ins)
381 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
384 RVM_STATUS_CLRALL(cpu);
385 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
386 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
390 static void rvm_op_bic(rvmcpu_t *cpu, rvm_asmins_t *ins)
392 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
395 RVM_CPUREG_SETU(cpu, ins->op1, res);
396 RVM_STATUS_CLRALL(cpu);
397 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
398 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
402 static void rvm_op_clz(rvmcpu_t *cpu, rvm_asmins_t *ins)
404 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2);
406 for (res = RVM_REGISTER_BITS; op2; ) {
410 RVM_CPUREG_SETU(cpu, ins->op1, res);
414 static void rvm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
416 RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3));
420 static void rvm_op_swi(rvmcpu_t *cpu, rvm_asmins_t *ins)
422 // rvmcpu_swi *cbt = cpu->switable[RVM_CB_TABLE(RVM_CPUREG_GETU(cpu, ins->op1))];
423 // cbt[RVM_CB_OFFSET(RVM_CPUREG_GETU(cpu, ins->op1))](cpu);
426 rvm_switable_t *switable;
427 ruint ntable = (ruint) RVM_SWI_TABLE(RVM_CPUREG_GETU(cpu, ins->op1));
428 ruint nswi = (ruint) RVM_SWI_NUM(RVM_CPUREG_GETU(cpu, ins->op1));
430 if (r_array_size(cpu->switables) <= ntable)
431 RVM_ABORT(cpu, RVM_E_SWITABLE);
432 switable = r_array_index(cpu->switables, ntable, rvm_switable_t*);
433 swi = switable[nswi].op;
438 static void rvm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
440 RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
444 static void rvm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
446 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
449 RVM_CPUREG_SETU(cpu, ins->op1, res);
450 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2)); /* borrow = !carry */
451 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
452 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
453 RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
454 (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
458 static void rvm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
460 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
462 res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
463 RVM_CPUREG_SETU(cpu, ins->op1, res);
464 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2)); /* borrow = !carry */
465 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
466 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
467 RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
468 (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
472 static void rvm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
474 RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
478 static void rvm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
481 rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
483 res = (rsword)(op2 * op3);
484 RVM_CPUREG_SETU(cpu, ins->op1, res);
485 /* TBD: Not sure how to update the RVM_STATUS_C */
486 RVM_STATUS_CLRALL(cpu);
487 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
488 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
492 static void rvm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
494 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
497 RVM_CPUREG_SETU(cpu, ins->op1, res);
498 RVM_STATUS_CLRALL(cpu);
499 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
500 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
501 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
505 static void rvm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
507 if (!RVM_CPUREG_GETU(cpu, ins->op3))
508 RVM_ABORT(cpu, RVM_E_DIVZERO);
510 RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
514 static void rvm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
516 rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
519 RVM_ABORT(cpu, RVM_E_DIVZERO);
521 RVM_CPUREG_SETU(cpu, ins->op1, res);
522 RVM_STATUS_CLRALL(cpu);
523 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
524 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
528 static void rvm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
531 rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
534 RVM_ABORT(cpu, RVM_E_DIVZERO);
535 res = (rsword)(op2 / op3);
536 RVM_CPUREG_SETU(cpu, ins->op1, res);
537 RVM_STATUS_CLRALL(cpu);
538 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
539 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
543 static void rvm_op_push(rvmcpu_t *cpu, rvm_asmins_t *ins)
545 rword sp = RVM_CPUREG_GETU(cpu, SP) + 1;
547 r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
548 RVM_CPUREG_SETU(cpu, SP, sp);
552 static void rvm_op_sts(rvmcpu_t *cpu, rvm_asmins_t *ins)
554 rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
556 r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, ins->op1));
560 static void rvm_op_pushm(rvmcpu_t *cpu, rvm_asmins_t *ins)
563 rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
564 rword sp = RVM_CPUREG_GETU(cpu, SP);
566 for (i = 0, n = 0; bits && n < RLST; n++) {
567 if (((rword)(1 << n)) & bits) {
570 r_array_replace(cpu->stack, sp, (rconstpointer)&RVM_CPUREG_GET(cpu, n));
574 RVM_CPUREG_SETU(cpu, SP, RVM_CPUREG_GETU(cpu, SP) + i);
578 static void rvm_op_pop(rvmcpu_t *cpu, rvm_asmins_t *ins)
580 rword sp = RVM_CPUREG_GETU(cpu, SP);
582 RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
584 RVM_CPUREG_SETU(cpu, SP, sp - 1);
588 static void rvm_op_popm(rvmcpu_t *cpu, rvm_asmins_t *ins)
591 rword bits = RVM_CPUREG_GETU(cpu, ins->op1);
592 rword sp = RVM_CPUREG_GETU(cpu, SP);
594 for (n = RLST - 1; bits && n >= 0; n--) {
595 if (((rword)(1 << n)) & bits) {
596 RVM_CPUREG_SET(cpu, n, r_array_index(cpu->stack, sp, rvmreg_t));
601 if (!(((rword)(1 << SP)) & bits))
602 RVM_CPUREG_SETU(cpu, SP, sp);
606 static void rvm_op_lds(rvmcpu_t *cpu, rvm_asmins_t *ins)
608 rword sp = RVM_CPUREG_GETU(cpu, ins->op2) + RVM_CPUREG_GETU(cpu, ins->op3);
610 RVM_CPUREG_SET(cpu, ins->op1, r_array_index(cpu->stack, sp, rvmreg_t));
614 static void rvm_op_stm(rvmcpu_t *cpu, rvm_asmins_t *ins)
617 rword *dst = (rword*) RVM_CPUREG_GETU(cpu, ins->op1);
618 rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
620 for (n = 0; bits && n < RLST; n++) {
621 if (((rword)(1 << n)) & bits) {
622 *dst = RVM_CPUREG_GETU(cpu, n);
630 static void rvm_op_ldm(rvmcpu_t *cpu, rvm_asmins_t *ins)
633 rword *src = (rword*)RVM_CPUREG_GETU(cpu, ins->op1);
634 rword bits = RVM_CPUREG_GETU(cpu, ins->op2);
636 for (n = 0; bits && n < RLST; n++) {
637 if (((rword)(1 << n)) & bits) {
638 RVM_CPUREG_SETU(cpu, n, *src);
646 static void rvm_op_cmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
648 rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
649 rword res = (rword)(op1 - op2);
651 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op1 < op2);
652 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
653 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
654 RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT) &&
655 (res & RVM_SIGN_BIT) == (op1 & RVM_SIGN_BIT));
659 static void rvm_op_cmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
661 rword op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
662 rword res = (rword)(op1 + op2);
664 RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op1 || res < op2);
665 RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
666 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
667 RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op1 & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT) &&
668 (res & RVM_SIGN_BIT) != (op1 & RVM_SIGN_BIT));
673 static void rvm_op_nop(rvmcpu_t *cpu, rvm_asmins_t *ins)
675 // fprintf(stdout, "nop\n");
679 static void rvm_op_ret(rvmcpu_t *cpu, rvm_asmins_t *ins)
681 RVM_CPUREG_SETU(cpu, PC, RVM_CPUREG_GETU(cpu, LR));
686 static int rvm_vsnprintf(char *str, ruint size, const char *format, va_list ap)
688 return vsnprintf(str, size, format, ap);
692 static int rvm_snprintf(char *str, ruint size, const char *format, ...)
697 va_start(ap, format);
698 ret = rvm_vsnprintf(str, size, format, ap);
704 static int rvm_printf(const char *format, ...)
709 va_start(ap, format);
710 ret = vfprintf(stdout, format, ap);
716 int rvm_asm_dump_reg_to_str(unsigned char reg, char *str, ruint size)
721 ret = rvm_snprintf(str, size, "XX ");
723 ret = rvm_snprintf(str, size, "FP ");
725 ret = rvm_snprintf(str, size, "SP ");
727 ret = rvm_snprintf(str, size, "LR ");
729 ret = rvm_snprintf(str, size, "PC ");
731 ret = rvm_snprintf(str, size, "DA ");
732 else if (reg >= 0 && reg < 10)
733 ret = rvm_snprintf(str, size, "R%d ", reg);
735 ret = rvm_snprintf(str, size, "R%d", reg);
741 int rvm_asm_dump_pi_to_str(rvm_asmins_t *pi, char *str, ruint size)
743 int ret = 0, sz = size;
745 if ((ret = rvm_snprintf(str, sz, "%10s ", stropcalls[pi->opcode])) < 0)
750 if ((ret = rvm_asm_dump_reg_to_str(pi->op1, str, sz)) < 0)
755 if ((ret = rvm_snprintf(str, sz, " ")) < 0)
760 if ((ret = rvm_asm_dump_reg_to_str(pi->op2, str, sz)) < 0)
765 if ((ret = rvm_snprintf(str, sz, " ")) < 0)
770 if ((ret = rvm_asm_dump_reg_to_str(pi->op3, str, sz)) < 0)
775 if ((ret = rvm_snprintf(str, sz, " ")) < 0)
780 if ((ret = rvm_snprintf(str, sz, "0x%lx ", (unsigned long)RVM_REG_GETU(&pi->data))) < 0)
789 void rvm_asm_dump(rvm_asmins_t *pi, ruint count)
793 rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
794 rvm_printf("%s\n", buffer);
801 static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
806 ret = rvm_asm_dump_pi_to_str(pi, buffer, sizeof(buffer));
809 ret = rvm_snprintf(buffer + ret, sizeof(buffer) - ret, " ");
811 rvm_printf("%s", buffer);
813 rvm_printf("0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, FP=%ld, SP=%ld, LR=%ld, PC=%ld, DA=0x%lx, S( %c%c%c%c )",
814 RVM_CPUREG_GETU(vm, 0), RVM_CPUREG_GETU(vm, 1), RVM_CPUREG_GETU(vm, 2), RVM_CPUREG_GETU(vm, 3),
815 RVM_CPUREG_GETU(vm, 4), RVM_CPUREG_GETU(vm, 5), RVM_CPUREG_GETU(vm, 6), RVM_CPUREG_GETU(vm, 7),
816 RVM_CPUREG_GETU(vm, 8), (long int)RVM_CPUREG_GETU(vm, FP), (long int)RVM_CPUREG_GETU(vm, SP),
817 (long int)RVM_CPUREG_GETU(vm, LR), (long int)RVM_CPUREG_GETU(vm, PC), RVM_CPUREG_GETU(vm, DA),
818 vm->status & RVM_STATUS_V ? 'V' : '_',
819 vm->status & RVM_STATUS_C ? 'C' : '_',
820 vm->status & RVM_STATUS_N ? 'N' : '_',
821 vm->status & RVM_STATUS_Z ? 'Z' : '_');
826 static rvm_cpu_op ops[] = {
827 rvm_op_exit, // RVM_EXT
828 rvm_op_asr, // RVM_ASR
829 rvm_op_swi, // RVM_swi
830 rvm_op_mov, // RVM_MOV
831 rvm_op_add, // RVM_ADD
832 rvm_op_adds, // RVM_ADDS
833 rvm_op_adc, // RVM_ADC
834 rvm_op_and, // RVM_AND
835 rvm_op_bic, // RVM_BIC
836 rvm_op_clz, // RVM_CLZ
837 rvm_op_cmn, // RVM_CMN
838 rvm_op_eor, // RVM_EOR
839 rvm_op_sub, // RVM_SUB
840 rvm_op_subs, // RVM_SUBS
841 rvm_op_sbc, // RVM_SBC
842 rvm_op_mul, // RVM_MUL
843 rvm_op_mls, // RVM_MLS
844 rvm_op_muls, // RVM_MULS
845 rvm_op_not, // RVM_NOT
846 rvm_op_div, // RVM_DIV
847 rvm_op_dvs, // RVM_DVS
848 rvm_op_divs, // RVM_DIVS
851 rvm_op_str, // RVM_STR
852 rvm_op_strp, // RVM_STRP
853 rvm_op_strb, // RVM_STRB
854 rvm_op_strh, // RVM_STRH
855 rvm_op_strw, // RVM_STRW
856 rvm_op_strr, // RVM_STRR
857 rvm_op_ldr, // RVM_LDR
858 rvm_op_ldrp, // RVM_LDRP
859 rvm_op_ldrb, // RVM_LDRB
860 rvm_op_ldrh, // RVM_LDRH
861 rvm_op_ldrw, // RVM_LDRW
862 rvm_op_ldrr, // RVM_LDRR
863 rvm_op_lsl, // RVM_LSL
864 rvm_op_lsr, // RVM_LSR
865 rvm_op_stm, // RVM_STM
866 rvm_op_ldm, // RVM_LDS
867 rvm_op_sts, // RVM_STS
868 rvm_op_lds, // RVM_LDM
869 rvm_op_orr, // RVM_ORR
870 rvm_op_push, // RVM_PUSH
871 rvm_op_pop, // RVM_POP
872 rvm_op_cmp, // RVM_CMP
873 rvm_op_nop, // RVM_NOP
874 rvm_op_beq, // RVM_BEQ
875 rvm_op_bneq, // RVM_BNEQ
876 rvm_op_bleq, // RVM_BLEQ
877 rvm_op_bgeq, // RVM_BGEQ
878 rvm_op_bles, // RVM_BLES
879 rvm_op_bgre, // RVM_BGRE
880 rvm_op_ret, // RVM_RET
881 rvm_op_ror, // RVM_ROR
882 rvm_op_pushm, // RVM_PUSHM
883 rvm_op_popm, // RVM_POPM
884 rvm_op_tst, // RVM_TST
885 rvm_op_teq, // RVM_TEQ
898 rvmcpu_t *rvm_cpu_create()
902 cpu = (rvmcpu_t *)r_malloc(sizeof(*cpu));
905 r_memset(cpu, 0, sizeof(*cpu));
906 cpu->switables = r_array_create(sizeof(rvm_switable_t*));
907 cpu->stack = r_array_create(sizeof(rvmreg_t));
912 void rvm_cpu_destroy(rvmcpu_t *cpu)
914 // rvm_free(cpu->stack);
915 r_array_destroy(cpu->switables);
916 r_array_destroy(cpu->stack);
921 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
925 RVM_CPUREG_SETIP(cpu, PC, prog + off);
929 pi = RVM_CPUREG_GETIP(cpu, PC);
930 cpu->r[DA] = pi->data;
931 ops[pi->opcode](cpu, pi);
934 RVM_CPUREG_INCIP(cpu, PC, 1);
935 } while (pi->opcode);
940 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
944 RVM_CPUREG_SETIP(cpu, PC, prog + off);
948 pi = RVM_CPUREG_GETIP(cpu, PC);
949 cpu->r[DA] = pi->data;
950 ops[pi->opcode](cpu, pi);
953 rvm_cpu_dumpregs(pi, cpu);
954 RVM_CPUREG_INCIP(cpu, PC, 1);
955 } while (pi->opcode);
960 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname)
963 rvm_switable_t *swientry;
965 for (ntable = 0; ntable < cpu->switables->len; ntable++) {
966 swientry = r_array_index(cpu->switables, ntable, rvm_switable_t*);
967 for (nswi = 0; swientry[nswi].name; nswi++) {
968 if (r_strcmp(swientry[nswi].name, swiname) == 0)
969 return (rint)RVM_SWI_ID(ntable, nswi);
977 rint rvmcpu_switable_add(rvmcpu_t *cpu, rvm_switable_t *switable)
981 for (nswi = 0; switable[nswi].name; nswi++) {
982 if (rvm_cpu_getswi(cpu, switable[nswi].name) >= 0)
986 return r_array_add(cpu->switables, &switable);
990 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
994 r_memset(&a, 0, sizeof(a));
995 a.opcode = (unsigned char) opcode;
996 a.op1 = (unsigned char)op1;
997 a.op2 = (unsigned char)op2;
998 a.op3 = (unsigned char)op3;
999 RVM_REG_GETD(&a.data) = data;
1000 RVM_REG_SETTYPE(&a.data, RVM_DTYPE_DOUBLE);
1005 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
1009 r_memset(&a, 0, sizeof(a));
1010 a.opcode = (unsigned char) opcode;
1011 a.op1 = (unsigned char)op1;
1012 a.op2 = (unsigned char)op2;
1013 a.op3 = (unsigned char)op3;
1014 RVM_REG_GETP(&a.data) = data;
1015 RVM_REG_SETTYPE(&a.data, RVM_DTYPE_POINTER);
1020 rvm_asmins_t rvm_asmu(rword opcode, rword op1, rword op2, rword op3, rword data)
1024 r_memset(&a, 0, sizeof(a));
1025 a.opcode = (unsigned char) opcode;
1026 a.op1 = (unsigned char)op1;
1027 a.op2 = (unsigned char)op2;
1028 a.op3 = (unsigned char)op3;
1029 RVM_REG_GETU(&a.data) = data;
1030 RVM_REG_SETTYPE(&a.data, RVM_DTYPE_WORD);
1035 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
1039 r_memset(&a, 0, sizeof(a));
1040 a.opcode = (unsigned char) opcode;
1041 a.op1 = (unsigned char)op1;
1042 a.op2 = (unsigned char)op2;
1043 a.op3 = (unsigned char)op3;
1044 RVM_REG_GETL(&a.data) = (rword)data;
1045 RVM_REG_SETTYPE(&a.data, RVM_DTYPE_LONG);
1050 rvm_asmins_t rvm_asmi(rword opcode, rword op1, rword op2, rword op3, rint data)
1052 return rvm_asml(opcode, op1, op2, op3, data);
1056 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1060 r_memset(&a, 0, sizeof(a));
1061 a.opcode = (unsigned char) opcode;
1062 a.op1 = (unsigned char)op1;
1063 a.op2 = (unsigned char)op2;
1064 a.op3 = (unsigned char)op3;
1065 RVM_REG_GETP(&a.data) = pReloc;
1066 RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCPTR);
1071 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
1075 r_memset(&a, 0, sizeof(a));
1076 a.opcode = (unsigned char) opcode;
1077 a.op1 = (unsigned char)op1;
1078 a.op2 = (unsigned char)op2;
1079 a.op3 = (unsigned char)op3;
1080 RVM_REG_GETP(&a.data) = pReloc;
1081 RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCINDEX);
1086 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
1088 return rvm_asmu(opcode, op1, op2, op3, data);
1092 void rvm_relocate(rvm_asmins_t *code, rsize_t size)
1094 rvm_asmins_t *reloc;
1098 for (off = 0; off < size; off++, code++) {
1099 if (RVM_REG_GETTYPE(&code->data) == RVM_DTYPE_RELOCPTR) {
1100 RVM_REG_SETTYPE(&code->data, RVM_DTYPE_NONE);
1101 reloc = *((rvm_asmins_t **)RVM_REG_GETP(&code->data));
1102 RVM_REG_GETU(&code->data) = reloc - code;
1103 } else if (RVM_REG_GETTYPE(&code->data) == RVM_DTYPE_RELOCINDEX) {
1104 RVM_REG_SETTYPE(&code->data, RVM_DTYPE_NONE);
1105 relocindex = *((rulong *)RVM_REG_GETP(&code->data));
1106 RVM_REG_GETU(&code->data) = relocindex - off;