changeset 246:0dcc0ec81ed2

MIPS on going (90%)
author kono
date Mon, 10 May 2004 21:12:55 +0900
parents 8a72b0afccfc
children 0252050601bd
files Changes mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-codegen.c mc.h
diffstat 6 files changed, 2794 insertions(+), 1340 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Thu May 06 11:38:56 2004 +0900
+++ b/Changes	Mon May 10 21:12:55 2004 +0900
@@ -4118,3 +4118,21 @@
 
 longlong/float のregressionはいいんだけど、もう少し
 整合性があった方がいいかもね。
+
+なんか、Linux のinclude directory って、どうにかなんないの?
+
+assop で、
+    calc left exp
+    move creg,dreg
+    move const,creg
+    op  creg,(dreg)
+って、やっているのなんか変じゃない?
+
+a && b で、b のboolを計算しているのは変。use のフラグ
+を見るのを追加したら。
+
+
+Sat May  8 21:29:32 JST 2004
+
+浮動小数点やlong longの代入で同じ値は一つにまとめるべきだよね。
+連想 list を一つ持てば良いだけだし。
--- a/mc-code-ia32.c	Thu May 06 11:38:56 2004 +0900
+++ b/mc-code-ia32.c	Mon May 10 21:12:55 2004 +0900
@@ -12,6 +12,7 @@
     "/usr/include/diet/",
     "/usr/lib/gcc-lib/i386-linux/2.95.4/include/",
     "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/",
+    "/usr/lib/dietlibc/include/",
     0
 };
 
@@ -1222,7 +1223,7 @@
     crn = register_name(creg,0);
     use_int(reg);
     printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0));
-    return us?UNSIGNED:INT;
+    return sign?INT:UNSIGNED;
 }
 
 int
@@ -1235,7 +1236,7 @@
     crn = register_name(creg,0);
     use_int(reg);
     printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0));
-    return us?UCHAR:CHAR;
+    return sign?CHAR:UCHAR;
 }
 
 int
@@ -1248,7 +1249,7 @@
     crn = register_name(creg,0);
     use_int(reg);
     printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0));
-    return us?USHORT:SHORT;
+    return sign?SHORT:USHORT;
 }
 
 #if FLOAT_CODE
--- a/mc-code-mips.c	Thu May 06 11:38:56 2004 +0900
+++ b/mc-code-mips.c	Mon May 10 21:12:55 2004 +0900
@@ -1,4 +1,4 @@
-/* Micro-C Code Generatation Part for MIPS (PS2Linux) */
+/* Micro-C Code Generatation Part for Power PC (Mac OS X) */
 /* $Id$ */
 
 #define EXTERN extern
@@ -16,46 +16,54 @@
 #define RODATA_EMIT_MODE 2
 
 static void data_mode(char *name);
-static void ld_indexx(int byte, int n, int xreg,int sign);
+static void init_ptr_cache();
+static void ld_indexx(int byte, int n, int xreg,int reg,int sign);
 static void local_table(void);
-static void shift(char *op, int reg);
+static void shift(char *op, int creg,int reg);
 static int struct_push(int e4,int t,int arg);
 
+static int creg;
+
 static int output_mode = TEXT_EMIT_MODE;
 static int data_alignment = 0;
 
 static int code_disp_label;
-static int disp_label;
+static int code_setup;
 static int r1_offset_label;
 static int lvar_offset_label;
-static int cprestore_label;
 
 static int reg_save;
 static int freg_save;
 
-static int freg,ireg,dreg;
-
-/* 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];  /* 実際のレジスタの領域 */
+static int freg,ireg,lreg;
+static int cmpreg;
+
+int code_lassop_p = 1;
+
+#define SIZE_OF_INT  4
+#define SIZE_OF_SHORT  2
+#define SIZE_OF_FLOAT  4
+#define SIZE_OF_DOUBLE  8
+#define SIZE_OF_LONGLONG  8
+#define ENDIAN  1
+
+int size_of_int = SIZE_OF_INT;
+int size_of_short = SIZE_OF_SHORT;
+int size_of_float = SIZE_OF_FLOAT;
+int size_of_double = SIZE_OF_DOUBLE;
+int size_of_longlong = SIZE_OF_LONGLONG;
+int endian = ENDIAN;
+
+static int  reg_sp;   /* REGister Stack-Pointer */
+static 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]; /* 実際のレジスタの領域 */
+static int  freg_sp;  /* floating point REGister Stack-Pointer */
+static int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
+
+static int  lreg_sp;  /* longlong  REGister Stack-Pointer */
+static int lreg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
 
 #define REG_fp   1
 #define REG_sp   30
@@ -64,31 +72,27 @@
 #define MIN_TMP_REG 4
 #define MAX_TMP_REG 11
 
-#define DREG_VAR_BASE 29
-#define DREG_VAR_MIN  18
-#define MIN_TMP_DREG 4
-#define MAX_TMP_DREG 17
-
 #define PTRC_REG 3
 
-#define FREG_VAR_BASE 31
-#define FREG_VAR_MIN  20
-#define MIN_TMP_FREG 1
-#define MAX_TMP_FREG 14
+#define FREG_VAR_BASE 29
+#define FREG_VAR_MIN  18
+#define MIN_TMP_FREG 4
+#define MAX_TMP_FREG 17
+
+int MAX_REGISTER=30;             /* PowerPCのレジスタを10個まで使う*/
+int MAX_FREGISTER=31;
+#define  REAL_MAX_REGISTER 32    /* PowerPCのレジスタが32ということ*/
+#define  REAL_MAX_FREGISTER 32    /* PowerPCのレジスタが32ということ*/
+#define  REAL_MAX_LREGISTER 16
+
+#define FREG_OFFSET REAL_MAX_REGISTER
+#define LREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER)
 
 #define RET_REGISTER 3
 #define RET_FREGISTER (1+FREG_OFFSET)
-#define RET_DREGISTER (1+DREG_OFFSET)
-
-int MAX_REGISTER=30;             /* PowerPCのレジスタを10個まで使う*/
-int MAX_FREGISTER=31;
-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 )
+#define RET_LREGISTER_H 3    /* high word */
+#define RET_LREGISTER_L 4    /* low word */
+#define RET_LREGISTER LREG_OFFSET
 
 int MAX_INPUT_REGISTER_VAR = 7-MIN_TMP_REG;
 int MAX_CODE_INPUT_REGISTER_VAR = 7-MIN_TMP_REG;
@@ -97,21 +101,20 @@
 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+FREG_OFFSET)
-#define DREG_DREGISTER (2+DREG_OFFSET)
-
-static int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+REAL_MAX_DREGISTER];
-
-static int dreg_pair0[REAL_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
-};
-static int dreg_pair1[REAL_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
-};
+static int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+
+   REAL_MAX_LREGISTER];
+static int regv_h0[REAL_MAX_LREGISTER];
+static int regv_l0[REAL_MAX_LREGISTER];
+#define regv_h(i)  regv_h0[(i)-LREG_OFFSET]
+#define regv_l(i)  regv_l0[(i)-LREG_OFFSET]
 
 static int *regs  = powerpc_regs;
 
+#define CREG_REGISTER  (MAX_TMP_REG)
+#define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET)
+#define LREG_LREGISTER (MAX_TMP_REG+LREG_OFFSET)
+
+
 static int max_reg_var, max_freg_var;
 
 static char *reg_name[] = {
@@ -125,71 +128,117 @@
     "$f30","$f31"
 }; 
 
-
-#define register_name(i)  reg_name0(i)
-#define fregister_name(i) reg_name0(i)
-#define dregister_name0(i) reg_name1(i,dreg_pair0)
-#define dregister_name1(i) reg_name1(i,dreg_pair1)
-
-static char *
-reg_name0(int i)
-{
-    if (i<=REAL_MAX_REGISTER+REAL_MAX_FREGISTER)
-	return reg_name[i];
-    else {
-	error(-1);
-	return reg_name[0];
-    }
-}
-
-static char *
-reg_name1(int i,int *d)
-{
-    if (i<=REAL_MAX_REGISTER+REAL_MAX_FREGISTER) {
-	error(-1);
-	return reg_name[0];
-    } else
-	return reg_name[d[i-DREG_OFFSET]];
-}
-
+#define register_name(i)  reg_name[i]
+#define fregister_name(i) reg_name[i]
+#define lregister_name_low(i) reg_name[regv_l(i)]
+#define lregister_name_high(i) reg_name[regv_h(i)]
+static int emit_dpop_regvar(int d);
+
+char *r(i) { return register_name(i); }
+char *f(i) { return fregister_name(i); }
+char *ll(i) { return lregister_name_low(i); }
+char *lh(i) { return lregister_name_high(i); }
 
 #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+REAL_MAX_DREGISTER)
-
-
-int use_int(int i) { 
-    if (!is_int_reg(i)) i = ireg;
-    if (!regs[i]) regs[i]=1;
+#define is_double_reg(i)  (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER&&regs[i]==USING_DREG)
+#define is_longlong_reg(i)  (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER&&regs[i]==USING_REG)
+
+#define  use_int(reg) if (reg==USE_CREG) reg=use_int0()
+static
+int use_int0() { 
+    int i = creg;
+    if (!i||!ireg||!is_int_reg(i)) {
+	if (lreg) { free_register(lreg); lreg = 0; }
+	if (!ireg) ireg = get_register();
+	// else if (ireg!=i) free_register(i);
+	i = ireg;
+    }
+    if (!regs[i]) regs[i]=USING_REG;
+    creg = i;
     return i;
 }
 
-int use_float(int i) { 
-    if (!is_float_reg(i)) i = freg;
-    if (!regs[i]) regs[i]=1;
+#if LONGLONG_CODE
+#define  use_longlong(reg) if (reg==USE_CREG) reg=use_longlong0()
+
+static
+int use_longlong0() {
+    int i = creg;
+    if (!is_longlong_reg(i)) {
+	if (ireg) { free_register(ireg); ireg=0; }
+	if (!lreg||!regs[lreg]) lreg = get_lregister();
+	// else if (lreg!=i) free_register(i);
+	i = lreg;
+    }
+    if (!regv_l(i)) regv_l(i) = get_register();
+    if (!regv_h(i)) regv_h(i) = get_register();
+    if (!regs[i]) regs[i]=USING_REG;
+    if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG;
+    if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG;
+    creg = i;
     return i;
 }
-
-int use_double(int i) { 
-    if (!is_double_reg(i)) i = dreg;
-    if (!regs[i]) regs[i]=1;
+#endif
+
+
+#if FLOAT_CODE
+#define  use_float(d,reg) if (reg==USE_CREG) reg=d?use_double0():use_float0()
+static
+int use_float0() { 
+    int i = creg;
+    if (!is_float_reg(i)) {
+	if (lreg) { free_register(lreg); lreg = 0; }
+	if (!freg) freg = get_dregister(0);
+	else if (freg!=i) free_register(i);
+	i = freg;
+    }
+    if (!regs[i]) regs[i]=USING_REG;
+    creg = i;
     return i;
 }
-
-int use_longlong(int i) { 
+static
+int use_double0() { 
+    int i = creg;
+    if (!is_double_reg(i)) {
+	if (ireg) { free_register(ireg); ireg=0; }
+	if (!lreg||!regs[lreg]) lreg = get_lregister();
+	// else if (lreg!=i) free_register(i);
+	i = lreg;
+    }
+    if (!regv_l(i)) regv_l(i) = get_register();
+    if (!regv_h(i)) regv_h(i) = get_register();
+    if (!regs[i]) regs[i]=USING_DREG;
+    if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG;
+    if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG;
+    creg = i;
     return i;
 }
+#endif
+
 
 #if FLOAT_CODE
+static
+NMTBL float_zero = {"_float_zero",STATIC,FLOAT,0};
+static
+NMTBL float_one = {"_float_one",STATIC,FLOAT,0};
+
+
+static char * fload(int d);
 static int code_d1(double d);
 static int code_d2(double d);
 #endif
+#if LONGLONG_CODE
+static int code_l1(long long ll);
+static int code_l2(long long ll);
+#endif
 
 static void code_save_stacks();
 static void code_save_input_registers();
-static void    set_creg(int,int);
+static void clear_ptr_cache_reg(int r);
+static void    set_ireg(int,int);
 static void    set_freg(int,int);
-static void    set_dreg(int,int);
+static void    set_lreg(int,int);
 
 static int    mask_label;
 static int    mask1_label;
@@ -199,12 +248,9 @@
 static FILE *asi;
 
 static int max_func_args;
-static int max_func_iargs;
 static int my_func_args;
 #define ARG_LVAR_OFFSET 0x10000000
 
-#define DOT_SIZE 1
-
 /*          
 
      Reorder is automatically done in assembler.
@@ -222,12 +268,12 @@
      $f14,$f12 input register
      $f20-$f31 saved register variable
 
-function call stack frame
+ function call stack frame
                        <------r1_offset------------------------------>
                                       <------------lvar_offset------->
  r+  +------------+---+---------------+----------+--------------+----+    -
       callee arg   xx   register save   local      caller arg     xx
-                          reg_save      disp       max_func_args*size_of_int
+                          reg_save      disp       max_func_args*SIZE_OF_INT
         lvar>0                         lvar<0       lvar>0x1000 0000
 
 code segment stack frame
@@ -238,11 +284,12 @@
     cousin arg xx  reg save !callee arg      !code local  caller arg  xx
                    r20-r29     lvar>0         lvar<0      lvar>0x1000 000
                    f20-f31  <-my_func_args--><--disp-----><-max_func_arg->
-                              *size_of_int                  *size_of_int
+                              *SIZE_OF_INT                  *SIZE_OF_INT
 
  */
 int arg_offset = 24; int arg_offset1 = 24; int disp_offset = -12;
-#define func_disp_offset 60
+// #define func_disp_offset 60
+#define func_disp_offset 68
 #define r1_offset func_disp_offset+12 
 int code_disp_offset = 0; int jump_offset = 0;
 #define CODE_LVAR l+code_disp_offset
@@ -257,16 +304,16 @@
 #if 0
     int l;
 #endif
-    int lvar_offsetv = -disp+max_func_args*size_of_int+func_disp_offset;
-    int r1_offsetv = -disp+max_func_args*size_of_int-reg_save+r1_offset;
-    printf("L_%d = %d\n",lvar_offset_label,lvar_offsetv);
-    printf("L_%d = %d\n",r1_offset_label,r1_offsetv);
+    int lvar_offsetv = -disp+max_func_args*SIZE_OF_INT+func_disp_offset;
+    int r1_offsetv = -disp+max_func_args*SIZE_OF_INT-reg_save+r1_offset;
+    printf(".set L_%d,%d\n",lvar_offset_label,lvar_offsetv);
+    printf(".set L_%d,%d\n",r1_offset_label,r1_offsetv);
 #if 0
 printf("# function %s\n",fnptr->nm);
     l = ARG_LVAR_OFFSET;
 printf("# offset call0\t%d\n",CALLER_ARG);
-    l = ARG_LVAR_OFFSET+max_func_args*size_of_int;
-printf("# offset calln\t%d %d\n",CALLER_ARG,max_func_args*size_of_int);
+    l = ARG_LVAR_OFFSET+max_func_args*SIZE_OF_INT;
+printf("# offset calln\t%d %d\n",CALLER_ARG,max_func_args*SIZE_OF_INT);
     l = disp;
 printf("# offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp);
     l = 0;
@@ -315,15 +362,23 @@
     }
 }
 
+
+#define lvar_intro(e)  /* do nothing */
+
 void
-code_lvar(int e2,int creg) {
-    lvar_address(e2,creg);
+code_lvar(int e2,int reg) {
+    use_int(reg);
+    lvar_address(e2,reg);
 }
 
 void
 code_init(void)
 {
-    /* this is called once program call */
+    // macro_define("__BIG_ENDIAN__ 1\n");
+    macro_define("__STDC__ 1\n");
+    init_ptr_cache();
+    regv_l(RET_LREGISTER) = RET_LREGISTER_L;
+    regv_h(RET_LREGISTER) = RET_LREGISTER_H;
 }
 
 void
@@ -332,7 +387,7 @@
 
 void
 code_gexpr(int e){
-    if (is_int_reg(creg) && creg!=ireg) error(-1);
+     if (is_int_reg(creg) && creg!=ireg) error(-1);
 }
 
 
@@ -345,6 +400,7 @@
     int freg_var = 0;
     int type;
     int reg;
+    int i;
     int is_code0 = is_code(fnptr);
 
     while (args) {
@@ -357,7 +413,7 @@
                 n->dsp = cadr(reg);
                 regs[n->dsp]= INPUT_REG;
                 reg_var++;
-                cadddr(args)=size_of_int; /* why we need this? */
+                cadddr(args)=SIZE_OF_INT;
             }
         } else if (type==FLOAT) {
             if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) {
@@ -365,15 +421,27 @@
                 n->dsp = cadr(reg);
                 regs[n->dsp]= INPUT_REG;
                 freg_var++;
-                cadddr(args)=size(type); /* why we need this? */
+                cadddr(args)=size(type);
             }
         } else if (type==DOUBLE) {
-            if ((reg = get_input_dregister_var(reg_var,n,is_code0,1))) {
+            if ((reg = get_input_lregister_var(reg_var,n,is_code0))) {
                 n->sc = DREGISTER;
                 n->dsp = cadr(reg);
-                regs[n->dsp]= INPUT_REG;
+                regs[i=n->dsp]= INPUT_DREG;
+                regs[regv_l(i)]= INPUT_REG;
+                regs[regv_h(i)]= INPUT_REG;
                 reg_var+=2;
-                cadddr(args)=size(type); /* why we need this? */
+                cadddr(args)=size(type);
+            }
+        } else if (type==LONGLONG||type==ULONGLONG) {
+            if ((reg = get_input_lregister_var(reg_var,n,is_code0))) {
+                n->sc = LREGISTER;
+                n->dsp = cadr(reg);
+                regs[i=n->dsp]= INPUT_REG;
+                regs[regv_l(i)]= INPUT_REG;
+                regs[regv_h(i)]= INPUT_REG;
+                reg_var+=2;
+                cadddr(args)=size(type);
             }
         }
         args = cadr(args);
@@ -382,33 +450,43 @@
 	code_save_input_registers();
 }
 
+
 int 
 get_register(void)
 {    /* 使われていないレジスタを調べる */
-    int i,reg;
+    int i,j,reg;
     for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) {
 	if (regs[i]) continue;  /* 使われている */
 	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
-	return i;               /* その場所を表す番号を返す */
+	return i;   /* その場所を表す番号を返す */
+    }
+    /* PTR_CACHE をつぶす */
+    for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) {
+	if (regs[i]==PTRC_REG) {
+	    clear_ptr_cache_reg(i);
+	} else 
+	    continue;
+	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
+	return i;   /* その場所を表す番号を返す */
     }
     /* search 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;
+                (j=new_lvar(SIZE_OF_INT)),reg,0); 
+            reg_stack[i]= j-REG_LVAR_OFFSET;
 	    return reg;
 	}
     }
-#if FLOAT_CODE
-    /* 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;
+#if LONGLONG_CODE||FLOAT_CODE
+    /* search register stack */
+    for(i=0;i<lreg_sp;i++) {
+	if ((reg=lreg_stack[i])>=0) {
+            code_lassign_lvar(
+                (j=new_lvar(SIZE_OF_LONGLONG)),reg); 
+            lreg_stack[i]= j-REG_LVAR_OFFSET;
 	    free_register(reg);
-	    return get_register(); /* 今度は必ずある */
+	    return get_register();
 	}
     }
 #endif
@@ -417,13 +495,23 @@
         if (! regs[reg]) {       /* 使われていないなら */
             regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
 	    if (i>max_reg_var) max_reg_var=i;
-	    return reg; 
+	    return reg;   /* その場所を表す番号を返す */
         }
     }
     /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */
     error(HPERR); return creg;
 }
 
