changeset 148:e0eba2993c37

MIPS version (incomplete)
author kono
date Sun, 13 Jul 2003 23:59:26 +0900
parents cb7aa0089681
children 0f36fdbcba9b
files Changes mc-code-mips.c mc-code-powerpc.c
diffstat 3 files changed, 968 insertions(+), 747 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Wed Jun 11 12:26:03 2003 +0900
+++ b/Changes	Sun Jul 13 23:59:26 2003 +0900
@@ -3084,3 +3084,46 @@
 
 あぁ、なんか乗り切れない。CONV の直前でcregが不定だ。
 どっかで use_float を忘れているんだろうな。
+
+Wed Jun 11 12:27:58 JST 2003
+
+なんか、ようやっと creg/ireg/freg が片付いたよ。
+creg を変更したときに、ireg を変更し忘れることが多かった
+みたい。set_creg を必ず使うようにすれば良いだけだと思う
+のだが。
+
+Thu Jun 12 19:34:48 JST 2003
+
+まぁ、MIPS用のレジスタ割り当てを書かないとだめだね。
+ちゃんと書いてもいいんだけどさ。なんか one path に
+するのが面白いんでしょ?
+
+Sun Jul 13 18:26:29 JST 2003
+
+また、一カ月なにも書かなかったのか。 mips は、mc-code-power.c
+から書き直した方が良さそうだね。
+
+   regs/regv は、i/f/d のすべてのレジスタに関して一つ
+
+でないと stack に積むのを統一できないから。そういう意味では、
+reg_stack と freg_stack を区別する意味はないわけね。でもstack
+は型付けした方が良いから。でも、区別しておくと、long を増や
+した時にも、stack を増やさないとだめなんじゃない? なので区別
+しない方が良い。でも、それに手をつけると、また時間かかるんじ
+ゃないの? そのためにはスタックそのものに型付けしないとだめだ
+から結局同じか。
+
+mips の double を格納するためのregister pairは、regs に
+格納する。regs にアクセスには必ずアクセス関数を通す。
+なるほど。
+
+get_input_dregister_var なんだけど、dregister pair の
+場合は、常にpairが決まった値になる必要があるよね。
+この分はどうする? 前もってとっておくか?
+
+あ、そうか、任意のregister pairを許さなくても良いよ。input register
+に対応する連続したregister pair だけを許そう。そうすれば、あ
+まり気にしなくても良くなるから。でも、gcc が奇数pairを許して
+いたら気まずくない? 
+
+regv は、register rename がなければいらないんじゃない?
--- a/mc-code-mips.c	Wed Jun 11 12:26:03 2003 +0900
+++ b/mc-code-mips.c	Sun Jul 13 23:59:26 2003 +0900
@@ -11,30 +11,46 @@
 #define RODATA_EMIT_MODE 2
 
 static void data_mode(char *name);
+static void init_ptr_cache();
 static void ld_indexx(int byte, int n, int xreg);
 static void local_table(void);
 static void shift(char *op, int reg);
 static int struct_push(int e4,int t,int arg);
-static int code_d1(double d);
-static int code_d2(double d);
-
 
 static int output_mode = TEXT_EMIT_MODE;
 static int data_alignment = 0;
 
 static int code_disp_label;
+static int code_setup;
 static int r1_offset_label;
 static int lvar_offset_label;
 
 static int reg_save;
 static int freg_save;
 
+static int freg,ireg;
+
+/* mips requires two registers for compare */
+static int cmpreg = -1;
+
 int size_of_int = 4;
 int size_of_float = 4;
 int size_of_double = 8;
 int size_of_longlong = 8;
 int endian = 1;
 
+int  reg_sp;   /* REGister Stack-Pointer */
+int reg_stack[MAX_MAX];  /* 実際のレジスタの領域 */
+
+/* floating point registers */
+
+int  freg_sp;  /* floating point REGister Stack-Pointer */
+int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
+
+/* double floating point registers */
+
+int  dreg_sp;  /* floating point REGister Stack-Pointer */
+int dreg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
 
 #define REG_fp   1
 #define REG_sp   30
@@ -51,76 +67,99 @@
 #define MAX_TMP_FREG 14
 
 #define RET_REGISTER 3
-#define RET_FREGISTER 1
+#define RET_FREGISTER (1+FREG_OFFSET)
+#define RET_DREGISTER (1+DREG_OFFSET)
 
-int MAX_REGISTER=30;             /* MIPSのレジスタを10個まで使う*/
+int MAX_REGISTER=30;             /* PowerPCのレジスタを10個まで使う*/
 int MAX_FREGISTER=31;
-#define  REAL_MAX_REGISTER 32    /* MIPSのレジスタが32ということ*/
-#define  REAL_MAX_FREGISTER 32    /* MIPSのレジスタが32ということ*/
+int MAX_DREGISTER=16;
+#define  REAL_MAX_REGISTER 32    /* PowerPCのレジスタが32ということ*/
+#define  REAL_MAX_FREGISTER 32    /* PowerPCのFレジスタが32ということ*/
+#define  REAL_MAX_DREGISTER 31    /* PowerPCのDレジスタ番号が31ということ*/
+
+#define FREG_OFFSET REAL_MAX_REGISTER
+#define DREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER )
 
 int MAX_INPUT_REGISTER_VAR = 7-MIN_TMP_REG;
 int MAX_CODE_INPUT_REGISTER_VAR = 7-MIN_TMP_REG;
 int MAX_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG;
+int MAX_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG;
 int MAX_CODE_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG;
+int MAX_CODE_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG;
 
 #define CREG_REGISTER  MAX_TMP_REG
-#define FREG_FREGISTER MAX_TMP_FREG
-
-int dreg;
+#define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET)
+#define DREG_DREGISTER (2+DFREG_OFFSET)
 
-int  reg_sp;   /* REGister Stack-Pointer */
-int reg_stack[MAX_MAX];  /* 実際のレジスタの領域 */
-
-/* floating point registers */
-
-int  freg_sp;  /* floating point REGister Stack-Pointer */
-int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
+int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+REL_MAX_DREGISTER];
+int powerpc_regv[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+REL_MAX_DREGISTER];
 
-#define dregister(i,j)  (i*32+j)
-#define dregister0(i)  (i/32)
-#define dregister1(i)  (i%32)
-
-
-int mips_regs[REAL_MAX_REGISTER];
-int mips_regv[REAL_MAX_REGISTER];
+unsigned char dreg_pair0[REL_MAX_DREGISTER] = {
+    0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
+};
+unsigned char dreg_pair1[REL_MAX_DREGISTER] = {
+    1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+};
 
-int *regv  = mips_regv;
-int *regs  = mips_regs;
-
-int mips_fregs[REAL_MAX_FREGISTER];
-int mips_fregv[REAL_MAX_FREGISTER];
-
-#define FDREG 40
-
-int *fregv = mips_fregv;
-int *fregs = mips_fregs;
+int *regv  = powerpc_regv;
+int *regs  = powerpc_regs;
 
 static int max_reg_var, max_freg_var;
-static int cond_reg=-1,cond_freg=-1;
+static int cond_reg=-1,cond_freg=-1,cond_dreg=-1;
 
 static char *reg_name[] = {
     "$0","$1","$2","$3","$4","$5","$6","$7","$8","$9",
     "$10","$11","$12","$13","$14","$15","$16","$17","$18","$19",
     "$20","$21","$22","$23","$24","$25","$26","$27","$28","$29",
-    "$30","$31"
-}; 
-
-static char *freg_name[] = {
+    "$30","$31",
     "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9",
     "$f10","$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18","$f19",
     "$f20","$f21","$f22","$f23","$f24","$f25","$f26","$f27","$f28","$f29",
     "$f30","$f31"
 }; 
 
-#define register_name(i)  reg_name[i]
-#define fregister_name(i) freg_name[i]
+
+#define register_name(i)  reg_name0(i)
+#define fregister_name(i) reg_name0(i)
+
+static
+reg_name0(int i)
+{
+    if (i<=REAL_MAX_REGISTER+REAL_MAX_FREGISTER)
+	return reg_name[i];
+    else
+	error(-1);
+}
+
+#define is_int_reg(i)  (0<=i&&i<REAL_MAX_REGISTER)
+#define is_float_reg(i)  (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER)
+#define is_double_reg(i)  (REAL_MAX_REGISTER+REAL_MAX_FREGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER+REL_MAX_DREGISTER)
+
 
+int use_int(int i) { 
+    if (!is_int_reg(i)) i = ireg;
+    if (!regs[i]) regs[i]=1;
+    return i;
+}
+
+int use_float(int i) { 
+    if (!is_float_reg(i)) i = freg;
+    if (!regs[i]) regs[i]=1;
+    return i;
+}
+
+int use_double(int i) { 
+    if (!is_double_reg(i)) i = dreg;
+    if (!regs[i]) regs[i]=1;
+    return i;
+}
 
 static char * fload(int d);
 static void code_save_stacks();
 static void code_save_input_registers();
 static void    set_creg(int,int);
 static void    set_freg(int,int);
+static void    set_dreg(int,int);
 
 static int    mask_label;
 static int    mask1_label;
@@ -128,6 +167,7 @@
 static int    fmask1_label;
 
 static FILE *asi;
+
 int max_func_args;
 int my_func_args;
 #define ARG_LVAR_OFFSET 0x10000000
@@ -206,21 +246,20 @@
 #endif
 }
 
-
 static void
 lvar(int l)
 {
     if (fnptr->sc==CODE) {
-	if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	    printf("%d($fp)\n",CODE_CALLER_ARG);
-	} else
-	    printf("%d($fp)\n",CODE_LVAR);
+        if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
+            printf("%d($fp)\n",CODE_CALLER_ARG);
+        } else
+            printf("%d($fp)\n",CODE_LVAR);
     } else if (l<0) {  /* local variable */
-	printf("%d+L_%d($fp)\n",FUNC_LVAR,lvar_offset_label);
+        printf("%d+L_%d($fp)\n",FUNC_LVAR,lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	printf("%d($fp)\n",CALLER_ARG);
+        printf("%d($fp)\n",CALLER_ARG);
     } else { /* callee's arguments */
-	printf("%d+L_%d($fp)\n",CALLEE_ARG,r1_offset_label);
+        printf("%d+L_%d($fp)\n",CALLEE_ARG,r1_offset_label);
     }
 }
 
@@ -228,20 +267,19 @@
 lvar_address(int l,int creg)
 {
     if (fnptr->sc==CODE) {
-	if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	    printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_CALLER_ARG);
-	} else
-	    printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR);
+        if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
+            printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_CALLER_ARG);
+        } else
+            printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR);
     } else if (l<0) {  /* local variable */
-	printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),FUNC_LVAR,lvar_offset_label);
+        printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),FUNC_LVAR,lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	printf("\taddu\t%s,$fp,%d\n",register_name(creg),CALLER_ARG);
+        printf("\taddu\t%s,$fp,%d\n",register_name(creg),CALLER_ARG);
     } else { /* callee's arguments */
-	printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),CALLEE_ARG,r1_offset_label);
+        printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),CALLEE_ARG,r1_offset_label);
     }
 }
 
-
 void
 code_lvar(int e2,int creg) {
     lvar_address(e2,creg);
@@ -257,10 +295,16 @@
 void
 gexpr_code_init(void){
     regv[creg]=0;
-    fregv[freg]=0;
+    regv[freg]=0;
 }
 
 void
+code_gexpr(int e){
+    if (is_int_reg(creg) && creg!=ireg) error(-1);
+}
+
+
+void
 code_arg_register(NMTBL *fnptr)
 {
     int args = fnptr->dsp;
@@ -288,20 +332,17 @@
             if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) {
                 n->sc = FREGISTER;
                 n->dsp = cadr(reg);
-                fregv[n->dsp]= 1;
-                fregs[n->dsp]= INPUT_REG;
-		if (freg_var<2) freg_var++;
-                else reg_var++;
+                regv[n->dsp]= 1;
+                regs[n->dsp]= INPUT_REG;
+                freg_var++;
                 cadddr(args)=size(type); /* why we need this? */
             }
         } else if (type==DOUBLE) {
             if ((reg = get_input_dregister_var(reg_var,n,is_code0,1))) {
                 n->sc = DREGISTER;
                 n->dsp = cadr(reg);
-                regv[dregister0(n->dsp)]= 1;
-                regv[dregister1(n->dsp)]= 1;
-                regs[dregister0(n->dsp)]= INPUT_REG;
-                regs[dregister1(n->dsp)]= INPUT_REG;
+                regv[n->dsp]= 1;
+                regs[n->dsp]= INPUT_REG;
                 reg_var+=2;
                 cadddr(args)=size(type); /* why we need this? */
             }
@@ -309,7 +350,7 @@
         args = cadr(args);
     }
     if (is_function(fnptr))
