changeset 280:affb054fe920

lrexpr fix. rexpr in MIPS fix.
author kono
date Sun, 23 May 2004 15:27:25 +0900
parents 3e8ba7024d25
children 1d60bbd8d3f8
files .gdbinit Changes mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-code.h mc-codegen.c mc-parse.c stdio.h test/code-gen.c
diffstat 10 files changed, 415 insertions(+), 205 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Sat May 22 13:00:03 2004 +0900
+++ b/.gdbinit	Sun May 23 15:27:25 2004 +0900
@@ -1,5 +1,5 @@
 tb main
-run  -s test/float.c
+run  -s test/arg.c
 # run  -s -ob00.s mc-parse.c
 # run -s test/code-gen-all.c
 define regs 
--- a/Changes	Sat May 22 13:00:03 2004 +0900
+++ b/Changes	Sun May 23 15:27:25 2004 +0900
@@ -4393,3 +4393,55 @@
 
 なんか構造体の先頭はレジスタに置くみたいね... いいけど。
 $5,$6,$7 か。
+
+continuation frame は、$sp=$fp にするの? 関数引数は
+$fpに積んでいるから、そうする必要があるわけだけど。
+そうすると$fp を毎回動かさないといけないんだよね。
+まぁ、PowerPCでも、そうしているわけだけど。
+
+jal 後に $gp を書き戻すわけだけど、そのアドレスは
+決まっているし、毎回セーブする必要もないけど。
+$sp 相対だとまずいなぁ。
+
+fmask,mask とかも要らないんじゃないの? そもそも
+なんでいるんだろう?
+
+(gdb) x/20i carg1
+0x400a80 <carg1>:       lui     $gp,0xfc0
+0x400a84 <carg1+4>:     addiu   $gp,$gp,30128
+0x400a88 <carg1+8>:     addu    $gp,$gp,$t9
+0x400a8c <carg1+12>:    addiu   $sp,$sp,-144
+0x400a90 <carg1+16>:    sw      $gp,32($sp)
+0x400a94 <carg1+20>:    move    $s8,$sp
+0x400a98 <carg1+24>:    sw      $s2,16($s8)
+0x400a9c <carg1+28>:    sw      $s1,20($s8)
+0x400aa0 <carg1+32>:    lw      $t3,-32692($gp)
+0x400aa4 <carg1+36>:    lw      $a0,0($t3)
+0x400aa8 <carg1+40>:    lui     $t2,0xf000
+
+というように .cp 関連は変換される。本当は自分でやった
+方が良いんだけど。
+
+ブランチは jal みたいには変換されないのか。まずい?
+
+0x400b00 <carg1+128>:   move    $a1,$s5
+0x400b04 <carg1+132>:   move    $a2,$s4
+0x400b08 <carg1+136>:   move    $a3,$s3
+0x400b0c <carg1+140>:   lw      $t9,-32664($gp)
+0x400b10 <carg1+144>:   jalr    $t9
+0x400b14 <carg1+148>:   nop
+0x400b18 <carg1+152>:   lw      $gp,32($s8)
+
+やっぱり sp 相対で $gp はセーブされるのか。jalr と
+自分で明示する方が安心か。
+
+  *.i が作られるのは良いが、 .include で
+ファイル名がずれる。出力ファイルに相対して
+ .i を作るべき。
+
+a.c b.c のようにつなげると止まらなくなる。(-Dのループか?)
+
+結構、比較のバグが残っているじゃん。定数比較でembugしたかもね。
+
+long long の比較は int の比較から作る汎用ルーチンを作った方が
+良くない?
--- a/mc-code-ia32.c	Sat May 22 13:00:03 2004 +0900
+++ b/mc-code-ia32.c	Sun May 23 15:27:25 2004 +0900
@@ -1593,8 +1593,22 @@
 }
 
 void