+#if 0
+int 
+get_register(void)
+{
+    int i = get_register0();
+    printf("# get_register %d\n",i);
+    return i;
+}
+#endif
+
 int
 pop_register(void)
 {     /* レジスタから値を取り出す */
@@ -431,69 +519,25 @@
 }
 
 #if FLOAT_CODE
-
-static int
-get_dregister1() {
-    int i;
-    for(i=MAX_TMP_DREG+DREG_OFFSET;i>MIN_TMP_DREG+DREG_OFFSET;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 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 reg;
-	}
-    }
-    /* 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 
+get_dregister(int d)
 {    /* 使われていないレジスタを調べる */
     int i,reg;
+    if (d) {
+      i = get_lregister();
+      if (i!=-1) regs[i]=USING_DREG;
+      return i;
+    }
     for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) {
 	if (regs[i]) continue;    /* 使われている */
 	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
-	return i;               /* その場所を表す番号を返す */
+	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_float)),reg,0); 
+                (freg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1); 
             freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET;
 	    return reg;
 	}
@@ -503,49 +547,95 @@
         if (! regs[reg]) {       /* 使われていないなら */
             regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
 	    if (i>max_freg_var) max_freg_var=i;
-	    return reg; 
+	    return reg;   /* その場所を表す番号を返す */
         }
     }
     /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */
     error(REG_ERR); return freg;
 }
 
+#if 0
 int 
 get_dregister(int d)
 {
-    if (d) {
-	return get_dregister0();
-    } else {
-	return get_fregister0();
-    }
+    int i = get_dregister0(d);
+printf("# get_dregister %d\n",i);
+    return i;
 }
+#endif
 
 int
 pop_fregister(void)
 {     /* レジスタから値を取り出す */
     return freg_stack[--freg_sp];
 }
+#endif
 
 int
-pop_dregister(void)
-{     /* レジスタから値を取り出す */
-    return dreg_stack[--dreg_sp];
+get_lregister0()
+{
+    int i;
+    for(i=LREG_OFFSET+1;i<REAL_MAX_LREGISTER+LREG_OFFSET;i++) {
+	if (regs[i]==0) {
+// printf("# get_lregister %d\n",i);
+	    return i;
+	}
+    }
+    return -1;
 }
-#endif
-
-#if LONGLONG_CODE
+
 int
-get_lregister() {
-    return -1;
+get_lregister()
+{
+    int h,l,i;
+    i = get_lregister0();
+    if (i==-1) return -1;
+    h = get_register(); 
+    if (h==-1) return -1;
+    regv_h(i) = h;
+    l = get_register(); 
+    if (l==-1) { free_register(h); return -1; }
+    regv_l(i) = l;
+    regs[i]=USING_REG;
+    return i;
 }
 
 int
 get_lregister_var(NMTBL *n)
 {
-    return list2(LVAR,new_lvar(size_of_double));
+    int i,j,ll;
+    int max_reg_var_save=max_reg_var;
+    ll = get_lregister0();
+    if (ll==-1) return -1;
+    if (regs[ll]==0) {
+	for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) {
+	    if (! regs[REG_VAR_BASE-i]) {       /* 使われていないなら */
+		/* そのレジスタを使うことを宣言し */
+		regs[REG_VAR_BASE-i]=USING_REG; 
+		if (i>max_reg_var) max_reg_var=i;
+		for(j=0;j<REG_VAR_BASE-REG_VAR_MIN;j++) {
+		    if (! regs[REG_VAR_BASE-j]) {       
+			/* 使われていないなら */
+			/* そのレジスタを使うことを宣言し */
+			regs[REG_VAR_BASE-j]=USING_REG; 
+			if (j>max_reg_var) max_reg_var=j;
+			/* その場所を表す番号を返す */
+			regs[ll]=USING_REG;
+			regv_l(ll) = REG_VAR_BASE-j;
+			regv_h(ll) = REG_VAR_BASE-i;
+			return list3(LREGISTER,ll,(int)n); 
+		    }
+		}
+		/* ひとつしかなかった */
+		regs[REG_VAR_BASE-i]=0; 
+		max_reg_var=max_reg_var_save;
+		goto not_found;
+	    }
+	}
+    }
+not_found:
+    return list2(LVAR,new_lvar(SIZE_OF_LONGLONG));
 }
-#endif
-
 
 void
 emit_pop_free(int xreg)
@@ -554,41 +644,58 @@
 	free_register(xreg);
 }
 
-void 
+void
+
 free_register(int i) {    /* いらなくなったレジスタを開放 */
-    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];
-	regs[i0]=0;
-	i1 = dreg_pair1[i-DREG_OFFSET];
-	regs[i1]=0;
+// printf("# free_register %d\n",i);
+    regs[i]=0;
+    if (is_longlong_reg(i)) {
+	regs[regv_l(i)]=0;
+	regs[regv_h(i)]=0;
+	//regv_l(i)=0;
+	//regv_h(i)=0;
     }
-    regs[i]=0;
 }
 
 int
 get_input_dregister_var(int i,NMTBL *n,int is_code,int d)
 {
+    int j;
     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<0||i>=MAX_INPUT_DREGISTER_VAR) return 0;
-	    i = i+MIN_TMP_DREG+DREG_OFFSET;
-	}
-	return list3(DREGISTER,i,(int)n);
+      j = get_input_lregister_var(i,n,is_code);
+      if (car(j)==LREGISTER) {
+	if (regs[cadr(j)]=INPUT_REG) regs[cadr(j)]=INPUT_DREG;
+	car(j) = DREGISTER;
+      }
+      return j;
+    }
+    if (is_code) {
+	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;
+    }
+    return list3(FREGISTER,i,(int)n);
+}
+
+int
+get_input_lregister_var(int i,NMTBL *n,int is_code)
+{
+    int ll;
+    ll = get_lregister0();
+    if (i!=-1) {
 	if (is_code) {
-	    if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0;
-	    i = FREG_VAR_BASE-i+FREG_OFFSET;
+	    if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0;
+	    i = REG_VAR_BASE-i;
 	} else {
-	    if (i<0||i>=MAX_INPUT_FREGISTER_VAR) return 0;
-	    i = i+MIN_TMP_FREG+FREG_OFFSET;
+	    if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0;
+	    i = i+MIN_TMP_REG;
 	}
-	return list3(FREGISTER,i,(int)n);
-    }
+	regv_h(ll)=i;
+	regv_l(ll)=i+1;
+    } else { error(-1); ll=LREG_OFFSET+2; }
+    return list3(LREGISTER,ll,(int)n);
 }
 
 int
@@ -634,7 +741,8 @@
     return d?fcount:count;
 }
 
-int
+#if 0
+static int
 register_full(void)
 {
     int i;
@@ -645,54 +753,75 @@
     }
     return 1;    
 }
+#endif
 
 void
 free_all_register(void)
 {
     int i;
+// printf("# free_all register\n");
+#if LONGLONG_CODE
+    for(i=0;i<REAL_MAX_LREGISTER;i++) {
+	regs[i+LREG_OFFSET]=0; 
+	regv_l(i+LREG_OFFSET) = 0;
+	regv_h(i+LREG_OFFSET) = 0;
+    }
+    lreg = 0;
+    // set_lreg(LREG_LREGISTER,0);
+#endif
     for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; }
     for(i=0;i<MAX_FREGISTER;i++) { regs[i+FREG_OFFSET]=0; }
-    for(i=0;i<MAX_DREGISTER;i++) { regs[i+DREG_OFFSET]=0; }
-    creg = get_register();
 #if FLOAT_CODE
-    freg = get_dregister(0);
-    dreg = DREG_DREGISTER;
+    freg = get_dregister(1);
+    set_freg(FREG_FREGISTER,0);
 #endif
-    set_creg(CREG_REGISTER,0);
-    set_freg(FREG_FREGISTER,0);
-    set_dreg(DREG_DREGISTER,0);
+    ireg = creg = get_register();
+    set_ireg(CREG_REGISTER,0);
     return;
 }
 
 void
 register_usage(char *s)
 {
-#if 0
+#if 1
     int i;
 #endif
     if (chk) return;
     if (!lsrc) return;
     printf("# %d: %s:",lineno,s);
-    printf(" creg=%s ireg=%s freg=%s dreg=%s",
-     is_int_reg(creg)?register_name(creg):
-     is_float_reg(creg)?fregister_name(creg):
-     is_double_reg(creg)?dregister_name0(creg):"bad",
-register_name(ireg),fregister_name(freg),dregister_name0(dreg));
-#if 0
+    if (ireg) printf(" creg=%s",register_name(ireg));
+    if (freg) printf(" freg=%s",fregister_name(freg));
+    if (lreg) printf(" lreg=%s,%s",lregister_name_high(lreg),
+	lregister_name_low(lreg));
+#if 1
     printf("\n# regs:");
-    printf(":");
-    for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); }
+    for(i=0;i<MAX_REGISTER;i++) {  printf("%d",regs[i]); }
+    printf(" stack ");
+    for(i=reg_sp;i>0;i--) {
+	if(reg_stack[i-1]>=0)
+	    printf(" %s",register_name(reg_stack[i]));
+    }
     printf("\n# freg:");
-    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]));
+    for(i=0;i<MAX_FREGISTER;i++) {  printf("%d",regs[i+FREG_OFFSET]); }
+    printf(" stack ");
+    for(i=freg_sp;i>0;i--) {
+	if(freg_stack[i-1]>=0)
+	    printf(" %s",fregister_name(freg_stack[i]));
+    }
+    printf("\n# lreg:");
+    for(i=0;i<REAL_MAX_LREGISTER;i++) {  printf("%d",regs[i+LREG_OFFSET]); }
+    printf(" stack ");
+    for(i=lreg_sp;i>0;i--) {
+	if(lreg_stack[i-1]>=0)
+	    printf(" %s",lregister_name_high(lreg_stack[i]));
+	    printf(",%s",lregister_name_low(lreg_stack[i]));
     }
 #endif
     printf("\n");
 }
 
-void 
+void
+
 gexpr_init(void)
 {
     while(reg_sp > 0) {
@@ -701,27 +830,28 @@
     while(freg_sp > 0) {
 	free_register(freg_stack[--freg_sp]);
     }
-    while(dreg_sp > 0) {
-	free_register(dreg_stack[--dreg_sp]);
+    while(lreg_sp > 0) {
+	free_register(lreg_stack[--lreg_sp]);
     }
-    cmpreg = -1;
+    use_int0();
     text_mode();
     gexpr_code_init();
     register_usage("gexpr_init");
 }
 
 
-void 
+void
+
 emit_init(void)
 {
     free_all_register();
     max_reg_var=-1; max_freg_var=-1;
     reg_sp = 0;
     freg_sp = 0;
-    dreg_sp = 0;
     text_mode();
 }
 
+
 int
 get_register_var(NMTBL *n)
 {
@@ -735,49 +865,42 @@
 	    return list3(REGISTER,REG_VAR_BASE-i,(int)n); 
 	}
     }
-    return list2(LVAR,new_lvar(size_of_int));
-}
-
-int
-fregister_var(int r) {
-    return r;
+    return list2(LVAR,new_lvar(SIZE_OF_INT));
 }
 
 int
 get_dregister_var(NMTBL *n,int d)
 {
-    int i,j;
+    int i;
     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; /*そのレジスタを使うことを宣言し*/
-		regs[dreg_pair0[j]] = regs[dreg_pair1[j]] = USING_REG;
-		if (dreg_pair1[j]>max_reg_var) max_reg_var=dreg_pair1[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; /*そのレジスタを使うことを宣言し*/
-		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));
+        i = get_lregister_var(n,d);
+	if (car(i)==LREGISTER) {
+	    car(i) = DREGISTER;
+	    regs[i] = USING_DREG;
+	} 
+	return 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; /*そのレジスタを使うことを宣言し*/
+	    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_DOUBLE));
 }
 
-void 
+void
+
 emit_push()
 {
     int new_reg;
+    if (!is_int_reg(creg)) error(-1);
     if (reg_sp>MAX_MAX) error(-1);
-    new_reg = get_register();
+    new_reg = get_register();       /* 絶対に取れる */
     reg_stack[reg_sp++] = creg;     /* push するかわりにレジスタを使う */
     ireg = creg = new_reg;
 }
@@ -796,78 +919,196 @@
     return xreg;
 }
 
+static int code_base;
+
+#define MAX_PTR_CACHE 10
+
+int ptr_cache=0;
+
+void
+init_ptr_cache()
+{
+    int i;
+    for(i=0;i<MAX_PTR_CACHE;i++) {
+	ptr_cache=glist3(0,ptr_cache,0);
+    }
+}
+
+void
+clear_ptr_cache_reg(int r)
+{
+    int ptcptr=ptr_cache;
+    while(ptcptr) {
+	if(car(ptcptr)&&caddr(ptcptr)==r) {
+	    car(ptcptr)=0;
+	    caddr(ptcptr)=0;
+	    free_register(r);
+	    return;
+	}
+	ptcptr=cadr(ptcptr);
+    }
+}
+
+void
+clear_ptr_cache()
+{
+    int ptcptr=ptr_cache;
+    while(ptcptr) {
+	if(car(ptcptr))
+	    free_register(caddr(ptcptr));
+	car(ptcptr)=0;
+	caddr(ptcptr)=0;
+	ptcptr=cadr(ptcptr);
+    }
+}
+
+
+int
+get_ptr_cache(NMTBL *nptr)
+{
+    int r;
+    int ptcptr=ptr_cache;
+    int g = (int)nptr;
+    int p,p1;
+    char *rrn;
+
+    p1 = ptcptr; p = cadr(p1); /* unnecesary, if ptcptr is initialized */
+    while(ptcptr) {
+	if(car(ptcptr)==g) return caddr(ptcptr);
+	p1=p; p=ptcptr;
+	ptcptr=cadr(ptcptr);
+    }
+    cadr(p1)=0;            /* remove the last one */
+    cadr(p) = ptr_cache;   /* connect current queue to the last one */
+    ptr_cache = p;         /* now the last one is the top */
+    if (!caddr(p)) {
+	if((r=get_register())) {
+	    caddr(p)=r; regs[r]=PTRC_REG;
+	} else {
+	    error(-1);
+	    r=creg; /* this can't happen */
+	}
+	car(p)=g;
+    } else {
+	r = caddr(p);
+    }
+    rrn = register_name(r);
+    printf("\tla %s,%s\n",rrn,nptr->nm);
+    return r;
+}
+
+static char *cload(int sz,int sign) { 
+    if (sign) {
+        return sz==1?"lb":sz==SIZE_OF_SHORT?"lh":"lw"; 
+    } else {
+        return sz==1?"lbu":sz==SIZE_OF_SHORT?"lhu":"lwu"; 
+    }
+}
+
+static char *cstore(int sz) { return sz==1?"sb":sz==SIZE_OF_SHORT?"sh":"sw"; }
+
+#define cext(sign,sz,reg)  /* do nothing */
+
+
 void
 code_label(int labelno)
 {
+    clear_ptr_cache();
     printf("L_%d:\n",labelno);
 }
 
 void
-code_gvar(int e1,int creg) {
-    printf("\tla %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm);
+code_gvar(int e1,int reg) {
+    int r;
+    use_int(reg);
+    r = get_ptr_cache((NMTBL*)cadr(e1));
+    if(r!=reg)
+	printf("\tmove %s,%s\n",register_name(reg),register_name(r));
+    return;
+}
+
+void
+code_rgvar(int e1,int reg) {
+    use_int(reg);
+    printf("\tlw %s,0(%s)\n",register_name(reg),
+                             register_name(get_ptr_cache((NMTBL*)cadr(e1))));
 }
 
 void
-code_rgvar(int e1,int creg) {
-    printf("\tlw %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm);
+code_crgvar(int e1,int reg,int sign,int sz){
+    char *crn;
+    use_int(reg);
+    crn = register_name(reg);
+    printf("\t%s %s,0(%s)\n",cload(sz,sign),crn,
+                             register_name(get_ptr_cache((NMTBL*)cadr(e1))));
+    cext(sign,sz,reg);
 }
-char *cload(int sign,int sz) { return sz==1?(sign?"lbu":"lb"):(sz==size_of_short?(sign?"lhu":"lh"):"lw");}
-char *cstore(int sz) { return sz==1?"sb":(sz==size_of_short)?"sh":"sw";}
-void
-code_crgvar(int e1,int creg,int sign,int sz){
-    printf("\t%s %s,%s\n",cload(sign,sz),register_name(creg),((NMTBL*)cadr(e1))->nm);
-}
+
 
 
 void
-code_register(int e2,int creg) {
-    if (creg!=e2)
-        printf("\tmove %s,%s\n",register_name(creg),register_name(e2));
+code_register(int e2,int reg) {
+    use_int(reg);
+    if (reg!=e2)
+	printf("\tmove %s,%s\n",register_name(reg),register_name(e2));
 }
 
 
 void
 code_rlvar(int e2,int reg) {
+    use_int(reg);
+    lvar_intro(e2);
     printf("\tlw %s,",register_name(reg));
     lvar(e2);
 }
 
+void
+code_crlvar(int e2,int reg,int sign,int sz) {
+    use_int(reg);
+    lvar_intro(e2);
+    printf("\t%s %s,",cload(sz,sign),register_name(reg));
+    lvar(e2);
+    cext(sign,sz,reg);
+}
+
+void
+code_fname(NMTBL *n,int reg) {
+    int r;
+    use_int(reg);
+    r = get_ptr_cache(n);
+    if(r!=reg)
+	printf("\tmove %s,%s\n",register_name(reg),register_name(r));
+    return;
+}
+
 
 void
-code_crlvar(int e2,int reg,int sign,int sz) {
-    printf("\t%s %s,",cload(sign,sz),register_name(reg));
-    lvar(e2);
-}
-
-
-void
-code_fname(NMTBL *n,int creg) {
-    printf("\tla %s,%s\n",register_name(creg),n->nm);
-}
-
-
-void
-code_const(int e2,int creg) {
-    printf("\tli %s,%d\n",register_name(creg),e2);
+code_const(int e2,int reg) {
+    char *crn;
+    use_int(reg);
+    crn = register_name(reg);
+    printf("\tli %s,%d\n",crn,e2);
 }
 
 
 void
 code_neg(int creg) {
+    use_int(creg);
     printf("\tsubu %s,$0,%s\n", register_name(creg), register_name(creg));
 }
 
 
 void
 code_not(int creg) {
+    use_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 */
+    use_int(creg);
     int dreg = get_register();
     printf("\txori %s,%s,0x0\n", 
         register_name(dreg),register_name(creg));
@@ -879,57 +1120,67 @@
 void
 code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) {
     char *xrn,*drn;
-    int i,dreg;
     if (car(e2)==REGISTER) {
-        printf("\taddu %s,%s,%d\n", 
-                register_name(cadr(e2)),register_name(cadr(e2)), dir);
-        if (cadr(reg)!=e2)
-            printf("\tmove %s,%s\n",register_name(cadr(reg)),register_name(e2));
-        return;
+	use_int(reg);
+	printf("\taddu %s,%s,%d\n", 
+		register_name(cadr(e2)),register_name(cadr(e2)), dir);
+	if (cadr(reg)!=e2)
+	    printf("\tmove %s,%s\n",register_name(cadr(reg)),register_name(e2));
+	return;
     } 
     g_expr(e2);
+    if (!is_int_reg(creg)) error(-1);
     xrn = register_name(creg);
-    dreg=get_register(); if (!dreg) error(-1);
-    drn = register_name(dreg);
-    printf("\t%s %s,0(%s)\n",cload(sign,sz),drn,xrn);
-    printf("\taddu %s,%s,%d\n",drn,drn,dir);
+    if (reg==USE_CREG) {
+	reg=get_register(); if (!reg) error(-1);
+	drn = register_name(reg);
+	set_ireg(reg,0);
+    } else {
+	drn = register_name(reg);
+    }
+    printf("\t%s %s,0(%s)\n",cload(sz,sign),drn,xrn);
+    if (use) cext(sign,sz,reg);
+    printf("\taddi %s,%s,%d\n",drn,drn,dir);
     printf("\t%s %s,0(%s)\n",cstore(sz),drn,xrn);
-    i=creg;creg=dreg;dreg=i;
-    ireg=creg;
-    free_register(dreg);
 }
 
 
 void
 code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) {
     char *xrn,*crn,*nrn;
-    int dreg,nreg,i;
+    int nreg;
     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)),dir);
-        return;
+	use_int(reg);
+	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)),dir);
+	return;
     } 
     g_expr(e2);
