changeset 583:421be86892b3

ia32 reorganization
author kono
date Tue, 17 Jan 2006 23:38:57 +0900
parents 3f60e599cc04
children ef6e0e05137f
files .gdbinit Changes mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c
diffstat 5 files changed, 487 insertions(+), 470 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Mon Jan 16 00:52:56 2006 +0900
+++ b/.gdbinit	Tue Jan 17 23:38:57 2006 +0900
@@ -39,7 +39,7 @@
 # run  -s l.c
 # run  -s test/const.c
 # run  -s test/basic.c
-# run -s test/code-gen-all.c
+run -s test/code-gen-all.c
 # run -s test/tmp7.c
 # run -s test/inline.c
 # run -s test/code-gen-inline.c
@@ -55,4 +55,4 @@
 # run -s test/func_conv_err.c
 # run -DINLINE=inline test/tmp7.c
 # run -DINLINE=inline test/code-gen-all.c
-run -s throw.c
+# run -s throw.c
--- a/Changes	Mon Jan 16 00:52:56 2006 +0900
+++ b/Changes	Tue Jan 17 23:38:57 2006 +0900
@@ -8414,4 +8414,97 @@
 esi/edi をget_regsiter しないと、assop などで、致命的に足り
 ないことになる。
 
-
+rname しないとすると、use_data_reg したら、必ず後で戻す
+みたいな実装か?
+
+get_register では data_registerが取れて、get_pointer では、
+esi が取れて、それは、use_data_reg/setup_edx では、使われない
+みたいな感じかなぁ。
+
+Mon Jan 16 08:42:16 JST 2006
+
+やっぱり ia32 は、設計が悪い。
+
+    rname, dreg は廃止
+    use_data_reg は、use_int などと同じ形式に
+    setup_edx などは止め、parallel_rassign を使用する
+
+とすれば、register を復活できるのではないだろうか?
+mc-code-mips とかから再構成する?
+
+Mon Jan 16 09:03:27 JST 2006
+
+というわけで、
+
+cbc - 環境/インタフェースの切替え
+
+やっぱり、そのままでは動きませんでしたが、付けてみました。
+うまく使うと、POSIX Thread 的に使うことも可能。
+
+例題は CbC_project/device/test/throw.c にあります。
+
+code
+throw(interface1 arg,int i,int j)
+{
+    char *space = (char *)malloc(ENVSIZE)+ENVSIZE;
+    printf("%d %d %d %d %d\n",arg.last,arg.a,arg.c[99],i,j);
+    arg.last=97;
+    goto throw1(arg,i,75),space;
+}
+
+こんな感じで使います。space (切替えるべき環境)は、stack な
+のでメモリ領域の一番下を指しているようにしてください。context
+とか呼ぶ人もいるだろうな。大きさ的にどれくらいいるかは、
+状況による。64Kbyteはとるべきでしょう。
+
+でも、常に interface がコピーされるのでは、あまり意味がない
+のか。interface をコピーしないで保存するモードがあれば良い
+のかな。
+
+    goto throw1(),space;
+
+みたいな感じ? env が最後を指しているのが不便だが。
+
+    code hoge(interface &hoge) {};
+
+みたいな? もともと参照だしね。引数のずれを防ぐのも考えないと。
+struct に64byteのalignment を入れるか。
+
+やっぱり、特定の型を作って、
+    __env env = new_env(size);
+    goto throw(env);
+みたいな感じの方がいいのかな。
+
+int
+main1()
+{
+    interface1 arg;
+    char *space = (char *)malloc(ENVSIZE)+ENVSIZE;
+    ret = return;
+    env = environment;
+    goto throw1(arg,-6,77),space;
+}
+
+ってな感じで、Cの環境から呼ぶことも可能。
+
+space が一番下ってのも変だが、stack だから仕方がない? こういう風に
+実装するなら、下向きに延ばすことも可能だが.... C のスタックと干渉
+するから、だめか。
+
+Tue Jan 17 10:56:08 JST 2006
+
+一応、ia32 から ranme と dreg は落しましたが....
+
+    get_register が必ず成功するようにする
+	register_var をセーブするような手法が必要かも?
+	free_register で戻す
+	でも、save されたって言う保証がない?
+    dreg を使っていたところを get_register に直す
+    use_data_reg0 を書き直し
+
+というわけで、結構あるなぁ。(こんなのより論文書いたら?)
+
+なんか creg=0 をemptyだと思っているみたいだけど、-1 だろ?
+
+酒飲んでないけど、頭が廻らん。
+
--- a/mc-code-ia32.c	Mon Jan 16 00:52:56 2006 +0900
+++ b/mc-code-ia32.c	Tue Jan 17 23:38:57 2006 +0900
@@ -165,11 +165,15 @@
 static int output_mode = TEXT_EMIT_MODE;
 
 static int creg;
+static int ireg;
 static int lreg;
 
+#define regv_l(r)    (r==REG_L?REG_ESI:REG_EAX)
+#define regv_h(r)    (r==REG_L?REG_EDI:REG_EDX)
+
 int code_lassop_p = 0;
 
-int MAX_REGISTER=6;            /* intel386のレジスタを6つまで使う*/
+#define MAX_REGISTER 6            /* intel386のレジスタを6つまで使う*/
 #define REAL_MAX_REGISTER 8    /* intel386のレジスタが8つということ*/
 static int MAX_DATA_REG=4;    
 static int MAX_POINTER=3;    
@@ -195,7 +199,6 @@
 static int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
 
 static int reg_var;
-static int regvar[2];
 
 
 /*
@@ -237,75 +240,64 @@
 }
 
 /*
-    creg   current virtual register
-    dreg   spare virtual register
-
-    rname[creg]   current real register
-    rname[dreg]   spare real register
-
-    regs[]        virtual register usage
-    regv[]        value in virtual register flag
-
-    reg_name[rname[creg]]
+    creg   current register
+
+    regs[]        register usage
+    regv[]        value in register flag
 
     freg    current floating point register
     fregv   value in floating point register
  */
 
-static int dreg; /* general temporal register */
-
 #define REAL_MAX_LREGISTER 2
-static int ia32regs[REAL_MAX_REGISTER+REAL_MAX_LREGISTER];
-static int ia32regv[REAL_MAX_REGISTER+REAL_MAX_LREGISTER];
-static int ia32rname[REAL_MAX_REGISTER+REAL_MAX_LREGISTER];
-
-static int *regv  = ia32regv;
+static int ia32regs[1+REAL_MAX_REGISTER+REAL_MAX_LREGISTER];
+
+
 static int *regs  = ia32regs;
-static int *rname = ia32rname;
 
 static int ia32fregs[1];
-static int ia32fregv[1];
-
+static int *fregs  = ia32fregs;
 static int freg;
-static int *fregv = ia32fregv;
-static int *fregs = ia32fregs;
-
-
-#define REG_EAX   0
-#define REG_EBX   1
-#define REG_ECX   2
-#define REG_EDX   3
-#define REG_ESI   4
-#define REG_EDI   5
-#define REG_EBP   6
-#define REG_ESP   7
-#define is_int_reg(reg) (reg<REG_EBP)
-#define REG_LCREG     8
-#define REG_L     9
+
+
+#define REG_EAX   1
+#define REG_EBX   2
+#define REG_ECX   3
+#define REG_EDX   4
+#define REG_ESI   5
+#define REG_EDI   6
+#define REG_EBP   7
+#define REG_ESP   8
+#define is_int_reg(reg) (1<=reg&&reg<REG_EBP)
+#define REG_LCREG     9
+#define REG_L     10
 #define REG_fp REG_EBP
 