-rexpr(int e1, int l1, char *s,int t)
-{       
+rexpr(int e1, int l1, int cond,int t)
+{
+    char *s;
+    switch(car(e1)) {
+    case GT:  s=code_gt(cond);	break;
+    case UGT: s=code_ugt(cond);	break;
+    case GE:  s=code_ge(cond);	break;
+    case UGE: s=code_uge(cond);	break;
+    case LT:  s=code_ge(!cond);	break;
+    case ULT: s=code_uge(!cond);break;
+    case LE:  s=code_gt(!cond);	break;
+    case ULE: s=code_ugt(!cond);break;
+    case EQ:  s=code_eq(cond);	break;
+    case NEQ: s=code_eq(!cond);	break;
+    default: error(-1);
+    }
     g_expr(list3(CMP,cadr(e1),caddr(e1)));
     printf("\tj%s\t_%d\n",s,l1);
 }
@@ -2329,32 +2343,47 @@
 void
 lrexpr(int e1, int e2,int l1, int op,int cond)
 {
-    int e3;
+    int l2;
+    code_save_stacks();
     g_expr(e1);
     emit_lpush();
     g_expr(e2);
-    ltosop(LSUB,USE_CREG,(e3==emit_lpop()));
-//    printf("\tpopl %%eax\n\tpopl %%edx\n");  // emit_pop_free
+    // we are sure %ecx,%ebx is free
+    printf("\tpopl %%ecx\n");   // LSW
+    printf("\tpopl %%ebx\n");   // MSW
+    printf("\tsubl %%edx,%%ebx\n");
+    l2 = fwdlabel();
+    // cond==0 jump on false condtion   ( if(x) => rexpr(..  cond=0 ...) )
     switch(op) {
     case LOP+GT:
-        pcond(code_gt(cond),l1); break;
     case LOP+GE:
-        pcond(code_ge(cond),l1); break;
+        pcond(code_gt(1),cond?l1:l2);
+        pcond(code_eq(0),cond?l2:l1);
+        break;
+    case LOP+UGT:
+    case LOP+UGE:
+        pcond(code_ugt(1),cond?l1:l2);
+        pcond(code_eq(0), cond?l2:l1);
+        break;
     case LOP+EQ:
-        pcond(code_eq(cond),l1); break;
+        pcond(code_eq(0),(cond?l2:l1));
+        pcond(code_eq(cond),l1);
+        break;
     case LOP+NEQ:
-        pcond(code_eq(!cond),l1); break;
-    case LOP+LT:
-        pcond(code_ge(!cond),l1); break;
-    case LOP+LE:
-        pcond(code_gt(!cond),l1); break;
-    case LOP+UGT:
-        pcond(code_ugt(cond),l1); break;
-    case LOP+UGE:
-        pcond(code_uge(cond),l1); break;
+        pcond(code_eq(0),(cond?l1:l2));
+        pcond(code_eq(!cond),l1);
+        break;
     default:
         error(-1);
     }
+    printf("\tsubl %%eax,%%ecx\n");
+    switch(op) {
+    case LOP+GT:  pcond(code_gt(cond),  l1); break;
+    case LOP+GE:  pcond(code_ge(cond),  l1); break;
+    case LOP+UGT: pcond(code_ugt(cond), l1); break;  
+    case LOP+UGE: pcond(code_uge(cond), l1); break;  
+    }  
+    fwddef(l2); 
 }
 
 int emit_lpop()
--- a/mc-code-mips.c	Sat May 22 13:00:03 2004 +0900
+++ b/mc-code-mips.c	Sun May 23 15:27:25 2004 +0900
@@ -340,10 +340,11 @@
 #define CALLER_ARG(l) ((l)+arg_offset1)
 #define CALLEE_ARG(l) ((l)+arg_offset1)
 
-static void
-code_offset_set(int *lvar_offsetv_p,int *r1_offsetv_p)
+static int
+code_offset_set(NMTBL *fnptr)
 {
     int lvar_offsetv,r1_offsetv;
+    // int code_f = (fnptr->sc==CODE);
 
     disp &= -SIZE_OF_INT;
     lvar_offsetv = round16(-disp) +
@@ -364,8 +365,8 @@
 );
     printf("# mask_label $L_%d=0x%x\n",mask_label,code_mask());
     printf("# mask_offset$L_%d=%d\n",mask_offset_label,code_mask_offset());
-    printf("#fmask_label $L_%d=0x%x\n",fmask_label,code_fmask());
-    printf("#fmask_offset$L_%d=%d\n",fmask_offset_label,code_fmask_offset());
+    printf("# fmask_label $L_%d=0x%x\n",fmask_label,code_fmask());
+    printf("# fmask_offset$L_%d=%d\n",fmask_offset_label,code_fmask_offset());
     printf("# cprestore  $L_%d=%d\n",cprestore_label ,round16(max_func_args*SIZE_OF_INT));
    printf("#\n");
    printf("# callee arg top=\t%d\n",CALLEE_ARG(0)+r1_offsetv);
@@ -391,8 +392,7 @@
     fprintf(asi,"$L_%d=%d\n",r1_offset_label,r1_offsetv);
     fprintf(asi,"$L_%d=%d\n",lvar_offset_label,lvar_offsetv);
 
-    *lvar_offsetv_p=lvar_offsetv;
-    *r1_offsetv_p= r1_offsetv;
+    return r1_offsetv;
 }
 
 static void
@@ -2179,16 +2179,18 @@
 
 void
 code_jmp(char *s) {
-    // max_reg_var = REG_VAR_BASE-REG_VAR_MIN;
-    // max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
-    printf("\tj $L_%s\n",s);
+    // jump to continuation means use all register variable
+    max_reg_var = REG_VAR_BASE-REG_VAR_MIN;
+    max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
+    printf("\tj %s\n",s);
 }
 
 
 void
 code_indirect_jmp(int e2) {
-    // max_reg_var = REG_VAR_BASE-REG_VAR_MIN;
-    // max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
+    // jump to continuation means use all register variable
+    max_reg_var = REG_VAR_BASE-REG_VAR_MIN;
+    max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN;
     use_int(e2);
     printf("\tj %s\n",register_name(e2));
 }