-        code_save_input_registers();
+	code_save_input_registers();
 }
 
 int 
@@ -330,6 +371,16 @@
 	    return reg;
 	}
     }
+    /* search dregister stack */
+    for(i=0;i<dreg_sp;i++) {
+	if ((reg=dreg_stack[i])>=0) {
+            code_dassign_lvar(
+                (dreg_stack[i]=new_lvar(size_of_double)),reg,1); 
+            dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET;
+	    free_dregister(reg);
+	    return get_register(); /* 今度は必ずある */
+	}
+    }
     for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) {
         reg =REG_VAR_BASE-i;
         if (! regs[reg]) {       /* 使われていないなら */
@@ -340,7 +391,7 @@
         }
     }
     /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */
-    error(-1); return creg;
+    error(HPERR); return creg;
 }
 
 int
@@ -349,34 +400,76 @@
     return reg_stack[--reg_sp];
 }
 
-int 
-get_dregister(int d)
+static int
+get_dregister1() {
+    for(i=MAX_TMP_DREG;i>MIN_TMP_DREG;i--) {
+	if (regs[i]) continue;  /* 使われている */
+	if (regs[dreg_pair0[i-DREG_OFFSET]]) continue;
+	if (regs[dreg_pair1[i-DREG_OFFSET]]) continue;
+	regs[dreg_pair0[i-DREG_OFFSET]]=USING_REG;
+	regs[dreg_pair1[i-DREG_OFFSET]]=USING_REG;
+	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
+	return i;               /* その場所を表す番号を返す */
+    }
+    return -1;
+}
+
+static int 
+get_dregister0()
+{
+    int i0,i1,reg,i;
+    /* とりあえず、空き int register pair を探す */
+    if ((i=get_dregister1())!=-1) {
+	return i;
+    }
+    /* search dregister stack */
+    for(i=0;i<dreg_sp;i++) {
+	if ((reg=dreg_stack[i])>=0) {
+            code_dassign_lvar(
+                (dreg_stack[i]=new_lvar(size_of_double)),reg,1); 
+            dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET;
+	    return i;
+	}
+    }
+    /* clear integer register stack */
+    for(i=0;i<reg_sp;i++) {
+	if ((reg=reg_stack[i])>=0) {
+            code_assign_lvar(
+                (reg_stack[i]=new_lvar(size_of_int)),reg,0); 
+            reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET;
+	    free_register(reg);
+	}
+    }
+    if ((i=get_dregister1())!=-1) {
+	return i;
+    }
+
+    error(REG_ERR); return dreg;
+}
+
+static int
+get_fregister0()
 {    /* 使われていないレジスタを調べる */
-    int i,j,reg;
-    if (d) {
-	i = get_register();
-	j = get_register();
-	return dregister(i,j);
-    }
-    for(i=MAX_TMP_FREG;i>MIN_TMP_FREG;i--) {
-	if (fregs[i]) continue;    /* 使われている */
-	fregs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
+    int i,reg;
+    for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) {
+	if (regs[i]) continue;    /* 使われている */
+	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
 	return i;               /* その場所を表す番号を返す */
     }
     /* search register stack */
     for(i=0;i<freg_sp;i++) {
 	if ((reg=freg_stack[i])>=0) {
             code_dassign_lvar(
-                (freg_stack[i]=new_lvar(size_of_double)),reg,1); 
+                (freg_stack[i]=new_lvar(size_of_float)),reg,1); 
             freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET;
 	    return reg;
 	}
     }
     for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) {
-        reg =FREG_VAR_BASE-i;
-        if (! fregs[reg]) {       /* 使われていないなら */
-            fregs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
-            fregv[reg]=0;
+        reg =FREG_VAR_BASE-i+FREG_OFFSET;
+        if (! regs[reg]) {       /* 使われていないなら */
+            regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
+            regv[reg]=0;
 	    if (i>max_freg_var) max_freg_var=i;
 	    return reg; 
         }
@@ -385,12 +478,29 @@
     error(REG_ERR); return freg;
 }
 
+int 
+get_dregister(int d)
+{    /* 使われていないレジスタを調べる */
+    int i,reg;
+    if (d) {
+	return get_dregister0();
+    } else {
+	return get_fregister0();
+    }
+}
+
 int
 pop_fregister(void)
 {     /* レジスタから値を取り出す */
     return freg_stack[--freg_sp];
 }
 
+int
+pop_dregister(void)
+{     /* レジスタから値を取り出す */
+    return dreg_stack[--dreg_sp];
+}
+
 void
 emit_pop_free(int xreg)
 {
@@ -400,56 +510,39 @@
 
 void 
 free_register(int i) {    /* いらなくなったレジスタを開放 */
-    if (i<0||MAX_REGISTER<i) error(-1);
+    int i0,i1;
+    if (i<0||MAX_FREGISTER+FREG_OFFSET+REAL_MAX_DREGISTER<i) error(-1);
+    if (is_double_reg(i)) {
+	i0 = dreg_pair0[i-DREG_OFFSET];
+	regv[i0]=regs[i0]=0;
+	i1 = dreg_pair1[i-DREG_OFFSET];
+	regv[i1]=regs[i1]=0;
+    }
     regv[i]=regs[i]=0;
 }
 
-void 
-free_dregister(int i) {    /* いらなくなったレジスタを開放 */
-    int j;
-    if (i>FDREG) {
-	j = dregister0(i);
-	regv[j]=regs[j]=0;
-	j = dregister1(i);
-	regv[j]=regs[j]=0;
-    }
-    if (i<0||MAX_FREGISTER<i) error(-1);
-    fregv[i]=fregs[i]=0;
-}
-
 int
 get_input_dregister_var(int i,NMTBL *n,int is_code,int d)
 {
-    if (is_code) {
-	if (d) {
-	    if(!(i*2<MAX_INPUT_REGISTER_VAR)) return 0;
-	    i = REG_VAR_BASE-i*2;
-	    return list3(DREGISTER,dregister(i,i+1),(int)n);
+    if (d) {
+	if (is_code) {
+	    if(!(i<DREG_VAR_BASE-DREG_VAR_MIN)) return 0;
+	    i = DREG_VAR_BASE-i+DREG_OFFSET;
 	} else {
-	    if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0;
-	    i = FREG_VAR_BASE-i;
-	    return list3(FREGISTER,i,(int)n);
+	    if (i<0||i>=MAX_INPUT_DREGISTER_VAR) return 0;
+	    i = i+MIN_TMP_DREG+DREG_OFFSET;
 	}
+	return list3(DREGISTER,i,(int)n);
     } else {
-	if  (d) {
-	    if (i==0) {
-		return list3(DREGISTER,dregister(4,5),(int)n);
-	    } else if (i==1) {
-		return list3(DREGISTER,dregister(6,7),(int)n);
-	    }
+	if (is_code) {
+	    if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0;
+	    i = FREG_VAR_BASE-i+FREG_OFFSET;
 	} else {
-	    if (i==0) {
-		return list3(FREGISTER,12,(int)n);
-	    } else if (i==1) {
-		return list3(FREGISTER,14,(int)n);
-	    } else if (i==2) {
-		return list3(FREGISTER,6+FDREG,(int)n);
-	    } else if (i==3) {
-		return list3(FREGISTER,7+FDREG,(int)n);
-	    }
+	    if (i<0||i>=MAX_INPUT_FREGISTER_VAR) return 0;
+	    i = i+MIN_TMP_FREG+FREG_OFFSET;
 	}
+	return list3(FREGISTER,i,(int)n);
     }
-    return 0;
 }
 
 int
@@ -459,7 +552,22 @@
 	if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0;
 	i = REG_VAR_BASE-i;
     } else {
-	if (i<0||MAX_REGISTER<i+MIN_TMP_REG) return 0;
+	if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0;
+	i = i+MIN_TMP_REG;
+    }
+    return list3(REGISTER,i,(int)n);
+}
+
+/* double register case? */
+
+int
+get_input_register_var_1(int i,NMTBL *n,int is_code)
+{
+    if (is_code) {
+	if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0;
+	i = REG_VAR_BASE-i;
+    } else {
+	if (i<0||i>=MAX_INPUT_REGISTER_VAR+1) return 0;
 	i = i+MIN_TMP_REG;
     }
     return list3(REGISTER,i,(int)n);
@@ -474,9 +582,9 @@
         if (! regs[i] && ! regv[i]) count++;
     }
     for(i=0;i<MAX_FREGISTER;i++) {
-        if (! fregs[i] && ! fregv[i]) fcount++;
+        if (! regs[i+FREG_OFFSET] && ! regv[i+FREG_OFFSET]) fcount++;
     }
-    fprintf(stderr,"# free reg %d freg %d\n",count,fcount);
+    printf("# free reg %d freg %d\n",count,fcount);
     return d?fcount:count;
 }
 
@@ -497,11 +605,14 @@
 {
     int i;
     for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0; }
-    for(i=0;i<MAX_FREGISTER;i++) { fregs[i]=0; fregv[i]=0; }
+    for(i=0;i<MAX_FREGISTER;i++) { regs[i+FREG_OFFSET]=0; regv[i+FREG_OFFSET]=0; }
+    for(i=0;i<MAX_DREGISTER;i++) { regs[i+DREG_OFFSET]=0; regv[i+DREG_OFFSET]=0; }
     creg = get_register();
     freg = get_dregister(0);
+    dreg = -1;
     set_creg(CREG_REGISTER,0);
     set_freg(FREG_FREGISTER,0);
+    set_dreg(DREG_DREGISTER,0);
     return;
 }
 
@@ -521,11 +632,10 @@
     printf(":");
     for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); }
     printf("\n# freg:");
-    for(i=0;i<MAX_FREGISTER;i++) { printf("%d",fregs[i]); }
-    printf(" regs_stack",register_name(creg),register_name(dreg));
+    for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); }
     for(i=reg_sp;i>=0;i--) {
 	if(reg_stack[i]>=0)
-	    printf(" %s",register_name(reg_stack[i],0));
+	    printf(" %s",register_name(reg_stack[i]));
     }
 #endif
     printf("\n");
@@ -537,15 +647,25 @@
     while(reg_sp > 0) {
 	free_register(reg_stack[--reg_sp]);
     }
+    while(freg_sp > 0) {
+	free_register(freg_stack[--freg_sp]);
+    }
+    while(dreg_sp > 0) {
+	free_register(dreg_stack[--dreg_sp]);
+    }
     if (cond_freg!=-1) { 
-	if(car(cond_freg)==DREGISTER) free_dregister(cadr(cond_freg)); 
-	else if(car(cond_freg)==FREGISTER) free_dregister(cadr(cond_freg)); 
+	if(car(cond_freg)==FREGISTER) free_register(cadr(cond_freg)); 
 	cond_freg=-1; 
     }
+    if (cond_dreg!=-1) { 
+	if(car(cond_dreg)==DREGISTER) free_register(cadr(cond_dreg)); 
+	cond_dreg=-1; 
+    }
     if (cond_reg!=-1)  { 
 	if(car(cond_reg)==REGISTER) free_register(cadr(cond_reg)); 
 	cond_reg=-1;  
     }
+    cmpreg = -1;
     text_mode();
     gexpr_code_init();
     register_usage("gexpr_init");
@@ -559,6 +679,7 @@
     max_reg_var=-1; max_freg_var=-1;
     reg_sp = 0;
     freg_sp = 0;
+    dreg_sp = 0;
     text_mode();
 }
 