-#define regv_l(r)    (virtual(r==REG_L?REG_ESI:REG_EAX))
-#define regv_h(r)    (virtual(r==REG_L?REG_EDI:REG_EDX))
-
-
 #define DATA_REG 0    
 #define POINTER_REG 3    
-static char *reg_name[8]; 
-static char *reg_name_l[4];
-static char *reg_name_w[4];
+
+#define RET_FREGISTER
+#define RET_DREGISTER
+#define RET_LREGISTER   REG_LCREG
+#define RET_REGISTER    REG_EAX
+
+
+static char *reg_name[8+1]; 
+static char *reg_name_l[4+1];
+static char *reg_name_w[4+1];
 
 static void ascii(char *s);
 
-static void use_register(int virt, int real, int move);
-static int virtual(int real);
+static int use_register(int virt, int real, int move);
 static void shift(char *op, int reg,int creg);
 static void ld_indexx(int byte, int n, int xreg,int reg,int sign);
 //static void data_mode(char *name);
 // static void text_mode(int align);
-static int edx_setup(int rreg);
-static void edx_cleanup();
+static int get_data_register(void);
+
 static void local_table(void);
 static int push_struct(int e4,int t) ;
+static void code_clear_stack_reg(int reg1);
 #if FLOAT_CODE
 static char * fload(int d);
 static int code_d1(double d);
@@ -319,25 +311,110 @@
 #endif
 
 #define use_int(reg)   if (reg==-1) reg=use_int0()
-static int use_int0() { lreg = 0; if (!is_int_reg(creg)) { creg = virtual(REG_EBX); regs[creg]=1;} return creg; }
-
-#define use_longlong(reg)   reg=use_longlong0(reg)
+
+static int
+use_int0() { 
+    int i = creg;
+    if (!i||!ireg||!is_int_reg(i)) {
+        if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; }
+        if (!ireg) ireg = get_register();
+        i = ireg;
+    }
+    if (!regs[i]) regs[i]=USING_REG;
+    creg = ireg = i;
+    return i;
+}
+
+#define is_data_reg(reg) (REG_EAX<=reg&&reg<=REG_EDX)
+#define is_pointer_reg(reg) (REG_ESI<=reg&&reg<=REG_EBP)
+
+static int 
+use_register(int reg0, int reg1, int move)
+{
+    /*
+	reg0 becomes reg1, if (move) copy the content.
+	if reg1 is used, reg0 contains old value.
+     */
+
+
+    char *move_op;
+    code_clear_stack_reg(reg1); 
+    move_op = regs[reg0]?"\txchg %s,%s\n":"\tmovl %s,%s\n";
+    if (move) {
+	printf(move_op,reg_name[reg0],reg_name[reg1]);
+    } 
+    return reg0;
+}
+
+#define use_data_reg(reg,keep)   \
+    if (reg==-1||!is_data_reg(reg)) reg=use_data_reg0(keep)
+
+int 
+use_data_reg0(int keep)
+{
+    int i = creg;
+    int ptreg =0;
+    if (is_pointer_reg(creg)) {
+	free_register(ptreg=creg); creg = 0;
+    }
+    if (!i||!ireg||!is_int_reg(i)) {
+        if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; }
+        if (!ireg) ireg = get_data_register();
+        // else if (ireg!=i) free_register(i);
+        i = ireg;
+    }
+    if (!regs[i]) regs[i]=USING_REG;
+    creg = i;
+    if (ptreg && keep) {
+	printf("\tmovl %s,%s\n",reg_name[ptreg],reg_name[creg]);
+    }
+    return i;
+}
+
+static void
+set_ireg(int reg,int mode)
+{
+    if (!is_int_reg(reg)) error(-1);
+    if (reg!=creg) {
+        // clear_ptr_cache_reg(reg);
+        if (ireg && reg!=ireg ) {
+            free_register(ireg);
+            if (mode) {
+                printf("\tmovl %s,%s\n",reg_name[reg],reg_name[ireg]);
+            }
+        }
+        if (regs[creg]!=REG_VAR) free_register(creg);
+        if (creg==lreg) lreg = 0;
+        regs[reg]=USING_REG;
+    }
+    creg = ireg = reg;
+}
+
+#define is_long_reg(reg)   (reg==REG_LCREG||reg==REG_L)
+#define use_longlong(reg)   \
+    if (reg==-1||is_long_reg(reg)) reg=use_longlong0(reg)
+
 static int
 use_longlong0(int reg)
 {
-    int i;
-    if (reg==USE_CREG)
-	reg = REG_LCREG;
-    if (!lreg) {
+    int i = creg;
+    if (ireg) { free_register(ireg); ireg=0; }
+    if (!lreg||!regs[lreg]) {
 	code_save_stacks();
-	// make edx,eax free
-	use_register(creg,REG_EBX,regv[creg]);
-	use_register(dreg,REG_ECX,regv[dreg]);
-	for(i=0;i<reg_var;i++)
-	    use_register(regvar[i],REG_ESI+i,1);
-    } 
-    creg = lreg = reg;
-    return lreg;
+	lreg = REG_LCREG;
+        i = lreg;
+    }
+    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 = lreg = i;
+    return i;
+}
+
+static void
+set_lreg(int reg,int mode)
+{
+    use_longlong(reg);
 }
 
 char *
@@ -364,7 +441,7 @@
     endian = ENDIAN;
 
     arg_offset = 8;
-    MAX_REGISTER=6;
+    // MAX_REGISTER=6;
     MAX_DATA_REG=4;    
     MAX_POINTER=3;    
     MAX_REGISTER_VAR=2;    
