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 */
98 #define RVM_DTYPE_NONE 0
99 #define RVM_DTYPE_WORD RVM_DTYPE_NONE
100 #define RVM_DTYPE_LONG 1
101 #define RVM_DTYPE_DOUBLE 2
102 #define RVM_DTYPE_BOOLEAN 3
103 #define RVM_DTYPE_OBJECT 4
104 #define RVM_DTYPE_STRING 5
105 #define RVM_DTYPE_ARRAY 6
106 #define RVM_DTYPE_HARRAY 7
107 #define RVM_DTYPE_REFREG 8 /* Reference pointer, points to another rrefreg_t object */
108 #define RVM_DTYPE_POINTER 9 /* Generic pointer, it can point to any memory object */
109 #define RVM_DTYPE_RELOCPTR 14 /* Relocation, using pointers */
110 #define RVM_DTYPE_RELOCINDEX 15 /* Relocation, using offsets */
111 #define RVM_DTYPE_USER 16
112 #define RVM_DTYPE_SIZE (1 << 5)
113 #define RVM_DTYPE_MASK (RVM_DTYPE_SIZE - 1)
114 #define RVM_DTYPE_MAX (RVM_DTYPE_MASK)
115 #define RVM_DTYPE_USERDEF(__n__) (RVM_DTYPE_USER + (__n__))
117 #define RVM_INFOBIT_ROBJECT (1 << 0)
118 #define RVM_INFOBIT_LAST (1 << 15)
119 #define RVM_INFOBIT_ALL (RVM_INFOBIT_ROBJECT | RVM_INFOBIT_LAST)
121 #define RVM_REGISTER_BITS (8 * sizeof(rword))
122 #define RVM_SIGN_BIT (1LU << (RVM_REGISTER_BITS - 1))
123 #define RVM_STATUS_Z (1 << 0)
124 #define RVM_STATUS_N (1 << 1)
125 #define RVM_STATUS_C (1 << 2)
126 #define RVM_STATUS_V (1 << 3)
127 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
128 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
129 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
130 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V))
132 #define RVM_STATUS_UPDATE(cpu, b, c) \
135 RVM_STATUS_SETBIT(cpu, b); \
137 RVM_STATUS_CLRBIT(cpu, b); \
165 #define RVM_STACK_CHUNK 256
166 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; return; } while (0)
167 #define BIT(__shiftby__) (1 << (__shiftby__))
169 #define RVM_CPUREG_PTR(__cpu__, __r__) (&(__cpu__)->r[(__r__)])
170 #define RVM_CPUREG_GET(__cpu__, __r__) (__cpu__)->r[(__r__)]
171 #define RVM_CPUREG_SET(__cpu__, __r__, __val__) do { (__cpu__)->r[(__r__)] = (rvmreg_t)(__val__); } while (0)
173 #define RVM_REG_GETTYPE(__r__) (__r__)->type
174 #define RVM_REG_SETTYPE(__r__, __val__) do { (__r__)->type = (__val__); } while(0);
175 #define RVM_CPUREG_GETTYPE(__cpu__, __r__) RVM_CPUREG_GETTYPE(RVM_CPUREG_PTR(__cpu__, __r__))
176 #define RVM_CPUREG_SETTYPE(__cpu__, __r__, __val__) RVM_REG_SETTYPE(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
178 #define RVM_REG_TSTFLAG(__r__, __flag__) ((__r__)->flags & (__flag__)) ? TRUE : FALSE
179 #define RVM_REG_SETFLAG(__r__, __flag__) do { (__r__)->flags |= (__flag__); } while (0)
180 #define RVM_REG_CLRFLAG(__r__, __flag__) do { (__r__)->flags &= ~(__flag__); } while (0)
181 #define RVM_CPUREG_GETFLAG(__cpu__, __r__, __flag__) RVM_REG_TSTFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
182 #define RVM_CPUREG_SETFLAG(__cpu__, __r__, __flag__) RVM_REG_SETFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
183 #define RVM_CPUREG_CLRFLAG(__cpu__, __r__, __flag__) RVM_REG_CLRFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
185 #define RVM_REG_GETU(__r__) (__r__)->v.w
186 #define RVM_REG_SETU(__r__, __val__) do { (__r__)->v.w = (rword)(__val__); } while (0)
187 #define RVM_CPUREG_GETU(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.w
188 #define RVM_CPUREG_SETU(__cpu__, __r__, __val__) RVM_REG_SETU(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
190 #define RVM_REG_GETL(__r__) (__r__)->v.l
191 #define RVM_REG_SETL(__r__, __val__) do { (__r__)->v.l = (rlong)(__val__); } while (0)
192 #define RVM_CPUREG_GETL(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.l
193 #define RVM_CPUREG_SETL(__cpu__, __r__, __val__) RVM_REG_SETL(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
195 #define RVM_REG_GETP(__r__) (__r__)->v.p
196 #define RVM_REG_SETP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
197 #define RVM_CPUREG_GETP(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.p
198 #define RVM_CPUREG_SETP(__cpu__, __r__, __val__) RVM_REG_SETP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
200 #define RVM_REG_GETD(__r__) (__r__)->v.d
201 #define RVM_REG_SETD(__r__, __val__) do { (__r__)->v.d = (rdouble)(__val__); } while (0)
202 #define RVM_CPUREG_GETD(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.d
203 #define RVM_CPUREG_SETD(__cpu__, __r__, __val__) RVM_REG_SETD(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
205 #define RVM_REG_GETIP(__r__) (rvm_asmins_t*)((__r__)->v.p)
206 #define RVM_REG_SETIP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
207 #define RVM_CPUREG_GETIP(__cpu__, __r__) ((rvm_asmins_t*)RVM_CPUREG_PTR(__cpu__, __r__)->v.p)
208 #define RVM_CPUREG_SETIP(__cpu__, __r__, __val__) RVM_REG_SETIP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
209 #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)
211 #define RVM_REG_SIZE(__r__) (__r__)->size
212 //#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)
213 //#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)
214 #define RVM_REG_CLEAR(__r__) do { (__r__)->v.w = 0UL; (__r__)->type = 0; (__r__)->flags = 0; } while (0)
216 #define RVM_SWI_TABLE(__op__) ((__op__) >> 16)
217 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << 16) - 1))
218 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << 16) - 1)) << 16) | ((__o__) & ((1 << 16) - 1)))
221 #define RVM_E_DIVZERO (1)
222 #define RVM_E_ILLEGAL (2)
223 #define RVM_E_SWINUM (3)
224 #define RVM_E_SWITABLE (4)
227 typedef struct rvm_asmins_s rvm_asmins_t;
228 typedef struct rvmcpu_s rvmcpu_t;
229 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
230 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
232 typedef struct rvm_switable_s {
238 typedef struct rvmreg_s {
244 ruint8 c[RVM_MIN_REGSIZE];
252 struct rvm_asmins_s {
272 rvmcpu_t *rvm_cpu_create();
273 void rvm_cpu_destroy(rvmcpu_t * vm);
274 rint rvmcpu_switable_add(rvmcpu_t * cpu, rvm_switable_t *switalbe);
275 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
276 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
277 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname);
278 void rvm_relocate(rvm_asmins_t *code, rsize_t size);
279 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data);
280 rvm_asmins_t rvm_asmi(rword opcode, rword op1, rword op2, rword op3, rint data);
281 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data);
282 rvm_asmins_t rvm_asmu(rword opcode, rword op1, rword op2, rword op3, rword data);
283 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data);
284 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
285 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
286 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data);
287 void rvm_asm_dump(rvm_asmins_t *pi, ruint count);