RPA Toolkit
work on RVM based parser
authorMartin Stoilov <martin@rpasearch.com>
Sun, 20 Feb 2011 07:20:41 +0000 (23:20 -0800)
committerMartin Stoilov <martin@rpasearch.com>
Sun, 20 Feb 2011 07:20:41 +0000 (23:20 -0800)
rvm/rvmcpu.c
rvm/rvmcpu.h
tests/regex-test.c

index 57cffce..9e00701 100644 (file)
@@ -69,6 +69,10 @@ static const char *stropcalls[] = {
        "RVM_BX",
        "RVM_BXEQ",
        "RVM_BXNEQ",
+       "RVM_BXLEQ",
+       "RVM_BXGEQ",
+       "RVM_BXLES",
+       "RVM_BXGRE",
        "RVM_BXL",
        "RVM_BL",
        "RVM_B",
@@ -237,7 +241,7 @@ static void rvm_op_bgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
        rword pc = 0;
 
-       if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1){
+       if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1) {
 //             if (ins->op1 != XX)
 //                     pc += RVM_CPUREG_GETU(cpu, ins->op1);
 //             if (ins->op2 != XX)
@@ -291,6 +295,38 @@ static void rvm_op_bx(rvmcpu_t *cpu, rvm_asmins_t *ins)
 }
 
 
+static void rvm_op_bxleq(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       if ((cpu->status & RVM_STATUS_N) || (cpu->status & RVM_STATUS_Z)) {
+               RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
+       }
+}
+
+
+static void rvm_op_bxgeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       if ((cpu->status & RVM_STATUS_N) == 0 || (cpu->status & RVM_STATUS_Z) == 1){
+               RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
+       }
+}
+
+
+static void rvm_op_bxles(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       if ((cpu->status & RVM_STATUS_N)) {
+               RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
+       }
+}
+
+
+static void rvm_op_bxgre(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       if ((cpu->status & RVM_STATUS_N) == 0 && (cpu->status & RVM_STATUS_Z) == 0) {
+               RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
+       }
+}
+
+
 static void rvm_op_bxeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
        if ((cpu->status & RVM_STATUS_Z)) {
@@ -566,9 +602,9 @@ static void rvm_op_ror(rvmcpu_t *cpu, rvm_asmins_t *ins)
 
 static void rvm_op_tst(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
-       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+       rword res, op1 = RVM_CPUREG_GETU(cpu, ins->op1), op2 = RVM_CPUREG_GETU(cpu, ins->op2);
        
-       res = op2 & op3;
+       res = op1 & op2;
        RVM_STATUS_CLRALL(cpu);
        RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
        RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
@@ -1750,6 +1786,10 @@ static rvm_cpu_op ops[] = {
        rvm_op_bx,                      // RVM_BX
        rvm_op_bxeq,            // RVM_BXEQ
        rvm_op_bxneq,           // RVM_BXNEQ
+       rvm_op_bxleq,           // RVM_BXLEQ
+       rvm_op_bxgeq,           // RVM_BXGEQ
+       rvm_op_bxles,           // RVM_BXLES
+       rvm_op_bxgre,           // RVM_BXGRE
        rvm_op_bxl,                     // RVM_BXL
        rvm_op_bl,                      // RVM_BL
        rvm_op_b,                       // RVM_B
index abe8a90..ee45acb 100644 (file)
@@ -68,6 +68,13 @@ enum {
        RVM_BX,                 /* Jump to op1 */
        RVM_BXEQ,               /* Jump to op1, if equal */
        RVM_BXNEQ,              /* Jump to op1, if not equal */
+
+       RVM_BXLEQ,              /* Branch if less or equal */
+       RVM_BXGEQ,              /* Branch if greater or equal */
+       RVM_BXLES,              /* Branch if less */
+       RVM_BXGRE,              /* Branch if greater */
+
+
        RVM_BXL,                /* Jump to op1, link */
        RVM_BL,                 /* Branch Link */
        RVM_B,                  /* Branch */
index 6234729..b8db1e5 100644 (file)
@@ -18,7 +18,8 @@ static int compileonly = 0;
 #define RPA_MATCH_MULTIOPT (RPA_MATCH_MULTIPLE | RPA_MATCH_OPTIONAL)
 #define R_WHT R9
 #define R_FLG R8
-#define R_TOP R7
+#define R_ARG R7
+#define R_TOP R6
 
 
 
@@ -212,7 +213,13 @@ static void rpa_matchchr_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
 
 static void rpa_matchchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
-       rpa_matchchr_do(cpu, ins, RPA_MATCH_NONE);
+       rpastat_t *stat = (rpastat_t *)cpu->userdata1;
+       rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
+
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) ? 0 : 1);
+       if (!(cpu->status & RVM_STATUS_N))
+               rpa_shift(cpu, ins);
+//     rpa_matchchr_do(cpu, ins, RPA_MATCH_NONE);
 }
 
 
@@ -372,29 +379,183 @@ void codegen_rpa_match_abc(rpa_compiler_t *co)
 }
 
 