@@ -398,16 +475,16 @@
 char *
 register_name(int i,int byte)
 {
-    if (i<0) {
+    if (i<=0) {
 	error(REG_ERR);
 	return "%eax";
     }
-    if (byte==1 && rname[i] <= REG_EDX) {
-	return reg_name_l[rname[i]];
-    } else if (byte==SIZE_OF_SHORT && rname[i] <= REG_EDX) {
-	return reg_name_w[rname[i]];
+    if (byte==1 && i <= REG_EDX) {
+	return reg_name_l[i];
+    } else if (byte==SIZE_OF_SHORT && i <= REG_EDX) {
+	return reg_name_w[i];
     } else {
-	return reg_name[rname[i]]; /* 0 or 4 means int */
+	return reg_name[i]; /* 0 or 4 means int */
     }
 }
 
@@ -421,9 +498,8 @@
 
 void
 gexpr_code_init(void){
-    use_register(creg,REG_EAX,0);
-    regv[creg]=0;
-    regv[dreg]=0;
+    // use_register(creg,REG_EAX,0);
+    set_ireg(REG_EAX,0);
 }
 
 void
@@ -433,13 +509,46 @@
 int 
 get_register(void)
 {    /* 使われていないレジスタを調べる */
-    int i;
-    for(i=0;i<MAX_REGISTER;i++) {
+    int i,reg,j;
+    for(i=1;i<MAX_REGISTER+1;i++) {
 	if (! regs[i]) {    /* 使われていないなら */
 	    regs[i]=1;      /* そのレジスタを使うことを宣言し */
 	    return i;       /* その場所を表す番号を返す */
 	}
     }
+    /* search register stack */
+    for(i=0;i<reg_sp;i++) {
+        if ((reg=reg_stack[i])>=0) {
+            code_assign_lvar(
+                (j=new_lvar(SIZE_OF_INT)),reg,0); 
+            reg_stack[i]= j-REG_LVAR_OFFSET;
+            return reg;
+        }
+    }
+    error(-1);
+    return -1;    /* 空いている場所がないなら、それを表す -1 を返す */
+}
+
+static int 
+get_data_register(void)
+{    /* 使われていないレジスタを調べる */
+    int i,reg,j;
+    for(i=1;i<=REG_EDX;i++) {
+	if (! regs[i]) {    /* 使われていないなら */
+	    regs[i]=1;      /* そのレジスタを使うことを宣言し */
+	    return i;       /* その場所を表す番号を返す */
+	}
+    }
+    /* search register stack */
+    for(i=0;i<reg_sp;i++) {
+        if (is_data_reg(i) && (reg=reg_stack[i])>=0) {
+            code_assign_lvar(
+                (j=new_lvar(SIZE_OF_INT)),reg,0); 
+            reg_stack[i]= j-REG_LVAR_OFFSET;
+            return reg;
+        }
+    }
+    error(-1);
     return -1;    /* 空いている場所がないなら、それを表す -1 を返す */
 }
 
@@ -447,17 +556,12 @@
 free_register(int i) {    /* いらなくなったレジスタを開放 */
     if (i==REG_L) {
 	reg_var=0;
-	regv[virtual(REG_ESI)]=regv[virtual(REG_EDI)]=0;
+	regs[REG_ESI]=regs[REG_EDI]=0;
     } else if (regs[i]==REG_VAR) { reg_var--;
     } else if(i==REG_LCREG) { //? REG_L?
-	regv[virtual(REG_EAX)]=regv[virtual(REG_EDX)]=0;
+	regs[REG_EAX]=regs[REG_EDX]=0;
     }
-    regv[i]=regs[i]=0;
-#if 0
-    if(i==REAL_MAX_REGISTER) { //? REG_L?
-	regv[virtual(REG_ESI)]=regv[virtual(REG_EDI)]=0;
-    }
-#endif
+    regs[i]=0;
 }
 
 extern void
@@ -477,8 +581,8 @@
 {
     if (is_code) {
 	if (i>=MAX_CODE_INPUT_REGISTER_VAR) return 0;
-	i =  virtual(i+REG_ESI);
-	regs[i]=regv[i]=INPUT_REG;
+	i += REG_ESI;
+	regs[i]=INPUT_REG;
 	return list3(REGISTER,i,(int)nptr);
     } else {
 	return 0;
@@ -497,10 +601,9 @@
     int h,l;
     if (is_code) {
 	if (i+1>=MAX_CODE_INPUT_REGISTER_VAR) return 0;
-	h = virtual(REG_ESI);
-	l = virtual(REG_EDI);
+	h = REG_ESI;
+	l = REG_EDI;
 	regs[h]=regs[l]=INPUT_REG;
-	regv[h]=regv[l]=INPUT_REG;
 	return list2(LREGISTER,REG_L);
     }
     return 0;
@@ -516,13 +619,11 @@
 get_lregister_var(NMTBL *n)
 {
     int h,l;
-    h = virtual(REG_ESI);
-    l = virtual(REG_EDI);
-    if (regv[REAL_MAX_REGISTER]==0&&regs[h]==0&&regs[l]==0) {
+    h = REG_ESI;
+    l = REG_EDI;
+    if (regs[h]==0&&regs[l]==0) {
 	regs[h]=regs[l]=REG_VAR;
-	regv[h]=regv[l]=REG_VAR;
-	regv[REAL_MAX_REGISTER]=1;
-	reg_var=2; regvar[0]=h; regvar[1]=l;
+	reg_var=2; 
 	return list2(LREGISTER,REG_L);
     }
     return list3(LVAR,new_lvar(SIZE_OF_LONGLONG),0);
@@ -539,7 +640,7 @@
 register_full(void)
 {
     int i;
-    for(i=0;i<MAX_REGISTER;i++) {
+    for(i=1;i<MAX_REGISTER+1;i++) {
 	if (! regs[i]) { 
 	    return 0;  
 	}
@@ -552,8 +653,8 @@
 {
     int i,count;
     count = 0;
-    for(i=0;i<MAX_REGISTER;i++) {
-	if (! regs[i] && ! regv[i]) count++;
+    for(i=1;i<MAX_REGISTER+1;i++) {
+	if (! regs[i]) count++;
     }
     return d?0:count;    
 }
@@ -562,11 +663,10 @@
 free_all_register(void)
 {
     int i;
-    for(i=0;i<MAX_REGISTER+REAL_MAX_LREGISTER;i++) {
-	regs[i]=regv[i]=0;
+    for(i=1;i<MAX_REGISTER+REAL_MAX_LREGISTER+1;i++) {
+	regs[i]=0;
     }
-    creg = get_register();
-    dreg = get_register();
+    lreg = creg = ireg = 0;
     reg_var = 0;
     return;
 }
@@ -577,11 +677,11 @@
     if (car(s)==REGISTER) {
 	if (car(t)==REGISTER) return cadr(s)==cadr(t);
 	if (car(t)==LREGISTER)
-	    return cadr(s)==virtual(REG_ESI)|| cadr(s)==virtual(REG_EDI);
+	    return cadr(s)==REG_ESI|| cadr(s)==REG_EDI;
     } else if (car(s)==LREGISTER) {
 	if (car(t)==LREGISTER) return 1;
 	if (car(t)==REGISTER)
-	    return cadr(t)==virtual(REG_ESI)|| cadr(t)==virtual(REG_EDI);
+	    return cadr(t)==REG_ESI|| cadr(t)==REG_EDI;
     }
     return 0;
 }
@@ -591,16 +691,12 @@
 {
     int i;
     printf("## %d: %s:",lineno,s);
-    printf(" creg=%s dreg=%s ",register_name(creg,0),register_name(dreg,0));
-    for(i=0;i<MAX_REGISTER;i++) {
+    if (creg) printf(" creg=%s ",register_name(creg,0));
+    for(i=1;i<MAX_REGISTER+1;i++) {
 	printf("%d",regs[i]);
     }
-    printf(":");
-    for(i=0;i<MAX_REGISTER;i++) {
-	printf("%d",regv[i]);
-    }
 #if 0
-    printf(" regs_stack",register_name(creg,0),register_name(dreg,0));
+    printf(" regs_stack",register_name(creg,0);
     for(i=reg_sp;i>=0;i--) {
 	if(reg_stack[i]>=0)
 	    printf(" %s",register_name(reg_stack[i],0));
@@ -632,7 +728,6 @@
             if ((reg = get_input_register_var(reg_var,n,is_code0))) {
                 n->sc = REGISTER;
                 n->dsp = cadr(reg);
-                regv[n->dsp]= 1;
                 regs[n->dsp]= INPUT_REG;
                 reg_var++;
                 cadddr(args)=SIZE_OF_INT; /* why we need this? */
@@ -642,7 +737,6 @@
             if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) {
                 n->sc = DREGISTER;
                 n->dsp = cadr(reg);
-                fregv[n->dsp]= 1;
                 fregs[n->dsp]= INPUT_REG;
                 freg_var++;
                 cadddr(args)=size(type); /* why we need this? */
@@ -664,7 +758,7 @@
     stack_depth = 0;
     text_mode(0);
     gexpr_code_init();
-    regs[creg]=1; regv[creg]=1;
+    regs[creg]=1;
     register_usage("gexpr_init");
 }
 
@@ -673,26 +767,12 @@
 emit_init(void)
 {
     int i;
-    for(i=0;i<REAL_MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;}
+    for(i=1;i<REAL_MAX_REGISTER+1;i++) regs[i]=0; 
     free_all_register();
     reg_sp = 0;
     freg_sp = 0;
 }
 
-int
-virtual(int real)
-{
-    int real_v,i;
-    real_v = -1;
-    for(i=0;i<REAL_MAX_REGISTER;i++) {
-	if (rname[i]==real) {
-	    real_v=i;
-	    break;
-	}
-    }
-    return real_v;
-}
-
 int 
 pop_register(void)
 {     /* レジスタから値を取り出す */
@@ -702,9 +782,7 @@
 void
 emit_pop_free(int xreg)
 {
-    if (xreg==dreg||xreg==creg) {
-	regv[dreg]=0;
-    } else if (xreg>=0) {
+    if (xreg>=0 && xreg!=creg) {
 	free_register(xreg);
     }
 }
@@ -713,25 +791,13 @@
 int
 get_register_var(NMTBL *nptr)
 {
-#if 0
-    int i,j;
-    どうしても、%esi,%edi がvirtualでずれてループしてしまうのを
-    止められないので、とりえあず諦める。
-
-    edx_setup あたりがまずいらしいが...
-
-    if (reg_var<2) {
-	for(i=REG_ESI;i<REG_EBP;i++) {
-	    j = virtual(i);
-	    if (! regs[j]) {    /* 使われていないなら */
-		regs[j]=REG_VAR;      /* そのレジスタを使うことを宣言し */
-		regv[j]=0;
-		regvar[reg_var++]=i;
-		return list3(REGISTER,j,(int)nptr); /* その場所を表す番号を返す */
-	    }
+    int i;
+    for(i=REG_ESI;i<REG_EBP;i++) {
+	if (! regs[i]) {    /* 使われていないなら */
+	    regs[i]=REG_VAR;      /* そのレジスタを使うことを宣言し */
+	    return list3(REGISTER,i,(int)nptr); /* その場所を表す番号を返す */
 	}
     }
-#endif
     return list3(LVAR,new_lvar(SIZE_OF_INT),0);
 }
 
@@ -741,82 +807,13 @@
     return list3(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT),0);
 }
 
-static void 
-use_register(int virt, int real, int move)
-{
-    int real_v;
-    char *move_op;
-    if (rname[virt]==real)
-	return;
-    real_v = virtual(real);
-    move_op = regs[real_v]?"\txchg %s,%s\n":"\tmovl %s,%s\n";
-    if (move || (regv[real_v])) {
-	printf(move_op,reg_name[rname[virt]],reg_name[real]);
-    } 
-    rname[real_v] = rname[virt];
-    rname[virt] = real; 
-}
-
-#if 0
-static void
-check_virtual()
-{
-    int real;
-    if (rname[REG_ESI]!=REG_ESI) {
-	real = rname[REG_ESI];
-	printf("\txchg %%esi,%s\n",reg_name[real]);
-	rname[real] = real;
-	rname[REG_ESI] = REG_ESI;
-    }
-    if (rname[REG_EDI]!=REG_EDI) {
-	real = rname[REG_EDI];
-	printf("\txchg %%edi,%s\n",reg_name[real]);
-	rname[real] = real;
-	rname[REG_EDI] = REG_EDI;
-    }
-}
-#endif
-
-#if 0
-static void 
-use_pointer(int virt, int move)
-{
-    int i;
-    if (rname[virt]>=POINTER_REG)
-	return;
-    for(i=POINTER_REG;i<MAX_REGISTER;i++) {
-	if (!regs[virtual(i)]) {
-	    use_register(virt,i,move);
-	    return;
-	}
-    }
-    /* we prefer EBX */
-    use_register(virt,REG_EBX,move);
-}
-#endif
-
-void 
-use_data_reg(int virt, int move)
-{
-    int i;
-    if (rname[virt]<MAX_DATA_REG)
-	return;
-    for(i=0;i<MAX_DATA_REG;i++) {
-	if (!regs[virtual(i)]) {
-	    use_register(virt,i,move);
-	    return;
-	}
-    }
-    /* we prefer EBX */
-    use_register(virt,REG_EBX,move);
-}
-
 
 int 
 emit_push()
 {
     int new_reg,old;
     new_reg = get_register();
+    // who free new_reg?
     if (new_reg==creg) error(-1);
     old = creg;
     if(new_reg<0) {                     /* もうレジスタがない */
@@ -827,8 +824,8 @@
 	/* creg is used soon, don't regv[creg]=0 */
     } else {
 	reg_stack[reg_sp++] = creg;     /* push するかわりにレジスタを使う */
-	creg = new_reg;
-	regv[creg]=1;
+	ireg = creg = new_reg;
+	regs[creg]=1;
     }
     return old;
 }
@@ -836,26 +833,19 @@
 int
 emit_pop(int type)
 {
-    int xreg;
-    if ((xreg=pop_register())==-1) {
-if (regv[dreg]) {
-    printf("### emit_pop dreg conflict\n");
-    error(-1);
-}
-	printf("\tpopl %s\n",register_name(dreg,0));
-	regv[dreg]=1;
-	stack_depth -= SIZE_OF_INT;
-	return dreg;
-    } else if (xreg<= -REG_LVAR_OFFSET) {
-	code_rlvar(xreg+REG_LVAR_OFFSET,dreg);
-	free_lvar(xreg+REG_LVAR_OFFSET);
-	regv[dreg]=1;
-	return dreg;
+    int xreg,reg;
+    xreg=pop_register();
+    if (xreg<= -REG_LVAR_OFFSET) {
+        reg = get_register();
+        code_rlvar(REG_LVAR_OFFSET+xreg,reg);
+        free_lvar(REG_LVAR_OFFSET+xreg);
+        xreg = reg;
     }
     return xreg;
 }
 
-int
+#if 0
+static int
 stack_top(int type)
 {
     int xreg;
@@ -876,7 +866,7 @@
     }
     return xreg;
 }
-
+#endif
 
 
 void 
@@ -894,7 +884,7 @@
     } else {
 	printf("\tmovl $%s,%s\n",((NMTBL*)caddr(e1))->nm,register_name(creg,0));
     }
-    regv[creg]=1;
+
 }
 
 
@@ -906,7 +896,7 @@
 		register_name(creg,0));
     } else
 	printf("\tmovl %s,%s\n",((NMTBL*)caddr(e1))->nm,register_name(creg,0));
-    regv[creg]=1;
+
 }
 
 static char *cload(int sign,int sz) { return sz==1?(sign?"movsbl":"movzbl"):sz==SIZE_OF_SHORT?(sign?"movswl":"movzwl"):"movl"; }
@@ -920,7 +910,7 @@
     } else
 	printf("\t%s %s,%s\n",cload(sign,sz),
 		((NMTBL*)caddr(e1))->nm,register_name(creg,0));
-    regv[creg]=1;
+
 }
 
 
@@ -928,7 +918,6 @@
 code_lvar(int e2,int creg) {
     use_int(creg);
     printf("\tlea %d(%%ebp),%s\n",lvar(e2),register_name(creg,0));
-    regv[creg]=1;
 }
 
 
@@ -936,7 +925,6 @@
 code_register(int e2,int creg) {
     use_int(creg);
     printf("\tmovl %s,%s\n",register_name(e2,0),register_name(creg,0));
-    regv[creg]=1;
 }
 
 
@@ -944,7 +932,6 @@
 code_rlvar(int e2,int reg) {
     use_int(reg);
     printf("\tmovl %d(%%ebp),%s\n",lvar(e2),register_name(reg,0));
-    regv[creg]=1;
 }
 
 extern void
@@ -987,7 +974,7 @@
 code_crlvar(int e2,int reg,int sign,int sz) {
     use_int(reg);
     printf("\t%s %d(%%ebp),%s\n",cload(sign,sz),lvar(e2),register_name(reg,0));
-    regv[creg]=1;
+
 }
 
 
@@ -995,21 +982,18 @@
 code_fname(NMTBL *n,int creg) {
     use_int(creg);
     printf("\tmovl $%s,%s\n",n->nm,register_name(creg,0));
-    regv[creg]=1;
 }
 
 void
 code_label_value(int label,int reg) {
     use_int(reg);
     printf("\tleal _%d,%s\n",label,register_name(reg,0));
-    regv[creg]=1;
 }
 
 void
 code_const(int e2,int creg) {
     use_int(creg);
     printf("\tmovl $%d,%s\n",e2,register_name(creg,0));
-    regv[creg]=1;
 }
 
 void
@@ -1029,7 +1013,7 @@
 void
 code_lnot(int creg) {
     char *xrn;
-    use_int(creg);
+
     use_data_reg(creg,1);
     xrn = register_name(creg,1);
     printf("\tcmpl $0,%s\n", register_name(creg,0));
@@ -1044,13 +1028,11 @@
 	use_int(reg);
 	printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0));
 	printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0));
-	regv[reg]=1;
 	return;
     } 
     g_expr(e2);
     xrn = register_name(creg,0);
     use_int(reg);
-    // use_data_reg(reg);
     printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn);
     printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0));
 }
@@ -1063,14 +1045,13 @@
 	use_int(reg);
 	printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0));
 	printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0));
