RPA Toolkit
added loopy/nonloopy branches
authorMartin Stoilov <martin@rpasearch.com>
Mon, 7 Mar 2011 01:05:41 +0000 (17:05 -0800)
committerMartin Stoilov <martin@rpasearch.com>
Mon, 7 Mar 2011 01:05:41 +0000 (17:05 -0800)
rpa2/rpacompiler.c
rpa2/rpacompiler.h
rpa2/rpavm.c
rvm/rvmcpu.c
rvm/rvmcpu.h
testrpa2/rpacompiler-ruleloop.c

index bb205ab..ed68161 100644 (file)
@@ -6,7 +6,11 @@
 void rpacompiler_mnode_nan(rpa_compiler_t *co)
 {
        rvm_codegen_addlabel_s(co->cg, "rpacompiler_mnode_nan");
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, R_WHT, XX, XX, 0));
+       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_BX, LR, XX, XX, 0));
 }
 
 
@@ -107,10 +111,9 @@ rint rpa_compiler_loop_begin(rpa_compiler_t *co, const rchar *name, ruint namesi
        exp.start = rvm_codegen_getcodesize(co->cg);
        rvm_codegen_addins(co->cg, rvm_asm(RPA_LOOPDETECT, DA, R_TOP, XX, exp.start));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_BLES, DA, XX, XX, 5));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 3));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BLES, DA, XX, XX, 4));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
 
        rvm_codegen_addins(co->cg, rvm_asm(RPA_GETRECLEN, R0, XX, XX, 0));
@@ -140,12 +143,24 @@ rint rpa_compiler_loop_end(rpa_compiler_t *co)
 {
        rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
 
+       /*
+        * Load R_TOP from the stack and check if we have made a progress
+        */
        rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R2, SP, DA, -3));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R2, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_BLEQ, DA, XX, XX, 9));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 4));
 
+       /*
+        * If R_LOO is 0, nothing matched - goto end
+        */
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 9));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
+
+       /*
+        * Loop again
+        */
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R0, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_PRN, R_LOO, XX, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, exp.emitidx, rvm_asm(RPA_EMITEND, DA, R2, R_LOO, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_SETRECID, DA, XX, XX, exp.start));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_TOP, R2, XX, 0));
@@ -153,6 +168,42 @@ rint rpa_compiler_loop_end(rpa_compiler_t *co)
        rvm_codegen_addins(co->cg, rvm_asm(RVM_STS, R1, SP, DA, -4));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.loopidx, rvm_asm(RVM_B, DA, XX, XX, 0));
 
+       /*
+        * End the loop successfully R0 > 0
+        */
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, R_LOO, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_TOP)|BIT(R_LOO)|BIT(R_WHT)|BIT(LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_SETRECLEN, R1, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R_TOP, R_TOP, R0, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+       rvm_codegen_redefinelabel(co->cg, exp.endidx);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R0)|BIT(R_TOP)|BIT(R_LOO)|BIT(R_WHT)|BIT(LR)));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_SETRECLEN, R0, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+
+       return 0;
+}
+
+
+rint rpa_compiler_loop_end_old(rpa_compiler_t *co)
+{
+       rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
+
+       /*
+        * Load R_TOP from the stack and check if we have made a progress
+        */
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R2, SP, DA, -3));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R2, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BLEQ, DA, XX, XX, 8));
+
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R0, XX, 0));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, exp.emitidx, rvm_asm(RPA_EMITEND, DA, R2, R_LOO, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_SETRECID, DA, XX, XX, exp.start));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_TOP, R2, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_GETRECLEN, R1, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_STS, R1, SP, DA, -4));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.loopidx, rvm_asm(RVM_B, DA, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, R_LOO, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_TOP)|BIT(R_LOO)|BIT(R_WHT)|BIT(LR)));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_SETRECLEN, R1, XX, XX, 0));
@@ -163,16 +214,13 @@ rint rpa_compiler_loop_end(rpa_compiler_t *co)
        rvm_codegen_redefinelabel(co->cg, exp.endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R0)|BIT(R_TOP)|BIT(R_LOO)|BIT(R_WHT)|BIT(LR)));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_SETRECLEN, R0, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
 