-void codegen_rpa_match_squared(rpa_compiler_t *co)
+void codegen_rpa_match_mnode(rpa_compiler_t *co)
 {
-       rulong rulename;
+       rvm_codegen_addlabel_s(co->cg, "rpa_match_mnode");
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BLES, DA, XX, XX, 3));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_TST, R0, R_FLG, DA, RPA_MATCH_MULTIPLE));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, -4));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R_TOP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SWP, R1, R_TOP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 2));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_TST, R_FLG, DA, XX, RPA_MATCH_OPTIONAL));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, R0, DA, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+}
 
-       rulename = rvm_codegen_addstring_s(co->cg, NULL, "rpa_match_squared");
-       rvm_codegen_addlabel_s(co->cg, "rpa_match_squared");
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 0));
-       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, rulename, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
-       codegen_rpa_match_char(co, '[', ' ');
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(LR,LR)));
-       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_abc", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
-       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match", rvm_asm(RVM_BL, DA, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(LR,LR)));
-       codegen_rpa_match_char(co, ']', ' ');
+
+void codegen_rpa_mnode_nan(rpa_compiler_t *co)
+{
+       rvm_codegen_addlabel_s(co->cg, "rpa_mnode_nan");
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, R_WHT, XX, XX, 0));
+}
+
+
+void codegen_rpa_mnode_opt(rpa_compiler_t *co)
+{
+       rvm_codegen_addlabel_s(co->cg, "rpa_mnode_opt");
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXGRE, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, DA, DA, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+}
+
+
+void codegen_rpa_mnode_mul(rpa_compiler_t *co)
+{
+       rvm_codegen_addlabel_s(co->cg, "rpa_mnode_mul");
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_XOR, R1, R1, R1, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R0, R0, R1, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, R0, R_TOP, R1, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_ELNOT, R2, R0, XX, 0));
-       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, rulename, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -5));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, R1, DA, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
+}
+
+
+void codegen_rpa_mnode_mop(rpa_compiler_t *co)
+{
+       rvm_codegen_addlabel_s(co->cg, "rpa_mnode_mop");
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 3));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, DA, DA, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_XOR, R1, R1, R1, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R0, R0, R1, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -5));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, R1, DA, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
+}
+
+
+
+void codegen_rpa_match_xyz(rpa_compiler_t *co)
+{
+       rulong ruleidx;
+       const rchar *rule = "rpa_match_xyz";
+       const rchar *ruleend = "rpa_match_xyz_end";
+
+       ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
+       rvm_codegen_addlabel_s(co->cg, rule);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
+
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_ARG, DA, XX, 'x'));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_matchonly_char", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_mnode_nan", rvm_asm(RVM_BL, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_ARG, DA, XX, 'y'));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_matchonly_char", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_mnode_opt", rvm_asm(RVM_BL, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_ARG, DA, XX, 'z'));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_matchonly_char", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_mnode_nan", rvm_asm(RVM_BL, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
+
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R_TOP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SWP, R1, R_TOP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+       rvm_codegen_addlabel_s(co->cg, ruleend);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
 }
 
 