-	regv[reg]=1;
+
 	return;
     } 
     g_expr(e2);
     emit_push();  
     xrn = register_name((e2=emit_pop(0)),0);
     use_int(reg);
-    // use_data_reg(reg);
     printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0));
     printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn);
     emit_pop_free(e2);
@@ -1082,7 +1063,6 @@
 code_return(int creg) {
     use_int(creg);
     printf("\tleal _%d,%s\n",retcont,register_name(creg,0));
-    regv[creg]=1;
 }
 
 
@@ -1090,7 +1070,6 @@
 code_environment(int creg) {
     use_int(creg);
     printf("\tmovl %%ebp,%s\n",register_name(creg,0));
-    regv[creg]=1;
 }
 
 static int rexpr_bool(int e1,int reg);
@@ -1115,7 +1094,6 @@
 	fwddef(e2);
 	printf("\tmovl $1,%s\n",xrn);
 	fwddef(e3);
-	regv[reg]=1;
     } else {
 	fwddef(e2);
     }
@@ -1231,29 +1209,35 @@
 void 
 emit_copy(int from,int  to,int length,int offset,int value,int det)
 {
-    /* length <0 means upward direction copy */
+    int dreg;
+    char *drn,*frn;
+    char *trn;
     use_int(from);
     use_int(to);
+    frn = register_name(from,0);
+    trn = register_name(to,0);
+
+    /* length <0 means upward direction copy */
     switch (length) {
-    case 0:	break;
+    case 0:     break;
     case 1: case -1:
-	printf("\tmovb %d(%s),%s\n",offset,
-	    register_name(from,0), reg_name_l[rname[dreg]] );
-	printf("\tmovb %s,%d(%s)\n",reg_name_l[rname[dreg]] ,offset,
-	    register_name(to,0));
-	break;
+	drn = register_name(dreg = get_data_register(),1);
+        printf("\tmovb %s,%d(%s)\n",drn,offset,frn);
+        printf("\tmovb %s,%d(%s)\n",drn,offset,trn);
+	free_register(dreg);
+        break;
     case 2: case -2:
-	printf("\tmovw %d(%s),%s\n",offset,
-	    register_name(from,0), reg_name_w[rname[dreg]] );
-	printf("\tmovw %s,%d(%s)\n",reg_name_w[rname[dreg]] ,offset,
-	    register_name(to,0));
-	break;
+	drn = register_name(dreg = get_data_register(),2);
+        printf("\tmovw %s,%d(%s)\n",drn,offset,frn);
+        printf("\tmovw %s,%d(%s)\n",drn,offset,trn);
+	free_register(dreg);
+        break;
     case 4: case -4:
-	printf("\tmovl %d(%s),%s\n",offset,
-	    register_name(from,0), register_name(dreg,0));
-	printf("\tmovl %s,%d(%s)\n",register_name(dreg,0), offset,
-	    register_name(to,0));
-	break;
+	drn = register_name(dreg = get_register(),0);
+        printf("\tmovl %s,%d(%s)\n",drn,offset,frn);
+        printf("\tmovl %s,%d(%s)\n",drn,offset,trn);
+	free_register(dreg);
+        break;
     default:
         if (length <0) {
             if (length > -MAX_COPY_LEN) {
@@ -1274,12 +1258,13 @@
                 emit_copy(from,to,length,offset,0,det);
             break;
         }
+	// should be parallel_rassign....
+
 	printf("\tpushl %%esi\n");
 	printf("\tpushl %%edi\n");
 	printf("\tpushl %%ecx\n");
 	printf("\tpushl %s\n",register_name(from,0));
 	printf("\tpushl %s\n",register_name(to,0));
-	printf("\tpushl %s\n",register_name(dreg,0));
 	printf("\tpopl %%ecx\n");
 	printf("\tpopl %%edi\n");
 	printf("\tpopl %%esi\n");
@@ -1314,26 +1299,21 @@
     /* this code is necessary for the value of assignment or function call */
     /* otherwise we don't need this */
 	if(creg!=to) {
-	    if (to==dreg) 
-		printf("\tmovl %s,%s\n",register_name(to,0),register_name(creg,0));
-	    else {
-		free_register(creg); creg=to;
-	    }
+	    free_register(creg); creg=to;
 	}
     }
-    regv[from]=regv[to]=regv[dreg]=0;
-    regv[creg]=1;
 }
 
 static int
 push_struct(int e4,int t) 
 {
-    int length,xreg,save,lreg,count;
+    int length,count;
     g_expr(e4);
     length=size(t); 
     if(length%SIZE_OF_INT) {
 	length += SIZE_OF_INT - (length%SIZE_OF_INT);
     }
+    // try small amount copy
     for(count=0;length<MAX_COPY_LEN;count++,length-=SIZE_OF_INT) {
 	if (length==0) return count;
 	else {
@@ -1341,32 +1321,11 @@
 		length-SIZE_OF_INT,register_name(creg,0));
 	}
     }
+    // alignment may remain
     printf("\tsubl $%d,%%esp\n",length);
-    if (register_full()) {
-	save = 1;
-	for(lreg=0;lreg==creg||lreg==dreg;lreg++);
-	printf("\tpushl %s\n",register_name(lreg,0));
-	xreg = lreg; regv[xreg]=0;
-    } else {
-	save=0;
-	xreg = get_register();
-    }
-    if (save) 
-	printf("\tlea %d(%%esp),%s\n",SIZE_OF_INT,register_name(xreg,0));
-    else
-	printf("\tmovl %%esp,%s\n",register_name(xreg,0));
-    regv[xreg]=1;
     /* downward direction copy */
-    emit_copy(creg,xreg,length,0,0,1);
+    emit_copy(creg,REG_ESP,length,0,0,1);
     /* we have value in creg, it may be changed */
-    if (save) {
-	if(creg==xreg) {
-	    creg = get_register();   /* creg is freed in emit_copy */
-	}
-	printf("\tpopl %s\n",register_name(xreg,0));
-	regv[xreg]=1;
-    } else
-	free_register(xreg);
     stack_depth += length*SIZE_OF_INT;
     return length/SIZE_OF_INT;
 }