+    if (!is_int_reg(creg)) error(-1);
     crn = register_name(creg);
-    dreg=get_register(); if (!dreg) error(-1);
-    xrn = register_name(dreg);
     nreg=get_register(); if (!nreg) error(-1);
     nrn = register_name(nreg);
-    printf("\t%s %s,0(%s)\n",cload(sign,sz),xrn,crn);
-    printf("\taddu %s,%s,%d\n",nrn,xrn,dir);
+    if (reg==USE_CREG) {
+	reg=get_register(); if (!reg) error(-1);
+	xrn = register_name(reg);
+	set_ireg(reg,0);
+    } else {
+	xrn = register_name(reg);
+    }
+    printf("\t%s %s,0(%s)\n",cload(sz,sign),xrn,crn);
+    if (use) cext(sign,sz,reg);
+    printf("\taddi %s,%s,%d\n",nrn,xrn,dir);
     printf("\t%s %s,0(%s)\n",cstore(sz),nrn,crn);
-    i=creg;creg=dreg;dreg=i; 
     free_register(nreg);
-    free_register(dreg);
-    ireg=creg;
 }
 
 
-
 void
 code_return(int creg) {
-    char *crn = register_name(creg);
+    char *crn;
+    use_int(creg);
+    crn = register_name(creg);
     printf("\tla %s,L_%d\n",crn,retcont);
 }
 
@@ -938,6 +1189,7 @@
 void
 code_environment(int creg) {
     /* save frame pointer */
+    use_int(creg);
 #if R1SAVE
     printf("\tlw %s,0($fp)\n",register_name(creg));
 #else
@@ -948,12 +1200,12 @@
 }
 
 void
-code_bool(int e1) {
+code_bool(int e1,int reg) {
     char *xrn;
     int e2,e3;
     b_expr(e1,1,e2=fwdlabel(),1);  /* including > < ... */
-    creg = use_int(creg);
-    xrn = register_name(creg);
+    use_int(reg);
+    xrn = register_name(reg);
     printf("\tli %s,0\n",xrn);
     jmp(e3=fwdlabel());
     fwddef(e2);
@@ -963,65 +1215,85 @@
 
 char *
 code_gt(int cond) {
-    return (cond?"\tslt  %s,%s,%s\n\tbeq %s,$0,L_%d\n":
-                 "\tslt  %s,%s,%s\n\tbne %s,$0,L_%d\n");
+  return (cond?"eq":"ne");
 }
 
 char *
 code_ugt(int cond) {
-    return (cond?"\tsltu %s,%s,%s\n\tbeq %s,$0,L_%d\n":
-                 "\tsltu %s,%s,%s\n\tbne %s,$0,L_%d\n");
+  return code_gt(cond);
 }
 
 char *
 code_ge(int cond) {
-    return (cond?"\tslt  %s,%s,%s\n\txori %s,%s,0x1\n\tbeq %s,$0,L_%d\n":
-                 "\tslt  %s,%s,%s\n\txori %s,%s,0x1\n\tbne %s,$0,L_%d\n");
+  return code_gt(!cond);
 }
 
 char *
 code_uge(int cond) {
-    return (cond?"\tsltu %s,%s,%s\n\txori %s,%s,0x1\n\tbeq %s,$0,L_%d\n":
-                 "\tsltu %s,%s,%s\n\txori %s,%s,0x1\n\tbne %s,$0,L_%d\n");
+  return code_gt(!cond);
 }
 
 char *
 code_eq(int cond) {
-    return (cond?"\tbeq %s,%s,L_%d\n":"\tbne %s,%s,L_%d\n");
+  return cond?"":0;
 }
 
+
 void
-code_cmp_crgvar(int e1,int sz) {
-    if (cmpreg==-1) cmpreg = get_register();
-    code_crgvar(cadr(e1),cmpreg,1,sz);
+code_cmp_crgvar(int e1,int reg,int sz) {
+    int r;
+    char *crn;
+    use_int(reg);
+    crn = register_name(reg);
+    r = get_ptr_cache((NMTBL*)cadr(e1));
+    printf("\t%s %s,0(%s)\n",cload(sz,sign),crn,register_name(r));
+    cext(0,sz,r);
+    cmpreg = reg;
+    // printf("\tcmpwi cr0,%s,0\n",crn);
 }
 
 
 void
-code_cmp_crlvar(int e2,int sz) {
-    if (cmpreg==-1) cmpreg = get_register();
-    code_crlvar(e2,cmpreg,1,sz);
+code_cmp_crlvar(int e2,int reg, int sz) {
+    char *crn;
+    use_int(reg);
+    crn = register_name(reg);
+    lvar_intro(e2);
+    printf("\t%s %s,",cload(sz,sign),crn);
+    lvar(e2);
+    cext(0,sz,reg);
+    code_cmp_register(reg);
 }
 
 
 void
-code_cmp_rgvar(int e1) {
-    if (cmpreg==-1) cmpreg = get_register();
-    code_rgvar(e1,cmpreg);
+code_cmp_rgvar(int e1,int reg) {
+    int r;
+    char *crn;
+    use_int(reg);
+    crn = register_name(reg);
+    r = get_ptr_cache((NMTBL*)cadr(e1));
+    printf("\tlw %s,0(%s)\n",crn,register_name(r));
+    code_cmp_register(reg);
 }
 
 
 void
-code_cmp_rlvar(int e2) {
-    if (cmpreg==-1) cmpreg = get_register();
-    code_rlvar(e2,cmpreg);
+code_cmp_rlvar(int e2,int reg) {
+    char *crn;
+    use_int(reg);
+    crn = register_name(reg);
+    lvar_intro(e2);
+    printf("\tlw %s,",crn);
+    lvar(e2);
+    code_cmp_register(reg);
 }
 
 
 void
 code_cmp_register(int e2) {
-    cmpreg = e2;
-    /* prevent cmpreg freeing */
+    use_int(e2);
+    cmpreg = reg;  // used by jcond,  beq $reg,$0,L_xx
 }
 
 
@@ -1050,7 +1322,9 @@
 {
     char *s,*crn;
     int lb;
-    crn=register_name(creg);
+
+    use_int(creg);
+    crn = register_name(creg);
 
     s=(char *)cadr(e1);
     printf("\t.rdata\n\t.align 2\n");
@@ -1058,80 +1332,88 @@
     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);
 }
 
 #define MAX_COPY_LEN 20
 
-void 
+void
+
 emit_copy(int from,int  to,int length,int offset,int value,int det)
 {
-    char *frn =	register_name(from);
-    char *trn =	register_name(to);
+    char *frn;
+    char *trn;
     char *drn;
     int fix = 0;
     char *memmove = "memmove";
     int dreg = get_register(); if (!dreg) error(-1);
+
     drn	 = register_name(dreg);
+    use_int(from);
+    use_int(to);
+    frn =	register_name(from);
+    trn =	register_name(to);
 
     /* 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;
+	}
+	clear_ptr_cache();
+	code_save_stacks();
+	printf("\tli $6,%d\n",length);
+	printf("\tmove $5,%s\n",frn);
+	printf("\tmove $4,%s\n",trn);
         /* overrap must be allowed */
-        printf("\tbl L_%s$stub\n",memmove);
+	printf("\tjal L_%s$stub\n",memmove);
+	extern_define(memmove,0,FUNCTION,1);
         fix=0;
-        set_creg(RET_REGISTER,0);
-        if (creg!=to) {
-            free_register(to); to = creg;
-        }
-        break;
+	set_ireg(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("\taddu %s,%s,%d\n",trn,trn,fix);
+	if(creg!=to) {
+	    free_register(creg); creg=to; ireg=to;
+	}
     }
     free_register(dreg);
 }
@@ -1142,9 +1424,10 @@
     int length,count;
     int dreg,sreg; char *drn,*crn,*srn;
     g_expr(e4);
+    if (!is_int_reg(creg)) error(-1);
     length=size(t); 
-    if(length%size_of_int) {
-	length += size_of_int - (length%size_of_int);
+    if(length%SIZE_OF_INT) {
+	length += SIZE_OF_INT - (length%SIZE_OF_INT);
     }
     dreg = get_register(); if (!dreg) error(-1);
     drn = register_name(dreg);
@@ -1153,14 +1436,14 @@
 	sreg = get_register(); if (!sreg) error(-1);
 	srn = register_name(sreg);
 	code_lvar(cadr(arg),sreg);
-	for(count=0;length<MAX_COPY_LEN;count++,length-=size_of_int) {
+	for(count=0;length<MAX_COPY_LEN;count++,length-=SIZE_OF_INT) {
 	    if (length==0) {
 		free_register(sreg);
 		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,-SIZE_OF_INT,srn);
 	    }
 	}
     }
@@ -1168,20 +1451,25 @@
     /* downward direction copy */
     emit_copy(creg,dreg,length,0,0,1);
     if (dreg) free_register(dreg);
-    return length/size_of_int;
+    return length/SIZE_OF_INT;
 }
 
 void
-set_creg(int reg,int mode)
+set_ireg(int reg,int mode)
 {
     if (!is_int_reg(reg)) error(-1);
     if (reg!=creg) {
-	if (reg!=ireg && mode) 
-            printf("\tmove %s,%s\n",register_name(reg),register_name(ireg));
+	clear_ptr_cache_reg(reg);
+	if (ireg && reg!=ireg ) {
+	    free_register(ireg);
+	    if (mode) {
+		printf("\tmove %s,%s\n",register_name(reg),register_name(ireg));
+	    }
+	}
 	free_register(creg);
-	creg = ireg = reg;
-	regs[creg]=1;
+	regs[reg]=USING_REG;
     }
+    creg = ireg = reg;
 }
 
 void
@@ -1189,52 +1477,93 @@
 {
     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));
+	if (freg && reg!=freg) {
+	    free_register(freg);
+	    if (mode) {
+		printf("\tmov.s %s,%s\n",fregister_name(reg),fregister_name(freg));
+	    }
+	}
+	// if (creg!=ireg) free_register(creg);
+	regs[reg]=USING_REG;
+    }
+    creg = freg = reg;
+}
+
+void
+set_lreg(int reg,int mode)
+{
+    if (reg==RET_LREGISTER) {
+	regv_l(reg) = RET_LREGISTER_L;
+	regv_h(reg) = RET_LREGISTER_H;
+    }
+    if (!is_longlong_reg(reg)) error(-1);
+    if (reg!=creg) {
+	if (lreg && reg!=lreg) {
+	    if (mode) {
+		printf("\tmove %s,%s\n",
+		    lregister_name_low(reg),lregister_name_low(lreg));
+		printf("\tmove %s,%s\n",
+		    lregister_name_high(reg),lregister_name_high(lreg));
+	    }
+	    free_register(lreg);
 	}
 	free_register(creg);
-	creg = freg = reg;
-	regs[freg]=1;
+	regs[reg]=USING_REG;
+	clear_ptr_cache_reg(regv_l(reg));
+	regs[regv_l(reg)]=USING_REG;
+	clear_ptr_cache_reg(regv_h(reg));
+	regs[regv_h(reg)]=USING_REG;
     }
-}
-
-static void
-move_dreg(int reg,int dreg)
-{
-    if (reg!=dreg) {
-	printf("\tmove %s,%s\n",dregister_name0(reg),
-				dregister_name0(dreg));
-	printf("\tmove %s,%s\n",dregister_name1(reg),
-				dregister_name1(dreg));
-    }
+    creg = lreg = reg;
 }
 
 void
 set_dreg(int reg,int mode)
 {
-    if (!is_double_reg(reg)) error(-1);
-    if (reg!=creg) {
-	if (mode) {
-	    move_dreg(reg,dreg);
-	}
-	free_register(creg);
-	creg = dreg = reg;
-	regs[dreg]=1;
-	regs[dreg_pair0[dreg-DREG_OFFSET]]=1;
-	regs[dreg_pair1[dreg-DREG_OFFSET]]=1;
+     set_lreg(reg,mode);
+     regs[regv_l(reg)]=USING_DREG;
+     clear_ptr_cache_reg(regv_h(reg));
+     regs[regv_h(reg)]=USING_DREG;
+}
+
+void
+set_lreg_operand(int reg,int mode)
+{
+    // save_stack,clear_ptr_cache is assmued    
+    if (!is_longlong_reg(reg)) { error(-1); return; }
+    if (mode) {
+	if (regv_l(reg)!=6)
+	    printf("\tmove $6,%s\n", lregister_name_high(reg));
+	if (regv_l(reg)!=7)
+	    printf("\tmove $7,%s\n", lregister_name_low(reg));
     }
 }
 
+void
+set_dreg_operand(int reg,int mode)
+{
+     set_lreg_operand(reg,mode);
+}
 
 void
-use_var(int arg)
+use_reg(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)
-	regs[cadr(arg)]=USING_REG;
+// printf("# use reg %d\n",arg);
+    if (arg<0||arg> REAL_MAX_REGISTER+REAL_MAX_FREGISTER+ REAL_MAX_LREGISTER)
+	error(-1);
+    clear_ptr_cache_reg(arg);
+    regs[arg]=USING_REG;
+    if (is_longlong_reg(arg)) {
+	clear_ptr_cache_reg(regv_l(arg));
+	regs[regv_l(arg)]=USING_REG;
+	clear_ptr_cache_reg(regv_h(arg));
+	regs[regv_h(arg)]=USING_REG;
+    } else if (is_double_reg(arg)) {
+	clear_ptr_cache_reg(regv_l(arg));
+	regs[regv_l(arg)]=USING_DREG;
+	clear_ptr_cache_reg(regv_h(arg));
+	regs[regv_h(arg)]=USING_DREG;
+    }
 }
 
 void
@@ -1258,23 +1587,26 @@
 	if (tag==REGISTER) {
 	    /* regs[reg]==INPUT_REG case should be considered */
 	    n->dsp = offset;
-	    offset+=size_of_int;
+	    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) {
+	    /* regs[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) {
+	    /* regs[reg]==INPUT_REG case should be considered */
+	    n->dsp = offset;
+	    t = n->ty;
+	    offset+=SIZE_OF_DOUBLE; reg_offset+=2;
+	} else if (tag==LREGISTER) {
+	    /* regs[reg]==INPUT_REG case should be considered */
+	    n->dsp = offset;
+	    t = n->ty;
+	    offset+=SIZE_OF_LONGLONG; reg_offset+=2;
 	} else {
 	    offset += size(n->ty);
 	    continue;
@@ -1282,41 +1614,88 @@
 	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||tag==DREGISTER||tag==FREGISTER) {
+	if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) {
 	    free_register(reg);
 	}
     }
     my_func_args = offset;
 }
 
+static int
+not_simple_p(int e3)
+{
+    return (e3==FUNCTION||e3==CONV||e3==RSTRUCT||e3==STASS|| 
+	(((e3/100)==LOP)&&(e3!=LREGISTER||e3!=LADD||e3!=LSUB)));
+}
+
 int
 simple_args(int e3)
 {
-    return 
-	!contains_in_list(e3,FUNCTION) &&
-	!contains_in_list(e3,CONV) &&
-	!contains_in_list(e3,RSTRUCT) &&
-	!contains_in_list(e3,STASS)
-    ;
+    return !contains_in_list_p(e3,not_simple_p);
 }
 
 int
 caller_arg_offset_v(int arg)
 {
-    return ARG_LVAR_OFFSET+arg*size_of_int;
+    return ARG_LVAR_OFFSET+arg*SIZE_OF_INT;
+}
+
+void
+use_input_reg(int reg,int mode)
+{
+    if (is_int_reg(reg)) {
+	if (ireg&&reg == ireg) {
+	    if (creg==ireg) creg = 0;
+	    ireg = 0;
+	} 
+	if (lreg) {
+	    if (regv_l(lreg)==reg) {
+		regs[lreg]=0;
+		if (regv_h(lreg)>reg&&
+		    (regs[regv_h(lreg)]==USING_REG||
+		     regs[regv_h(lreg)]==USING_DREG))
+		  {
+		    free_register(regv_h(lreg));
+		}
+		if (creg==lreg) creg = 0;
+		lreg = 0;
+	    } else if (regv_h(lreg)==reg) {
+		regs[lreg]=0;
+		if (regv_h(lreg)>reg&&
+		    (regs[regv_l(lreg)]==USING_DREG) ||
+		    (regs[regv_l(lreg)]==USING_DREG) )
+		  {
+		    free_register(regv_l(lreg));
+		}
+		if (creg==lreg) creg = 0;
+		lreg = 0;
+	    }
+	}
+    } else if (is_longlong_reg(reg)) {
+	use_input_reg(regv_h(reg),0);
+	use_input_reg(regv_l(reg),0);
+    } else if (is_double_reg(reg)) {
+	use_input_reg(regv_h(reg),0);
+	use_input_reg(regv_l(reg),0);
+    } else if (is_float_reg(reg)) {
+	if (freg&&reg == freg) {
+	    if (creg==freg) creg = 0;
+	    freg = 0;
+	} 
+    }
+    if (mode) use_reg(reg);
 }
 
 int
 function(int e1)
 {
-    int e2,e3,e4,nargs,t;
+    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;
-    int iargs=0;
 
     special_lvar = -1;
     ret_type = cadr(cadddr(e1));
@@ -1340,15 +1719,16 @@
 	if (car(jmp)!=REGISTER) error(-1);
 	reg_arg_list = list2(jmp,reg_arg_list);
 	g_expr(e2);
+	if (!is_int_reg(creg)) error(-1);
 	code_register(creg,cadr(jmp));
         /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */
     }
 
     /* now all input register vars are free */
     code_save_stacks();
-    set_creg(CREG_REGISTER,0);
+    // set_lreg(LREG_LREGISTER,0);
     set_freg(FREG_FREGISTER,0);
-    set_dreg(DREG_DREGISTER,0);
+    set_ireg(CREG_REGISTER,0);
 
     nargs = reg_arg = freg_arg = arg_assign = 0;
     for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {	
@@ -1366,13 +1746,38 @@
 	    } else {
 		arg = get_input_register_var(reg_arg,0,0); 
 	    }