@@ -573,13 +694,14 @@
 {
     int i;
     for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) {
-        if (! regs[REG_VAR_BASE-i]) {       /* 使われていないなら */
-            regs[REG_VAR_BASE-i]=USING_REG; /* そのレジスタを使うことを宣言し */
-            regv[REG_VAR_BASE-i]=0;
+	if (! regs[REG_VAR_BASE-i]) {       /* 使われていないなら */
+	    /* そのレジスタを使うことを宣言し */
+	    regs[REG_VAR_BASE-i]=USING_REG; 
+	    regv[REG_VAR_BASE-i]=0;
 	    if (i>max_reg_var) max_reg_var=i;
 	    /* その場所を表す番号を返す */
 	    return list3(REGISTER,REG_VAR_BASE-i,(int)n); 
-        }
+	}
     }
     return list2(LVAR,new_lvar(size_of_int));
 }
@@ -592,17 +714,33 @@
 int
 get_dregister_var(NMTBL *n,int d)
 {
-    int i;
-    for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) {
-        if (! regs[FREG_VAR_BASE-i]) {       /* 使われていないなら */
-            regs[FREG_VAR_BASE-i]=USING_REG; /*そのレジスタを使うことを宣言し*/
-            regv[FREG_VAR_BASE-i]=0;
-	    if (i>max_freg_var) max_freg_var=i;
-	    /* その場所を表す番号を返す */
-	    return list3(DREGISTER,FREG_VAR_BASE-i,(int)n); 
-        }
+    int i,j;
+    if (d) {
+	for(i=0;i<DREG_VAR_BASE-DREG_VAR_MIN;i++) {
+	    if (! regs[j=(DREG_VAR_BASE-i+DREG_OFFSET])) {       /* 使われていないなら */
+		if (regs[dreg_pair0[j]] || regs[dreg_pair1[j]]) continue;
+		regs[DREG_VAR_BASE-i+DREG_OFFSET]=USING_REG; /*そのレジスタを使うことを宣言し*/
+		regv[DREG_VAR_BASE-i+DREG_OFFSET]=0;
+		regs[dreg_pair0[j]] = regs[dreg_pair1[j]] = USING_REG;
+		regv[dreg_pair0[j]] = regv[dreg_pair1[j]] = 0;
+		if (dreg_pair1[j]>max_reg_var) max_reg_var=dreg_pair[j];
+		/* その場所を表す番号を返す */
+		return list3(DREGISTER,DREG_VAR_BASE-i+DREG_OFFSET,(int)n); 
+	    }
+	}
+	return list2(LVAR,new_lvar(size_of_double));
+    } else {
+	for(i=0;i<FREG_VAR_BASE-FREG_VAR_MIN;i++) {
+	    if (! regs[FREG_VAR_BASE-i+FREG_OFFSET]) {       /* 使われていないなら */
+		regs[FREG_VAR_BASE-i+FREG_OFFSET]=USING_REG; /*そのレジスタを使うことを宣言し*/
+		regv[FREG_VAR_BASE-i+FREG_OFFSET]=0;
+		if (i>max_freg_var) max_freg_var=i;
+		/* その場所を表す番号を返す */
+		return list3(FREGISTER,FREG_VAR_BASE-i+FREG_OFFSET,(int)n); 
+	    }
+	}
+	return list2(LVAR,new_lvar(size_of_float));
     }
-    return list2(LVAR,new_lvar(size_of_double));
 }
 
 void 
@@ -612,7 +750,7 @@
     if (reg_sp>MAX_MAX) error(-1);
     new_reg = get_register();
     reg_stack[reg_sp++] = creg;     /* push するかわりにレジスタを使う */
-    creg = new_reg;
+    ireg = creg = new_reg;
     regv[creg]=1;
 }
 
@@ -626,7 +764,7 @@
         code_rlvar(REG_LVAR_OFFSET+xreg,reg);
 	free_lvar(REG_LVAR_OFFSET+xreg);
 	xreg = reg;
-	regv[xreg]=1;
+	regv[creg]=1;
     }
     return xreg;
 }
@@ -634,6 +772,7 @@
 void
 code_label(int labelno)
 {
+    clear_ptr_cache();
     printf("L_%d:\n",labelno);
 }
 
@@ -659,7 +798,7 @@
 void
 code_register(int e2,int creg) {
     if (creg!=e2)
-	printf("\tmove %s,%s\n",register_name(creg),register_name(e2));
+        printf("\tmove %s,%s\n",register_name(creg),register_name(e2));
     regv[creg]=1;
 }
 
@@ -684,7 +823,6 @@
 code_fname(NMTBL *n,int creg) {
     printf("\tla %s,%s\n",register_name(creg),n->nm);
     regv[creg]=1;
-    return;
 }
 
 
@@ -704,19 +842,18 @@
 void
 code_not(int creg) {
     printf("\tnor %s,%s,%s\n", 
-	register_name(creg), register_name(creg),register_name(creg));
+        register_name(creg), register_name(creg),register_name(creg));
 }
 
 
 void
 code_lnot(int creg) {
     /* if non zero 1 else 0 */
-
     int dreg = get_register();
     printf("\txori %s,%s,0x0\n", 
-	register_name(dreg),register_name(creg));
+        register_name(dreg),register_name(creg));
     printf("\tsltu %s,%s,1\n", 
-	register_name(creg),register_name(dreg));
+        register_name(creg),register_name(dreg));
     free_register(dreg);
 }
 
@@ -725,12 +862,12 @@
     char *xrn,*drn;
     int i,dreg;
     if (car(e2)==REGISTER) {
-	printf("\taddu %s,%s,%d\n", 
-		register_name(cadr(e2)),register_name(cadr(e2)), caddr(e1));
-	if (cadr(reg)!=e2)
-	    printf("\tmove %s,%s\n",register_name(cadr(reg)),register_name(e2));
-	regv[reg]=1;
-	return;
+        printf("\taddu %s,%s,%d\n", 
+                register_name(cadr(e2)),register_name(cadr(e2)), caddr(e1));
+        if (cadr(reg)!=e2)
+            printf("\tmove %s,%s\n",register_name(cadr(reg)),register_name(e2));
+        regv[reg]=1;
+        return;
     } 
     g_expr(e2);
     xrn = register_name(creg);
@@ -750,11 +887,11 @@
     char *xrn,*crn,*nrn;
     int dreg,nreg,i;
     if (car(e2)==REGISTER) {
-	printf("\tmove %s,%s\n",register_name(reg),register_name(cadr(e2)));
-	printf("\taddu %s,%s,%d\n", 
-	    register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
-	regv[reg]=1;
-	return;
+        printf("\tmove %s,%s\n",register_name(reg),register_name(cadr(e2)));
+        printf("\taddu %s,%s,%d\n", 
+            register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
+        regv[reg]=1;
+        return;
     } 
     g_expr(e2);
     crn = register_name(creg);
@@ -777,11 +914,11 @@
     char *xrn,*crn,*nrn;
     int i,nreg,dreg;
     if (car(e2)==REGISTER) {
-	printf("\tlb %s,0(%s)\n",register_name(reg),register_name(cadr(e2)));
-	printf("\taddu %s,%s,%d\n", 
-	    register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
-	regv[reg]=1;
-	return;
+        printf("\tlb %s,0(%s)\n",register_name(reg),register_name(cadr(e2)));
+        printf("\taddu %s,%s,%d\n", 
+            register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
+        regv[reg]=1;
+        return;
     } 
     g_expr(e2);
     crn = register_name(creg);
@@ -805,11 +942,11 @@
     char *xrn,*crn,*nrn;
     int i,nreg,dreg;
     if (car(e2)==REGISTER) {
-	printf("\taddu %s,%s,%d\n", 
-	    register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
-	printf("\tlb %s,0(%s)\n",register_name(reg),register_name(cadr(e2)));
-	regv[reg]=1;
-	return;
+        printf("\taddu %s,%s,%d\n", 
+            register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
+        printf("\tlb %s,0(%s)\n",register_name(reg),register_name(cadr(e2)));
+        regv[reg]=1;
+        return;
     } 
     g_expr(e2);
     crn = register_name(creg);
@@ -833,12 +970,12 @@
     char *xrn,*crn,*nrn;
     int i,nreg,dreg;
     if (car(e2)==REGISTER) {
-	crn=register_name(reg);
-	xrn=register_name(cadr(e2));
-	printf("\tlb %s,0(%s)\n",crn,xrn);
-	printf("\taddu %s,%s,%d\n",xrn,xrn,caddr(e1));
-	regv[reg]=1;
-	return;
+        crn=register_name(reg);
+        xrn=register_name(cadr(e2));
+        printf("\tlb %s,0(%s)\n",crn,xrn);
+        printf("\taddu %s,%s,%d\n",xrn,xrn,caddr(e1));
+        regv[reg]=1;
+        return;
     } 
     g_expr(e2);
     crn = register_name(creg);
@@ -862,12 +999,12 @@
     char *xrn,*crn,*nrn;
     int i,nreg,dreg;
     if (car(e2)==REGISTER) {
-	crn=register_name(reg);
-	xrn=register_name(cadr(e2));
-	printf("\taddu %s,%s,%d\n",xrn,xrn,caddr(e1));
-	printf("\tlb %s,%d(%s)\n",crn,caddr(e1),xrn);
-	regv[reg]=1;
-	return;
+        crn=register_name(reg);
+        xrn=register_name(cadr(e2));
+        printf("\taddu %s,%s,%d\n",xrn,xrn,caddr(e1));
+        printf("\tlb %s,%d(%s)\n",crn,caddr(e1),xrn);
+        regv[reg]=1;
+        return;
     } 
     g_expr(e2);
     crn = register_name(creg);
@@ -919,10 +1056,6 @@
     fwddef(e3);
 }
 
-/* slt $2,$2,$3; beq $2,$0,L1 */
-/* slt $2,$2,$3; xori $2,$2,,0x1,beq $2,$0,L1 */
-/* beq $2,$3,L1 */
-
 char *
 code_gt(int cond) {
     return (cond?"\tslt  %s,%s,%s\n\tbeq %s,$0,%s\n":
@@ -954,41 +1087,41 @@
 
 void
 code_cmp_crgvar(int e1) {
-    if (dreg==-1) dreg = get_register();
-    code_crgvar(cadr(e1),dreg);
-    regv[dreg]=1;
+    if (cmpreg==-1) cmpreg = get_register();
+    code_crgvar(cadr(e1),cmpreg);
+    regv[cmpreg]=1;
 }
 
 
 void
 code_cmp_crlvar(int e2) {
-    if (dreg==-1) dreg = get_register();
-    code_crlvar(e2,dreg);
-    regv[dreg]=1;
+    if (cmpreg==-1) cmpreg = get_register();
+    code_crlvar(e2,cmpreg);
+    regv[cmpreg]=1;
 }
 
 
 void
 code_cmp_rgvar(int e1) {
-    if (dreg==-1) dreg = get_register();
-    code_rgvar(e1,dreg);
-    regv[dreg]=1;
+    if (cmpreg==-1) cmpreg = get_register();
+    code_rgvar(e1,cmpreg);
+    regv[cmpreg]=1;
 }
 
 
 void
 code_cmp_rlvar(int e2) {
-    if (dreg==-1) dreg = get_register();
-    code_rlvar(e2,dreg);
-    regv[dreg]=1;
+    if (cmpreg==-1) cmpreg = get_register();
+    code_rlvar(e1,cmpreg);
+    regv[cmpreg]=1;
 }
 
 
 void
 code_cmp_register(int e2) {
-    dreg = e2;
-    /* prevent dreg freeing */
-    regv[dreg]=2;
+    cmpreg = e2;
+    /* prevent cmpreg freeing */
+    regv[cmpreg]=2;
 }
 
 
@@ -1009,7 +1142,7 @@
 	    printf("%c",*s);
 	s++;
     }
-    printf("\\000%c\n\t.align 2\n",34);
+    printf("\\0%c\n\t.align 2\n",34);
 }
 
 void
@@ -1025,9 +1158,9 @@
     printf("L_%d:\n",lb);
     ascii(s);
     if (output_mode==TEXT_EMIT_MODE) {
-	printf(".text\n");
+        printf(".text\n");
     } else {
-	text_mode();
+        text_mode();
     }
     printf("\tla %s,L_%d\n",crn,lb);
 }
@@ -1047,58 +1180,57 @@
 
     /* length <0 means upward direction copy */
     switch (length) {
-    case 0:	break;
+    case 0:     break;
     case 1: case -1:
-	printf("\tlb %s,%d(%s)\n",drn,offset,frn);
-	printf("\tsb %s,%d(%s)\n",drn,offset,trn);
-	break;
+        printf("\tlb %s,%d(%s)\n",drn,offset,frn);
+        printf("\tsb %s,%d(%s)\n",drn,offset,trn);
+        break;
     case 2: case -2:
-	printf("\tlh %s,%d(%s)\n",drn,offset,frn);
-	printf("\tsh %s,%d(%s)\n",drn,offset,trn);
-	break;
+        printf("\tlh %s,%d(%s)\n",drn,offset,frn);
+        printf("\tsh %s,%d(%s)\n",drn,offset,trn);
+        break;
     case 4: case -4:
-	printf("\tlw %s,%d(%s)\n",drn,offset,frn);
-	printf("\tsw %s,%d(%s)\n",drn,offset,trn);
-	break;
+        printf("\tlw %s,%d(%s)\n",drn,offset,frn);
+        printf("\tsw %s,%d(%s)\n",drn,offset,trn);
+        break;
     default:
-	if (-MAX_COPY_LEN<length && length <0) {
-	    for(;length<=4;length+=4,offset-=4)
-		emit_copy(from,to,4,offset,0,det);
-	    for(;length<=2;length+=2,offset-=2)
-		emit_copy(from,to,2,offset,0,det);
-	    if(length>0)
-		emit_copy(from,to,length,offset,0,det);
-	    break;
-	} else if (length <=MAX_COPY_LEN) {
-	    for(;length>=4;length-=4,offset+=4)
-		emit_copy(from,to,4,offset,0,det);
-	    for(;length>=2;length-=2,offset+=2)
-		emit_copy(from,to,2,offset,0,det);
-	    if(length>0)
-		emit_copy(from,to,length,offset,0,det);
-	    break;
-	}
-	code_save_stacks();
-	printf("\tli $6,%d\n",length);
-	printf("\tmr $5,%s\n",frn);
-	printf("\tmr $4,%s\n",trn);
+        if (-MAX_COPY_LEN<length && length <0) {
+            for(;length<=4;length+=4,offset-=4)
+                emit_copy(from,to,4,offset,0,det);
+            for(;length<=2;length+=2,offset-=2)
+                emit_copy(from,to,2,offset,0,det);
+            if(length>0)
+                emit_copy(from,to,length,offset,0,det);
+            break;
+        } else if (length <=MAX_COPY_LEN) {
+            for(;length>=4;length-=4,offset+=4)
+                emit_copy(from,to,4,offset,0,det);
+            for(;length>=2;length-=2,offset+=2)
+                emit_copy(from,to,2,offset,0,det);
+            if(length>0)
+                emit_copy(from,to,length,offset,0,det);
+            break;
+        }
+        code_save_stacks();
+        printf("\tli $6,%d\n",length);
+        printf("\tmr $5,%s\n",frn);
+        printf("\tmr $4,%s\n",trn);
         /* overrap must be allowed */
-	printf("\tbl L_%s$stub\n",memmove);
+        printf("\tbl L_%s$stub\n",memmove);
         fix=0;
-	set_creg(RET_REGISTER,0);
-	if (creg!=to) {
-	    free_register(to); to = creg;
-	}
-	break;
+        set_creg(RET_REGISTER,0);
+        if (creg!=to) {
+            free_register(to); to = creg;
+        }
+        break;
     }
-    if (value) {
     /* creg must point top of the destination data */
     /* this code is necessary for the value of assignment or function call */
     /* otherwise we don't need this */
-	if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix);
-	if(creg!=to) {
-	    free_register(creg); creg=to;
-	}
+        if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix);
+        if(creg!=to) {
+            free_register(creg); creg=to;
+        }
     }
     free_register(dreg);
     regv[from]=regv[to]=regv[dreg]=0;
@@ -1128,8 +1260,8 @@
 		free_register(dreg);
 		return count;
 	    } else {
-		printf("\tlw %s,%d(%s)\n",drn,length-size_of_int,crn);
-		printf("\tsw %s,%d(%s)\n",drn,length-size_of_int,srn);
+                printf("\tlw %s,%d(%s)\n",drn,length-size_of_int,crn);
+                printf("\tsw %s,%d(%s)\n",drn,length-size_of_int,srn);
 	    }
 	}
     }