@@ -1376,7 +1335,6 @@
 {
     int e2,e3,e4,nargs,t,ret_type;
     NMTBL *n=0;
-    int save,saved;
     int stack_depth_save = stack_depth;
 
     ret_type = cadr(cadddr(e1));
@@ -1388,15 +1346,6 @@
     code_save_fstacks();
 #endif
 
-    if (free_register_count(0)<1) {
-        for(save = 0;save==dreg||save==creg;save++);
-	printf("\tpushl %s\n",register_name(save,0));
-        saved = 1;
-    } else {
-        save = get_register();
-        saved = 0;
-    }
-    regv[save]=0;
     e2 = cadr(e1);
     nargs = 0;
     for (e3 = caddr(e1); e3; e3 = cadr(e3)) {	
@@ -1431,14 +1380,12 @@
 	    g_expr(e4);
 	    printf("\tleal\t-8(%%esp),%%esp\n\tfstpl\t(%%esp)\n");
 	    nargs += SIZE_OF_DOUBLE/SIZE_OF_INT;
-	    fregv[freg]=0;
 	    stack_depth += SIZE_OF_DOUBLE;
 	    continue;
 	} else if (t==FLOAT) {
 	    g_expr(e4);
 	    printf("\tleal\t-4(%%esp),%%esp\n\tfstps\t(%%esp)\n");
 	    nargs += SIZE_OF_FLOAT/SIZE_OF_INT;
-	    fregv[freg]=0;
 	    stack_depth += SIZE_OF_FLOAT;
 	    continue;
 	} else if (car(t)==STRUCT||car(t)==UNION) {
@@ -1451,45 +1398,27 @@
     }
     if (car(e2) == FNAME) {	
 	n=(NMTBL *)cadr(e2);
-	regv[creg]=0;
 	use_register(creg,REG_EAX,0);  /* will be destroyed */
     } else {	
 	g_expr(e2);
-	regv[creg]=1;
 	use_register(creg,REG_EAX,1);  /* will be destroyed */
     }
 
-    /* we don't have to save creg nor dreg */
-    regs[creg]=0; regs[dreg]=0;
-    regv[dreg]= regv[save]= 0;
-    use_register(dreg,REG_EBX,0);  /* will be destroyed */
-    use_register(save,REG_ECX,0);  /* will be destroyed */
-    regs[creg]=1; regs[dreg]=1;
-
     if (car(e2) == FNAME) {	
 	printf("\tcall\t%s\n",n->nm);
     } else {
 	printf("\tcall\t*%s\n",register_name(creg,0));
     }
     if (nargs) printf("\taddl $%d,%%esp\n",SIZE_OF_INT*nargs);
-    if (saved) {
-	printf("\tpopl %s\n",register_name(save,0));
-    } else {
-        free_register(save);
-    }
-    regv[save]=0;
     if (ret_type==DOUBLE||ret_type==FLOAT) {
     } else if (ret_type==LONGLONG||ret_type==ULONGLONG) {
 	use_longlong0(USE_CREG);
-	regv[creg]=1;
     } else if (ret_type==VOID) {
-	regv[freg]=0; regv[creg]=0;
     } else {
 	if (!is_int_reg(creg)) {
-	    lreg=0; creg=virtual(REG_EAX);
+	    lreg=0; creg=REG_EAX;
 	}
 	use_register(creg,REG_EAX,0);
-	fregv[freg]=0; regv[creg]=1;
     }
     stack_depth = stack_depth_save;
     return ret_type;
@@ -1504,7 +1433,7 @@
     g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15))); 
     use_int(reg);
     if (stack_depth>0) {
-	edx = edx_setup(-1);
+
 	crn = register_name(reg,0);
 	drn = register_name(edx,0);
 	printf("\tmovl %%esp,%s\n",drn);
@@ -1512,7 +1441,7 @@
 	printf("\tmovl %%esp,%s\n",crn);
 	emit_copy(edx,creg,stack_depth,0,1,1);
 	printf("\taddl $%d,%s\n",stack_depth,register_name(creg,0));
-	edx_cleanup();
+
     } else {
 	crn = register_name(reg,0);
 	printf("\tsubl %s,%%esp\n",crn);
@@ -1529,7 +1458,7 @@
 int
 code_frame_pointer_register()
 {
-    return list2(REGISTER,virtual(REG_fp));
+    return list2(REGISTER,REG_fp);
 }
 
 void
@@ -1580,7 +1509,7 @@
 {
     char *crn = register_name(creg,0);
     use_longlong(reg);
-    if((reg==REG_L&&rname[creg]==REG_ESI)||(rname[creg]==REG_EAX)) {
+    if((reg==REG_L&&creg==REG_ESI)||(creg==REG_EAX)) {
 	printf("\tmovl %d(%s),%s\n",offset+SIZE_OF_INT,crn,l_edx(reg));
 	printf("\tmovl %d(%s),%s\n",offset,crn,l_eax(reg));
     } else {
@@ -1594,7 +1523,7 @@
 {
     int reg0;
     g_expr(e1);
-    regv[reg0=creg]=1;
+    reg0=creg;
     use_longlong(reg);
     lload(reg0,offset,reg);
     return LONGLONG;
@@ -1609,8 +1538,8 @@
 
 void
 code_assign_gvar(int e2,int creg,int byte) {
-    use_int(creg);
-    if (byte) use_data_reg(creg,1);
+    if (byte) { use_data_reg(creg,1); 
+    } else { use_int(creg); }
     if (cadr(e2)) 
 	printf("\t%s %s,%s+%d\n",move(byte),register_name(creg,byte),((NMTBL*)caddr(e2))->nm,cadr(e2));
     else
@@ -1619,8 +1548,8 @@
 
 void
 code_assign_lvar(int e2,int creg,int byte) {
-    use_int(creg);
-    if (byte) use_data_reg(creg,1);
+    if (byte) { use_data_reg(creg,1); 
+    } else { use_int(creg); }
     printf("\t%s %s,%d(%%ebp)\n",move(byte),register_name(creg,byte),lvar(e2));
 }
 
@@ -1634,10 +1563,9 @@
 void
 code_assign(int e2,int byte,int creg) {
     use_int(e2);
-    use_int(creg);
-    if (byte) use_data_reg(creg,1);
+    if (byte) { use_data_reg(creg,1); 
+    } else { use_int(creg); }
     printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte),register_name(e2,0));
-    regv[creg]=1;
 }
 
 void
@@ -1646,64 +1574,79 @@
     int xreg = creg;
     creg = reg = e2;
     tosop(op,reg,xreg);
-    creg = xreg;
-    // printf("\tmovl %s,%s\n",register_name(reg,0),register_name(creg,0));
-    regs[creg]=regv[creg]=1;
+    set_ireg(xreg,0);
 }
 
-
 void
-code_assop(int op,int reg,int byte,int sign) {
-    char *xrn;
+code_assop(int op,int creg,int byte,int sign) {
     int xreg;
-    int edx = edx_setup(-1);
+    //  (*creg) op = pop()
+
+    use_int(creg);
+    xreg = emit_pop(0);       /* pop e3 value */
+    emit_push();
+    emit_pop_free(xreg);
+    ld_indexx(byte,0,creg,ireg,sign);
+    tosop(op,ireg,xreg);
+    if (byte) {
+	use_data_reg(ireg,1);
+    }
+    xreg = emit_pop(0);       /* pop e3 value */
+    printf("\t%s %s,(%s)\n",move(byte),register_name(ireg,byte),register_name(xreg,0));
+    emit_pop_free(xreg);
+}
+
+#if 0
+    int xreg;
+    int edx;
     use_int(reg);
-    xrn = register_name(xreg = emit_pop(0),0);       /* pop e3 value */
-    regv[xreg]=regs[xreg]=1;
+    xreg = emit_pop(0);       /* pop e3 value */
+    regs[xreg]=1;
+    edx = get_register();
     printf("\tmovl %s,%s  # assop \n",register_name(reg,0),register_name(edx,0));
-    regv[edx]=1;
     ld_indexx(byte,0,edx,reg,sign);
     tosop(op,reg,xreg);
     printf("\t%s %s,(%s)\n",move(byte),register_name(reg,byte),register_name(edx,0));
-    edx_cleanup();
+
     emit_pop_free(xreg);
-    regv[creg]=1;
+    free_register(edx);
 }
+#endif
 
 
 void
 tosop(int op,int reg,int oreg)
 {
-    int dx;
+    int ox=0;
     char *orn,*crn;
-    use_int(reg);
+    // creg = creg op oreg
+
+    use_int(creg);
+
+    if(oreg==-1) {
+        error(-1);
+    } else if (oreg<= -REG_LVAR_OFFSET) {
+        ox = get_register(); if (ox<0) error(-1);
+        code_rlvar(oreg+REG_LVAR_OFFSET,ox);
+        oreg = ox;
+    }
 
     switch(op) {
     case LSHIFT:
     case ULSHIFT:
 	shift("sall",oreg,reg);
-	regv[creg]=1;
+        if(ox) free_register(ox);
 	return;
     case RSHIFT:
 	shift("sarl",oreg,reg);
-	regv[creg]=1;
+        if(ox) free_register(ox);
 	return;
     case URSHIFT:
 	shift("shrl",oreg,reg);
-	regv[creg]=1;
+        if(ox) free_register(ox);
 	return;
     }
-    if(oreg==-1) {
-        printf("\tpopl %s\n",register_name(dreg,0));
-	oreg = dreg;
-	regv[dreg]=1;
-    } else if (oreg<= -REG_LVAR_OFFSET) {
-	code_rlvar(oreg+REG_LVAR_OFFSET,dreg);
-	free_lvar(oreg+REG_LVAR_OFFSET);
-	oreg = dreg;
-	regv[dreg]=1;
-    }
-    regv[oreg]=1; regs[oreg]=1;
+    // regs[oreg]=1;
     orn = register_name(oreg,0);
     crn = register_name(creg,0);
     switch(op) {
@@ -1729,35 +1672,35 @@
     case DIV:
     case UDIV:
 	use_register(creg,REG_EAX,1);
-	edx_setup(REG_EDX);
+	if (oreg==REG_EAX) oreg=creg;
+	else if (oreg==REG_EDX) {
+	    use_register(oreg,REG_ECX,1);
+	    oreg = REG_ECX;
+	}
 	orn = register_name(oreg,0);
 	if (op==DIV)
 	    printf("\tcltd\n\tidivl %s\n",orn);
 	else 
 	    printf("\txor %%edx,%%edx\n\tdivl %s\n",orn);
-	edx_cleanup();
+	set_ireg(REG_EAX,0);
 	break;
     case MOD:
     case UMOD:
 	use_register(creg,REG_EAX,1);
-	edx_setup(REG_EDX);
+	if (oreg==REG_EAX) oreg=creg;
+	else if (oreg==REG_EDX) {
+	    use_register(oreg,REG_ECX,1);
+	    oreg = REG_ECX;
+	}
 	orn = register_name(oreg,0);
 	if (op==MOD)
 	    printf("\tcltd\n\tidivl %s\n",orn);
 	else 
 	    printf("\txor %%edx,%%edx\n\tdivl %s\n",orn);
-        dx = virtual(REG_EDX);	
-	if (dx!=creg) {
-	    rname[dx]=rname[creg];
-	    rname[creg]=REG_EDX;
-	}
-	edx_cleanup();
+	set_ireg(REG_EDX,0);
 	break;
     }
-    if (oreg!=dreg&&oreg!=creg&&oreg>=0)
-	free_register(oreg);
-    else if (oreg==dreg) regv[dreg]=0;
-    regv[creg]=1;
+    if(ox) free_register(ox);
 }
 
 int
@@ -1777,7 +1720,7 @@
     use_int(reg);
     crn = register_name(reg,0);
     orn = cadr(orn);
-    datareg=(rname[reg]<MAX_DATA_REG);
+    datareg=is_data_reg(reg);
 
     switch(op) {
     case LSHIFT:
@@ -1832,37 +1775,7 @@
 }
 
 
-static int edx_stack=0;
-
-int
-edx_setup(int rreg)
-{
-    int edx_save;
-    /* make real EDX (or rreg) register empty */
-    if (free_register_count(0)<1) {
-        for(edx_save = 0;edx_save==dreg||edx_save==creg;edx_save++);
-	printf("\tpushl %s\n",register_name(edx_save,0));
-        edx_stack = list3(edx_save,edx_stack,0);
-    } else {
-        edx_save = get_register();
-        edx_stack = list3(edx_save,edx_stack,1);
-    }
-    regv[edx_save]=0;
-    if (rreg!=-1)
-	use_register(edx_save,rreg,0);
-    return edx_save;
-}
-
-
-void
-edx_cleanup()
-{
-    if (caddr(edx_stack)==0) {
-	printf("\tpopl %s\n",register_name(car(edx_stack),0));
-    } else
-	free_register(car(edx_stack));
-    edx_stack = cadr(edx_stack);
-}
+
 
 void
 shift(char *op, int reg,int creg)
@@ -1870,15 +1783,8 @@
     use_int(creg);
     if (reg>=0) {
 	use_register(reg,REG_ECX,1);
-    } else if (reg<= -REG_LVAR_OFFSET) {
-	use_register(dreg,REG_ECX,0);
-        code_rlvar(reg+REG_LVAR_OFFSET,dreg);
-        reg = dreg;
-        regv[dreg]=0;
     } else {
-	use_register(dreg,REG_ECX,0);
 	printf("\tpopl %%ecx\n");
-        regv[dreg]=0;
     }
     printf("\t%s %%cl,%s\n",op,register_name(creg,0));
 }
@@ -1886,7 +1792,11 @@
 void
 ld_indexx(int byte, int n, int xreg,int reg,int sign)
 {	
-    use_int(reg);
+    if (byte) {
+	use_data_reg(reg,1);
+    } else {
+	use_int(reg);
+    }
     if (n) 
 	    printf("\t%s %d(%s),%s\n",cload(sign,byte),n,
 		register_name(xreg,0),register_name(reg,0));
@@ -1898,7 +1808,7 @@
 int
 code_csvalue()
 {
-    return glist2(REGISTER,rname[creg]); /* for switch value */
+    return glist2(REGISTER,creg); /* for switch value */
 }
 
 void
@@ -1950,8 +1860,7 @@
     char *s;
     if (!(s=code_cond(car(e1),1))) return 0;
     g_expr(list3(CMP,cadr(e1),caddr(e1)));
-    use_int(reg);
-    use_data_reg(reg,0);
+    use_data_reg(reg,1);
     printf("\tset%s\t%s\n",s,register_name(reg,1));
     printf("\tmovzbl %s,%s\n",register_name(reg,1),register_name(reg,0));
     return 1;
@@ -1979,9 +1888,7 @@
     /* align? */
     /*
       this is not allowed because of ? operator
-    regv[creg]=regv[dreg]=0; 
     use_register(creg,REG_EAX,0);
-    use_register(dreg,REG_EBX,0);
      */
 }
 
@@ -2082,10 +1989,9 @@
             car(cadr(fnptr->ty))==STRUCT ||
             car(cadr(fnptr->ty))==UNION)) {
             sz = size(cadr(fnptr->ty));
-            printf("\tlea %d(%%ebp),%s\n",-sz,register_name(dreg,0));
             printf("\tmovl %d(%%ebp),%s\n",disp-SIZE_OF_INT,
 		register_name(creg,0));
-            emit_copy(dreg,creg,sz,0,1,1);
+            // emit_copy(dreg,creg,sz,0,1,1);
         } else if (cadr(fnptr->ty)!=VOID) {
 	    use_register(creg,REG_EAX,0);
 	    printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0));