@@ -2645,27 +2647,70 @@
     if (!asi) error(-1);
 }
 
-void
-rexpr(int e1, int l1, char *s,int t)
-{       
-    int op = car(e1);
+static void
+pcond(int op, int r2,int r1,int r0,int cond,int l1)
+{
+    char *slt  = "slt";
+    char *sltu = "sltu";
+    char *eq = "eq";
+    char *ne = "ne";
+    int t;
+printf("# pcond %d cond %d\n",op,cond);
+    switch(op+(!cond)*BNOT) {
+    case GT:  case LE+BNOT:
+		    t=r1;r1=r0;r0=t;
+    case LT:  case GE+BNOT:
+		    eq = ne;
+		    break;
+    case UGT: case ULE+BNOT:
+		    t=r1;r1=r0;r0=t;
+    case ULT: case UGE+BNOT:
+		    eq = ne; slt = sltu;
+		    break;
+    case ULE: case UGT+BNOT:
+		    t=r1;r1=r0;r0=t;
+    case UGE: case ULT+BNOT:
+		    slt = sltu;
+		    break;
+    case LE:  case GT+BNOT:
+		    t=r1;r1=r0;r0=t;
+    case GE:  case LT+BNOT:
+    case EQ:  case NEQ+BNOT:
+		    break;
+    case NEQ: case EQ+BNOT:   
+		    eq = ne;
+		    break;
+    default:        error(-1);
+    }
+
     if (op==EQ||op==NEQ) {
-        op = s?CMPEQ:CMPNEQ;
-	g_expr(list3(op,cadr(e1),caddr(e1)));
-	printf(",$L_%d\n",l1);
+	printf("\tb%s\t%s,%s,$L_%d\n",eq,
+	    register_name(r0),
+	    register_name(r1),
+	    l1);
     } else {
-	if (t==INT) {
-	    if (op==LE||op==GE) op=CMPGE;
-	    else op=CMP;
-	} else {
-	    if (op==ULE||op==UGE) op=UCMPGE;
-	    else op=UCMP;
-	}
-	g_expr(list3(op,cadr(e1),caddr(e1)));
-	printf("\tb%s %s,$0,$L_%d\n",s,register_name(cmpreg),l1);
+	printf("\t%s\t%s,%s,%s\n",slt,
+	    register_name(r2),
+	    register_name(r1),
+	    register_name(r0));
+	printf("\tb%s %s,$0,$L_%d\n",eq,register_name(r2),l1);
     }
 }
 
+void
+rexpr(int e1, int l1, int cond,int t)
+{       
+    int e2;
+    int op = car(e1);
+
+    g_expr(cadr(e1));
+    emit_push();
+    g_expr(caddr(e1));
+    e2 = emit_pop(1);
+    pcond(op, e2,e2,ireg,cond,l1);
+    emit_pop_free(e2);
+}
+
 #define CMP_C1T (-1)
 
 void
@@ -2801,23 +2846,24 @@
     else
 	printf("\t.align 3\n");
     if (stmode!=STATIC)
-	printf(".globl %s\n",name);
+    printf("\t.globl\t%s\n",name);
 #ifdef DOT_SIZE
     printf("\t.type\t%s,@function\n",name);
 #endif
-
+    printf(".ent %s\n",name);
     printf("%s:\n",name);
-    printf("\t.frame $fp,$L_%d,$31\n",0);
-    printf("\t.mask  0x%x,%d\n",code_mask(),0);
-    printf("\t.fmask 0x%x,%d\n",code_fmask(),0);
-
+    printf("\t.frame $fp,$L_%d,$31\n",r1_offset_label=fwdlabel());
+    printf("\t.mask  $L_%d,$L_%d\n",mask_label=fwdlabel(),
+	mask_offset_label=fwdlabel());
+    printf("\t.fmask  $L_%d,$L_%d\n",fmask_label=fwdlabel(),
+	fmask_offset_label=fwdlabel());
     printf("\t.set noreorder\n");
     printf("\t.cpload $25\n");
     printf("\t.set reorder\n");
-    printf("\tsubu $sp,$sp,$L_%d\n", r1_offset_label = fwdlabel());
-    printf("\t.cprestore %d\n",max_func_args);
+    printf("\tsubu $sp,$sp,$L_%d\n",r1_offset_label);
+    printf("\t.cprestore $L_%d\n",cprestore_label=fwdlabel());
+    printf("\tmove  $fp,$sp\n");
     lvar_offset_label = fwdlabel();
-
     max_func_args = 0;
 }
 
@@ -2833,15 +2879,9 @@
 void
 code_leave(char *name)
 {
-    int r1_offsetv;
-    disp&= -SIZE_OF_INT;
-    r1_offsetv = -disp+max_func_args*SIZE_OF_INT+code_disp_offset;
-
-    printf("L_%d=%d\n",r1_offset_label,r1_offsetv);
-
+    code_offset_set(fnptr);
     local_table();
     printf("\t.end    %s\n",name);
-    // free_all_register();
 }
 
 void
