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>
25 #include "rlib/rarray.h"
26 #include "rlib/rcarray.h"
27 #include "rvm/rvmreg.h"
38 RVM_ABORT, /* Abort: set the error code, op1: error code */
40 RVM_ASR, /* Arithmetic shift right: op1 = op2 >> op3, preserve the signed bit */
43 RVM_CALL, /* if op1 is of type RVM_DTYPE_SWIID, then invoke RVM_SWIID, otherwise invoke RVM_BL */
45 RVM_MOVS, /* op1 <-- op2, compare to 0 and set the status accordingly */
46 RVM_SWP, /* op1 <--> op2 */
47 RVM_INC, /* INC: op1 = op1 + 1 */
48 RVM_DEC, /* DEC: op1 = op1 - 1 */
49 RVM_ADD, /* Add: op1 = op2 + op3 */
50 RVM_ADDS, /* Add: op1 = op2 + op3, update the status register */
51 RVM_ADC, /* Add: op1 = op2 + op3 + C, update the status register */
52 RVM_AND, /* Bitwise AND: op1 = op2 & op3, update status register */
53 RVM_BIC, /* Bit Clear: op1 = op2 & ~op3, update status register */
54 RVM_CLZ, /* Count rvm_reg_settypeLeading Zeros: op1 = leading_zeros(op2) */
55 RVM_CMN, /* Compare Negative: status register is updated based on the result: op1 + op2 */
56 RVM_XOR, /* XOR: op1 = op2 ^ op3, update the status register */
61 RVM_MLS, /* Signed multiplication: op1 = op2 * op3 */
63 RVM_NOT, /* Bitwise NOT: op1 = ~op2, Update the status register */
64 RVM_DIV, /* Divide: op1 = op2 / op3 */
65 RVM_DVS, /* Signed division: op1 = op2 / op3 */
66 RVM_DIVS, /* Divide: op1 = op2 / op3, Update the status register */
67 RVM_MOD, /* Modulo: op1 = op2 % op3 */
68 RVM_MODS, /* Modulo: op1 = op2 % op3, Update the status register */
69 RVM_BX, /* Jump to op1 */
70 RVM_BXEQ, /* Jump to op1, if equal */
71 RVM_BXNEQ, /* Jump to op1, if not equal */
73 RVM_BXLEQ, /* Branch if less or equal */
74 RVM_BXGEQ, /* Branch if greater or equal */
75 RVM_BXLES, /* Branch if less */
76 RVM_BXGRE, /* Branch if greater */
79 RVM_BXL, /* Jump to op1, link */
80 RVM_BL, /* Branch Link */
82 RVM_STR, /* Save: val_at_location(op2) = op1 */
83 RVM_STRP, /* Save pointer: pointer_at_location(op2) = op1 */
84 RVM_STRB, /* Save: byte_at_location(op2) = op1 */
85 RVM_STRH, /* Save: u16_at_location(op2) = op1 */
86 RVM_STRW, /* Save: u32_at_location(op2) = op1 */
87 RVM_STRR, /* Save: rvmreg_t_at_location(op2) = op1 */
88 RVM_LDR, /* Load: op1 = val_at_location(op2) */
89 RVM_LDRP, /* Load pointer: op1 = pointer_at_location(op2) */
90 RVM_LDRB, /* Load Byte: op1 = byte_at_location(op2) */
91 RVM_LDRH, /* Load Half Word: op1 = u16_at_location(op2) */
92 RVM_LDRW, /* Load Word: op1 = u32_at_location(op2) */
93 RVM_LDRR, /* Load rvmreg_t: op1 = rvmreg_t_at_location(op2) */
94 RVM_CFLAG, /* Clear flag */
95 RVM_CLR, /* Clear op1 */
96 RVM_CLRR, /* Clear: rvmreg_t at memory location op1 */
97 RVM_LSL, /* Logical Shift Left: op1 = op2 << op3, update the status register */
98 RVM_LSR, /* Logical Shift Right: op1 = op2 >> op3, update the status register */
99 RVM_LSRS, /* Signed Logical Shift Right: op1 = op2 >> op3, update the status register */
100 RVM_STM, /* Store multiple */
101 RVM_LDM, /* Load multiple */
102 RVM_STS, /* Store op1 on the stack at position op2 + op3, i.e. stack[op2 + op3] = op1 */
103 RVM_LDS, /* Load op1 from thes stack at position op2 + op3, i.e. op1 = stack[op2 + op3] */
104 RVM_ORR, /* ORR: op1 = op2 | op3, update the status register */
109 RVM_BEQ, /* Branch if equal */
110 RVM_BNEQ, /* Branch if not equal */
111 RVM_BLEQ, /* Branch if less or equal */
112 RVM_BGEQ, /* Branch if greater or equal */
113 RVM_BLES, /* Branch if less */
114 RVM_BGRE, /* Branch if greater */
116 RVM_ROR, /* Rotate right, the last bit rotated out updates the Carry flag */
121 RVM_ADDRS, /* Memory location of the stack at offset op2 + op3 */
123 /* Extended VM opcodes, */
124 RVM_CAST, /* Cast: op1 = (op3)op2 */
125 RVM_TYPE, /* Type: op1 = typeof(op2) */
126 RVM_SETTYPE, /* Type: op1.type = op2 */
128 RVM_ENEG, /* Negative: op1 = -op2, Update the status register */
129 RVM_EADD, /* Add: op1 = op2 + op3, update the status register */
130 RVM_ESUB, /* Subtract: op1 = op2 - op3, update the status register */
131 RVM_EMUL, /* Multiply: op1 = op2 * op3, update the status register */
132 RVM_EDIV, /* Divide: op1 = op2 / op3, update the status register */
133 RVM_EMOD, /* Modulo: op1 = op2 % op3, update the status register */
134 RVM_ELSL, /* Logical Shift Left: op1 = op2 << op3, update the status register */
135 RVM_ELSR, /* Logical Shift Right: op1 = op2 >> op3, update the status register */
136 RVM_ELSRU, /* Logical Unsigned Shift Right: op1 = op2 >>> op3, update the status register */
137 RVM_EAND, /* Bitwise AND: op1 = op2 & op3, update status register */
138 RVM_EORR, /* Bitwise OR: op1 = op2 | op3, update the status register */
139 RVM_EXOR, /* Bitwise XOR: op1 = op2 ^ op3, update the status register */
140 RVM_ENOT, /* Bitwise NOT: op1 = ~op2, Update the status register */
141 RVM_ELAND, /* Logical AND: op1 = op2 && op3, update status register */
142 RVM_ELOR, /* Logical OR: op1 = op2 || op3, update the status register */
143 RVM_ELNOT, /* Logical NOT: op1 = !op2, update the status register */
144 RVM_EEQ, /* op1 = op2 == op3 ? 1 : 0, update the status register */
145 RVM_ENOTEQ, /* op1 = op2 != op3 ? 1 : 0, update the status register */
146 RVM_EGREAT, /* op1 = op2 > op3 ? 1 : 0, update the status register */
147 RVM_EGREATEQ, /* op1 = op2 >= op3 ? 1 : 0, update the status register */
148 RVM_ELESS, /* op1 = op2 < op3 ? 1 : 0, update the status register */
149 RVM_ELESSEQ, /* op1 = op2 <= op3 ? 1 : 0, update the status register */
151 RVM_ECMP, /* Compare: status register is updated based on the result: op1 - op2 */
152 RVM_ECMN, /* Compare Negative: status register is updated based on the result: op1 + op2 */
153 RVM_ALLOCSTR, /* Allocate string in op1, op2 is pointer (char*) to string, op3 is the size */
154 RVM_ALLOCARR, /* Allocate array in op1, op2 is the size */
155 RVM_ADDRA, /* op1 is the destination memory, op2 is the array, op3 is the offset */
156 RVM_LDA, /* op1 is the destination, op2 is the array, op3 is the offset */
157 RVM_STA, /* op1 is the source, op2 is the array, op3 is the offset */
168 #define RVM_REGISTER_BITS (8 * sizeof(ruword))
169 #define RVM_SIGN_BIT (((ruword)1) << (RVM_REGISTER_BITS - 1))
170 #define RVM_STATUS_Z (1 << 0)
171 #define RVM_STATUS_N (1 << 1)
172 #define RVM_STATUS_C (1 << 2)
173 #define RVM_STATUS_V (1 << 3)
174 #define RVM_STATUS_E (1 << 4)
175 #define RVM_STATUS_ALL (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V | RVM_STATUS_E)
176 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
177 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
178 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
179 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, RVM_STATUS_ALL)
181 #define RVM_STATUS_UPDATE(cpu, b, c) \
184 RVM_STATUS_SETBIT(cpu, b); \
186 RVM_STATUS_CLRBIT(cpu, b); \
189 #define RVM_OPERAND_BITS 4
190 #define RVM_REGS_NUM (1 << RVM_OPERAND_BITS)
224 #define RLST (RVM_REGS_NUM - 1)
225 #define IP (RLST - 7)
226 #define TP (RLST - 6)
227 #define FP (RLST - 5)
228 #define SP (RLST - 4)
229 #define LR (RLST - 3)
230 #define PC (RLST - 2)
231 #define DA (RLST - 1) /* The DA register should never be modified manually, otherwise the result is undefined */
235 #define RVM_STACK_CHUNK 256
236 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; R_ASSERT(0); return; } while (0)
237 #define BIT(__shiftby__) (1 << (__shiftby__))
238 #define BITR(__f__, __l__, __r__) (((__r__) >= (__f__) && (__r__) <= (__l__)) ? BIT(__r__) : 0)
239 #define BITS(__f__, __l__) (BITR(__f__, __l__, R0)) | (BITR(__f__, __l__, R1)) | (BITR(__f__, __l__, R2)) | (BITR(__f__, __l__, R3)) | \
240 (BITR(__f__, __l__, R4)) | (BITR(__f__, __l__, R5)) | (BITR(__f__, __l__, R6)) | (BITR(__f__, __l__, R7)) | \
241 (BITR(__f__, __l__, R8)) | (BITR(__f__, __l__, R9)) | (BITR(__f__, __l__, R10)) | (BITR(__f__, __l__, R11)) | \
242 (BITR(__f__, __l__, R12)) | (BITR(__f__, __l__, R13)) | (BITR(__f__, __l__, R14)) | (BITR(__f__, __l__, R15)) | \
243 (BITR(__f__, __l__, R16)) | (BITR(__f__, __l__, R17)) | (BITR(__f__, __l__, R18)) | (BITR(__f__, __l__, R19)) | \
244 (BITR(__f__, __l__, R20)) | (BITR(__f__, __l__, R21)) | (BITR(__f__, __l__, R22)) | (BITR(__f__, __l__, R23)) | \
245 (BITR(__f__, __l__, R24)) | (BITR(__f__, __l__, R25)) | (BITR(__f__, __l__, R26)) | (BITR(__f__, __l__, R27)) | \
246 (BITR(__f__, __l__, R28)) | (BITR(__f__, __l__, R29)) | (BITR(__f__, __l__, R30)) | (BITR(__f__, __l__, R31))
248 #define RVM_OPCODE_BITS 8
249 #define RVM_SWI_TABLE_BITS 8
250 #define RVM_SWI_NUM_BITS 8
251 #define RVM_SWI_TABLE(__op__) ((__op__) >> RVM_SWI_NUM_BITS)
252 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << RVM_SWI_NUM_BITS) - 1))
253 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << RVM_SWI_TABLE_BITS) - 1)) << RVM_SWI_NUM_BITS) | ((__o__) & ((1 << RVM_SWI_NUM_BITS) - 1)))
254 #define RVM_ASMINS_OPCODE(__opcode__) ((__opcode__) & ((1 << RVM_OPCODE_BITS) - 1))
255 #define RVM_ASMINS_SWI(__opcode__) ((__opcode__) >> RVM_OPCODE_BITS)
256 #define RVM_OPSWI(__id__) (((__id__) << RVM_OPCODE_BITS) | RVM_SWI)
258 //#define RVM_STACK_WRITE(__s__, __sp__, __p__) r_carray_replace((__s__), (__sp__), (rconstpointer)(__p__));
259 //#define RVM_STACK_READ(__s__, __sp__) r_carray_index((__s__), (__sp__), rvmreg_t)
260 //#define RVM_STACK_ADDR(__s__, __sp__) r_carray_slot_expand((__s__), (__sp__))
263 #define RVM_STACK_WRITE(__s__, __sp__, __p__) do { r_memcpy(((rvmreg_t*)(__s__)) + (__sp__), (__p__), sizeof(rvmreg_t)); } while(0)
264 #define RVM_STACK_READ(__s__, __sp__) *RVM_STACK_ADDR(__s__, __sp__)
265 #define RVM_STACK_ADDR(__s__, __sp__) (((rvmreg_t*)(__s__)) + (__sp__))
266 #define RVM_STACK_CHECKSIZE(__cpu__, __s__, __sp__) ((__sp__) < (__cpu__)->stacksize ? 1 : 0)
267 #define RVM_CODE2BYTE_OFFSET(__codeoff__) ((ruword)(((rword)(__codeoff__)) * ((rword)sizeof(rvm_asmins_t))))
268 #define RVM_BYTE2CODE_OFFSET(__byteoff__) ((ruword)(((rword)(__byteoff__)) / ((rword)sizeof(rvm_asmins_t))))
270 #define RVM_E_DIVZERO (1)
271 #define RVM_E_ILLEGAL (2)
272 #define RVM_E_CAST (3)
273 #define RVM_E_SWINUM (4)
274 #define RVM_E_SWITABLE (5)
275 #define RVM_E_LVALUE (6)
276 #define RVM_E_NOMEM (7)
277 #define RVM_E_NOTFUNCTION (8)
278 #define RVM_E_NOTOBJECT (9)
279 #define RVM_E_USERABORT (10)
281 typedef struct rvm_asmins_s rvm_asmins_t;
282 typedef struct rvmcpu_s rvmcpu_t;
283 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
284 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
286 typedef struct rvm_switable_s {
291 #define RVM_CEXEC_NAN 0
292 #define RVM_CEXEC_GRE 1
293 #define RVM_CEXEC_GEQ 2
294 #define RVM_CEXEC_EQ 3
295 #define RVM_CEXEC_NEQ 4
296 #define RVM_CEXEC_LEQ 5
297 #define RVM_CEXEC_LES 6
299 struct rvm_asmins_s {
301 ruint16 op1:RVM_OPERAND_BITS;
302 ruint16 op2:RVM_OPERAND_BITS;
303 ruint16 op3:RVM_OPERAND_BITS;
314 rvmreg_t r[RVM_REGS_NUM];
318 rharray_t *switables;
319 unsigned long stacksize;
322 struct rvm_opmap_s *opmap;
335 rvmcpu_t *rvm_cpu_create_default();
336 rvmcpu_t *rvm_cpu_create(unsigned long stacksize);
337 void rvm_cpu_destroy(rvmcpu_t * vm);
338 int rvm_cpu_abort(rvmcpu_t *cpu);
339 int rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off);
340 int rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, ruword off);
341 int rvm_cpu_swilookup(rvmcpu_t *cpu, const char *tabname, const char *swiname, unsigned long size);
342 int rvm_cpu_swilookup_s(rvmcpu_t *cpu, const char *tabname, const char *swiname);
343 int rvm_cpu_addswitable(rvmcpu_t * cpu, const char *tabname, rvm_switable_t *switalbe);
344 rvmreg_t *rvm_cpu_alloc_global(rvmcpu_t *cpu);
345 int rvm_cpu_setreg(rvmcpu_t *cpu, ruword regnum, const rvmreg_t *src);
346 rvmreg_t *rvm_cpu_getreg(rvmcpu_t *cpu, ruword regnum);
347 void rvm_cpu_dumpregs( rvmcpu_t *cpu, rvm_asmins_t *pi);
348 rvm_asmins_t rvm_asm(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
349 rvm_asmins_t rvm_asma(ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size);
350 rvm_asmins_t rvm_asml(ruword opcode, ruword op1, ruword op2, ruword op3, long data);
351 rvm_asmins_t rvm_asmb(ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data);
352 rvm_asmins_t rvm_asmd(ruword opcode, ruword op1, ruword op2, ruword op3, double data);
353 rvm_asmins_t rvm_asmp(ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data);
354 rvm_asmins_t rvm_asms(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
355 rvm_asmins_t rvm_asmf(ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
356 rvm_asmins_t rvm_asm2(ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2);
358 rvm_asmins_t rvm_cond_asm(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
359 rvm_asmins_t rvm_cond_asma(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, char *data, unsigned long size);
360 rvm_asmins_t rvm_cond_asml(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, long data);
361 rvm_asmins_t rvm_cond_asmb(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, unsigned int data);
362 rvm_asmins_t rvm_cond_asmp(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, rpointer data);
363 rvm_asmins_t rvm_cond_asms(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
364 rvm_asmins_t rvm_cond_asmd(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, double data);
365 rvm_asmins_t rvm_cond_asmf(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruword data);
366 rvm_asmins_t rvm_cond_asm2(ruword cond, ruword opcode, ruword op1, ruword op2, ruword op3, ruint32 p1, ruint32 p2);
369 void rvm_asm_dump(rvm_asmins_t *pi, unsigned int count);