@@ -2116,7 +2022,7 @@
 	return reg;
     } else {
 	use_int(reg);
-	return rname[reg];
+	return reg;
     }
 }
 
@@ -2131,11 +2037,15 @@
 
 void
 code_set_return_register(int mode) {
-    if (fnptr->ty==DOUBLE||fnptr->ty==FLOAT) {
-    } else if (fnptr->ty==LONGLONG||fnptr->ty==ULONGLONG) {
-	use_longlong0(USE_CREG);
+    if (cadr(fnptr->ty)==FLOAT) {
+        // set_freg(RET_FREGISTER,mode);
+    } else if (cadr(fnptr->ty)==DOUBLE) {
+        // set_dreg(RET_DREGISTER,mode);
+    } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) {
+        set_lreg(RET_LREGISTER,mode);
+    } else if (cadr(fnptr->ty)==VOID) {
     } else {
-	use_register(creg,REG_EAX,mode);
+        set_ireg(RET_REGISTER,mode);
     }
 }
 
@@ -2707,7 +2617,7 @@
     if (mode==COND_BRANCH) {
 	printf("\tj%s\t_%d\n",s,l1);
     } else {
-	use_int(reg); use_data_reg(reg,0);
+	use_data_reg(reg,0);
 	printf("\tset%s\t%s\n",s,register_name(reg,1));
 	printf("\tmovzbl\t%s,%s\n",
 	    register_name(reg,1),register_name(reg,0));
@@ -2788,22 +2698,31 @@
 void
 code_save_stacks()
 {
+    /* registers stacks are saved in local variable */
+    int i,reg;
+    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);
+        }
+    }
+}
+
+static void
+code_clear_stack_reg(int reg1)
+{
+    /* specified registers stacks are saved in local variable */
     /* temporal registers or stacks in fpu are saved in local variable */
-    int xreg,sp,screg;
-    sp=reg_sp;
-    while(sp-->0) {
-	if ((xreg=reg_stack[sp])>=0) {
-	    screg=creg;
-	    if(creg!=xreg) {
-		if (xreg!=dreg) free_register(xreg); 
-		creg = xreg;
-	    }
-	    code_assign_lvar(
-		(reg_stack[sp]=new_lvar(SIZE_OF_INT)),creg,0); 
-	    reg_stack[sp]= reg_stack[sp]-REG_LVAR_OFFSET;
-	    regv[xreg]=0;
-	    creg=screg;
-	}
+    int i,reg;
+    for(i=0;i<reg_sp;i++) {
+        if ((reg=reg_stack[i])>=0 && reg==reg1) {
+            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);
+        }
     }
 }
 