-	    use_var(arg); /* protect from input register free */
+	    reg_arg_list = list2(arg,reg_arg_list);
+	    /* protect from input register free */
+	    if (car(arg)==REGISTER)
+		use_input_reg(cadr(arg),1);
+	    g_expr_u(assign_expr0(arg,e4,t,t));
+	    nargs ++ ; reg_arg++;
+	    continue;
+	} else if (t==LONGLONG||t==ULONGLONG||t==DOUBLE) {
+	    if (reg_arg>=MAX_INPUT_REGISTER_VAR) { 
+		arg = list2(LVAR,caller_arg_offset_v(nargs));
+	    } else if (!simple_args(e3) && cadr(e3)) {
+		arg = get_lregister_var(0); 
+		arg_assign = list2(
+		    assign_expr0(r0=
+				 (t==DOUBLE?
+				  get_input_dregister_var(reg_arg,0,0):
+				  get_input_lregister_var(reg_arg,0,0)
+				  ),
+			arg,t,t),
+		    arg_assign);
+		use_input_reg(cadr(r0),1);
+	    } else {
+		arg = get_input_lregister_var(reg_arg,0,0); 
+		use_input_reg(cadr(arg),1);
+	    }
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    g_expr_u(assign_expr0(arg,e4,t,t));
-	    nargs ++ ; reg_arg++; iargs += size_of_int;
+	    nargs ++ ; reg_arg++;
+	    nargs ++ ; reg_arg++;
 	    continue;
-	} else if (t==DOUBLE||t==FLOAT) {
-	    if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
+	} else if (t==FLOAT) {
+	    if (freg_arg>=MAX_INPUT_FREGISTER_VAR) {
 		arg = list2(LVAR,caller_arg_offset_v(nargs));
 	    } else if (!simple_args(e3) && cadr(e3)) {
 		arg = get_dregister_var(0,1); 
@@ -1383,17 +1788,16 @@
 	    } else {
 		arg = get_input_dregister_var(freg_arg,0,0,1); 
 	    }
-	    use_var(arg); /* protect from input register free */
 	    reg_arg_list = list2(arg,reg_arg_list);
+	    if (car(arg)==FREGISTER)
+		use_input_reg(cadr(arg),1); /* protect from input register free */
 	    g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */
 	    freg_arg++;
-	    nargs += size(t)/size_of_int;
-	    if (t==DOUBLE) iargs += size(t);
+	    nargs += size(t)/SIZE_OF_INT;
 	    continue;
-	} else if (car(t)==STRUCT||car(t)==UNION) {
+	} else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
 	    arg = list2(LVAR,caller_arg_offset_v(nargs));
 	    nargs += struct_push(e4,t,arg);
-	    iargs += ((size(t)+3)/size_of_int)*size_of_int;
 	    continue;
 	} else {
 	    error(TYERR);
@@ -1401,35 +1805,41 @@
 	++nargs;
     }
     if (max_func_args<nargs) max_func_args=nargs;
-    if (max_func_iargs<iargs) max_func_iargs=iargs;
     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);
+	printf("\tjal\tL_%s$stub\n",fn->nm);
     } else {
         jrn = register_name(cadr(jmp));
         printf("\tj %s\n",jrn);
     }
     for(;reg_arg_list;reg_arg_list=cadr(reg_arg_list)) {
 	arg = car(reg_arg_list);
-	if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER) 
+	if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER
+		||car(arg)==LREGISTER) 
 	    free_register(cadr(arg));
 	else if (car(arg)==LVAR&&cadr(arg)<0) free_lvar(cadr(arg));
     }
     if (ret_type==DOUBLE) {
 	set_dreg(RET_DREGISTER,0);
-    } else if (ret_type==FLOAT) {
+	use_reg(RET_DREGISTER);
+    } else if (ret_type==DOUBLE||ret_type==FLOAT) {
 	set_freg(RET_FREGISTER,0);
+    } else if (ret_type==ULONGLONG||ret_type==LONGLONG) {
+	set_lreg(RET_LREGISTER,0);
+	use_reg(RET_LREGISTER);
     } else if (ret_type==VOID) {
     } else {
-	set_creg(RET_REGISTER,0);
+	set_ireg(RET_REGISTER,0);
     }
     return ret_type;
 }
 
 void
 code_frame_pointer(int e3) {
+    use_int(e3);
 #if R1SAVE
     printf("\tmove $fp,%s\n",register_name(e3));
 #else
@@ -1457,168 +1867,192 @@
 code_indirect_jmp(int e2) {
     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));
 }
 
 int
-code_rindirect(int e1, int offset, int us)
+code_rindirect(int e1, int reg,int offset, int us)
 {
-    char *crn;
+    char *crn,*rrn;
     g_expr(e1);
+    if (!is_int_reg(creg)) error(-1);
     crn=register_name(creg);
-    printf("\tlw %s,%d(%s)\n",crn,offset,crn);
-    return INT;
+    use_int(reg);
+    rrn=register_name(reg);
+    printf("\tlw %s,%d(%s)\n",rrn,offset,crn);
+    return us?UNSIGNED:INT;
 }
 
 int
-code_crindirect(int e1, int offset, int us)
+code_crindirect(int e1, int reg,int offset, int sign)
 {
-    char *crn;
+    char *crn,*rrn;
     g_expr(e1);
+    if (!is_int_reg(creg)) error(-1);
     crn=register_name(creg);
-    if (us) {
-        printf("\tlbu %s,%d(%s)\n",crn,offset,crn);
-        return UCHAR;
-    } else {
-        printf("\tlb %s,%d(%s)\n",crn,offset,crn);
-        return CHAR;
+    use_int(reg);
+    rrn=register_name(reg);
+    printf("\t%s %s,%d(%s)\n",cload(1,sign),rrn,offset,crn);
+    if (sign) {
+	cext(sign,1,reg);
+	return CHAR;
     }
+    return UCHAR;
 }
 
 int
-code_srindirect(int e1, int offset, int us)
+code_srindirect(int e1, int reg,int offset, int sign)
 {
-    char *crn;
+    char *crn,*rrn;
     g_expr(e1);
+    if (!is_int_reg(creg)) error(-1);
     crn=register_name(creg);
-    if (us) {
-        printf("\tlhu %s,%d(%s)\n",crn,offset,crn);
-        return USHORT;
-    } else {
-        printf("\tlh %s,%d(%s)\n",crn,offset,crn);
-        return SHORT;
+    use_int(reg);
+    rrn = register_name(reg);
+    printf("\t%s %s,%d(%s)\n",cload(SIZE_OF_SHORT,sign),rrn,offset,crn);
+    if (sign) {
+	cext(sign,SIZE_OF_SHORT,reg);
+	return SHORT;
     }
+    return USHORT;
 }
 
 #if FLOAT_CODE
 int
-code_drindirect(int e1, int offset, int d)
+code_drindirect(int e1, int reg,int offset, int d)
 {
-    char *crn;
-    g_expr(e1);
-    crn=register_name(creg);
+     char *crn;
     if (d) {
-        printf("\tlw %s,%d(%s)\n",
-            dregister_name0(dreg),offset,crn);
-        printf("\tlw %s,%d(%s)\n",
-            dregister_name1(dreg),offset+size_of_int,crn);
-	creg = dreg;
-        return DOUBLE;
-    } else {
-        printf("\tl.s %s,%d(%s)\n", fregister_name(freg),offset,crn);
-	creg = freg;
-        return FLOAT;
+        code_lrindirect(e1,reg,offset,1);
+	use_float(d,reg);
+	// regs[reg==USE_CREG?lreg:reg]=USING_DREG;
+	return DOUBLE;
     }
+    g_expr(e1);
+    if (!is_int_reg(creg)) error(-1);
+    crn=register_name(creg);
+    use_float(d,reg);
+    printf("\t%s %s,%d(%s)\n",fload(d),
+	fregister_name(reg),offset,crn);
+    return FLOAT;
 }
 #endif
 
 #if LONGLONG_CODE
 int
-code_lrindirect(int e1, int offset, int us)
+code_lrindirect(int e1, int reg, int offset, int us)
 {
     char *crn;
+    int creg0;
+
     g_expr(e1);
-    crn=register_name(creg);
-    return LONGLONG;
+    if (!is_int_reg(creg)) error(-1);
+    crn=register_name(creg0=creg);
+    use_longlong(reg);
+    if (creg0!=regv_h(reg)) {
+	printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),offset,crn);
+	printf("\tlw %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn);
+    } else {
+	printf("\tlw %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn);
+	printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),offset,crn);
+    }
+    return us?ULONGLONG:LONGLONG;
 }
 #endif
 
+
 void
 code_assign_gvar(int e2,int creg,int byte) {
-    char *crn,*name;
-
-    name = ((NMTBL*)cadr(e2))->nm;
-    crn=register_name(creg);
-    if (byte==1) {
-        printf("\tsb %s,%s\n",crn,name);
-    } if (byte==size_of_short) {
-        printf("\tsh %s,%s\n",crn,name);
-    } else {
-        printf("\tsw %s,%s\n",crn,name);
-    }
+    int r;
+    use_int(creg);
+    r = get_ptr_cache((NMTBL*)cadr(e2));
+    code_assign(r,byte,creg);
 }
 
 void
 code_assign_lvar(int e2,int creg,int byte) {
     char *crn;
+    use_int(creg);
     crn=register_name(creg);
+    lvar_intro(e2);
     if (byte==1) {
-        printf("\tsb %s,",crn);
-    } else if (byte==size_of_short) {
-        printf("\tsh %s,",crn);
+	printf("\tsb %s,",crn);
+    } else if (byte==SIZE_OF_SHORT) {
+	printf("\tsh %s,",crn);
     } else {
-        printf("\tsw %s,",crn); 
+	printf("\tsw %s,",crn);
     }
     lvar(e2);
 }
 
 void
 code_assign_register(int e2,int byte,int creg) {
+    use_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
 code_assign(int e2,int byte,int creg) {
-    char *drn=register_name(e2);
-    char *crn=register_name(creg);
+    char *drn;
+    char *crn;
+    use_int(e2);
+    drn=register_name(e2);
+    use_int(creg);
+    crn=register_name(creg);
 
     if (byte==1) {
-        printf("\tsb %s,0(%s)\n",crn,drn);
-    } else if (byte==size_of_short) {
-        printf("\tsh %s,0(%s)\n",crn,drn);
+	printf("\tsb %s,0(%s)\n",crn,drn);
+    } else if (byte==SIZE_OF_SHORT) {
+	printf("\tsh %s,0(%s)\n",crn,drn);
     } else {
-        printf("\tsw %s,0(%s)\n",crn,drn);
+	printf("\tsw %s,0(%s)\n",crn,drn);
     }
 }
 
 
 void
-code_register_assop(int e2,int op,int byte) {
-    int reg;
-    int xreg = creg;
-    creg = reg = e2;
-    tosop(op,xreg);
-    creg = xreg;
-    if (creg!=reg)
-        printf("\tmove %s,%s\n",register_name(creg),register_name(reg));
+code_register_assop(int e2,int reg, int op,int byte) {
+    //  reg <= reg(e2) op=reg
+    use_int(reg);
+    tosop(op,e2,reg);
 }
 
-
 void
-code_assop(int op,int byte,int sign) {
+code_assop(int op,int creg, int byte,int sign) {
     char *xrn,*crn,*drn;
     int xreg;
     int edx = get_register(); if(!edx) error(-1);
+    //  (*creg) op = pop()
+
+    use_int(creg);
     xrn = register_name(xreg = emit_pop(0));       /* pop e3 value */
-    regs[xreg]=1;
-    printf("# assop\n\tmr %s,%s\n",register_name(edx),register_name(creg));
-    ld_indexx(byte,0,edx,sign);
-    tosop(op,xreg);
+    printf("# assop\n\tmove %s,%s\n",register_name(edx),register_name(creg));
+    ld_indexx(byte,0,edx,creg,sign);
+    tosop(op,creg,xreg);
     crn = register_name(creg);
     drn = register_name(edx);
-    printf("\t%s %s,0(%s)\n",cstore(byte),crn,drn);
+    if (byte==1) {
+	printf("\tsb %s,0(%s)\n",crn,drn);
+    } else if (byte==SIZE_OF_SHORT) {
+	printf("\tsh %s,0(%s)\n",crn,drn);
+    } else {
+	printf("\tsw %s,0(%s)\n",crn,drn);
+    }
     free_register(edx);
     emit_pop_free(xreg);
 }
 
 
 void
-tosop(int op,int oreg)
+tosop(int op,int creg,int oreg)
 {
-    int dx;
-    char *orn,*crn;
-
+    int dx = -1;
+    char *orn,*crn,*drn;
+    // creg = creg op oreg
+
+    use_int(creg);
     if(oreg==-1) {
 	error(-1);
     } else if (oreg<= -REG_LVAR_OFFSET) {
@@ -1630,13 +2064,13 @@
     switch(op) {
     case LSHIFT:
     case ULSHIFT:
-	shift("sll",oreg);
+	shift("sll",creg,oreg);
 	return;
     case RSHIFT:
-	shift("srl",oreg);
+	shift("sra",creg,oreg);
 	return;
     case URSHIFT:
-	shift("sra",oreg);
+	shift("srl",creg,oreg);
 	return;
     }
     orn = register_name(oreg);
@@ -1649,7 +2083,18 @@
 	printf("\tsubu %s,%s,%s\n",crn,crn,orn);
 	break;
     case CMP:
-	printf("\tslt %s,%s\n",crn,orn);
+        printf("\tslt %s,%s,%s\n",crn,orn,crn);
+	cmpreg = creg;
+	break;
+    case UCMP:
+        printf("\tsltu %s,%s,%s\n",crn,orn,crn);
+	cmpreg = creg;
+	break;
+    case CMPEQ:
+        printf("\tbeq %s,%s",crn,orn);  // beq  $2,$3,L1
+	break;
+    case CMPNEQ:
+	printf("\tbne %s,%s",crn,orn);  // beq  $2,$3,L1
 	break;
     case BAND: 
 	printf("\tand %s,%s,%s\n",crn,crn,orn);
@@ -1681,37 +2126,72 @@
     default:
 	error(-1);
     }
-    if(oreg!=creg) free_register(oreg);
-}
-
-
-void
-shift(char *op, int reg)
-{
-    char *crn = register_name(creg);
-    char *rrn = register_name(reg);
-    printf("\t%s %s,%s,%s\n",op,crn,rrn,crn);
+    if(dx!=-1) free_register(dx);
 }
 
 int 
 code_const_op_p(int op,int v)
 {
-    if (op==BAND||op==DIV||op==UDIV||op==MOD||op==UMOD) return 0;
-    return 0;
+    if (car(v)!=CONST) return 0;
+    if (op==BAND||op==DIV||op==UDIV||op==MOD||op==UMOD||op==XOR||op==MUL||op==UMUL) return 0;
+    v = cadr(v);
+    return (-32766<v&&v<32767);
 }
 
-void 
-oprtc(int op,int v)
-{
-}
-
-
 void
-ld_indexx(int byte, int n, int xreg,int sign)
+oprtc(int op,int creg, int v)
+{
+    char *crn;
+    use_int(creg);
+    crn = register_name(creg);
+    v = cadr(v);
+    
+    switch(op) {
+    case LSHIFT:
+    case ULSHIFT:
+	printf("\tsll %s,%s,%d\n",crn,crn,v);
+	return;
+    case RSHIFT:
+	printf("\tsra %s,%s,%d\n",crn,crn,v);
+	return;
+    case URSHIFT:
+	printf("\tsrl %s,%s,%d\n",crn,crn,v);
+	return;
+    case ADD:
+	printf("\taddu %s,%s,%d\n",crn,crn,v);
+	break;
+    case SUB:
+	printf("\taddu %s,%s,-%d\n",crn,crn,v);
+	break;
+    case CMP:
+      printf("\tslt %s,%s,%d\n",crn,crn,v);
+	break;
+    case BOR:
+	printf("\tori %s,%s,%d\n",crn,crn,v);
+	break;
+    default:
+	error(-1);
+    }
+}
+
+void
+shift(char *op, int creg, int reg)
+{
+    char *crn;
+    char *rrn = register_name(reg);
+    use_int(creg);
+    crn = register_name(creg);
+    printf("\t%s %s,%s,%s\n",op,crn,crn,rrn);
+}
+
+void
+ld_indexx(int byte, int n, int xreg,int creg, int sign)
 {	
-    char *crn = register_name(creg);
-    printf("\t%s %s,%d(%s)\n",cload(sign,byte),crn,n,
-	register_name(xreg));
+    char *crn;
+    use_int(creg);
+    crn = register_name(creg);
+    printf("\t%s %s,%d(%s)\n",cload(byte,sign),register_name(creg),n,
+	    register_name(xreg));
 }
 
 int
@@ -1724,24 +2204,22 @@
 code_cmpdimm(int e, int csreg)
 {
     /* used in dosiwtch() */
+    int reg;
+    char *rn;
     if(chk) return;
-    creg = use_int(creg);
-    printf("\tli %s,%d\n",register_name(creg),e);
-    cmpreg = csreg;
+    rn = register_name(reg = get_register());
+    printf("\tli %s,%d\n",rn,e);
+    printf("\tsltu %s,%s,%s\n",rn,register_name(csreg),rn);
 }
 
 void
-code_opening(char *s)
+code_opening(char *filename)
 {
-    /* this is called once per month */
+    /* this is called once per file */
     char *p=cheapp;
-
-    printf("\t.file \"%s\"\n",s);
-    /* printf("\t.version\t\"01.01\"\n"); */
-    /* printf("gcc2_compiled.:\n"); */
-    printf("\t.abicalls\n");
-    printf("\t.text\n");
-
+    printf("\t.file \"%s\"\n",filename);
+    printf(".abicalls\n");
+    printf(".text\n");
     if (asi) {
         fclose(asi);
         asi = 0;
@@ -1761,41 +2239,27 @@
 void
 rexpr(int e1, int l1, char *s,int t)
 {       
-    char *crn,*drn;
-    if (cmpreg>=0) { free_register(cmpreg); cmpreg = -1; }
-
-    g_expr(cadr(e1));
-    emit_push();
-    g_expr(caddr(e1));
-    cmpreg = emit_pop(0);
-    crn = register_name(creg);
-    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);
-        }
+    int op;
+    if (car(e1)==EQ||car(e1)==NEQ) {
+         op = s?CMPEQ:CMPNEQ;
+	 g_expr(list3(op,cadr(e1),caddr(e1)));
+	 printf(",L_%d\n",l1);
     } else {
-        /* beq $2,$3,L1 */
-        printf(s,crn,drn,l1);
+         op = t==INT?CMP:UCMP;
+	 g_expr(list3(op,cadr(e1),caddr(e1)));
+	 printf("\tb%s %s,%0,L_%d\n",s,register_name(cmpreg),l1);
     }
-    free_register(cmpreg) ; cmpreg = -1;
 }
 
+
 void
 jcond(int l, char cond)
-{
+{       
     if (chk) return;
-    if (cmpreg==-1) error(-1);
-    printf("\tb%s %s,%s,L_%d\n",
-        cond?"ne":"eq",
-	register_name(creg),register_name(cmpreg),
-	l);
-    free_register(cmpreg); cmpreg = -1;
+    if (cmpreg==CMP_C1T) 
+      printf("\tbc1%s L_%d\n",cond?"f":"t",l);
+    else
+      printf("\tb%s %s,$0,L_%d\n",register_name(cmpreg),cond?"ne":"eq",l);
 }
 
 void
@@ -1820,12 +2284,13 @@
 	text_mode();
     else
 	printf("\t.align 3\n");
-    /* if (stmode!=STATIC)
-	printf(".globl _%s\n",name); */
-    printf(".ent %s\n",name);
+    if (stmode!=STATIC)
+	printf(".globl _%s\n",name);
+#ifdef DOT_SIZE
+    printf("\t.type\t%s,@function\n",name);
+#endif
     printf("_%s:\n",name);
     code_disp_label=fwdlabel();
-
     printf("\t.set noreorder\n");
     printf("\t.cpload $25\n");
     printf("\t.set reorder\n");
@@ -1840,22 +2305,21 @@
 void
 code_enter1(int args)
 {
-    set_creg(CREG_REGISTER,0);
+    // set_lreg(LREG_LREGISTER,0);
+    set_ireg(CREG_REGISTER,0);
     set_freg(FREG_FREGISTER,0);
-    set_dreg(DREG_DREGISTER,0);
 }
 
 void
 code_leave(char *name)
 {
     int r1_offsetv;
-    disp&= -size_of_int;
-    r1_offsetv = -disp+max_func_args*size_of_int+code_disp_offset;
-
-    fprintf(asi,"L_%d=%d\n",code_disp_label,-r1_offsetv);
-
+    disp&= -SIZE_OF_INT;
+    r1_offsetv = -disp+max_func_args*SIZE_OF_INT+code_disp_offset;
+
+    printf(".set L_%d,%d\n",code_disp_label,-r1_offsetv);
     local_table();
-    free_all_register();
+    // free_all_register();
 }
 
 void
@@ -1865,8 +2329,6 @@
 	text_mode();
     else
 	printf("\t.align 2\n");
-    /* if (stmode!=STATIC)
-	printf(".globl _%s\n",name); */
     printf(".ent %s\n",name);
     printf("_%s:\n",name);
 
@@ -1890,15 +2352,15 @@
     printf("\t.cprestore L_%d\n",cprestore_label);
     max_func_args = 0;
     max_func_iargs = 0;
-
 }
 
 void
 enter1()
 {
-    set_creg(CREG_REGISTER,0);
+    text_mode();
+    // set_lreg(LREG_LREGISTER,0);
+    set_ireg(CREG_REGISTER,0);
     set_freg(FREG_FREGISTER,0);
-    set_dreg(DREG_DREGISTER,0);
 }
 
 static unsigned int
@@ -2004,13 +2466,13 @@
 
 void
 code_set_return_register(int mode) {
-    if (cadr(fnptr->ty)==DOUBLE) {
-	set_dreg(RET_DREGISTER,mode);
-    } else if (cadr(fnptr->ty)==FLOAT) {
+    if (cadr(fnptr->ty)==DOUBLE||cadr(fnptr->ty)==FLOAT) {
 	set_freg(RET_FREGISTER,mode);
+    } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) {
+	set_lreg(RET_LREGISTER,mode);
     } else if (cadr(fnptr->ty)==VOID) {
     } else {
-	set_creg(RET_REGISTER,mode);
+	set_ireg(RET_REGISTER,mode);
     }
 }
 
@@ -2021,24 +2483,27 @@
 
 void
 code_set_fixed_creg(int reg,int mode,int type) {
-    if (type==FLOAT) {
-        set_freg(reg,mode);
-    } else if (type==DOUBLE) {
-        set_dreg(reg,mode);
+    if (type==FLOAT||type==DOUBLE) {
+	set_freg(reg,mode);
+    } else if (type==LONGLONG||type==ULONGLONG) {
+	set_lreg(reg,mode);
+	// use_reg(reg);
     } else {
-        set_creg(reg,mode);
+	set_ireg(reg,mode);
     }
 }
 
-
 void
 gen_gdecl(char *n, int gpc)
 {
+    /*
     if (stmode!=STATIC)
-	printf("\t.globl _%s\n",n); 
+	printf(".globl _%s\n",n); 
+     */
 }
 
-void 
+void
+
 align(int t)
 {
     if (t!=CHAR) {
@@ -2056,15 +2521,18 @@
     double d;
     float f;
 #endif
+#if LONGLONG_CODE
+    long long ll;
+#endif
     char *name;
     name = n->nm; 
-    if(mode!=GDECL&&mode!=STADECL)  { 
+    if(mode!=GDECL && mode!=STADECL)  { 
 	error(-1); return;
     }
     if (chk) return;
     if (n->dsp != -1) {
 	n->dsp = -1;   /* initiallized flag */
-	/* printf(".globl\t_%s\n",name); */
+	printf(".globl\t_%s\n",name);
 	data_mode(name);
 	align(t);
 	printf("_%s:\n",name); 
@@ -2080,36 +2548,41 @@
 	} else if (t==SHORT||t==USHORT) {
 	    printf("\t.short %d\n",cadr(e));
 	    if (data_alignment>0) data_alignment++;
-	    gpc += 2;
+	    gpc += SIZE_OF_SHORT;
 	} else {
-	    printf("\t.word %d\n",cadr(e));
-	    gpc += size_of_int;
+	    printf("\t.long %d\n",cadr(e));
+	    gpc += SIZE_OF_INT;
 	}
+#if LONGLONG_CODE
+    } else if(t==LONGLONG||t==ULONGLONG) {       
+	ll = lcadr(e);
+	printf("\t.long\t0x%x,0x%x\n",code_l2(ll),code_l1(ll));
+#endif
 #if FLOAT_CODE
     } else if(t==DOUBLE) {       
-        d = dcadr(e);
-        printf("\t.word\t0x%x\n\t.word\t0x%x\n",code_d1(d),code_d2(d));
+	d = dcadr(e);
+	printf("\t.long\t0x%x,0x%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.long\t0x%x\n",*(int *)&f);
 #endif
     } 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));
+	gpc += SIZE_OF_INT;
+	if(car(e)==ADDRESS&&car(cadr(e))==GVAR) {
+	    printf("\t.long _%s\n",((NMTBL *)cadr(cadr(e)))->nm);
+	} else if(car(e)==FNAME) {
+	    printf("\t.long _%s\n",((NMTBL *)cadr(e))->nm);
+	} else if(car(e)==GVAR) {
+	    printf("\t.long _%s\n",((NMTBL *)cadr(e))->nm);
+	} else if(car(e)==STRING) {       
+	    if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) {
+		l = fwdlabel();
+		printf("\t.long L_%d\n",l);
+		printf(".cstring\n\t.align 2\n");
+		printf("L_%d:\n",l);
+		output_mode = RODATA_EMIT_MODE;
+	    }
+	    ascii((char *)cadr(e));
 	} else error(TYERR);
     } else error(TYERR);
 }
@@ -2135,24 +2608,24 @@
 global_table(void)
 {
     NMTBL *n;
-    int init; 
+    int init; char *extrn;
     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));