-
        return 0;
 }
 
 
-
 rint rpa_compiler_rule_begin(rpa_compiler_t *co, const rchar *name, ruint namesize)
 {
        rpa_ruledef_t exp;
@@ -216,7 +264,7 @@ rint rpa_compiler_rule_end(rpa_compiler_t *co)
        rvm_codegen_redefinelabel(co->cg, exp.endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R0)|BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_SETRECLEN, R0, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        return 0;
 }
@@ -247,7 +295,7 @@ rint rpa_compiler_exp_end(rpa_compiler_t *co, ruint qflag)
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_redefinelabel(co->cg, exp.endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_JUMP, exp.labelidx, rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
@@ -285,7 +333,7 @@ rint rpa_compiler_altexp_end(rpa_compiler_t *co, ruint qflag)
        rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
 
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_redefinelabel(co->cg, exp.endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
@@ -332,7 +380,7 @@ rint rpa_compiler_branch_end(rpa_compiler_t *co, ruint qflag)
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_redefinelabel(co->cg, exp.endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_JUMP, exp.labelidx, rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
@@ -351,6 +399,56 @@ rint rpa_compiler_branch_end(rpa_compiler_t *co, ruint qflag)
 }
 
 
+rint rpa_compiler_loopybranch_begin(rpa_compiler_t *co)
+{
+       rpa_ruledef_t exp;
+       rchar endlabel[64];
+
+       exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
+       r_snprintf(endlabel, sizeof(endlabel) - 1, "__begin:%ld", rvm_codegen_getcodesize(co->cg));
+       exp.labelidx = rvm_codegen_addlabel_s(co->cg, endlabel);
+       exp.start = rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
+       r_snprintf(endlabel, sizeof(endlabel) - 1, "__end:%ld", exp.start);
+       exp.endidx = rvm_codemap_invalid_add_s(co->cg->codemap, endlabel);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.endidx, rvm_asm(RVM_BLEQ, DA, XX, XX, 0));
+
+       r_array_add(co->expressions, &exp);
+       return 0;
+}
+
+
+rint rpa_compiler_loopybranch_end(rpa_compiler_t *co, ruint qflag)
+{
+       return rpa_compiler_branch_end(co, qflag);
+}
+
+
+rint rpa_compiler_nonloopybranch_begin(rpa_compiler_t *co)
+{
+       rpa_ruledef_t exp;
+       rchar endlabel[64];
+
+       exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
+       r_snprintf(endlabel, sizeof(endlabel) - 1, "__begin:%ld", rvm_codegen_getcodesize(co->cg));
+       exp.labelidx = rvm_codegen_addlabel_s(co->cg, endlabel);
+       exp.start = rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
+       r_snprintf(endlabel, sizeof(endlabel) - 1, "__end:%ld", exp.start);
+       exp.endidx = rvm_codemap_invalid_add_s(co->cg->codemap, endlabel);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
+
+       r_array_add(co->expressions, &exp);
+       return 0;
+}
+
+
+rint rpa_compiler_nonloopybranch_end(rpa_compiler_t *co, ruint qflag)
+{
+       return rpa_compiler_branch_end(co, qflag);
+}
+
+
 rint rpa_compiler_class_begin(rpa_compiler_t *co)
 {
        rpa_ruledef_t exp;
@@ -372,7 +470,7 @@ rint rpa_compiler_class_end(rpa_compiler_t *co, ruint qflag)
        rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
 
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_redefinelabel(co->cg, exp.endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
@@ -415,7 +513,7 @@ rint rpa_compiler_notexp_end(rpa_compiler_t *co, ruint qflag)
        rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
 
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_redefinelabel(co->cg, exp.endidx);
index 6cb49d6..0a7d993 100644 (file)
@@ -48,6 +48,12 @@ rint rpa_compiler_altexp_end(rpa_compiler_t *co, ruint qflag);
 rint rpa_compiler_branch_begin(rpa_compiler_t *co);
 rint rpa_compiler_branch_end(rpa_compiler_t *co, ruint qflag);
 
+rint rpa_compiler_loopybranch_begin(rpa_compiler_t *co);
+rint rpa_compiler_loopybranch_end(rpa_compiler_t *co, ruint qflag);
+
+rint rpa_compiler_nonloopybranch_begin(rpa_compiler_t *co);
+rint rpa_compiler_nonloopybranch_end(rpa_compiler_t *co, ruint qflag);
+
 rint rpa_compiler_class_begin(rpa_compiler_t *co);
 rint rpa_compiler_class_end(rpa_compiler_t *co, ruint qflag);
 
index 76637a4..52c4660 100644 (file)
@@ -27,8 +27,6 @@ static void rpavm_swi_shift(rvmcpu_t *cpu, rvm_asmins_t *ins)
                }
        }
        RVM_CPUREG_SETL(cpu, R_TOP, tp);
-       r_printf("shift (R_TOP = %d) instack.wc = %c(%d)\n", (rint)RVM_CPUREG_GETL(cpu, R_TOP), stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc, (rint)stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc);
-
 }
 
 