@@ -1143,11 +1275,12 @@
 void
 set_creg(int reg,int mode)
 {
+    if (!is_int_reg(reg)) error(-1);
     if (reg!=creg) {
-	if (mode) 
-	    printf("\tmove %s,%s\n",register_name(reg),register_name(creg));
+	if (reg!=ireg && mode) 
+            printf("\tmove %s,%s\n",register_name(reg),register_name(creg));
 	free_register(creg);
-	creg = reg;
+	creg = ireg = reg;
 	regs[creg]=1;
     }
 }
@@ -1155,22 +1288,46 @@
 void
 set_freg(int reg,int mode)
 {
-    if (reg!=freg) {
-	if (mode) 
-	    printf("\tfmove %s,%s\n",fregister_name(reg),fregister_name(freg));
-	free_dregister(freg);
-	freg = reg;
-	fregs[freg]=1;
+    if (!is_float_reg(reg)) error(-1);
+    if (reg!=creg) {
+	if (reg!=freg && mode) {
+            printf("\tfmove %s,%s\n",fregister_name(reg),fregister_name(freg));
+	}
+	free_register(creg);
+	creg = freg = reg;
+	regs[freg]=1;
     }
 }
 
 void
+set_dreg(int reg,int mode)
+{
+    if (!is_double_reg(reg)) error(-1);
+    if (reg!=creg) {
+	if (reg!=dreg && mode) {
+            printf("\tmove %s,%s\n",register_name(dreg_pair0(reg)),
+                                    register_name(dreg_pari0(dreg)));
+            printf("\tmove %s,%s\n",register_name(dreg_pari1(reg)),
+                                    register_name(dreg_pari1(dreg)));
+	}
+	free_register(creg);
+	creg = dreg = reg;
+	regs[dreg]=1;
+	regs[dreg_pair0(dreg)]=1;
+	regs[dreg_pair1(dreg)]=1;
+    }
+}
+
+
+void
 use_var(int arg)
 {
     if (car(arg)==REGISTER)
 	regs[cadr(arg)]=USING_REG;
+    else if (car(arg)==FREGISTER)
+	regs[cadr(arg)]=USING_REG;
     else if (car(arg)==DREGISTER)
-	fregs[cadr(arg)]=USING_REG;
+	regs[cadr(arg)]=USING_REG;
 }
 
 void
@@ -1197,20 +1354,20 @@
 	    offset+=size_of_int;
 	    t = INT;
 	    reg += reg_offset; /* for duplicated floating point argument */
-	} else if (tag==FREGISTER) {
-	    /* fregs[reg]==INPUT_REG case should be considered */
-	    n->dsp = offset;
-	    t = n->ty;
-	    if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; }
-	    else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; }
-	    else error(-1);
-	} else if (tag==DREGISTER) {
-	    /* fregs[reg]==INPUT_REG case should be considered */
-	    n->dsp = offset;
-	    t = n->ty;
-	    if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; }
-	    else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; }
-	    else error(-1);
+        } else if (tag==FREGISTER) {
+            /* fregs[reg]==INPUT_REG case should be considered */
+            n->dsp = offset;
+            t = n->ty;
+            if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; }
+            else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; }
+            else error(-1);
+        } else if (tag==DREGISTER) {
+            /* fregs[reg]==INPUT_REG case should be considered */
+            n->dsp = offset;
+            t = n->ty;
+            if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; }
+            else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; }
+            else error(-1);
 	} else {
 	    offset += size(n->ty);
 	    continue;
@@ -1218,12 +1375,8 @@
 	n->sc  = LVAR;
 	lvar = list2(LVAR,n->dsp);
 	g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),n->ty,t));
-	if (tag==REGISTER) {
+	if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER) {
 	    free_register(reg);
-	} else if (tag==DREGISTER) {
-	    free_dregister(reg);
-	} else if (tag==FREGISTER) {
-	    free_dregister(reg);
 	}
     }
     my_func_args = offset;
@@ -1251,13 +1404,25 @@
 {
     int e2,e3,e4,e5,nargs,t,r0,r1;
     int arg,reg_arg,freg_arg,arg_assign;
+    int dots;
     int reg_arg_list=0,ret_type,special_lvar;
     NMTBL *fn = 0;
     int jmp = 0;
     char *jrn;
 
     special_lvar = -1;
-    ret_type = cadddr(e1);
+    ret_type = cadr(cadddr(e1));
+    if (ret_type==CHAR) ret_type=INT;
+
+    /* check argments type is DOTS? */
+    t = caddr(cadddr(e1));
+    if (t==0 || t==DOTS) dots = 1;
+    else {
+	dots = 0;
+	for(t = caddr(cadddr(e1));t;t = cadr(t)) {
+	    if (car(t)==DOTS) dots = 1;
+	}
+    }
 
     e2 = cadr(e1);
     if (car(e2) == FNAME) {	
@@ -1275,6 +1440,7 @@
     code_save_stacks();
     set_creg(CREG_REGISTER,0);
     set_freg(FREG_FREGISTER,0);
+    set_dreg(DREG_DREGISTER,0);
 
     nargs = reg_arg = freg_arg = arg_assign = 0;
     for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {	
@@ -1286,7 +1452,8 @@
 	    } else if (!simple_args(e3) && cadr(e3)) {
 		arg = get_register_var(0); 
 		arg_assign = list2(
-		    assign_expr0(get_input_register_var(reg_arg,0,0),arg,t,t),
+		    assign_expr0(get_input_register_var(reg_arg,0,0),
+			arg,t,t),
 		    arg_assign);
 	    } else {
 		arg = get_input_register_var(reg_arg,0,0); 
@@ -1307,13 +1474,13 @@
 		} else {
 		    special_lvar = new_lvar(size_of_double);
 		    g_expr(assign_expr0(
-			(e5=list2(LVAR,special_lvar)),e4,t,t));
+			(e5=list2(LVAR,special_lvar)),e4,DOUBLE,t));
 		    reg_arg_list = list2(e5,reg_arg_list);
 		    e4 = list2(DREGISTER,freg);
 		    /* freg should not change until XXX */
 		}
 		r0=get_input_register_var(reg_arg,0,0);
-		r1=get_input_register_var(reg_arg+1,0,0);
+		r1=get_input_register_var_1(reg_arg+1,0,0);
 		use_var(r0); /* protect from input register free */
 		use_var(r1); /* protect from input register free */
 		reg_arg_list = list2(r0,reg_arg_list);
@@ -1324,22 +1491,13 @@
 			INT,INT), arg_assign);
 		reg_arg += 2;
 	    }
-	    if (freg_arg>=4 && freg_arg<MAX_INPUT_DREGISTER_VAR) { 
-		/* oh my god! 
-                   it requies integer register and floating register and
-                   stack value. You are crazy.
-                 */
-		arg_assign = list2(
-		    assign_expr0(list2(LVAR,caller_arg_offset_v(nargs)),
-			    get_input_dregister_var(freg_arg,0,0,1),t,t),
-		    arg_assign);
-	    }
 	    if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
 		arg = list2(LVAR,caller_arg_offset_v(nargs));
-	    } else if (!simple_args(e3)) {
+	    } else if (!simple_args(e3) && cadr(e3)) {
 		arg = get_dregister_var(0,1); 
 		arg_assign = list2(
-		    assign_expr0(get_input_dregister_var(freg_arg,0,0,1),arg,t,t),
+		    assign_expr0(get_input_dregister_var(freg_arg,0,0,1),
+			arg,t,t),
 		    arg_assign);
 	    } else {
 		arg = get_input_dregister_var(freg_arg,0,0,1); 
@@ -1363,6 +1521,7 @@
     for(;arg_assign;arg_assign=cadr(arg_assign)) {
 	g_expr_u(car(arg_assign));
     }
+    clear_ptr_cache();
     if (car(e2) == FNAME) {	
 	printf("\tbl\tL_%s$stub\n",fn->nm);
     } else {
@@ -1371,19 +1530,21 @@
     }
     for(;reg_arg_list;reg_arg_list=cadr(reg_arg_list)) {
 	arg = car(reg_arg_list);
-	if (car(arg)==DREGISTER) free_dregister(cadr(arg));
-	else if (car(arg)==FREGISTER) free_dregister(cadr(arg));
-	else if (car(arg)==REGISTER) free_register(cadr(arg));
+	if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER) 
+	    free_register(cadr(arg));
 	else if (car(arg)==LVAR&&cadr(arg)<0) free_lvar(cadr(arg));
     }