@@ -2856,7 +2896,8 @@
 
     lvar_offset_label = fwdlabel();
 
-    printf("\t.globl\t%s\n",name);
+    if (stmode!=STATIC)
+	printf("\t.globl\t%s\n",name);
     printf(".ent %s\n",name);
     printf("%s:\n",name);
     printf("\t.frame $fp,$L_%d,$31\n",r1_offset_label=fwdlabel());
@@ -2891,7 +2932,6 @@
 {
     int retcont1=0,sz;
     int r1_offsetv;
-    int lvar_offsetv;
 
     if (control) {
 	code_set_return_register(1);
@@ -2927,7 +2967,7 @@
 	fwddef(retcont1);
     }
 
-    code_offset_set(&lvar_offsetv,&r1_offsetv);
+    r1_offsetv = code_offset_set(fnptr);
 
     printf("\tmove    $sp,$fp\n");
     printf("\tlw      $31,$L_%d-%d($sp)\n",r1_offset_label,arg_offset);
@@ -4022,22 +4062,12 @@
 
 
 /* 64bit int part */
-static void
-pcond(int op,char *s,int l1)
-{
-    if (op==LOP+EQ||op==LOP+NEQ) {
-	 printf(",$L_%d\n",l1);
-    } else {
-	 printf("\tb%s %s,$0,$L_%d\n",s,register_name(cmpreg),l1);
-    }
-}
-
+
+#if 0
 static int
 lcmp(int op,int cond)
 {
-    if (op==LOP+EQ||op==LOP+NEQ) {
-	return ((op==LOP+EQ)^cond)?CMPNEQ:CMPEQ;
-    } else if (op==LOP+UGT||op==LOP+UGE) {
+    if (op==LOP+UGT||op==LOP+UGE) {
 	return UCMP;
     } else if (op==LOP+LE||op==LOP+GE) {
 	return CMPGE;
@@ -4045,61 +4075,45 @@
 	return CMP;
     }
 }
+#endif
 
 void
 lrexpr(int e1, int e2,int l1, int op,int cond)
 {
-    int reg;
-    int e3,op1;
+    int reg,regh,regl,e3h,e3l;
+    int e3,l2,cr0=-1;
     g_expr(e1);
     emit_lpush();
     g_expr(e2);
     e3 = emit_lpop();
     if (!is_longlong_reg(creg)) error(-1);
     reg = lreg;
-
-    tosop(op1=lcmp(op,cond),regv_h(reg),regv_h(e3));
+    l2 = fwdlabel();
+    if (!(op==LOP+EQ||op==LOP+NEQ))
+	cr0 = get_register();
+    regh = regv_h(reg); regl = regv_l(reg);
+    e3h =  regv_h(e3);  e3l = regv_l(e3);
     switch(op) {
-    case LOP+GT:
-        pcond(op,code_gt(cond),l1); break;
-    case LOP+GE:
-        pcond(op,code_ge(cond),l1); break;
+    case LOP+GT: case LOP+GE:
+	pcond(GT,  cr0,e3h,regh,1,cond?l1:l2);
+	pcond(NEQ, cr0,e3h,regh,1,cond?l2:l1);
+        break;
+    case LOP+UGT: case LOP+UGE:
+	pcond(UGT, cr0,e3h,regh,1,cond?l1:l2);
+	pcond(NEQ, cr0,e3h,regh,1,cond?l2:l1);
+        break;
     case LOP+EQ:
-        pcond(op,code_eq(cond),l1); break;
+	pcond(EQ, cr0,regh,e3h,0,cond?l2:l1);
+        break;
     case LOP+NEQ:
-        pcond(op,code_eq(!cond),l1); break;
-    case LOP+LT:
-        pcond(op,code_ge(!cond),l1); break;
-    case LOP+LE:
-        pcond(op,code_gt(!cond),l1); break;
-    case LOP+UGT:
-        pcond(op,code_ugt(cond),l1); break;
-    case LOP+UGE:
-        pcond(op,code_uge(cond),l1); break;
+	pcond(EQ, cr0,regh,e3h,0,cond?l1:l2);
+        break;
     default:
-	error(-1);
+        error(-1);
     }
-    tosop(op1,regv_l(reg),regv_l(e3));
-    switch(op) {
-    case LOP+GT:
-        pcond(op,code_gt(cond),l1); break;
-    case LOP+GE:
-        pcond(op,code_ge(cond),l1); break;
-    case LOP+EQ:
-        pcond(op,code_eq(cond),l1); break;
-    case LOP+NEQ:
-        pcond(op,code_eq(!cond),l1); break;
-    case LOP+LT:
-        pcond(op,code_ge(!cond),l1); break;
-    case LOP+LE:
-        pcond(op,code_gt(!cond),l1); break;
-    case LOP+UGT:
-        pcond(op,code_ugt(cond),l1); break;
-    case LOP+UGE:
-        pcond(op,code_uge(cond),l1); break;
-    default:
-	error(-1);
-    }
+    pcond(op%LOP,cr0,e3l,regl,cond,l1);
+    fwddef(l2);  
+    if (cr0!=-1) free_register(cr0);
     emit_lpop_free(e3);
 }
 
--- a/mc-code-powerpc.c	Sat May 22 13:00:03 2004 +0900
+++ b/mc-code-powerpc.c	Sun May 23 15:27:25 2004 +0900
@@ -1338,6 +1338,14 @@
     return (cond?"eq":"ne");
 }
 
+static int cmpflag = 0;
+
+static void
+inc_cmpflag()
+{
+    cmpflag = (cmpflag+1)%7;
+}
+
 void
 code_cmp_crgvar(int e1,int reg,int sz) {
     int r;
@@ -1347,7 +1355,7 @@
     r = get_ptr_cache((NMTBL*)cadr(e1));
     printf("\t%s %s,0(%s)\n",cload(sz),crn,register_name(r));
     cext(0,sz,r);
-    printf("\tcmpwi cr0,%s,0\n",crn);
+    printf("\tcmpwi cr%d,%s,0\n",cmpflag,crn);
 }
 
 
@@ -1391,7 +1399,7 @@
 void
 code_cmp_register(int e2) {
     use_int(e2);
-    printf("\tcmpwi cr0,%s,0\n",register_name(e2));
+    printf("\tcmpwi cr%d,%s,0\n",cmpflag,register_name(e2));
 }
 
 
@@ -2301,7 +2309,6 @@
     emit_pop_free(xreg);
 }
 
