RPA Toolkit
214643e08bfbf40674c23f2be11eb415c5e04d03
[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_ASR,                /* Arithmetic shift right: op1 = op2 >> op3, preserve the signed bit */
38         RVM_SWI,
39         RVM_MOV,
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 */
48         RVM_SUB,
49         RVM_SUBS,
50         RVM_SBC,
51         RVM_MUL,
52         RVM_MLS,                /* Signed multiplication: op1 = op2 * op3 */
53         RVM_MULS,
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 */
59         RVM_B,                  /* Branch */
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 */
74         RVM_STM,
75         RVM_LDM,
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 */
79         RVM_PUSH,
80         RVM_POP,
81         RVM_CMP,
82         RVM_NOP,
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 */
89         RVM_RET,
90         RVM_ROR,                /* Rotate right, the last bit rotated out updates the Carry flag */
91         RVM_PUSHM,
92         RVM_POPM,
93         RVM_TST,
94         RVM_TEQ,
95 };
96
97
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__))
116
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)
120
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))
131
132 #define RVM_STATUS_UPDATE(cpu, b, c) \
133 do { \
134     if (c) \
135         RVM_STATUS_SETBIT(cpu, b); \
136     else \
137         RVM_STATUS_CLRBIT(cpu, b); \
138 } while (0)
139
140
141 #define R0 0
142 #define R1 1
143 #define R2 2
144 #define R3 3
145 #define R4 4
146 #define R5 5
147 #define R6 6
148 #define R7 7
149 #define R8 8
150 #define R9 9
151 #define R10 10
152 #define R11 11
153 #define R12 12
154 #define R13 13
155 #define R14 14
156 #define R15 15
157 #define FP R12
158 #define SP R13
159 #define LR R14
160 #define PC R15
161 #define DA 16
162 #define RLST 16
163 #define XX 255
164
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__))
168
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)
172
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__)
177
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__)
184
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__)
189
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__)
194
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__)
199
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__)
204
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)
210
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)
215
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)))
219
220
221 #define RVM_E_DIVZERO  (1)
222 #define RVM_E_ILLEGAL  (2)
223 #define RVM_E_SWINUM   (3)
224 #define RVM_E_SWITABLE (4)
225
226
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);
231
232 typedef struct rvm_switable_s {
233         const char *name;
234         rvmcpu_swi op;
235 } rvm_switable_t;
236
237
238 typedef struct rvmreg_s {
239         union {
240                 rword w;
241                 rlong l;
242                 rpointer p;
243                 rdouble d;
244                 ruint8 c[RVM_MIN_REGSIZE];
245         } v;
246         ruint16 type;
247         ruint16 flags;
248         ruint32 size;
249 } rvmreg_t;
250
251
252 struct rvm_asmins_s {
253         ruint8 opcode;
254         ruint8 op1;
255         ruint8 op2;
256         ruint8 op3;
257         rvmreg_t data;  
258 };
259
260
261 struct rvmcpu_s {
262         rvmreg_t r[DA + 1];
263         rword status;
264         rword error;
265         rword abort;
266         rarray_t *switables;
267         rarray_t *stack;
268         void *userdata;
269 };
270
271
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);
288
289
290 #ifdef __cplusplus
291 }
292 #endif
293
294
295 #endif