RPA Toolkit
246734f11741fbd7e52b04619a52eaca4ce57e79
[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 tp = RVM_CPUREG_GETL(cpu, R_TOP);
11 //      rpainput_t * ptp = &stat->instack[tp];
12 //
13 //      if (ptp->eof)
14 //              return;
15 //      ptp++;
16 //      tp++;
17 //      if (tp >= (rlong)stat->ip.serial) {
18 //              rint inc = 0;
19 //              ptp->input = stat->ip.input;
20 //              if (ptp->input < stat->end) {
21 //                      inc = r_utf8_mbtowc(&ptp->wc, (const ruchar*)stat->ip.input, (const ruchar*)stat->end);
22 //                      stat->ip.input += inc;
23 //                      stat->ip.serial += 1;
24 //                      ptp->eof = 0;
25 //              } else {
26 //                      ptp->wc = (ruint32)-1;
27 //                      ptp->eof = 1;
28 //              }
29 //      }
30 //      RVM_CPUREG_SETL(cpu, R_TOP, tp);
31 //}
32
33 static void rpavm_swi_shift(rvmcpu_t *cpu, rvm_asmins_t *ins)
34 {
35         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
36         rlong top = RVM_CPUREG_GETL(cpu, R_TOP);
37
38         if ((top = rpa_stat_shift(stat, top)) >= 0)
39                 RVM_CPUREG_SETL(cpu, R_TOP, top);
40 }
41
42 static void rpavm_matchchr_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
43 {
44         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
45         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
46         rword matched = 0;
47
48         if (flags == RPA_MATCH_OPTIONAL) {
49                 if (rpa_stat_matchchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
50                         rpavm_swi_shift(cpu, ins);
51                         matched = 1;
52                 }
53                 cpu->status = matched ? 0 : RVM_STATUS_Z;
54                 RVM_CPUREG_SETU(cpu, R0, matched);
55         } else if (flags == RPA_MATCH_MULTIPLE) {
56                 while (rpa_stat_matchchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
57                         rpavm_swi_shift(cpu, ins);
58                         matched += 1;
59                 }
60                 cpu->status = matched ? 0 : RVM_STATUS_N;
61                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
62         } else if (flags == RPA_MATCH_MULTIOPT) {
63                 while (rpa_stat_matchchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
64                         rpavm_swi_shift(cpu, ins);
65                         matched += 1;
66                 }
67                 cpu->status = matched ? 0 : RVM_STATUS_Z;
68                 RVM_CPUREG_SETU(cpu, R0, matched );
69         } else {
70                 if (rpa_stat_matchchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
71                         rpavm_swi_shift(cpu, ins);
72                         matched = 1;
73                 }
74                 cpu->status = matched ? 0 : RVM_STATUS_N;
75                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
76         }
77 }
78
79
80 static void rpavm_matchspchr_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
81 {
82         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
83         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
84         rword matched = 0;
85
86         if (flags == RPA_MATCH_OPTIONAL) {
87                 if (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
88                         rpavm_swi_shift(cpu, ins);
89                         matched = 1;
90                 }
91                 cpu->status = matched ? 0 : RVM_STATUS_Z;
92                 RVM_CPUREG_SETU(cpu, R0, matched);
93         } else if (flags == RPA_MATCH_MULTIPLE) {
94                 while (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
95                         rpavm_swi_shift(cpu, ins);
96                         matched += 1;
97                 }
98                 cpu->status = matched ? 0 : RVM_STATUS_N;
99                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
100         } else if (flags == RPA_MATCH_MULTIOPT) {
101                 while (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
102                         rpavm_swi_shift(cpu, ins);
103                         matched += 1;
104                 }
105                 cpu->status = matched ? 0 : RVM_STATUS_Z;
106                 RVM_CPUREG_SETU(cpu, R0, matched );
107         } else {
108                 if (rpa_stat_matchspchr(stat, RVM_CPUREG_GETL(cpu, R_TOP), wc) > 0) {
109                         rpavm_swi_shift(cpu, ins);
110                         matched = 1;
111                 }
112                 cpu->status = matched ? 0 : RVM_STATUS_N;
113                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
114         }
115 }
116
117
118 static void rpavm_swi_matchchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
119 {
120         rpavm_matchchr_do(cpu, ins, RPA_MATCH_NONE);
121 }
122
123
124 static void rpavm_swi_matchchr_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
125 {
126         rpavm_matchchr_do(cpu, ins, RPA_MATCH_OPTIONAL);
127 }
128
129
130 static void rpavm_swi_matchchr_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
131 {
132         rpavm_matchchr_do(cpu, ins, RPA_MATCH_MULTIPLE);
133 }
134
135
136 static void rpavm_swi_matchchr_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
137 {
138         rpavm_matchchr_do(cpu, ins, RPA_MATCH_MULTIOPT);
139 }
140
141
142
143
144 static void rpavm_swi_matchspchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
145 {
146         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_NONE);
147 }
148
149
150 static void rpavm_swi_matchspchr_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
151 {
152         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_OPTIONAL);
153 }
154
155
156 static void rpavm_swi_matchspchr_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
157 {
158         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_MULTIPLE);
159 }
160
161
162 static void rpavm_swi_matchspchr_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
163 {
164         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_MULTIOPT);
165 }
166
167
168 static void rpavm_matchrng_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
169 {
170         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
171         rpair_t pr = RVM_CPUREG_GETPAIR(cpu, ins->op1);
172         rword matched = 0;
173
174         if (flags == RPA_MATCH_OPTIONAL) {
175                 if (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
176                         rpavm_swi_shift(cpu, ins);
177                         matched = 1;
178                 }
179                 cpu->status = matched ? 0 : RVM_STATUS_Z;
180                 RVM_CPUREG_SETU(cpu, R0, matched);
181         } else if (flags == RPA_MATCH_MULTIPLE) {
182                 while (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
183                         rpavm_swi_shift(cpu, ins);
184                         matched += 1;
185                 }
186                 cpu->status = matched ? 0 : RVM_STATUS_N;
187                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
188         } else if (flags == RPA_MATCH_MULTIOPT) {
189                 while (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
190                         rpavm_swi_shift(cpu, ins);
191                         matched += 1;
192                 }
193                 cpu->status = matched ? 0 : RVM_STATUS_Z;
194                 RVM_CPUREG_SETU(cpu, R0, matched );
195         } else {
196                 if (rpa_stat_matchrng(stat, RVM_CPUREG_GETL(cpu, R_TOP), pr.p1, pr.p2) > 0) {
197                         rpavm_swi_shift(cpu, ins);
198                         matched = 1;
199                 }
200                 cpu->status = matched ? 0 : RVM_STATUS_N;
201                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
202         }
203 }
204
205
206 static void rpavm_swi_matchrng_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
207 {
208         rpavm_matchrng_do(cpu, ins, RPA_MATCH_NONE);
209 }
210
211
212 static void rpavm_swi_matchrng_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
213 {
214         rpavm_matchrng_do(cpu, ins, RPA_MATCH_OPTIONAL);
215 }
216
217
218 static void rpavm_swi_matchrng_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
219 {
220         rpavm_matchrng_do(cpu, ins, RPA_MATCH_MULTIPLE);
221 }
222
223
224 static void rpavm_swi_matchrng_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
225 {
226         rpavm_matchrng_do(cpu, ins, RPA_MATCH_MULTIOPT);
227 }
228
229
230
231 static void rpavm_swi_emitstart(rvmcpu_t *cpu, rvm_asmins_t *ins)
232 {
233         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
234         rparecord_t *rec;
235         rlong index;
236         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
237         rstr_t name = {RVM_CPUREG_GETSTR(cpu, ins->op1), RVM_CPUREG_GETSIZE(cpu, ins->op1)};
238
239         index = r_array_add(stat->records, NULL);
240         rec = (rparecord_t *)r_array_slot(stat->records, index);
241         rec->rule = name.str;
242         rec->top = tp;
243         rec->type = RPA_RECORD_START;
244         rec->input = stat->instack[tp].input;
245         rec->inputsiz = 0;
246
247 //      r_printf("START: %s(%ld)\n", name.str, (rulong)tp);
248 }
249
250
251 static void rpavm_swi_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
252 {
253         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
254         rparecord_t *rec;
255         rlong index;
256         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
257         rword tplen = RVM_CPUREG_GETU(cpu, ins->op3);
258         rstr_t name = {RVM_CPUREG_GETSTR(cpu, ins->op1), RVM_CPUREG_GETSIZE(cpu, ins->op1)};
259
260         index = r_array_add(stat->records, NULL);
261         rec = (rparecord_t *)r_array_slot(stat->records, index);
262         rec->rule = name.str;
263         rec->top = tp;
264         rec->size = tplen;
265         rec->type = RPA_RECORD_START;
266         rec->input = stat->instack[tp].input;
267         rec->inputsiz = stat->instack[tp + tplen].input - stat->instack[tp].input;
268
269         if (tplen) {
270                 rec->type = RPA_RECORD_END | RPA_RECORD_MATCH;
271 //              r_printf("MATCHED: %s(%ld, %ld): %p(%d)\n", name.str, (rulong)tp, (rulong)tplen, name.str, name.size);
272         } else {
273                 rec->type = RPA_RECORD_END;
274 //              r_printf("MATCHED: %s(%ld, %ld)\n", name.str, (rulong)tp, (rulong)tplen);
275         }
276         rpa_stat_cacheinvalidate(stat);
277 }
278
279
280 static void rpavm_swi_bxlwht(rvmcpu_t *cpu, rvm_asmins_t *ins)
281 {
282         rword wht = RVM_CPUREG_GETU(cpu, ins->op2);
283
284         RVM_CPUREG_SETU(cpu, R_WHT, wht);
285         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
286         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
287 }
288
289
290 static void rpavm_swi_getreclen(rvmcpu_t *cpu, rvm_asmins_t *ins)
291 {
292         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
293         RVM_CPUREG_SETU(cpu, ins->op1, r_array_length(stat->records));
294 }
295
296
297 static void rpavm_swi_setreclen(rvmcpu_t *cpu, rvm_asmins_t *ins)
298 {
299         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
300
301         r_array_setlength(stat->records, (ruint)RVM_CPUREG_GETU(cpu, ins->op1));
302 }
303
304
305 static void rpavm_swi_setrecid(rvmcpu_t *cpu, rvm_asmins_t *ins)
306 {
307         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
308         rparecord_t *rec;
309         rword ruleid = RVM_CPUREG_GETU(cpu, ins->op1);
310
311         rec = (rparecord_t *)r_array_lastslot(stat->records);
312         if (rec) {
313                 rec->ruleid = ruleid;
314         }
315 }
316
317
318 static void rpavm_swi_loopdetect(rvmcpu_t *cpu, rvm_asmins_t *ins)
319 {
320         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
321         rparecord_t *rec;
322         rlong len;
323         rword ruleid = RVM_CPUREG_GETU(cpu, ins->op1);
324         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
325         rword fp = RVM_CPUREG_GETU(cpu, FP);
326         rvmreg_t loo, rid, top, pfp;
327
328         RVM_CPUREG_SETU(cpu, R0, -1);
329
330         while (fp > 5) {
331                 top = RVM_STACK_READ(cpu->stack, fp - 3);
332                 loo = RVM_STACK_READ(cpu->stack, fp - 4);
333                 rid = RVM_STACK_READ(cpu->stack, fp - 5);
334
335                 if (rid.v.l == ruleid && top.v.l == tp) {
336                         RVM_CPUREG_SETU(cpu, R0, loo.v.l);
337                         break;
338                 }
339                 RVM_REG_CLEAR(&loo);
340                 pfp = RVM_STACK_READ(cpu->stack, fp - 1);
341                 fp = pfp.v.l;
342         }
343
344 //      for (len = r_array_length(stat->records); len > 0; len--) {
345 //              rec = (rparecord_t *)r_array_slot(stat->records, len - 1);
346 //              if (rec->type == (RPA_RECORD_END | RPA_RECORD_MATCH)) {
347 //                      RVM_CPUREG_SETU(cpu, R0, -1);
348 //                      break;
349 //              } else if (rec->ruleid == ruleid && rec->top == tp) {
350 //                      RVM_CPUREG_SETU(cpu, R0, RVM_CPUREG_GETU(cpu, R_LOO));
351 //                      RVM_CPUREG_SETU(cpu, R_TOP, RVM_CPUREG_GETU(cpu, R_TOP) + RVM_CPUREG_GETU(cpu, R_LOO));
352 //                      r_printf("LOO = %ld, loo = %ld\n", RVM_CPUREG_GETU(cpu, R0), loo.v.l);
353 //                      RVM_CPUREG_SETU(cpu, R0, loo.v.l);
354 //                      break;
355 //              }
356 //      }
357 }
358
359
360 static void rpavm_swi_setcache(rvmcpu_t *cpu, rvm_asmins_t *ins)
361 {
362         rparecord_t *prec;
363         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
364         rlong ruleid = RVM_CPUREG_GETL(cpu, ins->op1);
365         rlong r0 = RVM_CPUREG_GETL(cpu, ins->op2);
366         rlong rec = RVM_CPUREG_GETL(cpu, ins->op3);
367         rlong nrecords = r_array_length(stat->records) - rec;
368
369         if (!RVM_STATUS_GETBIT(cpu, RVM_STATUS_N) && !RVM_STATUS_GETBIT(cpu, RVM_STATUS_Z)) {
370                 prec = (rparecord_t *)r_array_slot(stat->records, rec);
371                 R_ASSERT(nrecords);
372                 rpa_cache_set(stat->cache, prec->top, ruleid, r0, prec, nrecords);
373         }
374 }
375
376
377 static void rpavm_swi_checkcache(rvmcpu_t *cpu, rvm_asmins_t *ins)
378 {
379         rlong i;
380         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
381         rpacachedentry_t *entry;
382         rlong ruleid = RVM_CPUREG_GETL(cpu, ins->op1);
383         rlong top = RVM_CPUREG_GETL(cpu, ins->op2);
384         rlong r0 = 0;
385         entry = rpa_cache_lookup(stat->cache, top, ruleid);
386         if (entry) {
387                 for (i = 0; i < r_array_length(entry->records); i++) {
388                         r_array_add(stat->records, r_array_slot(entry->records, i));
389                 }
390                 r0 = entry->ret;
391                 top += r0;
392                 RVM_CPUREG_SETU(cpu, R_TOP, top);
393         }
394
395         RVM_STATUS_CLRALL(cpu);
396         RVM_CPUREG_SETU(cpu, R0, r0);
397         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !r0);
398 }
399
400
401 static void rpavm_swi_setrecuid(rvmcpu_t *cpu, rvm_asmins_t *ins)
402 {
403         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
404         rparecord_t *rec;
405         rword userid = RVM_CPUREG_GETU(cpu, ins->op1);
406
407         rec = (rparecord_t *)r_array_lastslot(stat->records);
408         if (rec) {
409                 rec->userid = (ruint32)userid;
410         }
411 }
412
413 static rvm_switable_t rpavm_swi_table[] = {
414                 {"RPA_MATCHCHR_NAN", rpavm_swi_matchchr_nan},
415                 {"RPA_MATCHCHR_OPT", rpavm_swi_matchchr_opt},
416                 {"RPA_MATCHCHR_MUL", rpavm_swi_matchchr_mul},
417                 {"RPA_MATCHCHR_MOP", rpavm_swi_matchchr_mop},
418                 {"RPA_MATCHRNG_NAN", rpavm_swi_matchrng_nan},
419                 {"RPA_MATCHRNG_OPT", rpavm_swi_matchrng_opt},
420                 {"RPA_MATCHRNG_MUL", rpavm_swi_matchrng_mul},
421                 {"RPA_MATCHRNG_MOP", rpavm_swi_matchrng_mop},
422                 {"RPA_MATCHSPCHR_NAN", rpavm_swi_matchspchr_nan},
423                 {"RPA_MATCHSPCHR_OPT", rpavm_swi_matchspchr_opt},
424                 {"RPA_MATCHSPCHR_MUL", rpavm_swi_matchspchr_mul},
425                 {"RPA_MATCHSPCHR_MOP", rpavm_swi_matchspchr_mop},
426                 {"RPA_SHIFT", rpavm_swi_shift},
427                 {"RPA_EMITSTART", rpavm_swi_emitstart},
428                 {"RPA_EMITEND", rpavm_swi_emitend},
429                 {"RPA_BXLWHT", rpavm_swi_bxlwht},
430                 {"RPA_GETRECLEN", rpavm_swi_getreclen},
431                 {"RPA_SETRECLEN", rpavm_swi_setreclen},
432                 {"RPA_SETRECID", rpavm_swi_setrecid},
433                 {"RPA_LOOPDETECT", rpavm_swi_loopdetect},
434                 {"RPA_SETCACHE", rpavm_swi_setcache},
435                 {"RPA_CHECKCACHE", rpavm_swi_checkcache},
436                 {"RPA_SETRECUID", rpavm_swi_setrecuid},
437                 {NULL, NULL},
438 };
439
440
441 rvmcpu_t *rpavm_cpu_create(rulong stacksize)
442 {
443         rvmcpu_t *cpu = rvm_cpu_create(stacksize);
444         rint tableid = rvm_cpu_addswitable(cpu, "rpavm_swi_table", rpavm_swi_table);
445
446         if (tableid != RPAVM_SWI_TABLEID) {
447                 rpavm_cpu_destroy(cpu);
448                 return NULL;
449         }
450         return cpu;
451 }
452
453
454 void rpavm_cpu_destroy(rvmcpu_t * cpu)
455 {
456         rvm_cpu_destroy(cpu);
457 }
458
459