+	}
     }
 }
 
@@ -2169,8 +2642,8 @@
 		data_mode(0);
 		init=1;
 	    }
-	    if (n->dsp!=-1) /* n->dsp = -1 means initialized global */
-	    printf(".lcomm _%s,%d\n",n->nm,size(n->ty));
+	    if (n->dsp != -1) /* initialized static */
+		printf(".lcomm _%s,%d\n",n->nm,size(n->ty));
 	}
     }
 }
@@ -2196,114 +2669,97 @@
 	printf("\t.type\t%s,@object\n",name);
 }
 
-#if FLOAT_CODE
-
-char *
-fstore(int d)
+static void
+extern_conv(char *conv)
 {
-    return (d?"stfd":"stfs");
+     code_save_stacks();
+     clear_ptr_cache();
+     extern_define(conv,0,FUNCTION,1);
+     printf("\tjal %s\n",conv);
+     if (max_func_iargs<16) max_func_iargs=16;
 }
 
-char *
-fload(int d)
-{
-    return d?"lfd":"lfs";
-}
-
-static
-void code_dpfunc(char *f)
-{
-    if (max_func_iargs<16) max_func_iargs=16;
-    printf("\tjal %s\n",f);
-}
+#if FLOAT_CODE
+
+/* floating point */
+
+#define  set_double(freg) regs[freg]=USING_DREG
 
 void
 code_cmp_dregister(int e2,int d)
 {
-    char *frn,*grn;
-    int greg;
-
     if (d) {
-	printf("\tli.d $6,%g\n",0.0);
         code_save_stacks();
-	move_dreg(4+DREG_OFFSET,freg);
-	code_dpfunc("dpcmp");
-        if (max_func_iargs<16) max_func_iargs=16;
-        set_dreg(RET_DREGISTER,0);
-	return;
-    } else {
-	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_register(greg);
+	clear_ptr_cache();
+	set_dreg(RET_DREGISTER,1);
+	printf("\tli.d $6,%g\n",0.0);
+        extern_conv("dpcmp");
 	return;
     }
+    grn =  register_name(greg = get_dregister(d));
+    frn = register_name(e2);
+    printf("\tmtc1 $0,%s\n",grn);
+    printf("\tc.eq.s %s,%s\n",grn,frn);
+    free_register(greg);
+    return;
 }
 
 void
 code_dregister(int e2,int freg,int d)
 {
-    if (freg!=e2) {
-	if (d) {
-	    if (!is_double_reg(e2)) error(-1);
-	    move_dreg(freg,e2);
-	} else {
-	    if (!is_float_reg(e2)) error(-1);
-	    printf("\tfmr %s,%s\n",fregister_name(freg),fregister_name(e2));
-	}
-    }
-}
-
-void code_dassign_gvar(int e2,int freg,int d)
-{ 
-    NMTBL *n = (NMTBL*)cadr(e2);
+    use_float(d,freg);
     if (d) {
-	if (!is_double_reg(freg)) error(-1);
-        printf("\tsw %s,0(%s)\n",dregister_name0(freg),n->nm);
-        printf("\tsw %s,0(%s)\n",dregister_name1(freg),n->nm);
-    } else {
-        printf("\ts.s %s,0(%s)\n",fregister_name(freg),n->nm);
+        code_lregister(e2,freg,0); set_bouble(freg); return;
     }
-}
-
-void code_dassign_lvar(int e2,int freg,int d)
-{ 
-    if (d) {
-	if (!is_double_reg(freg)) error(-1);
-        printf("\tsw %s,",dregister_name0(freg));
-        lvar(e2);
-        printf("\tsw %s,",dregister_name1(freg));
-        e2 += size_of_double/2;
-    } else {
-        printf("\ts.s %s,",fregister_name(freg));
-    }
-    lvar(e2);
-}
-
-void code_dassign(int e2,int freg,int d)
-{ 
-    if (d) {
-	if (!is_double_reg(freg)) error(-1);
-        printf("\tsw %s,0(%s)\n",dregister_name0(freg),register_name(e2));
-        printf("\tsw %s,4(%s)\n",dregister_name1(freg),register_name(e2));
-    } else {
-        printf("\ts.s %s,0(%s)\n",fregister_name(freg),register_name(e2));
+    if (freg!=e2) {
+        if (is_int_reg(e2)) error(-1);
+	printf("\tmov.s %s,%s\n",fregister_name(freg),fregister_name(e2));
     }
 }
 
 void
+code_dassign_gvar(int e2,int freg,int d)
+{ 
+    int r;
+    use_float(d,freg);
+    if (d) {
+         code_lassign_gvar(e2,freg,0);  set_double(freg); return;
+    }
+    r = get_ptr_cache((NMTBL*)cadr(e2));
+    printf("\ts.s %s,0(%s)\n",fregister_name(freg),register_name(r));
+}
+
+void
+code_dassign_lvar(int e2,int freg,int d)
+{ 
+    use_float(d,freg);
+    if (d) {
+        code_lassign_lvar(e2,freg,0); set_double(freg); return;
+    }
+    lvar_intro(e2);
+    printf("\ts.s %s,",fregister_name(freg));
+    lvar(e2);
+}
+
+void
+code_dassign(int e2,int freg,int d)
+{ 
+    use_float(d,freg);
+    if (d) {
+        code_lassign(e2,freg,0); set_double(freg); return;
+    }
+    printf("\ts.s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(e2));
+}
+
+void
 code_dassign_dregister(int e2,int d,int freg) {
-    /* これってさ、code_dregister と同じ? */
+    use_float(d,freg);
+    if (d) {
+        code_lassign_lregister(e2,0,freg); set_double(freg); return;
+    }
     if (e2!=freg) {
-        if (d) {
-	    if (!is_double_reg(freg)) error(-1);
-	    move_dreg(freg,e2);
-        } else {
-            printf("\tmov.s %s,%s\n",fregister_name(e2),fregister_name(freg));
-        }
+	printf("\tmov.s %s,%s\n",fregister_name(e2),fregister_name(freg));
     }
-
 }
 
 static double d0 = 1.0;
@@ -2330,276 +2786,488 @@
     return *j;
 }
 
-void 
+void
+
 code_dconst(int e2,int freg,int d)
 { 
+    int lb;
     double value = dcadr(e2);
-    char *frn;
+    int r;
+    char *rrn,*frn;
+
+    use_float(d,freg);
     if (d) {
-        printf("\tli.d %s,%g\n",dregister_name0(freg),value);
+	printf("\t.li %s,%g\n",lregister_name_high(freg),code_d2(value));
+	printf("\t.li %s,%g\n",lregister_name_low(freg),code_d1(value));
+	free_register(r);
     } else {
         frn = fregister_name(freg);
-        printf("\tli.s %s,%g\n",frn,value);
-    }
-}
-
-
-void code_dneg(int freg,int d)
-{ 
-    char *frn;
-    if (d) {
-        code_save_stacks();
-	move_dreg(4+DREG_OFFSET,freg);
-	code_dpfunc("dpneg");
-        set_dreg(RET_DREGISTER,0);
-    } else {
-        frn = fregister_name(freg);
-        printf("\tfneg %s,%s\n",frn,frn);
+        printf("\t.lis %s,%g\n",frn,value);
     }
 }
 
-void code_d2i(int freg0)
+
+void
+code_dneg(int freg,int d)
 { 
+    char *frn;
+    use_float(d,freg);
+    if (d) {
+        code_save_stacks();
+	clear_ptr_cache();
+	set_dreg(RET_DREGISTER,1);
+	/// set_dreg_operand(oreg,1);
+        extern_conv("dpneg");
+	return;
+    }
+    frn = fregister_name(freg);
+    printf("\tfneg %s,%s\n",frn,frn);
+}
+
+void
+code_d2i(int reg)
+{ 
+    use_float(reg,1);
     code_save_stacks();
+    clear_ptr_cache();
     set_dreg(RET_DREGISTER,1);
-    code_dpfunc("dptoli");
+    extern_conv("dptoli");
     set_creg(RET_REGISTER,0);
+    return;
 }
 
-void code_i2d(int creg0)
+void
+code_i2d(int reg)
 { 
-    code_save_stacks();
     set_creg(RET_REGISTER,1);
-    code_dpfunc("litodp");
-    set_dreg(RET_DREGISTER,0);
-}
-
-void code_d2u(int freg0)
-{ 
-    code_save_stacks();
-    set_dreg(RET_DREGISTER,1);
-    code_dpfunc("dptoul");
-    set_creg(RET_REGISTER,0);
-}
-
-void code_u2d(int creg0)
-{ 
     code_save_stacks();
-    set_creg(RET_REGISTER,1);
-    code_dpfunc("ultodp");
+    clear_ptr_cache();
+    extern_conv("litodp");
     set_dreg(RET_DREGISTER,0);
+    use_float(reg,1);
+    return;
 }
 
-void code_d2f(int freg) {
+void
+code_d2u(int reg)
+{ 
+    use_float(reg,1);
     code_save_stacks();
+    clear_ptr_cache();
     set_dreg(RET_DREGISTER,1);
-    code_dpfunc("dptofp");
-    set_freg(RET_FREGISTER,0);
+    extern_conv("dptoul");
+    set_creg(RET_REGISTER,0);
+    return;
 }
 
-void code_f2d(int freg) {
+void
+code_u2d(int reg)
+{ 
+    set_creg(RET_REGISTER,1);
     code_save_stacks();
-    set_freg(RET_FREGISTER,1);
-    code_dpfunc("fptodp");
+    clear_ptr_cache();
+    extern_conv("ultodp");
     set_dreg(RET_DREGISTER,0);
+    use_float(reg,1);
+    return;
 }
 
-void code_f2i(int freg) {
-    printf("\ttrunc.w.s %s,%s,%s\n",register_name(freg),
-	register_name(freg),register_name(ireg));
-    creg = ireg;
+void
+code_d2f(int reg) { 
+    set_dreg(RET_DREGISTER,1);
+    code_save_stacks();
+    clear_ptr_cache();
+    extern_conv("dptofp");
+    set_freg(RET_FREGISTER,0);
+    use_float(reg,0);
+    return;
 }
 
-void code_f2u(int freg) {
+void
+code_f2d(int reg) { 
+    set_freg(RET_FREGISTER,1);
+    code_save_stacks();
+    clear_ptr_cache();
+    extern_conv("fptodp");
+    set_dreg(RET_DREGISTER,0);
+    use_float(reg,1);
+    return;
+}
+
+void
+code_f2i(int reg) {
+    use_int(reg);
     printf("\ttrunc.w.s %s,%s,%s\n",register_name(freg),
 	register_name(freg),register_name(ireg));
-    creg = ireg;
 }
 
-void code_i2f(int creg0) {
-    printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg));
-    creg = freg;
+void
+code_f2u(int reg) {
+    int freg0 = freg;
+    int_freg1 = get_dregister(0);
+    int_freg2 = get_dregister(0);
+    int_ireg1 = get_register();
+    char *fr0 = dregister_name(freg0);
+    char *fr1 = dregister_name(freg1);
+    char *fr2 = dregister_name(freg2);
+    char *r1 = register_name(ireg1);
+    char *r0;
+    int lb1,lb2;
+
+    use_int(reg);
+    r0 = register_name(ireg);
+    
+    printf("\tli.s    %s,2.14748364800000000000e9\n",fr1);
+    printf("\tc.le.s  %s,%s\n",fr1,fr0);
+    printf("\tbc1t    L_%d\n",lb1=fwdlabel());
+    printf("\ttrunc.w.s %s,%s,%s\n",fr2,fr0,r0);
+    printf("\tmfc1    %s,%s\n",r0,fr2);
+    printf("\tj       L_%d\n",lb2=fwdlabel());
+    printf("\t.p2align 2\n");
+    fwddef(lb1);
+    printf("\tsub.s   %s,%s,%s\n",fr0,fr0,fr1);
+    printf("\tli      $3,-2147483648                  # 0x80000000\n");
+    printf("\ttrunc.w.s %s,%s,%s\n",fr1,fr0,r1);
+    printf("\tmfc1    %s,%s\n",r1,fr1);
+    printf("\tor      %s,%s,%s\n",r1,r1,r0);
+    fwddef(lb2);
+    free_register(freg1);
+    free_register(freg2);
+    free_register(reg1);
 }
 
-void code_u2f(int creg0) {
-    printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg));
-    creg = freg;
+void
+code_i2f(int reg) {
+     int n = new_lvar(SIZE_OF_FLOAT);
+     code_assign_lvar(n,ireg);
+     use_float(reg,0);
+     code_drlvar(n,reg);
+     printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg));
 }
 
-void code_drgvar(int e2,int d,int freg)
+void
+code_u2f(int reg) {
+     int n = new_lvar(SIZE_OF_FLOAT);
+     int reg0;
+     int lb1;
+     char *frn;
+     code_assign_lvar(n,ireg);
+     printf("\tbltz    %s,L_%d\n",r0=register_name(ireg),lb1=fwdlabel());
+     use_float(reg,0);
+     code_drlvar(n,reg,0);
+     reg0 = get_register();
+     reg1 = get_register();
+     frn = dregister_name(reg);
+     printf("\tcvt.s.w %s,%s\n",frn,frn);
+     printf("\tj       L_%d\n",lb2=fwdlabel());
+    printf("\t.p2align 2\n");
+    fwddef(lb1);
+    printf("\tandi    %s,%s,0x1\n",r1,r0);
+    printf("\tsrl     %s,%s,1\n",r0,r0);
+    printf("\tor      %s,%s,%s\n",r1,r0);
+    printf("\tmtc1    %s,%s\n",r1,frn);
+    printf("\tcvt.s.w %s,%s\n",frn,frn);
+    printf("\tadd.s   %s,%s,%s\n",frn,frn,frn);
+    fwddef(lb2);
+    free_register(reg0);
+    free_register(reg1);
+}
+
+void
+code_drgvar(int e2,int d,int freg)
 { 
-    char *name = ((NMTBL*)cadr(e2))->nm;
+    int r;
     if (d) {
-        printf("\tlw %s,%s\n",dregister_name0(freg),name);
-        printf("\tlw %s,%s\n",dregister_name1(freg),name);
-    } else {
-        printf("\tl.s %s,%s\n",fregister_name(freg),name);
+         code_lrgvar(e2,0,freg);
+         set_double(freg);
+	 return;
     }
+    r = get_ptr_cache((NMTBL*)cadr(e2));
+    use_float(d,freg);
+    printf("\tl.s %s,0(%s)\n",fregister_name(freg),register_name(r));
 }
 
 
-void code_drlvar(int e2,int d,int freg)
+void
+code_drlvar(int e2,int d,int freg)
 { 
     if (d) {
-        printf("\tlw %s,",dregister_name0(freg)); lvar(e2);
-        printf("\tlw %s,",dregister_name1(freg)); lvar(e2+size_of_double/2);
-    } else {
-        printf("\tl.s %s,",fregister_name(freg)); lvar(e2);
+         code_lrlvar(e2,0,freg);
+         set_double(freg);
+	 return;
     }
+    use_float(d,freg);
+    lvar_intro(e2);
+    printf("\tl.s %s,",fregister_name(freg)); lvar(e2);
 }
 
-void code_cmp_drgvar(int e2,int d)
+void
+code_cmp_drgvar(int e2,int reg,int d)
 { 
-    char *frn;
+    int r;
+    char *frn,*fr1;
     int g;
+    use_float(d,reg);
+
+    r = get_ptr_cache((NMTBL*)cadr(e2));
+
     if (d) {
 	code_save_stacks();
-	set_dreg(RET_DREGISTER,1);
-        code_drgvar(e2,d,RET_DREGISTER+2);
-	code_dpfunc("dcmp");
+	set_dreg(RET_DREGISTER,0);
+        code_drgvar(e2,d,RET_DREGISTER);
+	clear_ptr_cache();
+	printf("\tmove  $6,$0\n");
+	printf("\tmove  $7,$0\n");
+	extern_conv("dcmp");
+	cmpreg = 2;
     } else {
-	frn=fregister_name(freg);
-        g=get_dregister(d);
-        code_drgvar(e2,d,g);
-        printf("\tfc.eq.s %s,%s\n",frn,fregister_name(g));
-	free_register(g);
-    }
-}
-
-void code_cmp_drlvar(int e2,int d)
-{ 
-    char *frn=fregister_name(freg);
-    int g;
-    if (d) {
-	code_save_stacks();
-	set_dreg(RET_DREGISTER,1);
-        code_drgvar(e2,d,RET_DREGISTER+2);
-	code_dpfunc("dcmp");
-    } else {
-        g=get_dregister(d);
-        code_drlvar(e2,d,g);
-        printf("\tc.eq.s %s,%s\n",frn,fregister_name(g));
+        code_drgvar(e2,d,USE_CREG);
+	frn = fregister_name(freg);
+	fr1=dregister_name(g = get_dregister(0));
+	printf("\tmtc1   $0,%s\n",fr1);
+        printf("\tfc.eq.s %s,%s\n",frn,fr1);
+	cmpreg = CMP_C1T;
 	free_register(g);
     }
 }
 
-static void
-dtosop0(char *opn,int e1,int d,int cmp)
-{
-    char *frn;
-    char *grn;
-    if (d) {
-	code_save_stacks();
-	set_dreg(RET_DREGISTER,1);
-	move_dreg(RET_DREGISTER+2,e1);
-	code_dpfunc(opn);
-    } 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_register(e1);
-}
-
-
-void dtosop(int op,int e1)
-{ 
-    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 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;
-    default:
-        error(-1); return;
-    }
-}
-
 void