-    if (ret_type==DOUBLE||ret_type==FLOAT) {
+    if (ret_type==DOUBLE) {
+	set_dreg(RET_DREGISTER,0);
+        regv[dreg]=1; regv[creg]=0;
+    } else if (ret_type==FLOAT) {
 	set_freg(RET_FREGISTER,0);
-        fregv[freg]=1; regv[creg]=0;
+        regv[freg]=1; regv[creg]=0;
     } else if (ret_type==VOID) {
-        fregv[freg]=0; regv[creg]=0;
+        regv[freg]=0; regv[creg]=0;
     } else {
 	set_creg(RET_REGISTER,0);
-        fregv[freg]=0; regv[creg]=1;
+        regv[freg]=0; regv[creg]=1;
     }
     return ret_type;
 }
@@ -1439,16 +1600,16 @@
     crn=register_name(creg);
     switch (car(e1)) {
     case FRINDIRECT: case DRINDIRECT:
-	printf("\t%s %s,%d(%s)\n",fload(car(e1)==DRINDIRECT),
-	    fregister_name(freg),offset,crn);
-	regv[creg]=0; regv[freg]=1;
-	return DOUBLE;
+        printf("\t%s %s,%d(%s)\n",fload(car(e1)==DRINDIRECT),
+            fregister_name(freg),offset,crn);
+        regv[creg]=0; regv[freg]=1;
+        return DOUBLE;
     case CRINDIRECT: 
-	printf("\tlb %s,%d(%s)\n",crn,offset,crn);
-	return CHAR;
+        printf("\tlb %s,%d(%s)\n",crn,offset,crn);
+        return CHAR;
     case RINDIRECT:
-	printf("\tlw %s,%d(%s)\n",crn,offset,crn);
-	return INT;
+        printf("\tlw %s,%d(%s)\n",crn,offset,crn);
+        return INT;
     }
     error(-1); return INT;
 }
@@ -1460,9 +1621,9 @@
     nm = ((NMTBL*)cadr(e2))->nm;
     crn=register_name(creg);
     if (byte) {
-	printf("\tsb %s,%s\n",crn,nm);
+        printf("\tsb %s,%s\n",crn,nm);
     } else {
-	printf("\tsw %s,%s\n",crn,nm);
+        printf("\tsw %s,%s\n",crn,nm);
     }
 }
 
@@ -1471,16 +1632,16 @@
     char *crn;
     crn=register_name(creg);
     if (byte) {
-	printf("\tsb %s,",crn); lvar(e2);
+        printf("\tsb %s,",crn); lvar(e2);
     } else {
-	printf("\tsw %s,",crn); lvar(e2);
+        printf("\tsw %s,",crn); lvar(e2);
     }
 }
 
 void
 code_assign_register(int e2,int byte,int creg) {
     if (e2!=creg)
-	printf("\tmove %s,%s\n",register_name(e2),register_name(creg));
+        printf("\tmove %s,%s\n",register_name(e2),register_name(creg));
 }
 
 void
@@ -1489,10 +1650,11 @@
     char *crn=register_name(creg);
 
     if (byte) {
-	printf("\tsb %s,0(%s)\n",crn,drn);
+        printf("\tsb %s,0(%s)\n",crn,drn);
     } else {
-	printf("\tsw %s,0(%s)\n",crn,drn);
+        printf("\tsw %s,0(%s)\n",crn,drn);
     }
+    regv[creg]=1;
 }
 
 
@@ -1504,7 +1666,8 @@
     tosop(op,xreg);
     creg = xreg;
     if (creg!=reg)
-	printf("\tmove %s,%s\n",register_name(creg),register_name(reg));
+        printf("\tmove %s,%s\n",register_name(creg),register_name(reg));
+    regv[creg]=1;
 }
 
 
@@ -1522,12 +1685,13 @@
     crn = register_name(creg);
     drn = register_name(edx);
     if (byte) {
-	printf("\tsb %s,0(%s)\n",crn,drn);
+        printf("\tsb %s,0(%s)\n",crn,drn);
     } else {
-	printf("\tsw %s,0(%s)\n",crn,drn);
+        printf("\tsw %s,0(%s)\n",crn,drn);
     }
     free_register(edx);
     emit_pop_free(xreg);
+    regv[creg]=1;
 }
 
 
@@ -1535,7 +1699,7 @@
 tosop(int op,int oreg)
 {
     int dx;
-    char *orn,*crn;
+    char *orn,*crn,*drn;
 
     if(oreg==-1) {
 	error(-1);
@@ -1550,12 +1714,15 @@
     case LSHIFT:
     case ULSHIFT:
 	shift("sll",oreg);
+	regv[creg]=1;
 	return;
     case RSHIFT:
 	shift("srl",oreg);
+	regv[creg]=1;
 	return;
     case URSHIFT:
 	shift("sra",oreg);
+	regv[creg]=1;
 	return;
     }
     orn = register_name(oreg);
@@ -1585,19 +1752,23 @@
     case UMUL:
 	printf("\tmultu %s,%s,%s\n",crn,crn,orn);
 	break;
+    case DIV:
+	printf("\tdivw %s,%s,%s\n",crn,crn,orn);
+	break;
     case DIV: case UDIV: case MOD: case UMOD:
-	printf("\t%s $0,%s,%s\n",(op==UDIV||op==UMOD)?"divu":"div",crn,orn);
-	printf("\t%s %s\n",(op==MOD||op==UMOD)?"mflo":"mfhi",crn);
-	printf("\t.set    noreorder\n");
-	printf("\tbeql    %s,$0,1f\n",orn);
-	printf("\tbreak   7\n");
-	printf("1:\n");
-	printf("\t.set    reorder\n");
-	break;
+        printf("\t%s $0,%s,%s\n",(op==UDIV||op==UMOD)?"divu":"div",crn,orn);
+        printf("\t%s %s\n",(op==MOD||op==UMOD)?"mflo":"mfhi",crn);
+        printf("\t.set    noreorder\n");
+        printf("\tbeql    %s,$0,1f\n",orn);
+        printf("\tbreak   7\n");
+        printf("1:\n");
+        printf("\t.set    reorder\n");
+        break;
     default:
 	error(-1);
     }
     if(oreg!=creg) free_register(oreg);
+    regv[creg]=1;
 }
 
 
@@ -1614,12 +1785,12 @@
 {	
     char *crn = register_name(creg);
     if (byte) {
-	printf("\tlb %s,%d(%s)\n",register_name(creg),n,
-	    register_name(xreg));
-	printf("\textsb %s,%s\n",crn,crn);
+        printf("\tlb %s,%d(%s)\n",register_name(creg),n,
+            register_name(xreg));
+        printf("\textsb %s,%s\n",crn,crn);
     } else 
-	printf("\tlw %s,%d(%s)\n",register_name(creg),n,
-	    register_name(xreg));
+        printf("\tlw %s,%d(%s)\n",register_name(creg),n,
+            register_name(xreg));
 }
 
 int
@@ -1634,8 +1805,8 @@
     /* used in dosiwtch() */
     if(chk) return;
     printf("\tli %s,%d\n",register_name(creg),e);
-    dreg = csreg;
-    regv[dreg]=2; /* prevent from freeing */
+    cmpreg = csreg;
+    regv[cmpreg]=2; /* prevent from freeing */
 }
 
 void
@@ -1651,13 +1822,13 @@
     printf("\t.text\n");
 
     if (asi) {
-	fclose(asi);
-	asi = 0;
+        fclose(asi);
+        asi = 0;
     }
     while ((*cheapp++ = *s++)) {
         if (*s=='.') {
             *cheapp++=*s++; *cheapp++='i';
-	    *cheapp++=0;
+            *cheapp++=0;
             break;
         }
     }
@@ -1670,39 +1841,39 @@
 rexpr(int e1, int l1, char *s,int t)
 {       
     char *crn,*drn;
-    if (dreg>=0) { free_register(dreg); dreg = -1; }
+    if (cmpreg>=0) { free_register(cmpreg); cmpreg = -1; }
 
     g_expr(cadr(e1));
     emit_push();
     g_expr(caddr(e1));
-    dreg = pop_register();
+    cmpreg = pop_register();
     crn = register_name(creg);
-    drn = register_name(dreg);
+    drn = register_name(cmpreg);
 
     if (s[1] == 's') {
-	if (s[16]=='x') {
-	    /* slt $2,$2,$3; xroi $2,$2,0x1; beq $2,$0,L1 */
-	    printf(s,crn,drn,drn,crn,crn,crn,l1);
-	} else {
-	    /* slt $2,$2,$3; beq $2,$0,L1 */
-	    printf(s,crn,drn,drn,crn,l1);
-	}
+        if (s[16]=='x') {
+            /* slt $2,$2,$3; xroi $2,$2,0x1; beq $2,$0,L1 */
+            printf(s,crn,drn,drn,crn,crn,crn,l1);
+        } else {
+            /* slt $2,$2,$3; beq $2,$0,L1 */
+            printf(s,crn,drn,drn,crn,l1);
+        }
     } else {
-	/* beq $2,$3,L1 */
-	printf(s,crn,drn,l1);
+        /* beq $2,$3,L1 */
+        printf(s,crn,drn,l1);
     }
-    free_register(dreg) ; dreg = -1;
+    free_register(cmpreg) ; cmpreg = -1;
 }
 
 void
 jcond(int l, char cond)
 {
     if (chk) return;
-    if (dreg==-1) error(-1);
-    printf("\tb%s %s,%s,L_%d\n",register_name(creg),register_name(dreg),
-	cond?"ne":"eq",l);
-    if (regv[dreg]==1) {
-	free_register(dreg); dreg = -1;
+    if (cmpreg==-1) error(-1);
+    printf("\tb%s %s,%s,L_%d\n",register_name(creg),register_name(cmpreg),
+        cond?"ne":"eq",l);
+    if (regv[cmpreg]==1) {
+        free_register(cmpreg); cmpreg = -1;
     } 
     regv[creg]=0;
 }
@@ -1730,7 +1901,7 @@
     else
 	printf("\t.align 3\n");
     if (stmode!=STATIC)
-	printf(".globl %s\n",name);
+	printf(".globl _%s\n",name);
     printf(".ent %s\n",name);
     printf("_%s:\n",name);
     code_disp_label=fwdlabel();
@@ -1740,6 +1911,7 @@
     printf("\t.set reorder\n");
     printf("\tsubu $sp,$sp,L_%d\n",code_disp_label);
     printf("\t.cprestore 16\n");
+
     max_func_args = 0;
 }
 
@@ -1749,6 +1921,7 @@
 {
     set_creg(CREG_REGISTER,0);
     set_freg(FREG_FREGISTER,0);
+    set_dreg(DREG_DREGISTER,0);
 }
 
 void
@@ -1759,6 +1932,7 @@
     r1_offsetv = -disp+max_func_args*size_of_int+code_disp_offset;
 
     fprintf(asi,"L_%d=%d\n",code_disp_label,-r1_offsetv);
+
     local_table();
     free_all_register();
 }
@@ -1771,7 +1945,7 @@
     else
 	printf("\t.align 2\n");
     if (stmode!=STATIC)
-	printf(".globl %s\n",name);
+	printf(".globl _%s\n",name);
     printf(".ent %s\n",name);
     printf("_%s:\n",name);
 
@@ -1792,6 +1966,7 @@
     printf("\tsubu $sp,$sp,L_%d\n",code_disp_label);
     printf("\t.cprestore 16\n");
     max_func_args = 0;
+
 }
 
 void
@@ -1799,6 +1974,7 @@
 {
     set_creg(CREG_REGISTER,0);
     set_freg(FREG_FREGISTER,0);
+    set_dreg(DREG_DREGISTER,0);
 }
 
 int
@@ -1865,9 +2041,17 @@
     }
 
     disp &= -size_of_int;