@@ -3200,11 +3119,13 @@
 	if (il==0) return;
 	else if (il==32) {
 	    code_register(regv_h(reg),regv_l(reg));
+	    creg = ireg = REG_EAX;
 	    code_i2ll(reg);
 	    return;
 	} else if (il>32) {
 	    code_register(regv_h(reg),regv_l(reg));
 	    printf("\tsarl $%d,%s\n",(int)il-32,l_eax(reg));
+	    creg = ireg = REG_EAX;
 	    code_i2ll(reg);
 	    return;
 	}
@@ -3220,6 +3141,7 @@
 	    code_const(0,regv_h(reg));
 	    return;
 	} else if (il>32) {
+	    if (il>64) error(-1);
 	    code_register(regv_h(reg),regv_l(reg));
 	    printf("\tsarl $%d,%s\n",(int)il-32,l_eax(reg));
 	    code_const(0,regv_h(reg));
@@ -3258,7 +3180,6 @@
 
     use_longlong(reg0);
     use_register(creg0,REG_EAX,1);
-    regv[creg0]=0;
 
     printf("\tcltd\n");
     check_lreg(reg);
@@ -3277,7 +3198,6 @@
 
     use_longlong(reg0);
     use_register(creg0,REG_EAX,1);
-    regv[creg0]=0;
 
     use_longlong(reg0);
     printf("\txorl %%edx,%%edx\n");
@@ -3293,7 +3213,7 @@
 void code_ll2i(int reg)
 {
     use_int(reg);
-    if (virtual(REG_EAX)!=reg)
+    if (REG_EAX!=reg)
 	printf("\tmovl %%eax,%s\n",register_name(creg,0));
 }
 
@@ -3461,7 +3381,7 @@
 	return;
     }
     use_register(creg,REG_EAX,1);
