RPA Toolkit
cb429a45d3b13ef9cd2cd77277e9d2ea6ffa14a2
[rpatk.git] / rpa2 / rpavm.c
1 #include "rpavm.h"
2 #include "rpastat.h"
3 #include "rutf.h"
4 #include "rmem.h"
5
6
7 static void rpavm_swi_shift(rvmcpu_t *cpu, rvm_asmins_t *ins)
8 {
9         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
10         rlong top = RVM_CPUREG_GETL(cpu, R_TOP);
11
12         if ((top = rpa_stat_shift(stat, top)) >= 0)
13                 RVM_CPUREG_SETL(cpu, R_TOP, top);
14 }
15
16
17 static void rpavm_swi_matchchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
18 {
19         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
20         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
21         rword matched = 0;
22
23         if (rpa_stat_matchchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
24                 rpavm_swi_shift(cpu, ins);
25                 matched = 1;
26         }
27         cpu->status = matched ? 0 : RVM_STATUS_N;
28         RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
29 }
30
31
32 static void rpavm_swi_matchchr_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
33 {
34         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
35         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
36         rword matched = 0;
37
38         if (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
39                 rpavm_swi_shift(cpu, ins);
40                 matched = 1;
41         }
42         cpu->status = matched ? 0 : RVM_STATUS_Z;
43         RVM_CPUREG_SETU(cpu, R0, matched);
44 }
45
46
47 static void rpavm_swi_matchchr_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
48 {
49         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
50         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
51         rword matched = 0;
52
53         while (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
54                 rpavm_swi_shift(cpu, ins);
55                 matched += 1;
56         }
57         cpu->status = matched ? 0 : RVM_STATUS_N;
58         RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
59 }
60
61
62 static void rpavm_swi_matchchr_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
63 {
64         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
65         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
66         rword matched = 0;
67
68         while (rpa_stat_matchchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
69                 rpavm_swi_shift(cpu, ins);
70                 matched += 1;
71         }
72         cpu->status = matched ? 0 : RVM_STATUS_Z;
73         RVM_CPUREG_SETU(cpu, R0, matched );
74 }
75
76
77 static void rpavm_swi_matchspchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
78 {
79         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
80         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
81         rword matched = 0;
82
83         if (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
84                 rpavm_swi_shift(cpu, ins);
85                 matched = 1;
86         }
87         cpu->status = matched ? 0 : RVM_STATUS_N;
88         RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
89 }
90
91
92 static void rpavm_swi_matchspchr_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
93 {
94         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
95         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
96         rword matched = 0;
97
98         if (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
99                 rpavm_swi_shift(cpu, ins);
100                 matched = 1;
101         }
102         cpu->status = matched ? 0 : RVM_STATUS_Z;
103         RVM_CPUREG_SETU(cpu, R0, matched);
104
105 }
106
107
108 static void rpavm_swi_matchspchr_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
109 {
110         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
111         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
112         rword matched = 0;
113
114         while (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
115                 rpavm_swi_shift(cpu, ins);
116                 matched += 1;
117         }
118         cpu->status = matched ? 0 : RVM_STATUS_N;
119         RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
120
121 }
122
123
124 static void rpavm_swi_matchspchr_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
125 {
126         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
127         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
128         rword matched = 0;
129
130         while (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
131                 rpavm_swi_shift(cpu, ins);
132                 matched += 1;
133         }
134         cpu->status = matched ? 0 : RVM_STATUS_Z;
135         RVM_CPUREG_SETU(cpu, R0, matched );
136 }
137
138
139 static void rpavm_swi_matchrng_peek(rvmcpu_t *cpu, rvm_asmins_t *ins)
140 {
141         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
142         rpair_t pr = RVM_CPUREG_GETPAIR(cpu, ins->op1);
143         rword matched = 0;
144
145         if (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) <= 0) {
146                 cpu->status = matched ? 0 : RVM_STATUS_N;
147                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
148         }
149 }
150
151
152 static void rpavm_swi_matchrng_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
153 {
154         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
155         rpair_t pr = RVM_CPUREG_GETPAIR(cpu, ins->op1);
156         rword matched = 0;
157
158         if (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
159                 rpavm_swi_shift(cpu, ins);
160                 matched = 1;
161         }
162         cpu->status = matched ? 0 : RVM_STATUS_N;
163         RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
164 }
165
166
167 static void rpavm_swi_matchrng_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
168 {
169         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
170         rpair_t pr = RVM_CPUREG_GETPAIR(cpu, ins->op1);
171         rword matched = 0;
172
173         if (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
174                 rpavm_swi_shift(cpu, ins);
175                 matched = 1;
176         }
177         cpu->status = matched ? 0 : RVM_STATUS_Z;
178         RVM_CPUREG_SETU(cpu, R0, matched);
179 }
180
181
182 static void rpavm_swi_matchrng_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
183 {
184         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
185         rpair_t pr = RVM_CPUREG_GETPAIR(cpu, ins->op1);
186         rword matched = 0;
187
188         while (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
189                 rpavm_swi_shift(cpu, ins);
190                 matched += 1;
191         }
192         cpu->status = matched ? 0 : RVM_STATUS_N;
193         RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
194 }
195
196
197 static void rpavm_swi_matchrng_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
198 {
199         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
200         rpair_t pr = RVM_CPUREG_GETPAIR(cpu, ins->op1);
201         rword matched = 0;
202
203         while (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
204                 rpavm_swi_shift(cpu, ins);
205                 matched += 1;
206         }
207         cpu->status = matched ? 0 : RVM_STATUS_Z;
208         RVM_CPUREG_SETU(cpu, R0, matched );
209 }
210
211
212
213 static void rpavm_swi_emithead(rvmcpu_t *cpu, rvm_asmins_t *ins)
214 {
215         rparecord_t *rec;
216         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
217         rlong index = RVM_CPUREG_GETL(cpu, R_REC);
218
219         index = r_array_add(stat->records, NULL);
220         RVM_CPUREG_SETL(cpu, R_REC, index);
221         rec = (rparecord_t *)r_array_slot(stat->records, index);
222         rec->type = RPA_RECORD_HEAD;
223 }
224
225
226 static void rpavm_swi_emittail(rvmcpu_t *cpu, rvm_asmins_t *ins)
227 {
228         rparecord_t *rec, *crec;
229         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
230         rlong index = RVM_CPUREG_GETL(cpu, R_REC);
231
232         index = r_array_add(stat->records, NULL);
233         crec = (rparecord_t *)r_array_slot(stat->records, RVM_CPUREG_GETL(cpu, R_REC));
234         RVM_CPUREG_SETL(cpu, R_REC, index);
235         rec = (rparecord_t *)r_array_slot(stat->records, index);
236         rec->type = RPA_RECORD_TAIL;
237         crec->next = index;
238 }
239
240
241 static void rpavm_swi_emitstart(rvmcpu_t *cpu, rvm_asmins_t *ins)
242 {
243         rpa_ruledata_t *ruledata = RVM_CPUREG_GETP(cpu, ins->op1);
244         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
245         rparecord_t *rec, *crec;
246         rlong index = RVM_CPUREG_GETL(cpu, R_REC);
247         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
248         rstr_t name = {(rchar*)ruledata + ruledata->name, ruledata->namesize};
249
250         if (!(ruledata->flags & RPA_RFLAG_EMITRECORD))
251                 return;
252 //      r_printf("%ld: %s, %s, tp = %ld\n", RVM_CPUREG_GETU(cpu, FP), "START", name.str, tp);
253         R_ASSERT(RVM_CPUREG_GETL(cpu, R_REC) >= 0);
254 //      index = r_array_replace(stat->records, index + 1, NULL);
255         index = r_array_add(stat->records, NULL);
256
257         /*
258          * Important: get the pointer to crec after modifying the array, because if
259          * it gets reallocated the pointer will be invalid.
260          */
261         crec = (rparecord_t *)r_array_slot(stat->records, RVM_CPUREG_GETL(cpu, R_REC));
262         RVM_CPUREG_SETL(cpu, R_REC, index);
263         rec = (rparecord_t *)r_array_slot(stat->records, index);
264         rec->rule = name.str;
265         rec->top = tp;
266         rec->ruleid = ruledata->ruleid;
267         rec->ruleuid = ruledata->ruleuid;
268         rec->type = RPA_RECORD_START;
269         rec->input = stat->instack[tp].input;
270         rec->inputsiz = 0;
271         crec->next = index;
272 }
273
274
275
276 static void rpavm_swi_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
277 {
278         rpa_ruledata_t *ruledata = RVM_CPUREG_GETP(cpu, ins->op1);
279         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
280         rparecord_t *rec, *crec;
281         rlong index = RVM_CPUREG_GETL(cpu, R_REC);
282         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
283         rword tplen = RVM_CPUREG_GETU(cpu, ins->op3);
284         rstr_t name = {(rchar*)ruledata + ruledata->name, ruledata->namesize};
285
286         if (!(ruledata->flags & RPA_RFLAG_EMITRECORD))
287                 return;
288 //      r_printf("%ld: %s, %s, tp = %ld, tplen = %ld\n", RVM_CPUREG_GETU(cpu, FP), "END ", name.str, tp, tplen);
289         R_ASSERT(RVM_CPUREG_GETL(cpu, R_REC) >= 0);
290 //      index = r_array_replace(stat->records, index + 1, NULL);
291         index = r_array_add(stat->records, NULL);
292
293         /*
294          * Important: get the pointer to crec after modifying the array, because if
295          * it gets reallocated the pointer will be invalid.
296          */
297         crec = (rparecord_t *)r_array_slot(stat->records, RVM_CPUREG_GETL(cpu, R_REC));
298         RVM_CPUREG_SETL(cpu, R_REC, index);
299         rec = (rparecord_t *)r_array_slot(stat->records, index);
300         rec->rule = name.str;
301         rec->top = tp;
302         rec->size = tplen;
303         rec->type = RPA_RECORD_END;
304         rec->ruleid = ruledata->ruleid;
305         rec->ruleuid = ruledata->ruleuid;
306         rec->input = stat->instack[tp].input;
307         rec->inputsiz = stat->instack[tp + tplen].input - stat->instack[tp].input;
308         crec->next = index;
309
310         if (tplen) {
311                 rec->type |= RPA_RECORD_MATCH;
312         }
313 }
314
315
316 static void rpavm_swi_prninfo(rvmcpu_t *cpu, rvm_asmins_t *ins)
317 {
318         rpa_ruledata_t *ruledata = RVM_CPUREG_GETP(cpu, ins->op1);
319         rstr_t name = {(rchar*)ruledata + ruledata->name, ruledata->namesize};
320
321         if (!(ruledata->flags & RPA_RFLAG_EMITRECORD))
322                 return;
323         r_printf("%s: ", name.str);
324         rvm_cpu_dumpregs(cpu, ins);
325 }
326
327
328 static void rpavm_swi_getnextrec(rvmcpu_t *cpu, rvm_asmins_t *ins)
329 {
330         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
331         rlong rec = RVM_CPUREG_GETL(cpu, ins->op2);
332
333         rparecord_t *prec = (rparecord_t *)r_array_slot(stat->records, rec);
334
335 //      r_printf("%s, rec = %ld, next = %ld\n", __FUNCTION__, rec, prec->next);
336         RVM_CPUREG_SETL(cpu, ins->op1, prec->next);
337 }
338
339
340 static void rpavm_swi_getreclen(rvmcpu_t *cpu, rvm_asmins_t *ins)
341 {
342         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
343         RVM_CPUREG_SETU(cpu, ins->op1, r_array_length(stat->records));
344 }
345
346
347 static void rpavm_swi_setreclen(rvmcpu_t *cpu, rvm_asmins_t *ins)
348 {
349         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
350
351         r_array_setlength(stat->records, (ruint)RVM_CPUREG_GETU(cpu, ins->op1));
352         RVM_CPUREG_SETL(cpu, R_REC, RVM_CPUREG_GETU(cpu, ins->op1) - 1);
353 }
354
355
356 static void rpavm_swi_getcurrec(rvmcpu_t *cpu, rvm_asmins_t *ins)
357 {
358         RVM_CPUREG_SETL(cpu, ins->op1, RVM_CPUREG_GETL(cpu, R_REC));
359 }
360
361
362 static void rpavm_swi_setcurrec(rvmcpu_t *cpu, rvm_asmins_t *ins)
363 {
364         RVM_CPUREG_SETL(cpu, R_REC, RVM_CPUREG_GETU(cpu, ins->op1));
365 }
366
367
368 static void rpavm_swi_setcache(rvmcpu_t *cpu, rvm_asmins_t *ins)
369 {
370         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
371         rlong r0 = RVM_CPUREG_GETL(cpu, R0);
372         rlong ruleid = RVM_CPUREG_GETL(cpu, ins->op1);
373         rlong prevrec = RVM_CPUREG_GETL(cpu, ins->op2);
374         rlong endrec = RVM_CPUREG_GETL(cpu, ins->op3);
375         rlong top = RVM_CPUREG_GETL(cpu, R_OTP);
376         rlong startrec = 0;
377         rparecord_t *prec = NULL;
378
379         if (stat->cache->disalbled)
380                 return;
381
382         if (r0 > 0 && prevrec != endrec) {
383                 prec = (rparecord_t *)r_array_slot(stat->records, prevrec);
384                 startrec = prec->next;
385                 prec = (rparecord_t *)r_array_slot(stat->records, startrec);
386 //              r_printf("Set the cache for: %s (%ld, %ld), top = %ld, ret = %ld, ruleid=%ld\n", prec->rule, startrec, endrec, prec->top, r0, ruleid);
387                 rpa_cache_set(stat->cache, top, ruleid, r0, startrec, endrec);
388         } else {
389                 rpa_cache_set(stat->cache, top, ruleid, r0, 0, 0);
390         }
391 }
392
393
394 static void rpavm_swi_checkcache(rvmcpu_t *cpu, rvm_asmins_t *ins)
395 {
396         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
397         rpacachedentry_t *entry;
398         rlong ruleid = RVM_CPUREG_GETL(cpu, ins->op1);
399         rlong top = RVM_CPUREG_GETL(cpu, ins->op2);
400         rlong r0 = 0;
401         entry = rpa_cache_lookup(stat->cache, top, ruleid);
402         if (entry) {
403 //              rparecord_t *prec = (rparecord_t *)r_array_slot(stat->records, entry->startrec);
404 //              r_printf("Hit the cache for: %s (%ld, %ld), r0 = %ld\n", prec->rule, entry->startrec, entry->endrec, entry->ret);
405
406                 r0 = entry->ret;
407                 if (entry->startrec != entry->endrec) {
408                         rparecord_t *crec = (rparecord_t *)r_array_slot(stat->records, RVM_CPUREG_GETL(cpu, R_REC));
409                         crec->next = entry->startrec;
410                         RVM_CPUREG_SETL(cpu, R_REC, entry->endrec);
411                 }
412                 if (r0 > 0) {
413                         top += r0;
414                         RVM_CPUREG_SETU(cpu, R_TOP, top);
415                 }
416         }
417
418         RVM_STATUS_CLRALL(cpu);
419         RVM_CPUREG_SETU(cpu, R0, r0);
420         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !r0);
421         if (r0 < 0 && entry) {
422                 RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, (r0 < 0));
423 //              r_printf("Hit the cache for: %ld, r0 = %ld\n", entry->ruleid, entry->ret);
424         }
425 }
426
427
428 static void rpavm_swi_matchchrinstr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
429 {
430         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
431         rchar *str = RVM_CPUREG_GETSTR(cpu, ins->op1);
432         rword matched = 0;
433         rword wc;
434
435         while (*str) {
436                 wc = *str++;
437                 if (rpa_stat_matchchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
438                         rpavm_swi_shift(cpu, ins);
439                         matched = 1;
440                         break;
441                 }
442         }
443         cpu->status = matched ? 0 : RVM_STATUS_N;
444         RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
445 }
446
447
448
449
450 static rvm_switable_t rpavm_swi_table[] = {
451                 {"RPA_MATCHCHR_NAN", rpavm_swi_matchchr_nan},
452                 {"RPA_MATCHCHR_OPT", rpavm_swi_matchchr_opt},
453                 {"RPA_MATCHCHR_MUL", rpavm_swi_matchchr_mul},
454                 {"RPA_MATCHCHR_MOP", rpavm_swi_matchchr_mop},
455                 {"RPA_MATCHRNG_NAN", rpavm_swi_matchrng_nan},
456                 {"RPA_MATCHRNG_OPT", rpavm_swi_matchrng_opt},
457                 {"RPA_MATCHRNG_MUL", rpavm_swi_matchrng_mul},
458                 {"RPA_MATCHRNG_MOP", rpavm_swi_matchrng_mop},
459                 {"RPA_MATCHRNG_PEEK", rpavm_swi_matchrng_peek},
460                 {"RPA_MATCHSPCHR_NAN", rpavm_swi_matchspchr_nan},
461                 {"RPA_MATCHSPCHR_OPT", rpavm_swi_matchspchr_opt},
462                 {"RPA_MATCHSPCHR_MUL", rpavm_swi_matchspchr_mul},
463                 {"RPA_MATCHSPCHR_MOP", rpavm_swi_matchspchr_mop},
464                 {"RPA_SHIFT", rpavm_swi_shift},
465                 {"RPA_SETCACHE", rpavm_swi_setcache},
466                 {"RPA_CHECKCACHE", rpavm_swi_checkcache},
467                 {"RPA_EMITSTART", rpavm_swi_emitstart},
468                 {"RPA_EMITEND", rpavm_swi_emitend},
469                 {"RPA_EMITHEAD", rpavm_swi_emithead},
470                 {"RPA_EMITTAIL", rpavm_swi_emittail},
471                 {"RPA_GETNEXTREC", rpavm_swi_getnextrec},
472                 {"RPA_PRNINFO", rpavm_swi_prninfo},
473                 {"RPA_MATCHCHRINSTR_NAN", rpavm_swi_matchchrinstr_nan},
474
475                 {"RPA_GETRECLEN", rpavm_swi_getreclen},
476                 {"RPA_SETRECLEN", rpavm_swi_setreclen},
477                 {"RPA_GETCURREC", rpavm_swi_getcurrec},
478                 {"RPA_SETCURREC", rpavm_swi_setcurrec},
479                 {NULL, NULL},
480 };
481
482
483 rvmcpu_t *rpavm_cpu_create(rulong stacksize)
484 {
485         rvmcpu_t *cpu = rvm_cpu_create(stacksize);
486         rint tableid = rvm_cpu_addswitable(cpu, "rpavm_swi_table", rpavm_swi_table);
487
488         if (tableid != RPAVM_SWI_TABLEID) {
489                 rpavm_cpu_destroy(cpu);
490                 return NULL;
491         }
492         return cpu;
493 }
494
495
496 void rpavm_cpu_destroy(rvmcpu_t * cpu)
497 {
498         rvm_cpu_destroy(cpu);
499 }
500
501