-
-    printf("\tj $31\n");
-    printf("\t.end %s\n",fnptr->nm);
+    fwddef(code_setup);
+    printf("\tstmw r%d,%d(r1)\n",
+		    REG_VAR_BASE-max_reg_var,reg_save);
+    printf("\tstw r0,8(r1)\n");
+    if (max_freg_var>=0)
+	printf("\tb saveFP+%d ; save f%d-f31\n",
+			freg_save,
+			FREG_VAR_BASE-max_freg_var);
+    else {
+	printf("\tblr\n");
+    }
 
     code_offset_set();
     local_table();
@@ -1878,8 +2062,11 @@
 
 void
 code_set_return_register(int mode) {
-    if (cadr(fnptr->ty)==DOUBLE||cadr(fnptr->ty)==FLOAT) {
+    if (cadr(fnptr->ty)==DOUBLE) {
+	set_dreg(RET_DREGISTER,mode);
+    } else if (cadr(fnptr->ty)==FLOAT) {
 	set_freg(RET_FREGISTER,mode);
+    } else if (cadr(fnptr->ty)==VOID) {
     } else {
 	set_creg(RET_REGISTER,mode);
     }
@@ -1887,12 +2074,18 @@
 
 void
 code_set_fixed_creg(int mode,int type) {
-    if (type==FLOAT||type==DOUBLE) {
+    if (type==FLOAT) {
 	if (cond_freg== -1) {
-	    cond_freg = get_dregister_var(0,1);
-	    if(car(cond_freg)!=DREGISTER) error(-1);
+	    cond_freg = get_dregister_var(0,0);
+	    if(car(cond_freg)!=FREGISTER) error(-1);
 	}
 	set_freg(cadr(cond_freg),mode);
+    } else if (type==DOUBLE) {
+	if (cond_dreg== -1) {
+	    cond_dreg = get_dregister_var(0,1);
+	    if(car(cond_dreg)!=DREGISTER) error(-1);
+	}
+	set_dreg(cadr(cond_dreg),mode);
     } else {
 	if (cond_reg== -1) {
 	    cond_reg = get_register_var(0);
@@ -1906,7 +2099,7 @@
 gen_gdecl(char *n, int gpc)
 {
     if (stmode!=STATIC)
-	printf(".globl %s\n",n); 
+	printf(".globl _%s\n",n); 
 }
 
 void 
@@ -1951,32 +2144,32 @@
 	    if (data_alignment>0) data_alignment++;
 	    gpc += 2;
 	} else {
-	    printf("\t.long %d\n",cadr(e));
+	    printf("\t.word %d\n",cadr(e));
 	    gpc += size_of_int;
 	}
     } else if(t==DOUBLE) {       
-	d = dcadr(e);
-	printf("\t.word\t0x%x\n\t.word\t0x%x\n",code_d2(d),code_d1(d));
+        d = dcadr(e);
+        printf("\t.word\t0x%x\n\t.word\t0x%x\n",code_d2(d),code_d1(d));
     } else if(t==FLOAT) {       
-	f = dcadr(e);
-	printf("\t.word\t0x%x\n",*(int *)&f);
+        f = dcadr(e);
+        printf("\t.word\t0x%x\n",*(int *)&f);
     } else if(t!=CHAR) {       
 	gpc += size_of_int;
-	if(car(e)==ADDRESS&&car(cadr(e))==GVAR) {
-	    printf("\t.word _%s\n",((NMTBL *)cadr(cadr(e)))->nm);
-	} else if(car(e)==FNAME) {
-	    printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm);
-	} else if(car(e)==GVAR) {
-	    printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm);
-	} else if(car(e)==STRING) {       
-	    if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) {
-		l = fwdlabel();
-		printf("\t.word L_%d\n",l);
-		printf(".rdata\n\t.align 2\n");
-		printf("L_%d:\n",l);
-		output_mode = RODATA_EMIT_MODE;
-	    }
-	    ascii((char *)cadr(e));
+        if(car(e)==ADDRESS&&car(cadr(e))==GVAR) {
+            printf("\t.word _%s\n",((NMTBL *)cadr(cadr(e)))->nm);
+        } else if(car(e)==FNAME) {
+            printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm);
+        } else if(car(e)==GVAR) {
+            printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm);
+        } else if(car(e)==STRING) {       
+            if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) {
+                l = fwdlabel();
+                printf("\t.word L_%d\n",l);
+                printf(".rdata\n\t.align 2\n");
+                printf("L_%d:\n",l);
+                output_mode = RODATA_EMIT_MODE;
+            }
+            ascii((char *)cadr(e));
 	} else error(TYERR);
     }
 }
@@ -1998,28 +2191,27 @@
     }
 }
 
-void
 global_table(void)
 {
     NMTBL *n;
     int init; 
     init=0;
     for(n=ntable;n < &ntable[GSYMS];n++) {
-	if ((n->sc == GVAR) && n->dsp != -1) {
-	    /* n->dsp = -1 means initialized global */
-	    if (init==0) {
-		data_mode(0);
-		init=1;
-	    }
-	    printf(".comm _%s,%d\n",n->nm,size(n->ty));
-	} else if ((n->sc==STATIC) && n->dsp != -1) {
-	    /* n->dsp = -1 means initialized global */
-	    if (init==0) {
-		data_mode(0);
-		init=1;
-	    }
-	    printf(".lcomm _%s,%d\n",n->nm,size(n->ty));
-	}
+        if ((n->sc == GVAR) && n->dsp != -1) {
+            /* n->dsp = -1 means initialized global */
+            if (init==0) {
+                data_mode(0);
+                init=1;
+            }
+            printf(".comm _%s,%d\n",n->nm,size(n->ty));
+        } else if ((n->sc==STATIC) && n->dsp != -1) {
+            /* n->dsp = -1 means initialized global */
+            if (init==0) {
+                data_mode(0);
+                init=1;
+            }
+            printf(".lcomm _%s,%d\n",n->nm,size(n->ty));
+        }
     }
 }
 
@@ -2062,32 +2254,31 @@
 	printf("\t.type\t%s,@object\n",name);
 }
 
-/* floating point */
-
 char *
 fstore(int d)
 {
-    return (d?"s.d":"s.s");
+    return (d?"stfd":"stfs");
 }
 
 char *
 fload(int d)
 {
-    return d?"l.d":"l.s";
+    return d?"lfd":"lfs";
 }
 
 void
 code_cmp_dregister(int e2,int d)
 {
-    /* not tested.. */
-    char *frn,*grn;
-    int greg;
-
+    char *frn,*rrn,*grn;
+    int greg,r;
     grn =  register_name(greg = get_dregister(d));
     frn = register_name(e2);
-    printf("\tli.s %s,%g\n",grn,0.0);
-    printf("\tc.eq.s %s,%s\n",grn,frn);
-    free_dregister(greg);
+    float_zero_lib_used=1;
+    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);
+    free_register(greg);
     return;
 }
 
@@ -2095,71 +2286,42 @@
 code_dregister(int e2,int freg,int d)
 {
     if (freg!=e2) {
-	if (d) {
-	    printf("\tmove %s,%s\n",
-		fregister_name0(freg),
-		fregister_name0(e2));
-	    printf("\tmove %s,%s\n",
-		fregister_name1(freg),
-		fregister_name1(e2));
-	} else {
-	    printf("\tmov.s %s,%s\n",fregister_name(freg),fregister_name(e2));
-	}
+	if (is_int_reg(e2)) error(-1);
+	printf("\tfmr %s,%s\n",fregister_name(freg),fregister_name(e2));
     }
-    fregv[freg]=1;
+    regv[freg]=1;
 }
 
 void code_dassign_gvar(int e2,int freg,int d)
 { 
-    NMTBL *n = (NMTBL*)cadr(e2);
-    if (d) {
-	printf("\tsw %s,0(%s)\n",fregister_name0(freg),n->nm);
-	printf("\tsw %s,0(%s)\n",fregister_name1(freg),n->nm);
-    } else {
-	printf("\t%s.s %s,0(%s)\n",fregister_name(freg),n->nm);
-    }
-    fregv[freg]=1;
+    int r;
+    r = get_ptr_cache((NMTBL*)cadr(e2));
+    if (!is_float_reg(freg)) error(-1);
+    printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(r));
+    regv[freg]=1;
 }
 
 void code_dassign_lvar(int e2,int freg,int d)
 { 
-    if (d) {
-	printf("\tsw %s,",fregister_name0(freg));
-	lvar(e2);
-	printf("\tsw %s,",fregister_name1(freg));
-	e2 += size_of_double/2;
-    } else {
-	printf("\ts.s %s,",fregister_name(freg));
-    }
+    lvar_intro(e2);
+    if (!is_float_reg(freg)) error(-1);
+    printf("\t%s %s,",fstore(d),fregister_name(freg));
     lvar(e2);
-    fregv[freg]=1;
+    regv[freg]=1;
 }
 
 void code_dassign(int e2,int freg,int d)
 { 
-    if (d) {
-	printf("\tsw %s,0(%s)\n",fregister_name0(freg),register_name(e2));
-	printf("\tsw %s,4(%s)\n",fregister_name1(freg),register_name(e2));
-    } else {
-	printf("\ts.s %s,0(%s)\n",fregister_name(freg),register_name(e2));
-    }
-    fregv[freg]=1;
+    if (!is_float_reg(freg)) error(-1);
+    printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(e2));
+    regv[freg]=1;
 }
 
 void
 code_dassign_dregister(int e2,int d,int freg) {
-    /* これってさ、code_dregister と同じ? */
     if (e2!=freg) {
-	if (d) {
-	    printf("\tmove %s,%s\n",
-		fregister_name0(freg),
-		fregister_name0(e2));
-	    printf("\tmove %s,%s\n",
-		fregister_name1(freg),
-		fregister_name1(e2));
-	} else {
-	    printf("\tmov.s %s,%s\n",fregister_name(e2),fregister_name(freg));
-	}
+	if (is_int_reg(freg)) error(-1);
+	printf("\tfmr %s,%s\n",fregister_name(e2),fregister_name(freg));
     }
 }
 
@@ -2187,268 +2349,301 @@
     return *j;
 }
 
-void code_dconst(int e2,int freg,int d)
+void 
+code_dconst(int e2,int freg,int d)
 { 
+    int lb;
     double value = dcadr(e2);
-    char *frn;
+    int r;
+    char *rrn,*frn;
+    frn = fregister_name(freg);
+    if (value==0.0) {
+	float_zero_lib_used=1;
+	r = get_ptr_cache(&float_zero);
+	rrn = register_name(r);
+	printf("\tlfs %s,0(%s)\n",frn,rrn);
+	return;
+    }
+    if (value==1.0) {
+	float_one_lib_used=1;
+	r = get_ptr_cache(&float_one);
+	rrn = register_name(r);
+	printf("\tlfs %s,0(%s)\n",frn,rrn);
+	return;
+    }
+    rrn = register_name((r=get_register()));
+    printf(" \t.data\n\t.align 3\n");
+    lb=fwdlabel();
+    printf("L_%d:\n",lb);
     if (d) {
-	printf("\tli %s,%g\n",fregister_name0(freg),code_d1(value));
-	printf("\tli %s,%g\n",fregister_name1(freg),code_d2(value));
+	printf("\t.long\t0x%x,0x%x\n",code_d2(value),code_d1(value));
+    } else {
+	printf("\t.long\t0x%x\n",code_f(value));
+    }
+    if (output_mode==TEXT_EMIT_MODE) {
+	printf(".text\n");
     } else {
-	frn = fregister_name(freg);
-	printf("\tli.s %s,%g\n",frn,value);
+	text_mode();
     }
-    fregv[freg]=1;
+    printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",rrn,lb,code_base);
+    printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",rrn,lb,code_base,rrn);
+    if (d) {
+	printf("\tlfd %s,0(%s)\n",frn,rrn);
+    } else {
+	printf("\tlfs %s,0(%s)\n",frn,rrn);
+    }
+    free_register(r);
+    regv[freg]=1;
 }
 
 
 void code_dneg(int freg,int d)
 { 
-    char *frn;
-    if (d) {
-	code_save_stacks();
-	printf("\tmove $4,%s\n", fregister_name0(freg));
-	printf("\tmove $5,%s\n", fregister_name1(freg));
-	printf("\tjal dpneg\n");
-	set_freg(RET_DREGISTER,0);
-    } else {
-	frn = fregister_name(freg);
-	printf("\tfneg %s,%s\n",frn,frn);
-    }
+    char *frn = fregister_name(freg);
+    if (is_int_reg(freg)) error(-1);
+    printf("\tfneg %s,%s\n",frn,frn);
 }
 