-
 void
 tosop(int op,int creg,int oreg)
 {
@@ -2344,7 +2351,10 @@
 	printf("\tsub %s,%s,%s\n",crn,crn,orn);
 	break;
     case CMP:
-	printf("\tcmpw cr0,%s,%s\n",crn,orn);
+	printf("\tcmpw cr%d,%s,%s\n",cmpflag,crn,orn);
+	break;
+    case UCMP:
+	printf("\tcmplw cr%d,%s,%s\n",cmpflag,crn,orn);
 	break;
     case BAND: 
 	printf("\tand %s,%s,%s\n",crn,crn,orn);
@@ -2423,7 +2433,7 @@
 	printf("\taddi %s,%s,lo16(-%d)\n",crn,crn,v);
 	break;
     case CMP:
-	printf("\tcmpwi cr0,%s,lo16(%d)\n",crn,v);
+	printf("\tcmpwi cr%d,%s,lo16(%d)\n",cmpflag,crn,v);
 	break;
     case EOR: 
 	printf("\txori %s,%s,lo16(%d)\n",crn,crn,v);
@@ -2474,7 +2484,7 @@
 {
     /* used in dosiwtch() */
     if(chk) return;
-    printf("\tcmpwi cr0,%s,%d\n",register_name(csreg),e);
+    printf("\tcmpwi cr%d,%s,%d\n",cmpflag,register_name(csreg),e);
 }
 
 void
@@ -2487,10 +2497,24 @@
 }
 
 void
-rexpr(int e1, int l1, char *s,int t)
+rexpr(int e1, int l1, int cond,int t)
 {       
-    g_expr(list3(CMP,cadr(e1),caddr(e1)));
-    printf("\tb%s cr0,L_%d\n",s,l1);
+    char *s;
+    switch(car(e1)) {
+    case GT:  s=code_gt(cond);  break;
+    case UGT: s=code_ugt(cond); break;
+    case GE:  s=code_ge(cond);  break;
+    case UGE: s=code_uge(cond); break;
+    case LT:  s=code_ge(!cond); break;
+    case ULT: s=code_uge(!cond);break;
+    case LE:  s=code_gt(!cond); break;
+    case ULE: s=code_ugt(!cond);break;
+    case EQ:  s=code_eq(cond);  break;
+    case NEQ: s=code_eq(!cond); break;
+    default: error(-1);
+    }
+    g_expr(list3((t==INT?CMP:UCMP),cadr(e1),caddr(e1)));
+    printf("\tb%s cr%d,L_%d\n",s,cmpflag,l1);
 }
 
 
@@ -2498,7 +2522,7 @@
 jcond(int l, char cond)
 {       
     if (chk) return;
-    printf("\tb%s cr0,L_%d\n",cond?"ne":"eq",l);
+    printf("\tb%s cr%d,L_%d\n",cond?"ne":"eq",cmpflag,l);
 }
 
 void
@@ -2990,7 +3014,7 @@
     r = get_ptr_cache(&float_zero);
     rrn = register_name(r);
     printf("\tlfs %s,0(%s)\n",grn,rrn);
-    printf("\tfcmpu cr0,%s,%s\n",grn,frn);
+    printf("\tfcmpu cr%d,%s,%s\n",cmpflag,grn,frn);
     free_register(greg);
     return;
 }
