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>
32 #define RVM_MIN_REGSIZE (sizeof(rword)/8)
37 RVM_ASR, /* Arithmetic shift right: op1 = op2 >> op3, preserve the signed bit */
40 RVM_ADD, /* Add: op1 = op2 + op3 */
41 RVM_ADDS, /* Add: op1 = op2 + op3, update the status register */
42 RVM_ADC, /* Add: op1 = op2 + op3 + C, update the status register */
43 RVM_AND, /* Bitwise AND: op1 = op2 & op3, update status register */
44 RVM_BIC, /* Bit Clear: op1 = op2 & ~op3, update status register */
45 RVM_CLZ, /* Count rvm_reg_settypeLeading Zeros: op1 = leading_zeros(op2) */
46 RVM_CMN, /* Compare Negative: status register is updated based on the result: op1 + op2 */
47 RVM_EOR, /* XOR: op1 = op2 ^ op3, update the status register */
52 RVM_MLS, /* Signed multiplication: op1 = op2 * op3 */
54 RVM_NOT, /* Bitwise NOT: op1 = ~op2, Update the status register */
55 RVM_DIV, /* Divide: op1 = op2 / op3 */
56 RVM_DVS, /* Signed division: op1 = op2 / op3 */
57 RVM_DIVS, /* Divide: op1 = op2 / op3, Update the status register */
58 RVM_BL, /* Branch Link */
60 RVM_STR, /* Save: val_at_location(op2) = op1 */
61 RVM_STRP, /* Save pointer: pointer_at_location(op2) = op1 */
62 RVM_STRB, /* Save: byte_at_location(op2) = op1 */
63 RVM_STRH, /* Save: u16_at_location(op2) = op1 */
64 RVM_STRW, /* Save: u32_at_location(op2) = op1 */
65 RVM_STRR, /* Save: rev_reg_t_at_location(op2) = op1 */
66 RVM_LDR, /* Load: op1 = val_at_location(op2) */
67 RVM_LDRP, /* Load pointer: op1 = pointer_at_location(op2) */
68 RVM_LDRB, /* Load Byte: op1 = byte_at_location(op2) */
69 RVM_LDRH, /* Load Half Word: op1 = u16_at_location(op2) */
70 RVM_LDRW, /* Load Word: op1 = u32_at_location(op2) */
71 RVM_LDRR, /* Load rvmreg_t: op1 = rvmreg_t_at_location(op2) */
72 RVM_LSL, /* Logical Shift Left: op1 = op2 << op3, update the status register */
73 RVM_LSR, /* Logical Shift Right: op1 = op2 >> op3, update the status register */
76 RVM_STS, /* Store op1 on the stack at position op2 + op3, i.e. stack[op2 + op3] = op1 */
77 RVM_LDS, /* Load op1 from thes stack at position op2 + op3, i.e. op1 = stack[op2 + op3] */
78 RVM_ORR, /* ORR: op1 = op2 | op3, update the status register */
83 RVM_BEQ, /* Branch if equal */
84 RVM_BNEQ, /* Branch if not equal */
85 RVM_BLEQ, /* Branch if less or equal */
86 RVM_BGEQ, /* Branch if greater or equal */
87 RVM_BLES, /* Branch if less */
88 RVM_BGRE, /* Branch if greater */
90 RVM_ROR, /* Rotate right, the last bit rotated out updates the Carry flag */
96 /* Extended VM opcodes, */
97 ERVM_CAST, /* Cast: op1 = (op3)op2 */
98 ERVM_TYPE, /* Type: op1 = typeof(op2) */
101 ERVM_ADDS, /* Add: op1 = op2 + op3, update the status register */
102 ERVM_ADC, /* Add: op1 = op2 + op3 + C, update the status register */
103 ERVM_AND, /* Bitwise AND: op1 = op2 & op3, update status register */
104 ERVM_EOR, /* XOR: op1 = op2 ^ op3, update the status register */
109 ERVM_MLS, /* Signed multiplication: op1 = op2 * op3 */
111 ERVM_DIV, /* Divide: op1 = op2 / op3 */
112 ERVM_DVS, /* Signed division: op1 = op2 / op3 */
113 ERVM_DIVS, /* Divide: op1 = op2 / op3, Update the status register */
117 #define RVM_DTYPE_NONE 0
118 #define RVM_DTYPE_WORD RVM_DTYPE_NONE
119 #define RVM_DTYPE_UNSIGNED RVM_DTYPE_NONE
120 #define RVM_DTYPE_LONG 1
121 #define RVM_DTYPE_DOUBLE 2
122 #define RVM_DTYPE_BOOLEAN 3
123 #define RVM_DTYPE_OBJECT 4
124 #define RVM_DTYPE_STRING 5
125 #define RVM_DTYPE_ARRAY 6
126 #define RVM_DTYPE_HARRAY 7
127 #define RVM_DTYPE_REFREG 8 /* Reference pointer, points to another rrefreg_t object */
128 #define RVM_DTYPE_POINTER 9 /* Generic pointer, it can point to any memory object */
129 #define RVM_DTYPE_RELOCPTR 14 /* Relocation, using pointers */
130 #define RVM_DTYPE_RELOCINDEX 15 /* Relocation, using offsets */
131 #define RVM_DTYPE_USER 16
132 #define RVM_DTYPE_SIZE (1 << 5)
133 #define RVM_DTYPE_MASK (RVM_DTYPE_SIZE - 1)
134 #define RVM_DTYPE_MAX (RVM_DTYPE_MASK)
135 #define RVM_DTYPE_USERDEF(__n__) (RVM_DTYPE_USER + (__n__))
137 #define RVM_INFOBIT_ROBJECT (1 << 0)
138 #define RVM_INFOBIT_LAST (1 << 15)
139 #define RVM_INFOBIT_ALL (RVM_INFOBIT_ROBJECT | RVM_INFOBIT_LAST)
141 #define RVM_REGISTER_BITS (8 * sizeof(rword))
142 #define RVM_SIGN_BIT (1LU << (RVM_REGISTER_BITS - 1))
143 #define RVM_STATUS_Z (1 << 0)
144 #define RVM_STATUS_N (1 << 1)
145 #define RVM_STATUS_C (1 << 2)
146 #define RVM_STATUS_V (1 << 3)
147 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
148 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
149 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
150 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V))
152 #define RVM_STATUS_UPDATE(cpu, b, c) \
155 RVM_STATUS_SETBIT(cpu, b); \
157 RVM_STATUS_CLRBIT(cpu, b); \
181 #define DA 16 /* The DA register should never be modified manually, otherwise the result is undefined */
185 #define RVM_STACK_CHUNK 256
186 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; ASSERT(0); return; } while (0)
187 #define BIT(__shiftby__) (1 << (__shiftby__))
189 #define RVM_CPUREG_PTR(__cpu__, __r__) (&(__cpu__)->r[(__r__)])
190 #define RVM_CPUREG_GET(__cpu__, __r__) (__cpu__)->r[(__r__)]
191 #define RVM_CPUREG_SET(__cpu__, __r__, __val__) do { (__cpu__)->r[(__r__)] = (rvmreg_t)(__val__); } while (0)
193 #define RVM_REG_GETTYPE(__r__) (__r__)->type
194 #define RVM_REG_SETTYPE(__r__, __val__) do { (__r__)->type = (__val__); } while(0);
195 #define RVM_CPUREG_GETTYPE(__cpu__, __r__) RVM_REG_GETTYPE(RVM_CPUREG_PTR(__cpu__, __r__))
196 #define RVM_CPUREG_SETTYPE(__cpu__, __r__, __val__) RVM_REG_SETTYPE(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
198 #define RVM_REG_TSTFLAG(__r__, __flag__) ((__r__)->flags & (__flag__)) ? TRUE : FALSE
199 #define RVM_REG_SETFLAG(__r__, __flag__) do { (__r__)->flags |= (__flag__); } while (0)
200 #define RVM_REG_CLRFLAG(__r__, __flag__) do { (__r__)->flags &= ~(__flag__); } while (0)
201 #define RVM_CPUREG_TSTFLAG(__cpu__, __r__, __flag__) RVM_REG_TSTFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
202 #define RVM_CPUREG_SETFLAG(__cpu__, __r__, __flag__) RVM_REG_SETFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
203 #define RVM_CPUREG_CLRFLAG(__cpu__, __r__, __flag__) RVM_REG_CLRFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
205 #define RVM_REG_GETU(__r__) (__r__)->v.w
206 #define RVM_REG_SETU(__r__, __val__) do { (__r__)->v.w = (rword)(__val__); } while (0)
207 #define RVM_CPUREG_GETU(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.w
208 #define RVM_CPUREG_SETU(__cpu__, __r__, __val__) RVM_REG_SETU(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
210 #define RVM_REG_GETL(__r__) (__r__)->v.l
211 #define RVM_REG_SETL(__r__, __val__) do { (__r__)->v.l = (rlong)(__val__); } while (0)
212 #define RVM_CPUREG_GETL(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.l
213 #define RVM_CPUREG_SETL(__cpu__, __r__, __val__) RVM_REG_SETL(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
215 #define RVM_REG_GETP(__r__) (__r__)->v.p
216 #define RVM_REG_SETP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
217 #define RVM_CPUREG_GETP(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.p
218 #define RVM_CPUREG_SETP(__cpu__, __r__, __val__) RVM_REG_SETP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
220 #define RVM_REG_GETD(__r__) (__r__)->v.d
221 #define RVM_REG_SETD(__r__, __val__) do { (__r__)->v.d = (rdouble)(__val__); } while (0)
222 #define RVM_CPUREG_GETD(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.d
223 #define RVM_CPUREG_SETD(__cpu__, __r__, __val__) RVM_REG_SETD(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
225 #define RVM_REG_GETIP(__r__) (rvm_asmins_t*)((__r__)->v.p)
226 #define RVM_REG_SETIP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
227 #define RVM_CPUREG_GETIP(__cpu__, __r__) ((rvm_asmins_t*)RVM_CPUREG_PTR(__cpu__, __r__)->v.p)
228 #define RVM_CPUREG_SETIP(__cpu__, __r__, __val__) RVM_REG_SETIP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
229 #define RVM_CPUREG_INCIP(__cpu__, __r__, __val__) do {rvm_asmins_t *p = RVM_CPUREG_GETIP(__cpu__, __r__); (__cpu__)->r[(__r__)].v.p = (rpointer)(p + (__val__)); } while (0)
231 #define RVM_REG_SIZE(__r__) (__r__)->size
232 //#define RVM_REG_REF(__r__) do { if (rvm_reg_gettype(__r__) == RVM_DTYPE_REFREG) r_ref_inc((rref_t*)RVM_REG_GETP(__r__));} while (0)
233 //#define RVM_REG_UNREF(__r__) do { if (rvm_reg_gettype(__r__) == RVM_DTYPE_REFREG) r_ref_dec((rref_t*)RVM_REG_GETP(__r__));} while (0)
234 #define RVM_REG_CLEAR(__r__) do { (__r__)->v.w = 0UL; (__r__)->type = 0; (__r__)->flags = 0; } while (0)
235 #define RVM_CPUREG_CLEAR(__cpu__, __r__) RVM_REG_CLEAR(RVM_CPUREG_PTR(__cpu__, __r__))
238 #define RVM_SWI_TABLE(__op__) ((__op__) >> 16)
239 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << 16) - 1))
240 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << 16) - 1)) << 16) | ((__o__) & ((1 << 16) - 1)))
243 #define RVM_E_DIVZERO (1)
244 #define RVM_E_ILLEGAL (2)
245 #define RVM_E_CAST (3)
246 #define RVM_E_SWINUM (4)
247 #define RVM_E_SWITABLE (5)
248 #define RVM_E_ILLEGALDST (6)
250 typedef struct rvm_asmins_s rvm_asmins_t;
251 typedef struct rvmcpu_s rvmcpu_t;
252 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
253 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
255 typedef struct rvm_switable_s {
261 typedef ruint16 rvmreg_type_t;
262 typedef ruint16 rvmreg_flags_t;
264 typedef struct rvmreg_s {
270 ruint8 c[RVM_MIN_REGSIZE];
273 rvmreg_flags_t flags;
277 #define RVM_ASMINS_RELOC (1 << 0)
278 #define RVM_ASMINS_RELOCPTR (1 << 1)
280 struct rvm_asmins_s {
298 struct rvm_opmap_s *opmap;
303 rvmcpu_t *rvm_cpu_create();
304 void rvm_cpu_destroy(rvmcpu_t * vm);
305 rint rvmcpu_switable_add(rvmcpu_t * cpu, rvm_switable_t *switalbe);
306 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
307 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
308 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname);
309 void rvm_relocate(rvm_asmins_t *code, rsize_t size);
310 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data);
311 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data);
312 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data);
313 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
314 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
315 void rvm_asm_dump(rvm_asmins_t *pi, ruint count);