-void code_d2i(int freg,int creg)
-{ 
-    char *frn = fregister_name(freg);
-    char *crn = register_name(creg);
-    int e2 = new_lvar(size_of_double);
-    free_lvar(e2);
-    code_save_stacks();
-    /* setup arguments */
-    printf("\tjal dptoli\n");
-    printf("\tstfd  %s,",frn); lvar(e2);
-    printf("\tlwz %s,",crn); lvar(e2+size_of_double-size_of_int);
-    fregs[freg]=0;
-    regs[creg]=1;
-}
-
-void code_i2d(int creg,int freg)
-{ 
-    code_save_stacks();
-    set_creg(RET_REGISTER,1);
-    printf("\tjal litodp\n");
-    set_freg(RET_DREGISTER,0);
-    fregs[freg]=1;
-    regs[creg]=0;
-}
-
-
-void code_d2u(int freg,int creg)
-{ 
-    code_save_stacks();
-    set_freg(RET_FREGISTER,1);
-    printf("\tjal dptoul\n");
-    set_creg(RET_REGISTER,0);
-    fregs[freg]=1;
-    regs[creg]=0;
-}
-
-void code_u2d(int creg,int freg)
+void code_d2i(int freg0)
 { 
     char *frn;
     char *crn;
-    code_save_stacks();
-    frn = fregister_name(freg);
+    int e2 = new_lvar(size_of_double);
+
+    freg0 = use_double(freg0);
+    frn = fregister_name(freg0);
+    creg = use_int(creg);
     crn = register_name(creg);
 
-    printf("\tmr r3,%s\n",crn);
-    printf("\tjal litodp\n");
-    printf("\tfmr %s,f1\n",frn);
-    fregs[freg]=1;
-    regs[creg]=0;
+    freg = freg0;
+    free_lvar(e2);
+    printf("\tfctiwz  %s,%s\n",frn,frn);
+    lvar_intro(e2);
+    printf("\tstfd  %s,",frn); lvar(e2);
+    lvar_intro(e2+size_of_double-size_of_int);
+    printf("\tlwz %s,",crn); lvar(e2+size_of_double-size_of_int);
+    regv[creg]=1;
 }
 
-void code_d2f(int freg) {
+static int i2d_lib_used=0;
+static char *i2d_lib[] = {
+".data",
+/* ".literal8", */
+"        .align 3",
+"__i2dLC0:",
+"        .long   1127219200",
+"        .long   -2147483648",
+".text",
+"        .align 2",
+"i2d_:",
+"        mflr r0",
+"        bcl 20,31,__i2dL1$pb",
+"__i2dL1$pb:",
+"        mflr r10",
+"        mtlr r0",
+"        xoris r3,r3,0x8000",
+"        stw r3,-28(r30)",
+"        lis r0,0x4330",
+"        stw r0,-32(r30)",
+"        lfd f0,-32(r30)",
+"        addis r9,r10,ha16(__i2dLC0-__i2dL1$pb)",
+"        lfd f1,lo16(__i2dLC0-__i2dL1$pb)(r9)",
+"        fsub f1,f0,f1",
+"        blr",
+0
+};
+
+void code_i2d(int creg0)
+{ 
+    i2d_lib_used = 1;
+    clear_ptr_cache();
     code_save_stacks();
-    /* setup arguments */
-    printf("\tmove $4,%s\n", fregister_name0(freg));
-    printf("\tmove $5,%s\n", fregister_name1(freg));
-    printf("\tjal dptofp\n");
+    set_creg(RET_REGISTER,1);
+    printf("\tbl i2d_\n");
     set_freg(RET_FREGISTER,0);
+    regv[freg]=1;
 }
 
-void code_f2d(int freg) {
+static int d2u_lib_used=0;
+static char *d2u_lib[] = {
+/* ".literal8", */
+"        .align 3",
+"__d2uLC0:",
+"        .long   1105199104",
+"        .long   0",
+".text",
+"        .align 2",
+"d2u_:",
+"        mflr r0",
+"        bcl 20,31,__d2uL1$pb",
+"__d2uL1$pb:",
+"        mflr r10",
+"        mtlr r0",
+"        addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)",
+"        lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)",
+"        fcmpu cr0,f1,f0",
+"        cror 2,1,2",
+"        beq- cr0,__d2uL2",
+"        fctiwz f0,f1",
+"        stfd f0,-32(r30)",
+"        lwz r3,-28(r30)",
+"        blr",
+"__d2uL2:",
+"        addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)",
+"        lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)",
+"        fsub f0,f1,f0",
+"        fctiwz f0,f0",
+"        stfd f0,-24(r30)",
+"        lwz r3,-20(r30)",
+"        xoris r3,r3,0x8000",
+"        blr",
+0
+};
+
+void code_d2u(int freg0)
+{ 
     code_save_stacks();
-    /* setup arguments */
-    printf("\tmov.s f12,%s\n", fregister_name(freg));
-    printf("\tjal fptodp\n");
-    set_freg(RET_DREGISTER,0);
-}
-
-void code_f2i(int freg,int creg) {
-    printf("\ttrunc.w.s %s,%s,%s\n",freg,freg,creg);
+    clear_ptr_cache();
+    d2u_lib_used=1;
+    set_freg(RET_FREGISTER,1);
+    printf("\tbl d2u_\n");
+    set_creg(RET_REGISTER,0);
+    regv[freg]=1;
 }
 
-void code_f2u(int freg,int creg) {
-    printf("\ttrunc.w.s %s,%s,%s\n",freg,freg,creg);
+static int u2d_lib_used=0;
+static char *u2d_lib[] = {
+".data",
+/* ".literal8", */
+"        .align 3",
+"__u2dLC1:",
+"        .long   1127219200",
+"        .long   0",
+".text",
+"        .align 2",
+"u2d_:",
+"        mflr r0",
+"        bcl 20,31,__u2dL2$pb",
+"__u2dL2$pb:",
+"        mflr r10",
+"        mtlr r0",
+"        stw r3,-28(r30)",
+"        lis r0,0x4330",
+"        stw r0,-32(r30)",
+"        lfd f0,-32(r30)",
+"        addis r9,r10,ha16(__u2dLC1-__u2dL2$pb)",
+"        lfd f1,lo16(__u2dLC1-__u2dL2$pb)(r9)",
+"        fsub f1,f0,f1",
+"        blr",
+0
+};
+
+void code_u2d(int creg0)
+{ 
+    code_save_stacks();
+    clear_ptr_cache();
+    u2d_lib_used = 1;
+    set_creg(RET_REGISTER,1);
+    printf("\tbl u2d_\n");
+    set_freg(FREG_FREGISTER,0);
+    regv[freg]=1;
 }
 
-void code_i2f(int creg,int freg) {
-    printf("\tcvt.s.w %s,%s\n",freg,freg);
-}
-
-void code_u2f(int creg,int freg) {
-    printf("\tcvt.s.w %s,%s\n",freg,freg);
-}
+void code_d2f(int freg) { }
+void code_f2d(int freg) { }
+void code_f2i(int freg) { code_d2i(freg); }
+void code_f2u(int freg) { code_d2u(freg); }
+void code_i2f(int creg) { code_i2d(creg); }
+void code_u2f(int creg) { code_u2d(creg); }
 
 void code_drgvar(int e2,int d,int freg)
 { 
-    char *nm = ((NMTBL*)cadr(e2))->nm;
-    if (d) {
-	printf("\tlw %s,%s\n",fregister_name0(freg),nm);
-	printf("\tlw %s,%s\n",fregister_name1(freg),nm);
-    } else {
-	printf("\tl.s %s,%s\n",fregister_name(freg),nm);
-    }
-    fregv[freg]=1;
+    int r;
+    r = get_ptr_cache((NMTBL*)cadr(e2));
+    printf("\t%s %s,0(%s)\n",fload(d),fregister_name(freg),register_name(r));
+    regv[freg]=1;
 }
 
 
 void code_drlvar(int e2,int d,int freg)
 { 
-    if (d) {
-	printf("\tlw %s,\n",fregister_name0(freg)); lvar(e2);
-	printf("\tlw %s,%s\n",fregister_name1(freg)); lvar(e2+size_of_double/2);
-    } else {
-	printf("\tl.s %s,",fregister_name(freg)); lvar(e2);
-    }
-    fregv[freg]=1;
+    lvar_intro(e2);
+    printf("\t%s %s,",fload(d),fregister_name(freg)); lvar(e2);
+    regv[freg]=1;
 }
 
 void code_cmp_drgvar(int e2,int d)
 { 
+    int r;
     char *frn=fregister_name(freg);
-    int g,g1;
-    char *grn;
-    if (d) {
-	g=get_input_dregister_var(0,0,0,d);
-	g1=get_input_dregister_var(1,0,0,d);
-	code_drgvar(e2,d,g1);
-	if (freg!=g) {
-	    printf("\tmove $3,%s\n", fregister_name0(freg));
-	    printf("\tmove $4,%s\n", fregister_name1(freg));
-	}
-	printf("\tjal dcmp\n");
-    } else {
-	g=get_dregister(d);
-	code_drgvar(e2,d,g);
-	printf("\tfc.eq.s %s,%s\n",frn,fregister_name(g));
-    }
-    free_dregister(g);
-    fregv[freg]=0;
+    int g=get_dregister(d);
+    char *grn=fregister_name(g);
+    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);
+    free_register(g);
+    regv[freg]=0;
 }
 
 void code_cmp_drlvar(int e2,int d)
 { 
     char *frn=fregister_name(freg);
-    int g,g1;
-    char *grn;
-    if (d) {
-	g=get_input_dregister_var(0,0,0,d);
-	g1=get_input_dregister_var(1,0,0,d);
-	if (freg!=g) {
-	    printf("\tmove $3,%s\n", fregister_name0(freg));
-	    printf("\tmove $4,%s\n", fregister_name1(freg));
-	}
-	code_drlvar(e2,d,g1);
-	printf("\tjal dcmp\n");
-    } else {
-	g=get_dregister(d);
-	code_drlvar(e2,d,g);
-	printf("\tc.eq.s %s,%s\n",frn,fregister_name(g));
-    }
-    free_dregister(g);
-    fregv[freg]=0;
-}
+    int g=get_dregister(d);
+    char *grn=fregister_name(g);
 
-static void
-dtosop0(char *opn,int e1,int d,int cmp)
-{
-    char *frn;
-    char *grn;
-    if (d) {
-	g=get_input_dregister_var(0,0,0,d);
-	g1=get_input_dregister_var(1,0,0,d);
-	if (freg!=g) {
-	    printf("\tmove $3,%s\n", fregister_name0(freg));
-	    printf("\tmove $4,%s\n", fregister_name1(freg));
-	}
-	if (e1!=g1) {
-	    printf("\tmove $5,%s\n", fregister_name0(e1));
-	    printf("\tmove $6,%s\n", fregister_name1(e1));
-	}
-	printf("\tjal %s\n",opn);
-	set_freg(RET_DREGISTER,0);
-    } else {
-	frn=fregister_name(freg);
-	grn=fregister_name(e1);
-	if (cmp) {
-	    printf("\t%s %s,%s\n",opn,frn,grn);
-	} else {
-	    printf("\t%s %s,%s,%s\n",opn,frn,frn,grn);
-	}
-    }
-    free_dregister(e1);
+    lvar_intro(e2);
+    printf("\t%s %s,",fload(1),grn); lvar(e2);
+    printf("\tfcmpu cr0,%s,%s\n",frn,grn);
+    free_register(g);
+    regv[freg]=0;
 }
 
 void dtosop(int op,int e1)
 { 
     char *opn="";
-    fregv[freg]=1;
+    char *frn=fregister_name(freg);
+    char *grn=fregister_name(e1);
+    regv[freg]=1;
     switch(op) {
-    case FADD: dtosop0("fadd",e1,0,0); return;
-    case DADD: dtosop0("dpadd",e1,1,0); return;
-    case FSUB: dtosop0("fadd",e1,0,0); return;
-    case DSUB: dtosop0("dpsub",e1,1,0); return;
-    case FDIV: dtosop0("fadd",e1,0,0); return;
-    case DDIV: dtosop0("dpdiv",e1,1,0); return;
-    case FMUL: dtosop0("fadd",e1,0,0); return;
-    case DMUL: dtosop0("dpmul",e1,1,0); return;
+    case FADD:
+    case DADD: opn="fadd"; break;
+    case FSUB:
+    case DSUB: opn="fsub"; break;
+    case FDIV:
+    case DDIV: opn="fdiv"; break;
+    case FMUL:
+    case DMUL: opn="fmul"; break;
+    case FCMP:
+    case DCMP: 
+	printf("\tfcmpu cr0,%s,%s\n",frn,grn);
+	free_register(e1);
+	return;
+    case FCMPGE: 
     case DCMPGE: 
-    case DCMP:  dtosop0("dpcmp",e1,1,1); return;
-    case FCMPGE: dtosop0("c.le.s",e1,0,1); return;
-    case FCMP: dtosop0("c.eq.s",e1,0,1); return;
+	printf("\tfcmpu cr7,%s,%s\n",frn,grn);
+	free_register(e1);
+	return;
     default:
 	error(-1); return;
     }
+    printf("\t%s %s,%s,%s\n",opn,frn,frn,grn);
+    regv[freg]=1;
+    free_register(e1);
 }
 
 void
 code_dassop(int op,int d) {
     /* we have lvalue in creg, applied floating value is in freg */
-    char *frn;
-    int  xreg;
+    char *frn=fregister_name(freg);
+    int  xreg=emit_dpop(d);
     char *crn=register_name(creg);
 
-    if (d) {
-	xreg=emit_dpop(d);
-	printf("\tlw %s,0(%s)\n",register_name0(freg),crn);
-	printf("\tlw %s,%d(%s)\n",register_name1(freg),size_of_int,crn);
-	dtosop(op,xreg);
-	printf("\tsw %s,0(%s)\n",register_name0(freg),crn);
-	printf("\tsw %s,%d(%s)\n",register_name1(freg),size_of_int,crn);
-	emit_dpop_free(xreg,d);
-    } else {
-	xreg=emit_dpop(d);
-	frn=fregister_name(freg);
-	crn=register_name(creg);
-
-	printf("\tl.s %s,0(%s)\n",frn,crn);
-	dtosop(op,xreg);
-	printf("\ts.s %s,0(%s)\n",frn,crn);
-	emit_dpop_free(xreg,d);
-    }
-    fregv[freg]=1;
+    if (!is_float_reg(freg)) error(-1);
+    printf("\t%s %s,0(%s)\n",fload(d),frn,crn);
+    dtosop(op,xreg);
+    printf("\t%s %s,0(%s)\n",fstore(d),frn,crn);
+    emit_dpop_free(xreg,d);
+    regv[freg]=1;
 }
 
 
@@ -2458,38 +2653,32 @@
     char *crn;
     int  g;
     char *grn,*drn;
+    int r;
+    r = get_ptr_cache(&float_one);
+    float_one_lib_used=1;
 
+    if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
+	error(-1); /* unspported now */
+    }
     g_expr(e2);
 
-    if (d) {
-	crn=register_name(creg);
-	frn=fregister_name(freg);
+    crn=register_name(creg);
+    frn=fregister_name(freg);
+    drn=register_name(r);
+    grn=fregister_name(g=get_dregister(d));
 
-	printf("\tlw $4,0(%s)\n",crn);
-	printf("\tlw $5,%d(%s)\n",size_of_int,crn);
-	printf("\tli.d $6,1.0\n");
-	if (caddr(e1)>0)
-	    printf("\tjal dpadd\n");
-	else
-	    printf("\tjal dpsub\n");
-	set_freg(RET_DREGISTER,0);
-	printf("\tsw $2,0(%s)\n",crn);
-	printf("\tsw $3,%d(%s)\n",size_of_int,crn);
-    } else {
-	crn=register_name(creg);
-	frn=fregister_name(freg);
-	grn=fregister_name(g=get_dregister(d));
-
-	printf("\tl.s %s,0(%s)\n",frn,crn);
-	printf("\tli.s %s,1.0\n",grn);
-	if (caddr(e1)>0)
-	    printf("\tfadd %s,%s,%s\n",frn,frn,grn);
-	else
-	    printf("\tfsub %s,%s,%s\n",frn,frn,grn);
-	printf("\ts.s %s,0(%s)\n",frn,crn);
-	free_dregister(g);
-    }
-    fregv[freg]=1;
+    printf("\t%s %s,0(%s)\n",fload(d),frn,crn);
+    printf("\tlfs %s,0(%s)\n",grn,drn);
+    if (caddr(e1)>0)
+	printf("\tfadd %s,%s,%s\n",frn,frn,grn);
+    else
+	printf("\tfsub %s,%s,%s\n",frn,frn,grn);
+    if (!is_float_reg(freg)) error(-1);
+    printf("\t%s %s,0(%s)\n",fstore(d),frn,crn);
+    free_register(g);
+    regv[freg]=1;
+    regv[ireg]=0;
+    creg = freg;
 }
 
 void