-code_dassop(int op,int d) {
-    /* we have lvalue in creg, applied floating value is in freg */
-    char *frn;
-    int  xreg;
-    char *crn=register_name(creg);
+code_cmp_drlvar(int e2,int reg,int d)
+{ 
+    char *frn,*fr1;
+    int g;
+    use_float(d,reg);
 
     if (d) {
-        xreg=emit_dpop(d);
-        printf("\tlw %s,0(%s)\n",dregister_name0(freg),crn);
-        printf("\tlw %s,%d(%s)\n",dregister_name1(freg),size_of_int,crn);
-        dtosop(op,xreg);
-        printf("\tsw %s,0(%s)\n",dregister_name0(freg),crn);
-        printf("\tsw %s,%d(%s)\n",dregister_name1(freg),size_of_int,crn);
-        emit_dpop_free(xreg,d);
-	creg = dreg;
+	code_save_stacks();
+	set_dreg(RET_DREGISTER,0);
+        code_drlvar(e2,d,RET_DREGISTER);
+	clear_ptr_cache();
+	printf("\tmove  $6,$0\n");
+	printf("\tmove  $7,$0\n");
+	extern_conv("dcmp");
+	cmpreg = 2;
+    } else {
+        code_drlvar(e2,d,USE_CREG);
+	frn = fregister_name(freg);
+	fr1=dregister_name(g = get_dregister(0));
+	printf("\tmtc1   $0,%s\n",fr1);
+        printf("\tfc.eq.s %s,%s\n",frn,fr1);
+	cmpreg = CMP_C1T;
+	free_register(g);
+    }
+}
+
+static
+longlong_lib(char *opc,int reg,int e1)
+{
+    use_longlong(reg);
+    code_save_stacks();
+    clear_ptr_cache();
+    if (reg!=REG_LREGISTER) {
+      lmove(REG_LREGISTER,reg);
+    }
+    if (e1!=-1) {
+      if (regv_h(e1)!=6) {
+	printf("move $6,%s\n",lregister_name_high(e1));
+      }
+      if (regv_h(e1)!=7) {
+	printf("move $7,%s\n",lregister_name_high(e1));
+      }
+    }
+    set_lreg(RET_LREGISTER,0);
+    extern_define(opc,0,FUNCTION,1);
+    printf("\tjal L_%s\n",opc);
+    if (max_func_iargs<16) max_func_iargs=16;
+}
+
+static
+double_lib(char *opc,int reg,int e1)
+{
+    longlong_lib(opc,reg,e1);
+    regv[reg]=USING_DREG;
+}
+
+void
+dtosop(int op,int reg,int e1)
+{ 
+    char *opn="";
+    char *opc="";
+    int d;
+    int cmp;
+
+    if ((d=(op<FOP))) { // double case
+      use_float(reg,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);
-	creg = freg;
+      use_float(reg,d);
+    }
+    switch(op) {
+    case FADD: opn="add.s"; break;
+    case DADD: opc="dpadd"; break;
+    case FSUB: opn="sub.s"; break;
+    case DSUB: opc="dpsub"; break;
+    case FDIV: opc="div.s"; break;
+    case DDIV: opn="dpdiv"; break;
+    case FMUL: opc="mul.s"; break;
+    case DMUL: opn="dpmul"; break;
+    case FCMP: opn="c.lt.s"; cmp=1; break;
+    case DCMP:  opc="dpcmp"; cmp=1; break;
+    case FCMPGE: opn="c.le.s"; break;
+    case FCMPEQ: opn="c.eq.s"; break;
+    default:
+	error(-1); return;
+    }
+    if (opn && !d) {
+      grn = fregister_name(e1);
+      frn = fregister_name(reg);
+      if (cmp) {
+	cmpreg=CMP_C1T;
+	printf("\t%s %s,%s\n",opn,frn,grn);
+      } else {
+	printf("\t%s %s,%s,%s\n",opn,frn,frn,grn);
+      }
+    } else if (opc && d) {
+      double_lib(opc,reg,e1);
+    } else error(-1);
+}
+
+void
+code_dassop(int op,int reg,int d) {
+    /* we have lvalue in creg, applied floating value is in freg */
+    //  (*creg) op = pop()
+    int  xreg;
+    char *crn;
+    char *frn;
+    int edx,edx0;
+
+    if (!d) {
+      int  xreg=emit_dpop(d);
+      crn=register_name(ireg);
+      use_float(d,reg);
+      frn  =fregister_name(reg);
+
+      printf("\tl.s %s,0(%s)\n",frn,crn);
+      dtosop(op,reg,xreg);
+      printf("\ts.s %s,0(%s)\n",frn,crn);
+      emit_dpop_free(xreg,d);
+    } else {
+      xreg = emit_lpop(0);       /* pop e3 value */
+      if (!is_int_reg(creg)) error(-1);
+      edx = ireg;
+      emit_push();
+      use_float(d,reg);
+      if (regv_l(lreg)==edx || regv_h(lreg)==edx) {
+	edx0 = get_register(); if(!edx0) error(-1);
+	printf("# dassop\n\tmr %s,%s\n",register_name(edx0),register_name(edx));
+	edx = edx0;
+      }
+      printf("\tlw %s,0(%s)\n",lregister_name_high(reg),
+	     register_name(edx));
+      printf("\tlw %s,%d(%s)\n",lregister_name_low(reg),
+	     SIZE_OF_INT,register_name(edx));
+      free_register(edx);
+      dtosop(op,reg,xreg);
+      edx = emit_pop(0);
+      printf("\tsw %s,0(%s)\n",lregister_name_high(reg),
+	     register_name(edx));
+      printf("\tsw %s,%d(%s)\n",lregister_name_low(reg),
+	     SIZE_OF_INT,register_name(edx));
+      free_register(edx);
+      emit_lpop_free(xreg);
+      set_double(reg);
     }
 }
 
 void
 code_register_dassop(int reg,int op,int d) {
-    error(-1);
+    // reg op= dpop()
+    int  xreg;
+    if (!d) {
+      xreg=emit_dpop(d);
+      dtosop(op,reg,xreg);
+      emit_dpop_free(xreg,d);
+    } else {
+       xreg=emit_lpop();
+       dtosop(op,reg,xreg);
+       emit_lpop_free(xreg);
+       set_double(lreg);
+    }
 }   
 
+static void
+double_lib_c(char *opc,double value);
+{
+      extern_define(opc,0,FUNCTION,1);
+      if (max_func_iargs<16) max_func_iargs=16;
+      printf("\tli.d $6,%g\n",value);
+      printf("\tjal L_%s\n",opc);
+}
 
 void
 code_dpreinc(int e1,int e2,int d,int reg) {
     char *frn;
     char *crn;
     int  g;
-    char *grn;
-
-    g_expr(e2);
-
-    if (d) {
-        crn=register_name(creg);
-        frn=fregister_name(freg);
-
+    char *grn,*drn;
+    int r;
+    int dir=caddr(e1);
+
+    if (!d) {
+      if (car(e2)==FREGISTER) {
+	crn=register_name(cadr(e2));
+      } else {
+	g_expr(e2);
+	if (!is_int_reg(creg)) error(-1);
+	crn=register_name(ireg);
+      }
+
+      use_float(d,reg);
+
+      frn=fregister_name(reg);
+      grn=fregister_name(g=get_dregister(d));
+      printf("\tli.s %s,1.0\n",grn);
+
+      if (car(e2)==FREGISTER) {
+	printf("\tmov.s %s,%s\n",crn,frn);
+	printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",crn,frn,grn);
+      } else {
+	printf("\tl.s %s,0(%s)\n",frn,crn);
+	printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",frn,frn,grn);
+	printf("\ts.s %s,0(%s)\n",frn,crn);
+      }
+      free_register(g);
+    } else {
+      if (car(e2)==DREGISTER) {
+	use_float(d,reg);
 	code_save_stacks();
-        set_dreg(RET_DREGISTER,0);
-        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)
-	    code_dpfunc("dpadd");
-        else
-	    code_dpfunc("dpsub");
-        printf("\tsw $2,0(%s)\n",crn);
-        printf("\tsw $3,%d(%s)\n",size_of_int,crn);
-	creg = dreg;
-    } 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_register(g);
-	creg = freg;
+	clear_ptr_cache();
+	lmove(DREGISTER_OPERAND_1,cadr(e2));
+	double_lib_c(dir>0?"dpadd":"dpsub",1.0);
+	free_register(g);
+	if (reg!=RET_DREGISTER) {
+	  lmove(RET_DREGISTER,cadr(reg));
+	}
+        return;
+      } 
+      g_expr(e2);
+      if(!is_int_reg(creg)) error(-1);
+      emit_push();
+      code_save_stacks();
+      clear_ptr_cache();
+      set_dreg(RET_DREGISTER,0);
+      xreg = emit_pop_regvar(0);
+      xrn = register_name(xreg);
+      printf("\tlw $4,%d(%s)\n",SIZE_OF_INT,xrn);
+      printf("\tlw $5,0(%s)\n",xrn);
+      double_lib_c(dir>0?"dpadd":"dpsub",1.0);
+      use_float(d,reg);
+      if (use) {
+	printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),SIZE_OF_INT,xrn);
+	printf("\tlw %s,0(%s)\n",lregister_name_low(reg),xrn);
+      }
+      printf("\tsw $2,%d(%s)\n",SIZE_OF_INT,xrn);
+      printf("\tsw %3,0(%s)\n",xrn);
+      emit_pop_free(xreg);
     }
 }
 
@@ -2608,113 +3276,1100 @@
     char *frn;
     char *crn;
     int  g;
-    char *grn;
-
-    g_expr(e2);
-
-    if (d) {
-        crn=register_name(creg);
-	g = get_dregister(d);
-        set_dreg(RET_DREGISTER,0);
-        printf("\tlw $4,0(%s)\n",crn);
-        printf("\tlw $5,%d(%s)\n",size_of_int,crn);
-	move_dreg(g,4+DREG_OFFSET);
-        printf("\tli.d $6,1.0\n");
-        if (caddr(e1)>0)
-	    code_dpfunc("dpadd");
-        else
-	    code_dpfunc("dpsub");
-        set_dreg(RET_DREGISTER,0);
-        printf("\tsw $2,0(%s)\n",crn);
-        printf("\tsw $3,%d(%s)\n",size_of_int,crn);
-        free_register(dreg);
-        set_dreg(g,0);
-	creg = g;
+    char *grn,*drn;
+    int dir=caddr(e1);
+
+    if (!d) {
+    if (car(e2)==FREGISTER) {
+	crn=register_name(cadr(e2));
+    } else {
+	g_expr(e2);
+	if (!is_int_reg(creg)) error(-1);
+	crn=register_name(creg);
+    }
+
+    use_float(d,reg);
+
+    frn=fregister_name(reg);
+    grn=fregister_name(g=get_dregister(d));
+    printf("\tli.s %s,1.0\n",grn);
+
+    if (car(e2)==FREGISTER) {
+	printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",frn,crn,grn);
+	printf("\tmov.s %s,%s\n",frn,crn);
+    } else {
+	printf("\tl.s %s,0(%s)\n",fload(d),frn,crn);
+	printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",grn,frn,grn);
+	printf("\ts.s %s,0(%s)\n",fstore(d),grn,crn);
+    }
+    free_register(g);
     } 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_register(g);
-	creg = freg;
+      if (car(e2)==DREGISTER) {
+	use_float(d,reg);
+	code_save_stacks();
+	clear_ptr_cache();
+	lmove(DREGISTER_OPERAND_1,cadr(e2));
+	double_lib_c(dir>0?"dpadd":"dpsub",1.0);
+	if (use && reg!=RET_DREGISTER) {
+	  lmove(reg,RET_DREGISTER);
+	}
+	if (cadr(e2)!=RET_DREGISTER) {
+	  lmove(cadr(e2),RET_DREGISTER);
+	}
+        return;
+      } 
+      g_expr(e2);
+      if(!is_int_reg(creg)) error(-1);
+      emit_push();
+      code_save_stacks();
+      clear_ptr_cache();
+      set_dreg(RET_LREGISTER,0);
+      xreg = emit_pop_regvar(0);
+      xrn = register_name(xreg);
+      printf("\tlw $4,%d(%s)\n",SIZE_OF_INT,xrn);
+      printf("\tlw $5,0(%s)\n",xrn);
+      double_lib_c(dir>0?"dpadd":"dpsub",1.0);
+      printf("\tsw $2,%d(%s)\n",SIZE_OF_INT,xrn);
+      printf("\tsw %3,0(%s)\n",xrn);
+      emit_pop_free(xreg);
+      if (use) {
+	printf("\tlw %s,%d(%s)\n",lregister_name_high(reg),SIZE_OF_INT,xrn);
+	printf("\tlw %s,0(%s)\n",lregister_name_low(reg),xrn);
+      }
     }
-
 }
 
 void
-drexpr(int e1, int e2,int l1, int op)
-{       
-    g_expr(list3(((op==FOP+EQ||op==FOP+NEQ)?DCMP:FCMPGE),e1,e2));
+drexpr(int e1, int e2,int l1, int op,int cond)
+{
+    int dop;
+    if (!cond) {
+	switch(op) {
+	    case FOP+GT:
+		drexpr(e2,e1,l1,FOP+GE,1); return;
+	    case FOP+GE:
+		drexpr(e2,e1,l1,FOP+GT,1); return;
+	    case FOP+EQ:
+		op=FOP+NEQ; break;
+	    case FOP+NEQ:
+		op=FOP+EQ; break;
+	    case DOP+GT:
+		drexpr(e2,e1,l1,DOP+GE,1); return;
+	    case DOP+GE:
+		drexpr(e2,e1,l1,DOP+GT,1); return;
+	    case DOP+EQ:
+		op=DOP+NEQ; break;
+	    case DOP+NEQ:
+		op=DOP+EQ; break;
+	}
+    }
+    dop>FOP?FOP:DOP;
     switch(op) {
-        case DOP+GE:
-            printf("\tbgez\tL_%d\n",l1);
-            break;
-        case DOP+GT:
-            printf("\tbltz\tL_%d\n",l1);
-            break;
-        case DOP+EQ:
-            printf("\tbeq\tL_%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);
-            break;
+    case FOP+GT: op=FOP+CMP; break;
+    case DOP+GT: op=DOP+CMP; break;
+    case FOP+GE: op=FOP+CMPGE; break;
+    case DOP+GE: op=DOP+CMPGE; break;
+    case FOP+EQ: op=FOP+CMPEQ; break;
+    case DOP+EQ: op=DOP+CMP; break;
+    case FOP+NEQ: op=FOP+CMPEQ; break;
+    case DOP+NEQ: op=DOP+CMP; break;
+    default: error(-1);
+    }
+    g_expr(list3(op,e2,e1));
+    switch(op) {
+	case DOP+GT:	printf("\tbgez\t$2,L_%d\n",l1);break;
+	case FOP+GT:	printf("\tbc1t\tL_%d\n",l1);break;
+	case DOP+GE:	printf("\tbltz\t$2,L_%d\n",l1);break;
+	case FOP+GE:	printf("\tbc1t\t$2,L_%d\n",l1);break;
+	case DOP+EQ:	printf("\tbeq\t$2,$0,L_%d\n",l1);break;
+	case FOP+EQ:	printf("\tbc1t\tL_%d\n",l1);break;
+	case DOP+NEQ:	printf("\tbne\t$2,$0,L_%d\n",l1);break;
+        case FOP+NEQ:	printf("\tbc1t\tL_%d\n",l1);break;
     }
 }
 
 int emit_dpop(int d)
 { 
     int xreg,reg;
-    if (d)
-	xreg=pop_dregister();
-    else
-	xreg=pop_fregister();
+    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);
 	xreg=reg;
     }
     return xreg;
 }
 
-void emit_dpop_free(int e1,int d)
+int emit_dpop_regvar(int d)
+{ 
+    int xreg,reg;
+    xreg=pop_fregister();
+    reg = cadr(get_dregister_var(d));
+    if (xreg<= -REG_LVAR_OFFSET) {
+        code_drlvar(REG_LVAR_OFFSET+xreg,1,reg);
+	free_lvar(REG_LVAR_OFFSET+xreg);
+	xreg=reg;
+    } else {
+        code_dassign_register(reg,d,xreg);
+    }
+    return xreg;
+}
+
+void
+emit_dpop_free(int e1,int d)
 { 
     free_register(e1);
 }
 