@@ -3310,7 +3334,7 @@
 
     r = get_ptr_cache((NMTBL*)cadr(e2));
     printf("\t%s %s,0(%s)\n",fload(1),grn,register_name(r));
-    printf("\tfcmpu cr0,%s,%s\n",frn,grn);
+    printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn);
     free_register(g);
 }
 
@@ -3326,7 +3350,7 @@
 
     lvar_intro(e2);
     printf("\t%s %s,",fload(1),grn); lvar(e2);
-    printf("\tfcmpu cr0,%s,%s\n",frn,grn);
+    printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn);
     free_register(g);
 }
 
@@ -3584,9 +3608,21 @@
 }
 
 static void
-pcond(char *s,int l1)
+pcond(char *s,int cmpflag,int l1)
+{
+    printf("\tb%s cr%d,L_%d\n",s,cmpflag,l1);
+}
+
+static int
+lcmp(int op,int cond)
 {
-    printf("\tb%s cr0,L_%d\n",s,l1);
+    if (op==LOP+UGT||op==LOP+UGE) {
+        return UCMP;
+    } else if (op==LOP+LE||op==LOP+GE) {
+        return CMP;
+    } else {
+        return CMP;
+    }
 }
 
 void
@@ -3594,57 +3630,55 @@
 {
     int reg;
     int e3;
+    int l2;
+    int op1,cr0,cr1;
+
     g_expr(e1);
     emit_lpush();
     g_expr(e2);
     e3 = emit_lpop();
     if (!is_longlong_reg(creg)) error(-1);
     reg = lreg;
-
-    tosop(CMP,regv_h(reg),regv_h(e3));
+    op1 = lcmp(op,cond);
+    tosop(op1,regv_h(e3),regv_h(reg));
+    cr0 = cmpflag;
+    inc_cmpflag();
+    cr1 = cmpflag;
+    tosop(op1,regv_l(e3),regv_l(reg));
+
+    l2 = fwdlabel();
+    // cond==0 jump on false condtion   ( if(x) => rexpr(..  cond=0 ...) )
     switch(op) {
     case LOP+GT:
-    	pcond(code_gt(cond),l1); break;
     case LOP+GE:
-    	pcond(code_ge(cond),l1); break;
+	pcond(code_gt(1),cr0,cond?l1:l2);
+	pcond(code_eq(0),cr0,cond?l2:l1);
+	break;
+    case LOP+UGT:
+    case LOP+UGE:
+	pcond(code_ugt(1),cr0,cond?l1:l2);
+	pcond(code_eq(0), cr0,cond?l2:l1);
+	break;
     case LOP+EQ:
-    	pcond(code_eq(cond),l1); break;
+	pcond(code_eq(0),cr0,(cond?l2:l1));
+	pcond(code_eq(cond),cr1,l1);
+	break;
     case LOP+NEQ:
-    	pcond(code_eq(!cond),l1); break;
-    case LOP+LT:
-    	pcond(code_ge(!cond),l1); break;
-    case LOP+LE:
-    	pcond(code_gt(!cond),l1); break;
-    case LOP+UGT:
-    	pcond(code_ugt(cond),l1); break;
-    case LOP+UGE:
-    	pcond(code_uge(cond),l1); break;
+	pcond(code_eq(0),cr0,(cond?l1:l2));
+	pcond(code_eq(!cond),cr1,l1);
+	break;
     default:
 	error(-1);
     }
-    tosop(CMP,regv_l(reg),regv_l(e3));
     switch(op) {
-    case LOP+GT:
-    	pcond(code_gt(cond),l1); break;
-    case LOP+GE:
-    	pcond(code_ge(cond),l1); break;
-    case LOP+EQ:
-    	pcond(code_eq(cond),l1); break;
-    case LOP+NEQ:
-    	pcond(code_eq(!cond),l1); break;
-    case LOP+LT:
-    	pcond(code_ge(!cond),l1); break;
-    case LOP+LE:
-    	pcond(code_gt(!cond),l1); break;
-    case LOP+UGT:
-    	pcond(code_ugt(cond),l1); break;
-    case LOP+UGE:
-    	pcond(code_uge(cond),l1); break;
-    default:
-	error(-1);
-    }
-    emit_lpop_free(e3);
-}
+    case LOP+GT:  pcond(code_gt(cond),  cr1,l1); break;
+    case LOP+GE:  pcond(code_ge(cond),  cr1,l1); break;
+    case LOP+UGT: pcond(code_ugt(cond), cr1,l1); break;  
+    case LOP+UGE: pcond(code_uge(cond), cr1,l1); break;  
+    }  
+    fwddef(l2);  
+    emit_lpop_free(e3); 
+} 
 
 int
 emit_lpop()
@@ -3677,7 +3711,7 @@
 		lregister_name_low(reg),
 		lregister_name_low(reg),
 		lregister_name_high(reg));