@@ -2498,73 +2687,55 @@
     char *crn;
     int  g;
     char *grn,*drn;
+    int r;
+    r = get_ptr_cache(&float_one);
+    float_one_lib_used=1;
 
+    if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
+	error(-1); /* unspported now */
+    }
     g_expr(e2);
 
-    if (d) {
-	crn=register_name(creg);
-	frn=fregister_name(freg);
-	g = get_dregister(d);
+    crn=register_name(creg);
+    frn=fregister_name(freg);
+    drn=register_name(r);
+    grn=fregister_name(g=get_dregister(d));
 
-	printf("\tlw $4,0(%s)\n",crn);
-	printf("\tlw $5,%d(%s)\n",size_of_int,crn);
-	printf("\tmove %s,$4\n",fregister_name0(g));
-	printf("\tmove %s,$5\n",fregister_name0(g));
-	printf("\tli.d $6,1.0\n");
-	if (caddr(e1)>0)
-	    printf("\tjal dpadd\n");
-	else
-	    printf("\tjal dpsub\n");
-	set_freg(RET_DREGISTER,0);
-	printf("\tsw $2,0(%s)\n",crn);
-	printf("\tsw $3,%d(%s)\n",size_of_int,crn);
-	free_dregister(freg);
-	set_freg(g,0);
-    } else {
-	crn=register_name(creg);
-	frn=fregister_name(freg);
-	grn=fregister_name(g=get_dregister(d));
-
-	printf("\tl.s %s,0(%s)\n",frn,crn);
-	printf("\tli.s %s,1.0\n",grn);
-	if (caddr(e1)>0)
-	    printf("\tfadd %s,%s,%s\n",frn,frn,grn);
-	else
-	    printf("\tfsub %s,%s,%s\n",frn,frn,grn);
-	printf("\ts.s %s,0(%s)\n",grn,crn);
-	free_dregister(g);
-    }
-    fregv[freg]=1;
+    printf("\t%s %s,0(%s)\n",fload(d),frn,crn);
+    printf("\tlfs %s,0(%s)\n",grn,drn);
+    if (caddr(e1)>0)
+	printf("\tfadd %s,%s,%s\n",grn,frn,grn);
+    else
+	printf("\tfsub %s,%s,%s\n",grn,frn,grn);
+    if (!is_float_reg(freg)) error(-1);
+    printf("\t%s %s,0(%s)\n",fstore(d),grn,crn);
+    free_register(g);
+    regv[freg]=1;
+    regv[ireg]=0;
+    creg = freg;
 }
 
 void
 drexpr(int e1, int e2,int l1, int op)
 {       
-    g_expr(list3(((op==FOP+EQ||op==FOP+NEQ)?DCMP:FCMPGE),e1,e2));
+    g_expr(list3(((op==DOP+GE)?DCMPGE:DCMP),e1,e2));
     switch(op) {
 	case DOP+GE:
-	    printf("\tbgez\tL_%d\n",l1);
+	case FOP+GE:
+	    printf("\tcror 2,29,30\n");
+	    printf("\tbne\tcr0,L_%d\n",l1);
 	    break;
 	case DOP+GT:
-	    printf("\tbltz\tL_%d\n",l1);
+	case FOP+GT:
+	    printf("\tble\tcr0,L_%d\n",l1);
 	    break;
 	case DOP+EQ:
-	    printf("\tbeq\tL_%d\n",l1);
+	case FOP+EQ:
+	    printf("\tbne\tcr0,L_%d\n",l1);
 	    break;
 	case DOP+NEQ:
-	    printf("\tbne\tL_%d\n",l1);
-	    break;
-	case FOP+GE:
-	    printf("\tbc1tl\tL_%d\n",l1);
-	    break;
-	case FOP+GT:
-	    printf("\tbc1tl\tL_%d\n",l1);
-	    break;
-	case FOP+EQ:
-	    printf("\tbc1f\tL_%d\n",l1);
-	    break;
 	case FOP+NEQ:
-	    printf("\tbc1f\tL_%d\n",l1);
+	    printf("\tbeq\tcr0,L_%d\n",l1);
 	    break;
     }
 }
@@ -2575,26 +2746,26 @@
     xreg=pop_fregister();
     if (xreg<= -REG_LVAR_OFFSET) {
 	reg = get_dregister(d);
-        code_drlvar(REG_LVAR_OFFSET+xreg,d,reg);
+        code_drlvar(REG_LVAR_OFFSET+xreg,1,reg);
 	free_lvar(REG_LVAR_OFFSET+xreg);
-	fregv[reg]=1; xreg=reg;
+	regv[reg]=1; xreg=reg;
     }
     return xreg;
 }
 
 void emit_dpop_free(int e1,int d)
 { 
-    free_dregister(e1);
+    free_register(e1);
 }
 
 void emit_dpush(int d)
 { 
     int new_reg;
     if (freg_sp>MAX_MAX) error(-1);
-    new_reg = get_dregister(d);
+    new_reg = get_dregister(1);
     freg_stack[freg_sp++] = freg;     /* push するかわりにレジスタを使う */
-    freg = new_reg;
-    fregv[freg]=1;
+    creg = freg = new_reg;
+    regv[freg]=1;
 }
 
 void
@@ -2628,9 +2799,13 @@
 void
 code_closing()
 {
+    if (d2u_lib_used) emit_lib(d2u_lib);
+    if (u2d_lib_used) emit_lib(u2d_lib);
+    if (float_one_lib_used) emit_lib(float_one_lib);
+    if (float_zero_lib_used) emit_lib(float_zero_lib);
+    if (i2d_lib_used) emit_lib(i2d_lib);
     global_table();
     /* printf("\t.ident \"Micro-C compiled\"\n"); */
-    fclose(asi);
 }
 
 /* end */
--- a/mc-code-powerpc.c	Wed Jun 11 12:26:03 2003 +0900
+++ b/mc-code-powerpc.c	Sun Jul 13 23:59:26 2003 +0900
@@ -458,8 +458,8 @@
 get_input_dregister_var(int i,NMTBL *n,int is_code,int d)
 {
     if (is_code) {
-	if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0;
-	i = REG_VAR_BASE-i+FREG_OFFSET;
+	if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0;
+	i = FREG_VAR_BASE-i+FREG_OFFSET;
     } else {
 	if (i<0||i>=MAX_INPUT_DREGISTER_VAR) return 0;
 	i = i+MIN_TMP_FREG+FREG_OFFSET;
@@ -566,6 +566,9 @@
     while(reg_sp > 0) {
 	free_register(reg_stack[--reg_sp]);
     }
+    while(freg_sp > 0) {
+	free_register(freg_stack[--freg_sp]);
+    }
     if (cond_freg!=-1) { 
 	if(car(cond_freg)==DREGISTER) free_register(cadr(cond_freg)); 
 	else if(car(cond_freg)==FREGISTER) free_register(cadr(cond_freg)); 
@@ -623,7 +626,7 @@
 get_dregister_var(NMTBL *n,int d)
 {
     int i;
-    for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) {
+    for(i=0;i<FREG_VAR_BASE-FREG_VAR_MIN;i++) {
         if (! regs[FREG_VAR_BASE-i+FREG_OFFSET]) {       /* 使われていないなら */
             regs[FREG_VAR_BASE-i+FREG_OFFSET]=USING_REG; /*そのレジスタを使うことを宣言し*/
             regv[FREG_VAR_BASE-i+FREG_OFFSET]=0;