RPA Toolkit
work on the alloc/dealloc system
[rpatk.git] / rvm / rvmcpu.h
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 #ifndef _RVMCPU_H_
22 #define _RVMCPU_H_
23
24 #include "rtypes.h"
25 #include "rarray.h"
26
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 #define RVM_MIN_REGSIZE (sizeof(rword)/8)
33
34
35 enum {
36         RVM_EXT = 0,
37         RVM_PRN,
38         RVM_ASR,                /* Arithmetic shift right: op1 = op2 >> op3, preserve the signed bit */
39         RVM_SWI,
40         RVM_MOV,
41         RVM_ADD,                /* Add: op1 = op2 + op3 */
42         RVM_ADDS,               /* Add: op1 = op2 + op3, update the status register */
43         RVM_ADC,                /* Add: op1 = op2 + op3 + C, update the status register */
44         RVM_AND,                /* Bitwise AND: op1 = op2 & op3, update status register */
45         RVM_BIC,                /* Bit Clear: op1 = op2 & ~op3, update status register */
46         RVM_CLZ,                /* Count rvm_reg_settypeLeading Zeros: op1 = leading_zeros(op2) */
47         RVM_CMN,                /* Compare Negative: status register is updated based on the result: op1 + op2 */
48         RVM_XOR,                /* XOR: op1 = op2 ^ op3, update the status register */
49         RVM_SUB,
50         RVM_SUBS,
51         RVM_SBC,
52         RVM_MUL,
53         RVM_MLS,                /* Signed multiplication: op1 = op2 * op3 */
54         RVM_MULS,
55         RVM_NOT,                /* Bitwise NOT: op1 = ~op2, Update the status register */
56         RVM_DIV,                /* Divide: op1 = op2 / op3 */
57         RVM_DVS,                /* Signed division: op1 = op2 / op3 */  
58         RVM_DIVS,               /* Divide: op1 = op2 / op3, Update the status register */
59         RVM_BX,                 /* Jump to op1 */
60         RVM_BL,                 /* Branch Link */
61         RVM_B,                  /* Branch */
62         RVM_STR,                /* Save: val_at_location(op2) = op1 */
63         RVM_STRP,               /* Save pointer: pointer_at_location(op2) = op1 */
64         RVM_STRB,               /* Save: byte_at_location(op2) = op1 */
65         RVM_STRH,               /* Save: u16_at_location(op2) = op1 */
66         RVM_STRW,               /* Save: u32_at_location(op2) = op1 */
67         RVM_STRR,               /* Save: rvmreg_t_at_location(op2) = op1 */
68         RVM_LDR,                /* Load: op1 = val_at_location(op2) */
69         RVM_LDRP,               /* Load pointer: op1 = pointer_at_location(op2) */
70         RVM_LDRB,               /* Load Byte: op1 = byte_at_location(op2) */
71         RVM_LDRH,               /* Load Half Word: op1 = u16_at_location(op2) */
72         RVM_LDRW,               /* Load Word: op1 = u32_at_location(op2) */
73         RVM_LDRR,               /* Load rvmreg_t: op1 = rvmreg_t_at_location(op2) */
74         RVM_CLRR,               /* Clear: rvmreg_t at memory location op1 */
75         RVM_LSL,                /* Logical Shift Left: op1 = op2 << op3, update the status register */
76         RVM_LSR,                /* Logical Shift Right: op1 = op2 >> op3, update the status register */
77         RVM_LSRS,               /* Signed Logical Shift Right: op1 = op2 >> op3, update the status register */
78         RVM_STM,                /* Store multiple */
79         RVM_LDM,                /* Load multiple */
80         RVM_STS,                /* Store op1 on the stack at position op2 + op3, i.e. stack[op2 + op3] = op1 */
81         RVM_LDS,                /* Load op1 from thes stack at position op2 + op3, i.e. op1 = stack[op2 + op3] */
82         RVM_ORR,                /* ORR: op1 = op2 | op3, update the status register */
83         RVM_PUSH,
84         RVM_POP,
85         RVM_CMP,
86         RVM_NOP,
87         RVM_BEQ,                /* Branch if equal */
88         RVM_BNEQ,               /* Branch if not equal */
89         RVM_BLEQ,               /* Branch if less or equal */
90         RVM_BGEQ,               /* Branch if greater or equal */
91         RVM_BLES,               /* Branch if less */
92         RVM_BGRE,               /* Branch if greater */
93         RVM_RET,
94         RVM_ROR,                /* Rotate right, the last bit rotated out updates the Carry flag */
95         RVM_PUSHM,
96         RVM_POPM,
97         RVM_TST,
98         RVM_TEQ,
99         RVM_CLR,                /* Clear op1. If the reg has dynamic memory associated with with it (RVM_INFOBIT_ROBJECT) it will be cleared */
100
101 /* Extended VM opcodes, */
102         RVM_CAST,               /* Cast: op1 = (op3)op2 */
103         RVM_TYPE,               /* Type: op1 = typeof(op2) */
104         RVM_EMOV,
105         RVM_EADD,               /* Add: op1 = op2 + op3 */
106         RVM_ESUB,               /* Subtract: op1 = op2 - op3 */
107         RVM_EMUL,               /* Multiply: op1 = op2 * op3 */
108         RVM_EDIV,               /* Divide: op1 = op2 / op3 */
109         RVM_ELSL,               /* Logical Shift Left: op1 = op2 << op3, update the status register */
110         RVM_ELSR,               /* Logical Shift Right: op1 = op2 >> op3, update the status register */
111         RVM_EAND,               /* Bitwise AND: op1 = op2 & op3, update status register */
112         RVM_EORR,               /* Logical OR: op1 = op2 | op3, update the status register */
113         RVM_EXOR,               /* LOGICAL XOR: op1 = op2 ^ op3, update the status register */
114         RVM_ENOT,               /* Bitwise NOT: op1 = ~op2, Update the status register */
115         RVM_ECMP,               /* Compare: status register is updated based on the result: op1 - op2 */
116         RVM_ECMN,               /* Compare Negative: status register is updated based on the result: op1 + op2 */
117         RVM_ALLOCSTR    /* Allocate string in op1, op2 is pointer (char*) to string, op3 is the size */
118 };
119
120
121 #define RVM_DTYPE_NONE 0
122 #define RVM_DTYPE_WORD RVM_DTYPE_NONE
123 #define RVM_DTYPE_UNSIGNED RVM_DTYPE_NONE
124 #define RVM_DTYPE_LONG 1
125 #define RVM_DTYPE_POINTER 2                     /* Generic pointer, it can point to any memory object */
126 #define RVM_DTYPE_DOUBLE 3
127 #define RVM_DTYPE_BOOLEAN 4
128 #define RVM_DTYPE_STRING 5
129 #define RVM_DTYPE_ARRAY 6
130 #define RVM_DTYPE_HARRAY 7
131 #define RVM_DTYPE_REFREG 8                      /* Reference pointer, points to another rrefreg_t object */
132 #define RVM_DTYPE_RELOCPTR 14           /* Relocation, using pointers */
133 #define RVM_DTYPE_RELOCINDEX 15         /* Relocation, using offsets */
134 #define RVM_DTYPE_USER 16
135 #define RVM_DTYPE_SIZE (1 << 5)
136 #define RVM_DTYPE_MASK (RVM_DTYPE_SIZE - 1)
137 #define RVM_DTYPE_MAX (RVM_DTYPE_MASK)
138 #define RVM_DTYPE_USERDEF(__n__) (RVM_DTYPE_USER + (__n__))
139
140 #define RVM_INFOBIT_ROBJECT (1 << 0)
141 #define RVM_INFOBIT_LAST (1 << 15)
142 #define RVM_INFOBIT_ALL (RVM_INFOBIT_ROBJECT | RVM_INFOBIT_LAST)
143
144 #define RVM_REGISTER_BITS (8 * sizeof(rword))
145 #define RVM_SIGN_BIT (1LU << (RVM_REGISTER_BITS - 1))
146 #define RVM_STATUS_Z (1 << 0)
147 #define RVM_STATUS_N (1 << 1)
148 #define RVM_STATUS_C (1 << 2)
149 #define RVM_STATUS_V (1 << 3)
150 #define RVM_STATUS_GETBIT(cpu, bit) ((cpu)->status & (bit))
151 #define RVM_STATUS_SETBIT(cpu, bit) do { (cpu)->status |= (bit); } while (0)
152 #define RVM_STATUS_CLRBIT(cpu, bit) do { (cpu)->status &= ~(bit); } while (0)
153 #define RVM_STATUS_CLRALL(cpu) RVM_STATUS_CLRBIT(cpu, (RVM_STATUS_Z | RVM_STATUS_N | RVM_STATUS_C | RVM_STATUS_V))
154
155 #define RVM_STATUS_UPDATE(cpu, b, c) \
156 do { \
157     if (c) \
158         RVM_STATUS_SETBIT(cpu, b); \
159     else \
160         RVM_STATUS_CLRBIT(cpu, b); \
161 } while (0)
162
163
164 #define R0 0
165 #define R1 1
166 #define R2 2
167 #define R3 3
168 #define R4 4
169 #define R5 5
170 #define R6 6
171 #define R7 7
172 #define R8 8
173 #define R9 9
174 #define R10 10
175 #define R11 11
176 #define R12 12
177 #define R13 13
178 #define R14 14
179 #define R15 15
180 #define R16 16
181 #define R17 17
182 #define R18 18
183 #define R19 19
184 #define R20 20
185 #define R21 21
186 #define R22 22
187 #define R23 23
188 #define R24 24
189 #define R25 25
190 #define R26 26
191 #define R27 27
192 #define R28 28
193 #define R29 29
194 #define R30 30
195 #define R31 31
196
197 #define FP R26
198 #define SP R27
199 #define LR R28
200 #define PC R29
201 #define DA 30           /* The DA register should never be modified manually, otherwise the result is undefined */
202 #define XX 31
203 #define RLST 31
204
205 #define RVM_STACK_CHUNK 256
206 #define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; ASSERT(0); return; } while (0)
207 #define BIT(__shiftby__) (1 << (__shiftby__))
208
209 #define RVM_CPUREG_PTR(__cpu__, __r__) (&(__cpu__)->r[(__r__)])
210 #define RVM_CPUREG_GET(__cpu__, __r__) (__cpu__)->r[(__r__)]
211 #define RVM_CPUREG_SET(__cpu__, __r__, __val__) do { (__cpu__)->r[(__r__)] = (rvmreg_t)(__val__); } while (0)
212
213 #define RVM_REG_GETTYPE(__r__) (__r__)->type
214 #define RVM_REG_SETTYPE(__r__, __val__) do { (__r__)->type = (__val__); } while(0);
215 #define RVM_CPUREG_GETTYPE(__cpu__, __r__) RVM_REG_GETTYPE(RVM_CPUREG_PTR(__cpu__, __r__))
216 #define RVM_CPUREG_SETTYPE(__cpu__, __r__, __val__) RVM_REG_SETTYPE(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
217
218 #define RVM_REG_TSTFLAG(__r__, __flag__) ((__r__)->flags & (__flag__)) ? TRUE : FALSE
219 #define RVM_REG_SETFLAG(__r__, __flag__) do { (__r__)->flags |= (__flag__); } while (0)
220 #define RVM_REG_CLRFLAG(__r__, __flag__) do { (__r__)->flags &= ~(__flag__); } while (0)
221 #define RVM_CPUREG_TSTFLAG(__cpu__, __r__, __flag__) RVM_REG_TSTFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
222 #define RVM_CPUREG_SETFLAG(__cpu__, __r__, __flag__) RVM_REG_SETFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
223 #define RVM_CPUREG_CLRFLAG(__cpu__, __r__, __flag__) RVM_REG_CLRFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
224
225 #define RVM_REG_GETU(__r__) (__r__)->v.w
226 #define RVM_REG_SETU(__r__, __val__) do { (__r__)->v.w = (rword)(__val__); } while (0)
227 #define RVM_CPUREG_GETU(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.w
228 #define RVM_CPUREG_SETU(__cpu__, __r__, __val__) RVM_REG_SETU(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
229
230 #define RVM_REG_GETL(__r__) (__r__)->v.l
231 #define RVM_REG_SETL(__r__, __val__) do { (__r__)->v.l = (rlong)(__val__); } while (0)
232 #define RVM_CPUREG_GETL(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.l
233 #define RVM_CPUREG_SETL(__cpu__, __r__, __val__) RVM_REG_SETL(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
234
235 #define RVM_REG_GETP(__r__) (__r__)->v.p
236 #define RVM_REG_SETP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
237 #define RVM_CPUREG_GETP(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.p
238 #define RVM_CPUREG_SETP(__cpu__, __r__, __val__) RVM_REG_SETP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
239
240 #define RVM_REG_GETD(__r__) (__r__)->v.d
241 #define RVM_REG_SETD(__r__, __val__) do { (__r__)->v.d = (rdouble)(__val__); } while (0)
242 #define RVM_CPUREG_GETD(__cpu__, __r__) RVM_CPUREG_PTR(__cpu__, __r__)->v.d
243 #define RVM_CPUREG_SETD(__cpu__, __r__, __val__) RVM_REG_SETD(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
244
245 #define RVM_REG_GETIP(__r__) (rvm_asmins_t*)((__r__)->v.p)
246 #define RVM_REG_SETIP(__r__, __val__) do { (__r__)->v.p = (rpointer)(__val__); } while (0)
247 #define RVM_REG_INCIP(__r__, __val__) do {rvm_asmins_t *p = RVM_REG_GETIP(__r__); (__r__)->v.p = (rpointer)(p + (__val__)); } while (0)
248 #define RVM_CPUREG_GETIP(__cpu__, __r__) ((rvm_asmins_t*)RVM_CPUREG_PTR(__cpu__, __r__)->v.p)
249 #define RVM_CPUREG_SETIP(__cpu__, __r__, __val__) RVM_REG_SETIP(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
250 #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)
251
252 #define RVM_REG_SIZE(__r__) (__r__)->size
253 //#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)
254 //#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)
255 #define RVM_REG_CLEAR(__r__) do { (__r__)->v.w = 0UL; (__r__)->type = 0; (__r__)->flags = 0;  } while (0)
256 #define RVM_CPUREG_CLEAR(__cpu__, __r__) RVM_REG_CLEAR(RVM_CPUREG_PTR(__cpu__, __r__))
257
258
259 #define RVM_OPCODE_BITS 8
260 #define RVM_SWI_TABLE_BITS 10
261 #define RVM_SWI_NUM_BITS 8
262 #define RVM_SWI_TABLE(__op__) ((__op__) >> RVM_SWI_NUM_BITS)
263 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << RVM_SWI_NUM_BITS) - 1))
264 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << RVM_SWI_TABLE_BITS) - 1))  << RVM_SWI_NUM_BITS) | ((__o__) & ((1 << RVM_SWI_NUM_BITS) - 1)))
265 #define RVM_ASMINS_OPCODE(__opcode__) ((__opcode__) & ((1 << RVM_OPCODE_BITS) - 1))
266 #define RVM_ASMINS_SWI(__opcode__) ((__opcode__) >> RVM_OPCODE_BITS)
267 #define RVM_OPSWI(__id__) (((__id__) << RVM_OPCODE_BITS) | RVM_SWI)
268
269 #define RVM_E_DIVZERO           (1)
270 #define RVM_E_ILLEGAL           (2)
271 #define RVM_E_CAST                      (3)
272 #define RVM_E_SWINUM            (4)
273 #define RVM_E_SWITABLE          (5)
274 #define RVM_E_ILLEGALDST        (6)
275
276 typedef struct rvm_asmins_s rvm_asmins_t;
277 typedef struct rvmcpu_s rvmcpu_t;
278 typedef void (*rvmcpu_swi)(rvmcpu_t *cpu, rvm_asmins_t *ins);
279 typedef void (*rvm_cpu_op)(rvmcpu_t *cpu, rvm_asmins_t *ins);
280
281 typedef struct rvm_switable_s {
282         const char *name;
283         rvmcpu_swi op;
284 } rvm_switable_t;
285
286
287 typedef ruint16 rvmreg_type_t;
288 typedef ruint16 rvmreg_flags_t;
289
290 typedef struct rvmreg_s {
291         union {
292                 rword w;
293                 rlong l;
294                 rpointer p;
295                 rdouble d;
296                 ruint8 c[RVM_MIN_REGSIZE];
297         } v;
298         rvmreg_type_t type;
299         rvmreg_flags_t flags;
300         ruint32 size;
301 } rvmreg_t;
302
303 #define RVM_ASMINS_RELOC (1 << 0)
304 #define RVM_ASMINS_RELOCPTR (1 << 1)
305
306 struct rvm_asmins_s {
307         union {
308                 rword u;
309                 rdouble d;
310         } data;
311         ruint16 op1:5;
312         ruint16 op2:5;
313         ruint16 op3:5;
314         ruint32 opcode:7;
315         ruint32 swi:18;
316         ruint32 type:3;
317         ruint32 flags:4;
318 };
319
320 struct rvm_opmap_s;
321
322 struct rvmcpu_s {
323         rvmreg_t r[DA + 1];
324         rword status;
325         rword error;
326         rword abort;
327         rarray_t *switables;
328         rarray_t *stack;
329         struct rvm_opmap_s *opmap;
330         void *userdata;
331 };
332
333
334 rvmcpu_t *rvm_cpu_create();
335 void rvm_cpu_destroy(rvmcpu_t * vm);
336 rint rvmcpu_switable_add(rvmcpu_t * cpu, rvm_switable_t *switalbe);
337 rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
338 rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
339 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname);
340 void rvm_relocate(rvm_asmins_t *code, rsize_t size);
341 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data);
342 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data);
343 rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data);
344 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data);
345 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
346 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
347 void rvm_asm_dump(rvm_asmins_t *pi, ruint count);
348
349
350 #ifdef __cplusplus
351 }
352 #endif
353
354
355 #endif