-    printf("\tcmpwi cr0,%s,0\n",lregister_name_low(reg));
+    printf("\tcmpwi cr%d,%s,0\n",cmpflag,lregister_name_low(reg));
 }
 
 void
--- a/mc-code.h	Sat May 22 13:00:03 2004 +0900
+++ b/mc-code.h	Sun May 23 15:27:25 2004 +0900
@@ -61,11 +61,6 @@
 extern void code_return(int reg);
 extern void code_environment(int reg);
 extern void code_bool(int e1,int reg);
-extern char *code_gt(int cond);
-extern char *code_ugt(int cond);
-extern char *code_ge(int cond);
-extern char *code_uge(int cond);
-extern char *code_eq(int cond);
 extern void code_cmp_crgvar(int e1,int reg,int sz);
 extern void code_cmp_crlvar(int e1,int reg,int sz);
 extern void code_cmp_rgvar(int e1,int reg);
@@ -98,7 +93,7 @@
 extern void tosop(int op,int reg,int oreg);
 extern void code_opening(char *filename);
 extern void code_closing();
-extern void rexpr(int e1, int l1, char *s,int t);
+extern void rexpr(int e1, int l1, int cond,int t);
 extern void jcond(int l, char cond);
 extern void jmp(int l);
 extern int code_get_fixed_creg(int reg,int type);
--- a/mc-codegen.c	Sat May 22 13:00:03 2004 +0900
+++ b/mc-codegen.c	Sun May 23 15:27:25 2004 +0900
@@ -491,35 +491,12 @@
     case LNOT:
 	b_expr(e2,!cond,l1,0);
 	return;
-    case GT:
-	rexpr(e1,l1,code_gt(cond),INT);
-	return;
-    case UGT:
-	rexpr(e1,l1,code_ugt(cond),UNSIGNED);
-	return;
-    case GE:
-	rexpr(e1,l1,code_ge(cond),INT);
-	return;
-    case UGE:
-	rexpr(e1,l1,code_uge(cond),UNSIGNED);
-	return;
-    case LT:
-	rexpr(e1,l1,code_ge(!cond),INT);
+    case GT: case GE: case LT: case LE:
+    case EQ: case NEQ:
+	rexpr(e1,l1,cond,INT);
 	return;
-    case ULT:
-	rexpr(e1,l1,code_uge(!cond),UNSIGNED);
-	return;
-    case LE:
-	rexpr(e1,l1,code_gt(!cond),INT);
-	return;
-    case ULE:
-	rexpr(e1,l1,code_ugt(!cond),UNSIGNED);
-	return;
-    case EQ:
-	rexpr(e1,l1,code_eq(cond),INT);
-	return;
-    case NEQ:
-	rexpr(e1,l1,code_eq(!cond),INT);
+    case UGT: case UGE: case ULT: case ULE:
+	rexpr(e1,l1,cond,UNSIGNED);
 	return;
 #if FLOAT_CODE
     case DOP+GT:
--- a/mc-parse.c	Sat May 22 13:00:03 2004 +0900
+++ b/mc-parse.c	Sun May 23 15:27:25 2004 +0900
@@ -1389,7 +1389,7 @@
 	error(STERR);
     control=0;
     conv->code_end_();
-    if(!chk) code_leave(n->nm);
+    if(!chk) code_leave(fnptr->nm);
     args = 0;
 }
 
--- a/stdio.h	Sat May 22 13:00:03 2004 +0900
+++ b/stdio.h	Sun May 23 15:27:25 2004 +0900
@@ -1,4 +1,4 @@
-#ifndef __micro_c__
+#ifndef __micro_c__aaa
 #include "/usr/include/stdio.h"
 long long strtoll(const char *, char **, int);
 #else