-void emit_dpush(int d)
+void
+emit_dpush(int d)
 { 
     int new_reg;
+    if (!is_float_reg(creg)) error(-1);
     if (freg_sp>MAX_MAX) error(-1);
-    new_reg = get_dregister(d);
-    if (d) {
-	dreg_stack[dreg_sp++] = dreg;     /* push するかわりにレジスタを使う */
-	creg = dreg = new_reg;
+    new_reg = get_dregister(1);       /* 絶対に取れる */
+    freg_stack[freg_sp++] = freg;     /* push するかわりにレジスタを使う */
+    creg = freg = new_reg;
+}
+
+#endif
+
+#if LONGLONG_CODE
+
+
+/* 64bit int part */
+static void
+lmove(int to,int from)
+{
+    int tmp;
+    if (regv_h(to)==regv_l(from)&&(regv_l(to)==regv_h(from))) {
+	tmp = get_register();
+	printf("\tmove %s,%s\n",register_name(tmp),lregister_name_low(from));
+	printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from));
+	printf("\tmove %s,%s\n",lregister_name_low(to),register_name(tmp));
+	free_register(tmp);
+    } else if (regv_h(to)==regv_l(from)) {
+	printf("\tmove %s,%s\n",lregister_name_low(to),lregister_name_low(from));
+	printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from));
+    } else {
+	printf("\tmove %s,%s\n",lregister_name_high(to),lregister_name_high(from));
+	printf("\tmove %s,%s\n",lregister_name_low(to),lregister_name_low(from));
+    }
+}
+
+static void
+pcond(int op,char *s,int l1)
+{
+    if (op==EQ||op==NEQ) {
+	 printf(",L_%d\n",l1);
+    } else {
+	 printf("\tb%s %s,$0,L_%d\n",s,register_name(cmpreg),l1);
+    }
+}
+
+static int
+lcmp(int op,int cond)
+{
+    if (op==EQ||op==NEQ) {
+	 if (!cond) { op=(op==EQ)?CMPNEQ:CMPEQ; }
     } else {
-	freg_stack[freg_sp++] = freg;     /* push するかわりにレジスタを使う */
-	creg = freg = new_reg;
+	 op = (op==UGT||op==UGE)?UCMP:CMP;
+    }
+    return op;
+}
+
+void
+lrexpr(int e1, int e2,int l1, int op,int cond)
+{
+    int reg;
+    int e3,op1;
+    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));
+    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);
+    }
+    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);
+    }
+    emit_lpop_free(e3);
+}
+
+int
+emit_lpop()
+{
+    int xreg,reg;
+    xreg=lreg_stack[--lreg_sp];
+    if (xreg<= -REG_LVAR_OFFSET) {
+        reg = get_lregister();
+        code_lrlvar(REG_LVAR_OFFSET+xreg,reg);
+        free_lvar(REG_LVAR_OFFSET+xreg);
+        xreg = reg;
+    }
+    return xreg;
+}
+
+void
+code_lregister(int e2,int reg)
+{
+    use_longlong(reg);
+    if (reg!=e2) {
+	lmove(reg,e2);
+    }
+}
+
+void
+code_cmp_lregister(int reg)
+{
+    use_longlong(reg);
+    printf("\tor %s,%s,%s\n",
+		lregister_name_low(reg),
+		lregister_name_low(reg),
+		lregister_name_high(reg));
+    printf("\tbeq %s,$0\n",lregister_name_low(reg));
+}
+
+void
+code_cmp_lrgvar(int e1,int creg)
+{
+    use_longlong(creg);
+    code_lrgvar(e1,creg);
+    code_cmp_lregister(creg);
+}
+
+void
+code_cmp_lrlvar(int e1,int creg)
+{
+    use_longlong(creg);
+    code_lrlvar(e1,creg);
+    code_cmp_lregister(creg);
+}
+
+void
+code_lassign(int e2,int creg)
+{
+    char *drn = register_name(e2);
+    char *crn_h;
+    char *crn_l;
+
+    use_longlong(creg);
+    crn_h = lregister_name_high(creg);
+    crn_l = lregister_name_low(creg);
+
+    if (e2==regv_h(creg)) {
+	printf("\tsw %s,%d(%s)\n",crn_l,SIZE_OF_INT,drn);
+	printf("\tsw %s,0(%s)\n",crn_h,drn);
+    } else {
+	printf("\tsw %s,0(%s)\n",crn_h,drn);
+	printf("\tsw %s,%d(%s)\n",crn_l,SIZE_OF_INT,drn);
+    }
+}
+
+void
+code_lassign_gvar(int e2,int creg)
+{
+    int r;
+    r = get_ptr_cache((NMTBL*)cadr(e2));
+    code_lassign(r,creg);
+}
+
+void
+code_lassign_lvar(int e2,int creg)
+{
+    char *crn_h;
+    char *crn_l;
+
+    use_longlong(creg);
+    crn_h = lregister_name_high(creg);
+    crn_l = lregister_name_low(creg);
+    lvar_intro(e2);
+    printf("\tsw %s,",crn_h);lvar(e2);
+    printf("\tsw %s,",crn_l);lvar(e2+SIZE_OF_INT);
+}
+
+void
+code_lassign_lregister(int e2,int reg)
+{
+    use_longlong(reg);
+    if (e2!=reg) {
+	lmove(e2,reg);
     }
 }
 
+static long long ll0 = 1LL;
+
+static int 
+code_l1(long long d)
+{
+    int *i = (int *)&ll0; int *j = (int *)&d;
+    return (i[1] == 1)?j[1]:j[0];
+}
+
+static int 
+code_l2(long long d)
+{
+    int *i = (int *)&ll0; int *j = (int *)&d;
+    return (i[1] == 1)?j[0]:j[1];
+}
+
+void
+code_lconst(int e1,int creg)
+{
+    use_longlong(creg);
+    code_const(code_l1(lcadr(e1)),regv_l(creg));
+    code_const(code_l2(lcadr(e1)),regv_h(creg));
+}
+
+void
+code_lneg(int creg)
+{
+    int dreg;
+    char *rh,*rl,*dh,*dl;
+    use_longlong(creg);
+    rl=lregister_name_low(creg);
+    rh=lregister_name_high(creg);
+    dreg = get_lregister();
+    dl=lregister_name_low(dreg);
+    dh=lregister_name_high(dreg);
+    printf("\tsubu %s,$0,%s\n",dl,rl);
+    printf("\tsubu %s,$0,%s\n",dh,rh);
+    printf("\tsltu %s,$0,%s\n",rl,dl);
+    printf("\tsubu %s,%s,%s\n",dh,dh);
+    free_register(lreg);
+    set_lreg(dreg,0);
+}
+
+void
+code_lrgvar(int e1,int creg)
+{
+    int r;
+    char *crn_h;
+    char *crn_l;
+    use_longlong(creg);
+    crn_h = lregister_name_high(creg);
+    crn_l = lregister_name_low(creg);
+    r = get_ptr_cache((NMTBL*)cadr(e1));
+    printf("\tlw %s,0(%s)\n",crn_h,register_name(r));
+    printf("\tlw %s,%d(%s)\n",crn_l,SIZE_OF_INT,register_name(r));
+}
+
+void
+code_lrlvar(int e1,int creg)
+{
+    char *crn_h;
+    char *crn_l;
+    use_longlong(creg);
+    crn_h = lregister_name_high(creg);
+    crn_l = lregister_name_low(creg);
+    lvar_intro(e1);
+    printf("\tlw %s,",crn_h); lvar(e1);
+    printf("\tlw %s,",crn_l); lvar(e1+SIZE_OF_INT);
+}
+
+
+
+static void
+code_asld_lib(int oreg)
+{
+    char *ch,*cl,*oh,*ol,*dh,*dl;
+    //    5   4   7   3   2   6
+    int dreg = get_lregister();
+    ch = lregister_name_high(creg);
+    cl = lregister_name_low(creg);
+    oh = lregister_name_high(oreg);
+    ol = lregister_name_low(oreg);
+    dh = lregister_name_high(dreg);
+    dl = lregister_name_low(dreg);
+    
+    printf("\tsll     %s,%s,26\n",dh,ol);
+    printf("\tbgez    %s,1f\n",dh);
+    printf("\tsll     %s,%s,%s\n",oh,cl,ol);
+    printf("\t.set    noreorder\n");
+    printf("\tb       3f\n");
+    printf("\tmove    %s,$0\n",dl);
+    printf("\t.set    reorder\n");
+    printf("\t1:\n");
+    printf("\t.set    noreorder\n");
+    printf("\tbeq     %s,$0,2f\n",dh);
+    printf("\tsll     %s,%s,%s\n",oh,ch,ol);
+    printf("\t.set    reorder\n");
+    printf("\tsubu    %s,%s,%s\n",dh,ol);
+    printf("\tsrl     %s,%s,%s\n",dh,cl,dh);
+    printf("\tor      %s,%s,%s\n",oh,oh,dh);
+    printf("\t2:\n");
+    printf("\tsll     %s,%s,%s\n",dl,cl,ol);
+    printf("\t3:\n");
+    printf("\tmove    %s,%s\n",cl,dl);
+    printf("\tmove    %s,%s\n",ch,oh);
+    free_register(dreg);
+}
+
+static void
+code_asrd_lib(int oreg) // ___ashrdi3$stub
+{
+    char *ch,*cl,*oh,*ol,*dh,*dl;
+    //    5   4   2   3   9   8
+    int dreg = get_lregister();
+    ch = lregister_name_high(creg);
+    cl = lregister_name_low(creg);
+    oh = lregister_name_high(oreg);
+    ol = lregister_name_low(oreg);
+    dh = lregister_name_high(dreg);
+    dl = lregister_name_low(dreg);
+
+    printf("\tsll     %s,%s,26\n",oh,ol);
+    printf("\tbgez    %s,1f\n",oh);
+    printf("\tsra     %s,%s,%s\n",dl,ch,ol);
+    printf("\t.set    noreorder\n");
+    printf("\tb       3f\n");
+    printf("\tsra     %s,%s,31\n",dh,ch);
+    printf("\t.set    reorder\n");
+    printf("\t1:\n");
+    printf("\t.set    noreorder\n");
+    printf("\tbeq     %s,$0,2f\n",oh);
+    printf("\tsrl     %s,%s,%s\n",dl,cl,ol);
+    printf("\t.set    reorder\n");
+    printf("\tsubu    %s,$0,%s\n",oh,ol);
+    printf("\tsll     %s,%s,%s\n",oh,ch,oh);
+    printf("\tor      %s,%s,%s\n",dl,dl,oh);
+    printf("\t2:\n");
+    printf("\tsra     %s,%s,%s\n",dh,ch,ol);
+    printf("\t3:\n");
+    printf("\tmove    %s,%s\n",cl,dl);
+    printf("\tmove    %s,%s\n",ch,dh);
+    free_register(dreg);
+}
+
+static void
+code_lsrd_lib(int oreg) // ___lshrdi3$stub
+{
+    char *ch,*cl,*oh,*ol,*dh,*dl;
+    //    5   4   2   3   9   8
+    int dreg = get_lregister();
+    ch = lregister_name_high(creg);
+    cl = lregister_name_low(creg);
+    oh = lregister_name_high(oreg);
+    ol = lregister_name_low(oreg);
+    dh = lregister_name_high(dreg);
+    dl = lregister_name_low(dreg);
+    
+    printf("\tsll     %s,%s,26\n",oh,ol);
+    printf("\tbgez    %s,1f\n",oh);
+    printf("\tsrl     %s,%s,%s\n",dl,ch,ol);
+    printf("\t.set    noreorder\n");
+    printf("\tb       3f\n");
+    printf("\tmove    %s,$0\n",dh);
+    printf("\t.set    reorder\n");
+    printf("\t\n");
+    printf("\t1:\n");
+    printf("\t.set    noreorder\n");
+    printf("\tbeq     %s,$0,2f\n",oh);
+    printf("\tsrl     %s,%s,%s\n",dl,cl,ol);
+    printf("\t.set    reorder\n");
+    printf("\t\n");
+    printf("\tsubu    %s,$0,%s\n",oh,ol);
+    printf("\tsll     %s,%s,%s\n",oh,ch,oh);
+    printf("\tor      %s,%s,%s\n",dl,dl,oh);
+    printf("\t2:\n");
+    printf("\tsrl     %s,%s,%s\n",dh,ch,ol);
+    printf("\t3:\n");
+    printf("\tmove    %s,%s\n",cl,dl);
+    printf("\tmove    %s,%s\n",ch,dh);
+}
+
+static void
+code_ldiv_lib(int oreg) // ___divdi3$stub
+{
+    code_save_stacks();
+    clear_ptr_cache();
+    set_lreg(LREGISTER_OPERAND,1);
+    set_lreg_operand(oreg,1);
+    extern_conv("__divdi3");
+}
+
+static void
+code_ludiv_lib(int oreg) // ___udivdi3$stub
+{
+    code_save_stacks();
+    clear_ptr_cache();
+    set_lreg(LREGISTER_OPERAND,1);
+    set_lreg_operand(oreg,1);
+    extern_conv("__udivdi3");
+}
+
+static void
+code_lmod_lib(int oreg) // ___moddi3$stub
+{
+    code_save_stacks();
+    clear_ptr_cache();
+    set_lreg(LREGISTER_OPERAND,1);
+    set_lreg_operand(oreg,1);
+    extern_conv("__moddi3");
+}
+
+static void
+code_lumod_lib(int oreg) // ___umoddi3$stub
+{
+    code_save_stacks();
+    clear_ptr_cache();
+    set_lreg(LREGISTER_OPERAND,1);
+    set_lreg_operand(oreg,1);
+    extern_conv("__umoddi3");
+}
+
+#define check_lreg(reg) if (reg!=lreg) { lmove(reg,lreg); }
+
+void
+ltosop(int op,int reg,int oreg)
+{
+    int dx = -1;
+    char *orn_h,*crn_h,*drn_h;
+    char *orn_l,*crn_l,*drn_l;
+    // creg = creg op oreg
+
+    use_longlong(reg);
+    if(oreg==-1) {
+	error(-1);
+    } else if (oreg<= -REG_LVAR_OFFSET) {
+	dx = get_lregister(); if (dx<0) error(-1);
+	use_reg(dx);
+        code_rlvar(oreg+REG_LVAR_OFFSET,dx);
+	oreg = dx;
+    }
+
+    switch(op) {
+    case LLSHIFT:
+    case LULSHIFT:
+	code_asld_lib(oreg); // ___ashldi3$stub
+	check_lreg(reg);
+	return;
+    case LRSHIFT:
+	code_asrd_lib(oreg); // ___ashrdi3$stub
+	check_lreg(reg);
+	return;
+    case LURSHIFT:
+	code_lsrd_lib(oreg); // ___lshrdi3$stub
+	check_lreg(reg);
+	return;
+    }
+    orn_h = lregister_name_high(oreg);
+    orn_l = lregister_name_low(oreg);
+    crn_h = lregister_name_high(reg);
+    crn_l = lregister_name_low(reg);
+    switch(op) {
+    case LADD:
+        drn = register_name(dx = get_register());
+	printf("\taddu %s,%s,%s\n",crn_l,crn_l,orn_l);
+	printf("\tsltu %s,%s,%s\n",drn,crn_l,orn_l);
+	printf("\taddu %s,%s,%s\n",crn_h,crn_h,orn_h);
+	printf("\taddu %s,%s,%s\n",crn_h,crn_h,drn);
+	break;
+    case LSUB:
+        drn = register_name(dx = get_register());
+	printf("\tsltu %s,%s,%s\n",drn,orn_l,crn_l);
+	printf("\tsubu %s,%s,%s\n",crn_l,orn_l,crn_l);
+	printf("\tsubu %s,%s,%s\n",crn_h,orn_h,crn_h);
+	printf("\tsubu %s,%s,%s\n",crn_h,crn_h,drn);
+	break;
+    case LCMP:
+	error(-1);
+	break;
+    case LBAND: 
+	printf("\tand %s,%s,%s\n",crn_l,crn_l,orn_l);
+	printf("\tand %s,%s,%s\n",crn_h,crn_h,orn_h);
+	break;
+    case LEOR: 
+	printf("\txor %s,%s,%s\n",crn_l,crn_l,orn_l);
+	printf("\txor %s,%s,%s\n",crn_h,crn_h,orn_h);
+	break;
+    case LBOR:
+	printf("\tor %s,%s,%s\n",crn_l,crn_l,orn_l);
+	printf("\tor %s,%s,%s\n",crn_h,crn_h,orn_h);
+	break;
+    case LMUL:
+    case LUMUL:
+	code_save_stacks();
+	clear_ptr_cache();
+	dx=get_lregister();
+	use_reg(dx);
+	drn_l = lregister_name_low(dx);
+	drn_h = lregister_name_high(dx);
+        /*
+            drn_l = l32( crn_l * orn_l);
+            drn_h = h32( crn_l * orn_l);
+            orn_l = l32( crn_h * orn_l);
+	    drn_h = drn_h + orn_l;
+            crn_l = l32( crn_l * orn_h);
+	    crn_h = drn_h + crn_l;
+	    crn_l = drn_l;
+        */
+	printf("\tlw      $5,96($fp)\n");
+	printf("\tsra     $4,$5,31\n");
+	printf("\tlw      $2,96($fp)\n");
+	printf("\tmove    $3,$4\n");
+	printf("\tlw      $6,48($fp)\n");
+	printf("\tmultu   $6,$2\n");
+	printf("\tmfhi    $5\n");
+	printf("\tmflo    $4\n");
+	printf("\tlw      $7,48($fp)\n");
+	printf("\tmult    $6,$7,$3\n");
+	printf("\taddu    $5,$5,$6\n");
+	printf("\tlw      $6,52($fp)\n");
+	printf("\tmult    $2,$2,$6\n");
+	printf("\taddu    $5,$5,$2\n");
+	break;
+    case LDIV:
+	code_ldiv_lib(oreg); // ___divdi3$stub
+	check_lreg(reg);
+	break;
+    case LUDIV:
+	code_ludiv_lib(oreg); // ___udivdi3$stub
+	check_lreg(reg);
+	break;
+    case LMOD:
+	code_lmod_lib(oreg); // ___moddi3$stub
+	check_lreg(reg);
+	break;
+    case LUMOD:
+	code_lumod_lib(oreg); // ___umoddi3$stub
+	check_lreg(reg);
+	break;
+    default:
+	error(-1);
+    }
+    if(dx!=-1) free_register(dx);
+}
+
+int
+code_lconst_op_p(int op,int e)
+{
+    int v;
+    if (car(e)==LCONST) {
+	if (!(-32766<lcadr(e)&&lcadr(e)<32767)) return 0;
+	v = lcaddr(e);
+    } else if (car(e)==CONST) {
+	if (!(-32766<cadr(e)&&cadr(e)<32767)) return 0;
+	v = caddr(e);
+    } else return 0;
+    
+    switch(op) {
+    case LLSHIFT:
+    case LULSHIFT:
+    case LRSHIFT:
+    case LURSHIFT:
+	return  (0<v&&v<31);
+    case LADD:
+    case LSUB:
+	return 1;
+    case LBOR:
+	return  (v>0);
+    default:
+	return 0;
+    }
+}
+
+void
+loprtc(int op,int creg,int e)
+{
+    char *crn_h;
+    char *crn_l;
+    char *grn;
+    int v;
+    int greg;
+
+    use_longlong(creg);
+    crn_h = lregister_name_high(creg);
+    crn_l = lregister_name_low(creg);
+
+    if (car(e)==LCONST) v = lcadr(e);
+    else if (car(e)==CONST) v = cadr(e);
+
+    switch(op) {
+    case LLSHIFT:
+    case LULSHIFT:
+	greg = get_register();
+	use_reg(greg);
+	grn = register_name(greg);
+	printf("\tsrwi %s,%s,%d\n",grn,crn_l,32-v);
+	printf("\tslwi %s,%s,%d\n",crn_h,crn_h,v);
+	printf("\tor %s,%s,%s\n",crn_h,grn,crn_h);
+	printf("\tslwi %s,%s,%d\n",crn_l,crn_l,v);
+	free_register(greg);
+	return;
+    case LRSHIFT:
+	greg = get_register();
+	use_reg(greg);
+	grn = register_name(greg);
+	printf("\tsrwi %s,%s,%d\n",grn,crn_l,v);
+	printf("\tinsrwi %s,%s,%d,0\n",grn,crn_h,v);
+	printf("\tsrawi %s,%s,%d\n",crn_h,crn_h,v);
+	printf("\tmr %s,%s\n",crn_l,grn);
+	free_register(greg);
+	return;
+    case LURSHIFT:
+	greg = get_register();
+	use_reg(greg);
+	grn = register_name(greg);
+	printf("\tslwi %s,%s,%d\n",grn,crn_h,32-v);
+	printf("\tsrwi %s,%s,%d\n",crn_l,crn_l,v);
+	printf("\tor %s,%s,%s\n",crn_l,grn,crn_l);
+	printf("\tsrwi %s,%s,%d\n",crn_h,crn_h,v);
+	free_register(greg);
+	return;
+    case LSUB:
+	v = -v;
+    case LADD:
+	printf("\taddic %s,%s,%d\n",crn_l,crn_l,v);
+	if (v<0)
+	    printf("\taddme %s,%s\n",crn_h,crn_h);
+	else
+	    printf("\taddze %s,%s\n",crn_h,crn_h);
+	break;
+    case LBOR:
+	printf("\tori %s,%s,lo16(%d)\n",crn_l,crn_l,v);
+	break;
+    default:
+	error(-1);
+    }
+}
+
+
+void
+emit_lpop_free(int xreg)
+{
+    if (xreg>=0)
+        free_register(xreg);
+}
+
+void
+emit_lpush()
+{
+    int new_reg;
+    if (!is_longlong_reg(creg)) error(-1);
+    if (lreg_sp>MAX_MAX) error(-1);
+    new_reg = get_lregister();        /* 絶対に取れる(?) */
+    lreg_stack[lreg_sp++] = creg;     /* push するかわりにレジスタを使う */
+    lreg = creg = new_reg;
+}
+
+void
+code_i2ll(int reg)
+{
+    char *crn,*crn_h,*crn_l;
+    int reg0;
+    crn = register_name(reg0 = ireg);
+    use_longlong(reg);
+    crn_h = lregister_name_high(lreg);
+    crn_l = lregister_name_low(lreg);
+    if (reg0!=regv_l(lreg))
+	printf("\tmr %s,%s\n",crn_l,crn);
+    printf("\tsrawi %s,%s,31\n",crn_h,crn_l);
+}
+
+void
+code_i2ull(int reg)
+{
+    code_i2ll(reg);
+}
+
+void
+code_u2ll(int reg)
+{
+    char *crn,*crn_h,*crn_l;
+    int reg0;
+    crn = register_name(reg0 = ireg);
+    use_longlong(reg);
+    crn_h = lregister_name_high(lreg);
+    crn_l = lregister_name_low(lreg);
+    if (reg0!=regv_l(lreg))
+	printf("\tmr %s,%s\n",crn_l,crn);
+    printf("\tli %s,0\n",crn_h);
+}
+
+void
+code_u2ull(int creg)
+{
+    code_u2ll(creg);
+}
+
+void
+code_ll2i(int reg)
+{
+    char *crn_l;
+    int reg0;
+    crn_l = lregister_name_low(reg0=lreg);
+    use_int(reg);
+    if (ireg!=regv_l(reg0))
+	printf("\tmr %s,%s\n",register_name(ireg),crn_l);
+}
+
+void
+code_ll2u(int creg)
+{
+    code_ll2i(creg);
+}
+
+void
+code_ull2i(int creg)
+{
+    code_ll2i(creg);
+}
+
+void
+code_ull2u(int creg)
+{
+    code_ll2i(creg);
+}
+
+#if FLOAT_CODE
+
+void
+code_d2ll(int reg)
+{
+    // fixdfdi$stub
+    set_freg(RET_FREGISTER,1);
+    extern_conv("__fixdfdi");
+    set_lreg(RET_LREGISTER,0);
+    if (reg!=USE_CREG&&reg!=RET_LREGISTER)
+	use_longlong(reg);
+}
+
+void
+code_d2ull(int reg)
+{
+    set_freg(RET_FREGISTER,1);
+    extern_conv("__fixunsdfdi");
+    set_lreg(RET_LREGISTER,0);
+    if (reg!=USE_CREG&&reg!=RET_LREGISTER)
+	use_longlong(reg);
+}
+
+void
+code_f2ll(int reg)
+{
+    set_freg(RET_FREGISTER,1);
+    extern_conv("__fixdfdi");
+    set_lreg(RET_LREGISTER,0);
+    if (reg!=USE_CREG&&reg!=RET_LREGISTER)
+	use_longlong(reg);
+}
+
+void
+code_f2ull(int reg)
+{
+    set_freg(RET_FREGISTER,1);
+    extern_conv("__fixsfdi");
+    set_lreg(RET_LREGISTER,0);
+    if (reg!=USE_CREG&&reg!=RET_LREGISTER)
+	use_longlong(reg);
+}
+
+void
+code_ll2d(int reg)
+{
+    set_lreg(RET_LREGISTER,1);
+    extern_conv("__floatdidf");
+    set_freg(RET_FREGISTER,0);
+    if (reg!=USE_CREG&&reg!=RET_FREGISTER)
+	use_float(1,reg);
+}
+
+
+void
+code_ll2f(int reg)
+{
+    set_lreg(RET_LREGISTER,1);
+    extern_conv("__floatdisf");
+    set_freg(RET_FREGISTER,0);
+    if (reg!=USE_CREG&&reg!=RET_FREGISTER)
+	use_float(0,reg);
+}
+
+void
+code_ull2d(int creg)
+{
+    code_ll2d(creg);
+}
+
+void
+code_ull2f(int creg)
+{
+    code_ll2f(creg);
+}
+
+#endif
+
+static char *
+addze(int dir)
+{
+    return dir>0?"ze":"me";
+}
+
+void
+code_lpreinc(int e1,int e2,int reg)
+{
+    char *xrn,*drn_h,*drn_l;
+    int dreg,xreg;
+    int dir=caddr(e1);
+    if (car(e2)==LREGISTER) {
+	use_longlong(reg);
+        printf("\taddic %s,%s,%d\n", 
+                lregister_name_low(cadr(e2)),lregister_name_low(cadr(e2)), dir);
+        printf("\tadd%s %s,%s\n", addze(dir),
+                lregister_name_high(cadr(e2)),lregister_name_high(cadr(e2)));
+        if (cadr(reg)!=cadr(e2)) {
+	    lmove(cadr(reg),cadr(e2));
+	}
+        return;
+    } 
+    g_expr(e2);
+    if(!is_int_reg(creg)) error(-1);
+    emit_push();
+    if (reg==USE_CREG) {
+	dreg=get_lregister(); if (!dreg) error(-1);
+	drn_h = lregister_name_high(dreg);
+	drn_l = lregister_name_low(dreg);
+	set_lreg(dreg,0);  // free old lreg==creg
+    } else {
+	drn_h = lregister_name_high(reg);
+	drn_l = lregister_name_low(reg);
+    }
+    xreg = emit_pop(0);
+    xrn = register_name(xreg);
+    printf("\tlwz %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn);
+    printf("\tlwz %s,0(%s)\n",drn_h,xrn);
+    printf("\taddic %s,%s,%d\n",drn_l,drn_l,dir);
+    printf("\tadd%s %s,%s\n",addze(dir),drn_h,drn_h);
+    printf("\tstw %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn);
+    printf("\tstw %s,0(%s)\n",drn_h,xrn);
+    emit_pop_free(xreg);
+}
+
+void
+code_lpostinc(int e1,int e2,int reg)
+{
+    char *xrn,*drn_h,*drn_l;
+    char *nrn_h,*nrn_l;
+    int dreg,nreg,xreg;
+    int dir=caddr(e1);
+    if (car(e2)==LREGISTER) {
+	use_longlong(reg);
+	lmove(cadr(reg),cadr(e2));
+        printf("\taddic %s,%s,%d\n", 
+                lregister_name_low(cadr(e2)),lregister_name_low(cadr(e2)), dir);
+        printf("\tadd%s %s,%s\n", addze(dir),
+                lregister_name_high(cadr(e2)),lregister_name_high(cadr(e2)));
+        return;
+    } 
+    g_expr(e2);
+    if(!is_int_reg(creg)) error(-1);
+    emit_push();
+    nreg=get_lregister(); if (!nreg) error(-1);
+    nrn_h = lregister_name_high(nreg);
+    nrn_l = lregister_name_low(nreg);
+    if (reg==USE_CREG) {
+	dreg=get_lregister(); if (!dreg) error(-1);
+	drn_h = lregister_name_high(dreg);
+	drn_l = lregister_name_low(dreg);
+	set_lreg(dreg,0);  // free old lreg==creg
+    } else {
+	drn_h = lregister_name_high(reg);
+	drn_l = lregister_name_low(reg);
+    }
+    xreg = emit_pop(0);
+    xrn = register_name(xreg);
+    printf("\tlwz %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn);
+    printf("\tlwz %s,0(%s)\n",drn_h,xrn);
+    printf("\taddic %s,%s,%d\n",nrn_l,drn_l,dir);
+    printf("\tadd%s %s,%s\n",addze(dir),nrn_h,drn_h);
+    printf("\tstw %s,%d(%s)\n",nrn_l,SIZE_OF_INT,xrn);
+    printf("\tstw %s,0(%s)\n",nrn_h,xrn);
+    emit_pop_free(xreg);
+    free_register(nreg);
+}
+
+void
+code_lassop(int op,int reg)
+{
+    int xreg;
+    int edx,edx0=-1;
+
+    // (*creg) op = pop()
+    xreg = emit_lpop(0);       /* pop e3 value */
+    if (!is_int_reg(creg)) error(-1);
+    edx = ireg;
+    emit_push();
+    use_longlong(reg);
+    if (regv_l(lreg)==edx || regv_h(lreg)==edx) {
+	edx0 = get_register(); if(!edx0) error(-1);
+	printf("# lassop\n\tmr %s,%s\n",register_name(edx0),register_name(edx));
+	edx = edx0;
+    }
+    printf("\tlwz %s,0(%s)\n",lregister_name_high(reg),
+	register_name(edx));
+    printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg),
+	SIZE_OF_INT,register_name(edx));
+    free_register(edx);
+    ltosop(op,reg,xreg);
+    edx = emit_pop(0);
+    printf("\tstw %s,0(%s)\n",lregister_name_high(reg),
+	register_name(edx));
+    printf("\tstw %s,%d(%s)\n",lregister_name_low(reg),
+	SIZE_OF_INT,register_name(edx));
+    free_register(edx);
+    emit_lpop_free(xreg);
+}
+
+void
+code_register_lassop(int reg,int op) {
+    // reg op = pop()
+    int  xreg=emit_lpop();
+    ltosop(op,reg,xreg);
+    emit_lpop_free(xreg);
+}   
+
+
 #endif
 
 void
@@ -2724,26 +4379,28 @@
     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]=new_lvar(SIZE_OF_INT)),reg,0); 
             reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET;
         }
     }
 #if FLOAT_CODE