+void codegen_rpa_match_squared(rpa_compiler_t *co)
+{
+       rulong ruleidx;
+       const rchar *rule = "rpa_match_squared";
+       const rchar *ruleend = "rpa_match_squared_end";
+
+       ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
+       rvm_codegen_addlabel_s(co->cg, rule);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
+
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_FLG, DA, XX, RPA_MATCH_NONE));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_ARG, DA, XX, '['));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_matchonly_char", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match_mnode", rvm_asm(RVM_BL, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_xyz", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_mnode_mop", rvm_asm(RVM_BL, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_FLG, DA, XX, RPA_MATCH_NONE));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_ARG, DA, XX, ']'));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_matchonly_char", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match_mnode", rvm_asm(RVM_BL, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R_TOP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SWP, R1, R_TOP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+       rvm_codegen_addlabel_s(co->cg, ruleend);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+
+}
+
+
+
+
 /*
  * R0 Char
  * R1 Flags
@@ -409,7 +570,7 @@ void rpa_match_char(rpa_compiler_t *co)
        rvm_codegen_addlabel_s(co->cg, "rpa_match_char");
        rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, R_WHT, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, R_ARG, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, 3));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_TST, R0, R_FLG, DA, RPA_MATCH_MULTIPLE));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, -3));
@@ -427,6 +588,17 @@ void rpa_match_char(rpa_compiler_t *co)
 }
 
 
+void rpa_matchonly_char(rpa_compiler_t *co)
+{
+       rvm_codegen_addlabel_s(co->cg, "rpa_matchonly_char");
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, R_ARG, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+}
+
+
 int main(int argc, char *argv[])
 {
        rvmcpu_t *cpu;
@@ -465,25 +637,33 @@ int main(int argc, char *argv[])
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, SP, DA, XX, co->fpoff));
 
        rvm_codegen_addins(co->cg, rvm_asm(RPA_SHIFT, XX, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_FLG, DA, XX, RPA_MATCH_MULTIPLE));
-       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_WHT, DA, XX, 'a'));
-       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match_char", rvm_asm(RVM_BL, DA, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
-       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "root_end", rvm_asm(RVM_BLES, DA, XX, XX, 0));
 
-       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_FLG, DA, XX, RPA_MATCH_NONE));
-       rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_WHT, DA, XX, 'b'));
-       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match_char", rvm_asm(RVM_BL, DA, XX, XX, 0));
 
-       rvm_codegen_addlabel_s(co->cg, "root_end");
+//     rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_FLG, DA, XX, RPA_MATCH_NONE));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_squared", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_mnode_mul", rvm_asm(RVM_BL, DA, XX, XX, 0));
+
+
+//     rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_xyz_p", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
+//     rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match_mnode", rvm_asm(RVM_BL, DA, XX, XX, 0));
+
        rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xabc));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
 
        rpa_match_char(co);
+       rpa_matchonly_char(co);
+       codegen_rpa_match_xyz(co);
+       codegen_rpa_match_squared(co);
+       codegen_rpa_match_mnode(co);
        codegen_rpa_match(co);
        codegen_rpa_match_mul(co);
        codegen_rpa_match_abc(co);
-       codegen_rpa_match_squared(co);
+
+       codegen_rpa_mnode_nan(co);
+       codegen_rpa_mnode_opt(co);
+       codegen_rpa_mnode_mul(co);
+       codegen_rpa_mnode_mop(co);
+
 
        if (rvm_codegen_relocate(co->cg, &err) < 0) {
                r_printf("Unresolved symbol: %s\n", err->name->str);