@@ -38,8 +36,6 @@ static void rpavm_matchchr_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
        rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
        rword matched = 0;
 
-       r_printf("(R_TOP = %d) instack.wc = %c, wc = %c\n", (rint)RVM_CPUREG_GETL(cpu, R_TOP), stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc, wc );
-
        if (flags == RPA_MATCH_OPTIONAL) {
                if (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
                        rpavm_swi_shift(cpu, ins);
index 9db9b0e..ef39791 100644 (file)
@@ -43,6 +43,7 @@ static const char *stropcalls[] = {
        "RVM_SWIID",
        "RVM_CALL",
        "RVM_MOV",
+       "RVM_MOVS",
        "RVM_SWP",
        "RVM_INC",
        "RVM_DEC",
@@ -379,6 +380,17 @@ static void rvm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
 }
 
 
+static void rvm_op_movs(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword op2 = RVM_CPUREG_GETU(cpu, ins->op2);;
+
+       RVM_CPUREG_SETU(cpu, ins->op1, op2);
+       RVM_STATUS_CLRALL(cpu);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !op2);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, op2 & RVM_SIGN_BIT);
+}
+
+
 static void rvm_op_swp(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
        rvmreg_t tmp = RVM_CPUREG_GET(cpu, ins->op1);
@@ -1768,6 +1780,7 @@ static rvm_cpu_op ops[] = {
        rvm_op_swiid,           // RVM_SWIID
        rvm_op_call,            // RVM_CALL
        rvm_op_mov,                     // RVM_MOV
+       rvm_op_movs,            // RVM_MOVS
        rvm_op_swp,                     // RVM_SWP
        rvm_op_inc,                     // RVM_INC
        rvm_op_dec,                     // RVM_DEC
index 350f072..3b75557 100644 (file)
@@ -42,6 +42,7 @@ enum {
        RVM_SWIID,
        RVM_CALL,               /* if op1 is of type RVM_DTYPE_SWIID, then invoke RVM_SWIID, otherwise invoke RVM_BL */
        RVM_MOV,
+       RVM_MOVS,               /* op1 <-- op2, compare to 0 and set the status accordingly */
        RVM_SWP,                /* op1 <--> op2 */
        RVM_INC,                /* INC: op1 = op1 + 1 */
        RVM_DEC,                /* DEC: op1 = op1 - 1 */
index 726db40..c60aa3d 100644 (file)
@@ -18,35 +18,26 @@ void code_rpa_match_aloop(rpa_compiler_t *co, rpastat_t *stat)
        rpa_compiler_loop_begin_s(co, "rpa_match_aloop");
        rpa_compiler_altexp_begin(co);
 
-       rpa_compiler_branch_begin(co);
-
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
-       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLEQ, DA, XX, XX, 0));
+       rpa_compiler_loopybranch_begin(co);
        rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_aloop", rvm_asm(RPA_BXLWHT, R_MNODE_NAN, DA, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
        rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'a'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'b'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'c'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_loopybranch_end(co, RPA_MATCH_NONE);
 
-       rpa_compiler_branch_end(co, RPA_MATCH_NONE);
-
-
-       rpa_compiler_branch_begin(co);
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 7));
+       rpa_compiler_nonloopybranch_begin(co);
        rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'a'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'b'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'c'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-