--- a/test/code-gen.c	Sat May 22 13:00:03 2004 +0900
+++ b/test/code-gen.c	Sun May 23 15:27:25 2004 +0900
@@ -297,40 +297,77 @@
 void
 code_gt()
 {
+    int reg;
     if (i1>i2)
 	printf("code_gt 1\n");
     else
 	printf("code_gt 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<reg && reg<3)
+	   printf("reg=%d code_gt  0<reg && reg <3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<reg && reg<0)
+	   printf("reg=%d code_gt -2<reg && reg <0\n",reg);
+    }
+    
 }
 
 // code_ugt(int cond) 
 void
 code_ugt()
 {
+    int reg;
     if (ui1>ui2)
 	printf("code_ugt 1\n");
     else
 	printf("code_ugt 0\n");
+    for (reg=0;reg<7;reg++) {
+        if (0<reg && reg<3)
+	   printf("reg=%d code_ugt  0<reg && reg <3\n",reg);
+    }
+    for (reg=0;reg<7;reg++) {
+        if (1<reg && reg<5)
+	   printf("reg=%d code_ugt  1<reg && reg <5\n",reg);
+    }
 }
 
 // code_ge(int cond) 
 void
 code_ge()
 {
+    int reg;
     if (i1>=i2)
 	printf("code_ge 1\n");
     else
 	printf("code_ge 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<=reg && reg<=3)
+	   printf("reg=%d code_ge  0<=reg && reg <=3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<=reg && reg<=0)
+	   printf("reg=%d code_ge -2<=reg && reg <=0\n",reg);
+    }
 }
 
 // code_uge(int cond) 
 void
 code_uge()
 {
+    unsigned reg;
     if (ui1>=ui2)
 	printf("code_uge 1\n");
     else
 	printf("code_uge 0\n");
+    for (reg=0;reg<7;reg++) {
+        if (0<=reg && reg<=3)
+	   printf("reg=%d code_uge  0<=reg && reg <=3\n",reg);
+    }
+    for (reg=0;reg<7;reg++) {
+        if (1<=reg && reg<=5)
+	   printf("reg=%d code_uge  1<=reg && reg <=5\n",reg);
+    }
 }
 
 // code_eq(int cond) 
@@ -1418,40 +1455,76 @@
 void
 code_dgt()
 {
+    double reg;
     if (d0>d1)
 	printf("code_dgt 1\n");
     else
 	printf("code_dgt 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<reg && reg<3)
+	   printf("reg=%g code_dgt  0<reg && reg <3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<reg && reg<0)
+	   printf("reg=%g code_dgt -2<reg && reg <0\n",reg);
+    }
 }
 
 // code_ugt(int cond) 
 void
 code_fgt()
 {
+    float reg;
     if (f0>f1)
 	printf("code_fgt 1\n");
     else
 	printf("code_fgt 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<reg && reg<3)
+	   printf("reg=%g code_fgt  0<reg && reg <3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<reg && reg<0)
+	   printf("reg=%g code_fgt -2<reg && reg <0\n",reg);
+    }
 }
 
 // code_ge(int cond) 
 void
 code_dge()
 {
+    double reg;
     if (d0>=d1)
 	printf("code_dge 1\n");
     else
 	printf("code_dge 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<=reg && reg<=3)
+	   printf("reg=%g code_dge  0<reg && reg <=3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<=reg && reg<=0)
+	   printf("reg=%g code_dge -2<reg && reg <=0\n",reg);
+    }
 }
 
 // code_uge(int cond) 
 void
 code_fge()
 {
+    float reg;
     if (f0>=f1)
 	printf("code_fge 1\n");
     else
 	printf("code_fge 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<=reg && reg<=3)
+	   printf("reg=%g code_fge  0<=reg && reg <=3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<=reg && reg<=0)
+	   printf("reg=%g code_fge -2<=reg && reg <=0\n",reg);
+    }
 }
 
 // code_eq(int cond) 
@@ -2412,40 +2485,76 @@
 void
 code_lgt()
 {
+    long long reg;
     if (l0>l1)
 	printf("code_lgt 1\n");
     else
 	printf("code_lgt 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<reg && reg<3)
+	   printf("reg=%lld code_lgt  0<reg && reg <3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<reg && reg<0)
+	   printf("reg=%lld code_lgt -2<reg && reg <0\n",reg);
+    }
 }
 
 // code_lugt(int cond) 
 void
 code_lugt()
 {
+    unsigned long long reg;
     if (ul0>ul1)
 	printf("code_lugt 1\n");
     else
 	printf("code_lugt 0\n");
+    for (reg=0;reg<7;reg++) {
+        if (2<reg && reg<4)
+	   printf("reg=%llu code_lugt  2<reg && reg <4\n",reg);
+    }
+    for (reg=0;reg<7;reg++) {
+        if (2<reg && reg<4)
+	   printf("reg=%llu code_lugt  2<reg && reg <4\n",reg);
+    }
 }
 
 // code_lge(int cond) 
 void
 code_lge()
 {
+    long long reg;
     if (l0>=l1)
 	printf("code_lge 1\n");
     else
 	printf("code_lge 0\n");
+    for (reg=-3;reg<7;reg++) {
+        if (0<=reg && reg<=3)
+	   printf("reg=%lld code_lge  0<=reg && reg <=3\n",reg);
+    }
+    for (reg=-3;reg<7;reg++) {
+        if (-2<=reg && reg<=0)
+	   printf("reg=%lld code_lge -2<=reg && reg <=0\n",reg);
+    }
 }
 
 // code_luge(int cond) 
 void
 code_luge()
 {
+    unsigned long long reg;
     if (ul0>=ul1)
 	printf("code_luge 1\n");
     else
 	printf("code_luge 0\n");
+    for (reg=0;reg<7;reg++) {
+        if (2<reg && reg<4)
+	   printf("reg=%llu code_luge  2<reg && reg <4\n",reg);
+    }
+    for (reg=0;reg<7;reg++) {
+        if (2<reg && reg<4)
+	   printf("reg=%llu code_luge  2<reg && reg <4\n",reg);
+    }
 }
 
 // code_leq(int cond)