-    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;
-        }
-    }
     for(i=0;i<freg_sp;i++) {
         if ((reg=freg_stack[i])>=0) {
             code_dassign_lvar(
-                (freg_stack[i]=new_lvar(size_of_float)),reg,0); 
+                (freg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1); 
             freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET;
         }
     }
 #endif
+#if LONGLONG_CODE
+    for(i=0;i<lreg_sp;i++) {
+        if ((reg=lreg_stack[i])>=0) {
+            code_lassign_lvar(
+                (lreg_stack[i]=new_lvar(SIZE_OF_LONGLONG)),reg); 
+            lreg_stack[i]= lreg_stack[i]-REG_LVAR_OFFSET;
+        }
+    }
+#endif
 }
 
 void
@@ -2759,223 +4416,7 @@
 {
     global_table();
     /* printf("\t.ident \"Micro-C compiled\"\n"); */
-    fclose(asi);
 }
 
-
-#if LONGLONG_CODE
-
-
-/* 64bit int part */
-
-void lrexpr(int e1, int e2,int l1, int op)
-{
-}
-
-int lpop_register()
-{
-	return 0;
-}
-
-int emit_lpop()
-{
-	return 0;
-}
-
-void code_lregister(int e2,int reg)
-{
-
-}
-
-void code_cmp_lregister(int reg)
-{
-
-}
-
-void code_cmp_lrgvar(int e1,int e2)
-{
-
-}
-
-void code_cmp_lrlvar(int e1,int e2)
-{
-
-}
-
-void code_lassign(int e1,int e2)
-{
-
-}
-
-void code_lassign_gvar(int e1,int e2)
-{
-
-}
-
-void code_lassign_lvar(int e1,int e2)
-{
-
-}
-
-void code_lassign_lregister(int e2,int reg)
-{
-
-}
-
-void code_lconst(int e1,int e2)
-{
-
-}
-
-void code_lneg(int e1)
-{
-
-}
-
-void code_lrgvar(int e1,int e2)
-{
-
-}
-
-void code_lrlvar(int e1,int e2)
-{
-
-}
-
-void ltosop(int e1,int e2)
-{
-
-}
-
-int code_lconst_op_p(int op,int e) {return 0;}
-void loprtc(int op,int e) {}
-
-void emit_lpop_free(int e1)
-{
-
-}
-
-void emit_lpush()
-{
-
-}
-
-void code_i2ll(int creg)
-{
-
-}
-
-void code_i2ull(int creg)
-{
-
-}
-
-void code_u2ll(int creg)
-{
-
-}
-
-void code_u2ull(int creg)
-{
-
-}
-
-void code_ll2i(int creg)
-{
-
-}
-
-void code_ll2u(int creg)
-{
-
-}
-
-void code_ull2i(int creg)
-{
-
-}
-
-void code_ull2u(int creg)
-{
-
-}
-
-#if FLOAT_CODE
-void code_d2ll(int creg)
-{
-
-}
-
-void code_d2ull(int creg)
-{
-
-}
-
-void code_f2ll(int creg)
-{
-
-}
-
-void code_f2ull(int creg)
-{
-
-}
-
-void code_ll2d(int creg)
-{
-
-}
-
-void code_ll2f(int creg)
-{
-
-}
-
-void code_ull2d(int creg)
-{
-
-}
-
-void code_ull2f(int creg)
-{
-
-}
-
-void code_ull2ll(int creg)
-{
-
-}
-
-void code_ull2ull(int creg)
-{
-
-}
-
-#endif
-
-
-void code_lpreinc(int e1,int e2,int reg)
-{
-
-}
-
-void code_lpostinc(int e1,int e2,int reg)
-{
-
-}
-
-void code_lassop(int op)
-{
-
-}
-
-void
-code_register_lassop(int reg,int op) {
-}
-
-
-
-#endif
-
 /* end */
 
--- a/mc-code-powerpc.c	Thu May 06 11:38:56 2004 +0900
+++ b/mc-code-powerpc.c	Mon May 10 21:12:55 2004 +0900
@@ -2234,19 +2234,9 @@
     char *crn;
     use_int(creg);
     crn = register_name(creg);
-    if (byte==1) {
-	printf("\tlbz %s,%d(%s)\n",register_name(creg),n,
+    printf("\t%s %s,%d(%s)\n",cload(byte),register_name(creg),n,
 	    register_name(xreg));
-	if (sign)
-	    printf("\textsb %s,%s\n",crn,crn);
-    } else if (byte==SIZE_OF_SHORT) {
-	printf("\tlhz %s,%d(%s)\n",register_name(creg),n,
-	    register_name(xreg));
-	if (sign)
-	    printf("\textsh %s,%s\n",crn,crn);
-    } else 
-	printf("\tlwz %s,%d(%s)\n",register_name(creg),n,
-	    register_name(xreg));
+    cext(sign,byte,creg);
 }
 
 int
--- a/mc-codegen.c	Thu May 06 11:38:56 2004 +0900
+++ b/mc-codegen.c	Mon May 10 21:12:55 2004 +0900
@@ -339,7 +339,8 @@
     case DIV: case UDIV:	   
     case MOD: case UMOD:
     case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT:
-    case ADD: case SUB: case BAND: case EOR: case BOR: case CMP:
+    case ADD: case SUB: case BAND: case EOR: case BOR: case CMP: case CMPGE:
+    case UCMP: case CMPEQ: case CMPNEQ:
 	machinop(e1);
 	return INT;
 #if FLOAT_CODE
--- a/mc.h	Thu May 06 11:38:56 2004 +0900
+++ b/mc.h	Mon May 10 21:12:55 2004 +0900
@@ -233,13 +233,16 @@
 #define LAND	55
 #define LOR	56
 #define ASS	57
-#define CMPGE	58
-#define ASSOP	59
-#define COMMA	60
+#define UCMP	58
+#define CMPGE	59
+#define CMPEQ	60
+#define CMPNEQ	61
+#define ASSOP	62
+#define COMMA	63
 
-#define CASS	61
-#define CASSOP	62
-#define CUASSOP	63
+#define CASS	64
+#define CASSOP	65
+#define CUASSOP	66
 
 #define SASS	(SOP+CASS)
 #define SASSOP (SOP+CASSOP)
@@ -290,13 +293,13 @@
 #define LBOR	(LOP+BOR)
 
 
-#define STASS	64
+#define STASS	67
 
 #define BINARY_ARGS(i) (MUL<=(i%SOP)&&(i%SOP)<=STASS)
 
 /* tarnary  argments */
 
-#define COND	65
+#define COND	68
 #define SCOND	(SOP+COND)
 #define DCOND	(DOP+COND)
 #define FCOND	(FOP+COND)
@@ -306,19 +309,19 @@
 
 /* not appeared as tags */
 
-#define I2I	66
-#define I2U	67
-#define I2D	68
-#define I2F	69
-#define I2LL	70
-#define I2ULL	71
+#define I2I	69
+#define I2U	70
+#define I2D	71
+#define I2F	72
+#define I2LL	73
+#define I2ULL	74
 
-#define U2I	72
-#define U2U	73
-#define U2D	74
-#define U2F	75
-#define U2LL	76
-#define U2ULL	77
+#define U2I	75
+#define U2U	76
+#define U2D	77
+#define U2F	78
+#define U2LL	79
+#define U2ULL	80
 
 #define D2I	(DOP+I2I)
 #define D2U	(DOP+I2U)
@@ -348,17 +351,17 @@
 #define ULL2LL	(LOP+U2LL)
 #define ULL2ULL	(LOP+U2ULL)
 
-#define LPAR	78
-#define RPAR	79
-#define LBRA	80
-#define RBRA	81
-#define LC	82
-#define RC	83
-#define COLON	84
-#define SM	85
-#define PERIOD	86
-#define ARROW	87
-#define CNAME	88
+#define LPAR	81
+#define RPAR	82
+#define LBRA	83
+#define RBRA	84
+#define LC	85
+#define RC	86
+#define COLON	87
+#define SM	88
+#define PERIOD	89
+#define ARROW	90
+#define CNAME	91
 
 /* tree node tags end */