-    edx_setup(-1);
+    
     switch(delta) {
     case 2:
 	printf("\tmovl\t$1,%%edx\n");
@@ -3480,7 +3400,7 @@
 	printf("\tjne\t_%d\n",dlabel);
 	printf("\tjmp\t*_%d(,%%eax,4)\n",l); break;
     }
-    edx_cleanup();
+    
 }
 
 void
@@ -3873,7 +3793,7 @@
     a = ~mask|c;
     if (a!=-1) {
 	/* do conjunction  */
-	if (rname[reg]<MAX_DATA_REG && ((a& ~0xffff)==~0xffff)) {
+	if (reg<MAX_DATA_REG && ((a& ~0xffff)==~0xffff)) {
 	    if ((a& ~0xff)==~0xff)
 		printf("\tandb $%d,%s\n",a&0xff,register_name(reg,1));
 	    else
@@ -3885,7 +3805,7 @@
     c = mask&c;
     if (c!=0) {
 	/* do disjunction  */
-	if (rname[reg]<MAX_DATA_REG && (!(c& ~0xffff))) {
+	if (reg<MAX_DATA_REG && (!(c& ~0xffff))) {
 	    if (!(c& ~0xff))
 		printf("\torb $%d,%s\n",c&0xff,register_name(reg,1));
 	    else
--- a/mc-code-mips.c	Mon Jan 16 00:52:56 2006 +0900
+++ b/mc-code-mips.c	Tue Jan 17 23:38:57 2006 +0900
@@ -1574,6 +1574,7 @@
     default:
         if (length <0) {
             if (length > -MAX_COPY_LEN) {
+		free_register(dreg); dreg = 0;
                 for(;length<=-4;length+=4,offset-=4)
                     emit_copy(from,to,-4,offset-4,0,det);
                 for(;length<=-2;length+=2,offset-=2)
@@ -1583,6 +1584,7 @@
                 break;
             }
 	} else if (length <=MAX_COPY_LEN) {
+	    free_register(dreg); dreg = 0;
 	    for(;length>=4;length-=4,offset+=4)
 		emit_copy(from,to,4,offset,0,det);
 	    for(;length>=2;length-=2,offset+=2)
@@ -1619,7 +1621,7 @@
 	    // set_ireg(to,1);
 	}
     }
-    free_register(dreg);
+    if (dreg) free_register(dreg);
 }
 
 int
@@ -2486,13 +2488,13 @@
 
 void
 code_assop(int op,int creg, int byte,int sign) {
-    char *xrn,*crn,*drn;
+    char *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 */
+    xreg = emit_pop(0);       /* pop e3 value */
 #if 1
     set_ireg(edx,0);
     ld_indexx(byte,0,creg,ireg,sign);
--- a/mc-code-powerpc.c	Mon Jan 16 00:52:56 2006 +0900
+++ b/mc-code-powerpc.c	Tue Jan 17 23:38:57 2006 +0900
@@ -1587,6 +1587,7 @@
     default:
 	if (length <0) {
 	    if (length >= -MAX_COPY_LEN) {
+		free_register(dreg); dreg = 0;
 		for(;length<=-4;length+=4,offset-=4)
 		    emit_copy(from,to,-4,offset-4,0,det);
 		for(;length<=-2;length+=2,offset-=2)
@@ -1596,6 +1597,7 @@
 		break;
 	    }
 	} else if (length <=MAX_COPY_LEN) {
+	    free_register(dreg); dreg = 0;
 	    for(;length>=4;length-=4,offset+=4)
 		emit_copy(from,to,4,offset,0,det);
 	    for(;length>=2;length-=2,offset+=2)
@@ -1631,7 +1633,7 @@
 	    // set_ireg(to,1);
 	}
     }
-    free_register(dreg);
+    if (dreg) free_register(dreg);
 }
 
 int