-
-       rpa_compiler_branch_end(co, RPA_MATCH_NONE);
+       rpa_compiler_nonloopybranch_end(co, RPA_MATCH_NONE);
 
        rpa_compiler_altexp_end(co, RPA_MATCH_NONE);
        rpa_compiler_loop_end(co);
@@ -59,10 +50,7 @@ void code_rpa_match_xloop(rpa_compiler_t *co, rpastat_t *stat)
        rpa_compiler_loop_begin_s(co, "rpa_match_xloop");
        rpa_compiler_altexp_begin(co);
 
-       rpa_compiler_branch_begin(co);
-
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
-       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLEQ, DA, XX, XX, 0));
+       rpa_compiler_loopybranch_begin(co);
        rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_xloop", rvm_asm(RPA_BXLWHT, R_MNODE_NAN, DA, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
 
@@ -78,19 +66,13 @@ void code_rpa_match_xloop(rpa_compiler_t *co, rpastat_t *stat)
 
        rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_aloop", rvm_asm(RPA_BXLWHT, R_MNODE_NAN, DA, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rpa_compiler_branch_end(co, RPA_MATCH_NONE);
+       rpa_compiler_loopybranch_end(co, RPA_MATCH_NONE);
 
-//     rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
-//     rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 2));
-//     rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
 
-
-       rpa_compiler_branch_begin(co);
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 3));
+       rpa_compiler_nonloopybranch_begin(co);
        rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_aloop", rvm_asm(RPA_BXLWHT, R_MNODE_NAN, DA, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rpa_compiler_branch_end(co, RPA_MATCH_NONE);
+       rpa_compiler_nonloopybranch_end(co, RPA_MATCH_NONE);
 
        rpa_compiler_altexp_end(co, RPA_MATCH_NONE);
        rpa_compiler_loop_end(co);
@@ -103,25 +85,21 @@ void code_rpa_matchmnode(rpa_compiler_t *co, rpastat_t *stat)
 
        rpa_compiler_exp_begin(co);
 
-/*
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'x'));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'X'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'y'));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'Y'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'z'));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'Z'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-*/
        rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_xloop", rvm_asm(RPA_BXLWHT, R_MNODE_NAN, DA, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
 
-/*
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'z'));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'Z'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'z'));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'Z'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'z'));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'Z'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-*/
 
        rpa_compiler_exp_end(co, RPA_MATCH_NONE);
 
@@ -138,13 +116,13 @@ int main(int argc, char *argv[])
        rpastat_t *stat;
        ruint mainoff;
        rint i;
-       char teststr[] = "abcabcabcXXXabcabcXXXabcabcababababzzzzzzzzzzzzzzzzzzzzzzzzzzz";
+       char teststr[] = "XYZabcabcabcXXXabcabcXXXabcabcabcabcZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
 
        co = rpa_compiler_create();
        stat = rpa_stat_create(4096);
        rvm_cpu_addswitable(stat->cpu, common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+40);
+       rpa_stat_init(stat, teststr, teststr, teststr+50);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_LOO, DA, XX, 5));