changeset 269:d9f4026de4e3

MIPS continue...
author kono
date Wed, 19 May 2004 09:56:53 +0900
parents 3a368fc37559
children 0c6bf0e3e475
files .gdbinit mc-code-mips.c mc-code-powerpc.c mc-codegen.c
diffstat 4 files changed, 243 insertions(+), 213 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Tue May 18 14:20:46 2004 +0900
+++ b/.gdbinit	Wed May 19 09:56:53 2004 +0900
@@ -1,7 +1,7 @@
 tb main
-run  -s -ob00.s test/basic.c
+# run  -s test/basic.c
 # run  -s -ob00.s mc-parse.c
-# run -s test/code-gen-all.c
+run -s test/code-gen-all.c
 define regs 
 printf "pc =%08x lr =%08x r0 =%08x r1 =%08x r3= %08x r4= %08x\n",$pc,$lr,$r0,$r1,$r3,$r4
 printf "r10=%08x r11=%08x r12=%08x r13=%08x r14=%08x r15=%08x\n",$r10,$r11,$r12,$r13,$r14,$r15
--- a/mc-code-mips.c	Tue May 18 14:20:46 2004 +0900
+++ b/mc-code-mips.c	Wed May 19 09:56:53 2004 +0900
@@ -77,8 +77,8 @@
 
 #define REG_fp   1
 #define REG_sp   30
-#define REG_VAR_BASE 29
-#define REG_VAR_MIN  18
+#define REG_VAR_BASE 23
+#define REG_VAR_MIN  16
 #define MIN_TMP_REG 4
 #define MAX_TMP_REG 11
 
@@ -221,7 +221,7 @@
     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);
+	// else if (freg!=i) free_register(i);
 	i = freg;
     }
     if (!regs[i]) regs[i]=USING_REG;
@@ -288,15 +288,6 @@
      $f14,$f12 input register
      $f20-$f31 saved register variable
 
- function call stack frame
-                   <----------r1_offset------------------------------>
-                                      <------------lvar_offset------->
- r+  +------------+---+---------------+----------+--------------+----+    -
-      callee arg   xx   register save   local      caller arg     xx
-                       ($fp) reg_save   disp       max_func_args*SIZE_OF_INT
-        lvar>0                         lvar<0       lvar>0x1000 0000
-                      prev $sp=$fp                                   $sp=$fp
- 
 code segment stack frame
 
                  * gotoを呼び出した関数のr1 ! r1(goto前のr1)
@@ -309,16 +300,19 @@
                  prev $sp=$fp                 $fp                        $sp
 
  */
-static int arg_offset = 0,arg_offset1 = 0,disp_offset = 0;
+#define arg_offset 8
+#define arg_offset1 0
+#define disp_offset  8
 
 #define func_disp_offset 8
-#define r1_offset func_disp_offset
-int code_disp_offset = 0; int jump_offset = 0;
-#define CODE_LVAR l+code_disp_offset
-#define CODE_CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1
-#define FUNC_LVAR l+disp_offset
-#define CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1
-#define CALLEE_ARG l+arg_offset
+#define code_disp_offset 0
+#define jump_offset 0
+
+#define CODE_LVAR(l) ((l)+code_disp_offset)
+#define CODE_CALLER_ARG(l) ((l)+arg_offset1)
+#define FUNC_LVAR(l) (l+disp_offset)
+#define CALLER_ARG(l) ((l)+arg_offset1)
+#define CALLEE_ARG(l) ((l)+arg_offset)
 
 #if 0
 void
@@ -336,18 +330,18 @@
     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);
+printf("# offset calln\t%d %d\n",CALLER_ARG(l),max_func_args*SIZE_OF_INT);
     l = disp;
-printf("# offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp);
+printf("# offset lvarn\t%d %d\n",FUNC_LVAR(l)+lvar_offsetv,disp);
     l = 0;
-printf("# offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv);
+printf("# offset lvar0\t%d\n",FUNC_LVAR(l)+lvar_offsetv);
     l = -reg_save;
-printf("# offset regs\t%d\n",FUNC_LVAR+lvar_offsetv);
+printf("# offset regs\t%d\n",FUNC_LVAR(l)+lvar_offsetv);
 printf("# offset r1off\t%d\n",r1_offsetv);
     l = 0;
-printf("# offset carg0\t%d\n",CALLEE_ARG+r1_offsetv);
+printf("# offset carg0\t%d\n",CALLEE_ARG(l)+r1_offsetv);
     l = my_func_args;
-printf("# offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args);
+printf("# offset cargn\t%d %d\n",CALLEE_ARG(l)+r1_offsetv,my_func_args);
 #endif
 }
 #endif
@@ -357,15 +351,15 @@
 {
     if (fnptr->sc==CODE) {
         if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-            printf("%d($fp)\n",CODE_CALLER_ARG);
+            printf("%d($fp)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
         } else
-            printf("%d($fp)\n",CODE_LVAR);
+            printf("%d($fp)\n",CODE_LVAR(l-ARG_LVAR_OFFSET));
     } else if (l<0) {  /* local variable */
-        printf("%d+$L_%d($fp)\n",FUNC_LVAR,lvar_offset_label);
+        printf("%d+$L_%d($fp)\n",FUNC_LVAR(l),lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-        printf("%d($fp)\n",CALLER_ARG);
+        printf("%d($fp)\n",CALLER_ARG(l-ARG_LVAR_OFFSET));
     } else { /* callee's arguments */
-        printf("%d+$L_%d($fp)\n",CALLEE_ARG,r1_offset_label);
+        printf("%d+$L_%d($fp)\n",CALLEE_ARG(l),r1_offset_label);
     }
 }
 
@@ -374,15 +368,19 @@
 {
     if (fnptr->sc==CODE) {
         if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-            printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_CALLER_ARG);
+            printf("\taddu\t%s,$fp,%d\n",
+		register_name(creg),CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
         } else
-            printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR);
+            printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR(l));
     } else if (l<0) {  /* local variable */
-        printf("\taddu\t%s,$fp,%d+$L_%d\n",register_name(creg),FUNC_LVAR,lvar_offset_label);
+        printf("\taddu\t%s,$fp,%d+$L_%d\n",register_name(creg),
+		FUNC_LVAR(l),lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-        printf("\taddu\t%s,$fp,%d\n",register_name(creg),CALLER_ARG);
+        printf("\taddu\t%s,$fp,%d\n",
+		register_name(creg),CALLER_ARG(l-ARG_LVAR_OFFSET));
     } else { /* callee's arguments */
-        printf("\taddu\t%s,$fp,%d+$L_%d\n",register_name(creg),CALLEE_ARG,r1_offset_label);
+        printf("\taddu\t%s,$fp,%d+$L_%d\n",
+		register_name(creg),CALLEE_ARG(l),r1_offset_label);
     }
 }
 
@@ -528,7 +526,7 @@
         reg =REG_VAR_BASE-i;
         if (! regs[reg]) {       /* 使われていないなら */
             regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
-	    if (i>max_reg_var) max_reg_var=i;
+	    if (i+1>max_reg_var) max_reg_var=i+1;
 	    return reg;   /* その場所を表す番号を返す */
         }
     }
@@ -580,7 +578,7 @@
         reg =FREG_VAR_BASE-i+FREG_OFFSET;
         if (! regs[reg]) {       /* 使われていないなら */
             regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
-	    if (i>max_freg_var) max_freg_var=i;
+	    if (i+1>max_freg_var) max_freg_var=i+1;
 	    return reg;   /* その場所を表す番号を返す */
         }
     }
@@ -646,13 +644,13 @@
 	    if (! regs[REG_VAR_BASE-i]) {       /* 使われていないなら */
 		/* そのレジスタを使うことを宣言し */
 		regs[REG_VAR_BASE-i]=USING_REG; 
-		if (i>max_reg_var) max_reg_var=i;
+		if (i+1>max_reg_var) max_reg_var=i+1;
 		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;
+			if (j+1>max_reg_var) max_reg_var=j+1;
 			/* その場所を表す番号を返す */
 			regs[ll]=USING_REG;
 			regv_l(ll) = REG_VAR_BASE-j;
@@ -898,7 +896,7 @@
 	if (! regs[j]) {       /* 使われていないなら */
 	    /* そのレジスタを使うことを宣言し */
 	    regs[j]=USING_REG; 
-	    if (i>=max_reg_var) max_reg_var=i+1;
+	    if (i+1>=max_reg_var) max_reg_var=i+1;
 	    /* その場所を表す番号を返す */
 	    return list3(REGISTER,j,(int)n); 
 	}
@@ -925,7 +923,7 @@
 	j = freg_var_num(i);
         if (! regs[j]) {       /* 使われていないなら */
             regs[j]=USING_REG; /*そのレジスタを使うことを宣言し*/
-	    if (i>=max_freg_var) max_freg_var=i+1;
+	    if (i+1>max_freg_var) max_freg_var=i+1;
 	    /* その場所を表す番号を返す */
 	    return list3(FREGISTER,j,(int)n); 
         }
@@ -1682,8 +1680,13 @@
 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)));
+    return (e3==FUNCTION||e3==CONV||e3==RSTRUCT||e3==STASS||
+	((e3/100==LOP/100)&&(e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD||
+		e3==LLSHIFT||e3==LULSHIFT||e3==LRSHIFT||e3==LURSHIFT))||
+	((e3/100==DOP/100)&&(e3==DDIV||e3==DADD||e3==DSUB||e3==DMUL||
+            e3== DPOSTINC || e3==DPREINC || e3==DASSOP ||
+            e3== DOP+LT || e3== DOP+LE || e3== DOP+GT ||
+            e3== DOP+GE || e3== DOP+EQ || e3== DOP+NEQ)));
 }
 
 int
@@ -1965,6 +1968,7 @@
 	if (complex_) {
 	    arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg);
 	    compute_complex_arg(complex_,reg_arg_list,arg);
+	    car(complex_) = 0; // done.
 	}
     }
 
@@ -2082,10 +2086,9 @@
 
 
 void
-code_fix_frame_pointer(int disp_offset) {
-    int l = 0;
+code_fix_frame_pointer(int offset) {
     printf("\tla $fp,");
-    printf("%d+$L_%d($sp)\n",FUNC_LVAR,lvar_offset_label);
+    printf("%d+$L_%d($sp)\n",FUNC_LVAR(0),lvar_offset_label);
 }
 
 void
@@ -2172,24 +2175,30 @@
 }
 #endif
 
-#if LONGLONG_CODE
-int
-code_lrindirect(int e1, int reg, int offset, int us)
+static void
+lload(int creg,int reg,int offset) 
 {
-    char *crn;
-    int creg0;
-
-    g_expr(e1);
-    if (!is_int_reg(creg)) error(-1);
-    crn=register_name(creg0=creg);
-    use_longlong(reg);
-    if (creg0!=regv_h(reg)) {
+    char *crn=register_name(creg);
+    if (creg!=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);
     }
+}
+
+#if LONGLONG_CODE
+int
+code_lrindirect(int e1, int reg, int offset, int us)
+{
+    int creg0;
+
+    g_expr(e1);
+    if (!is_int_reg(creg)) error(-1);
+    creg0=creg;
+    use_longlong(reg);
+    lload(creg0,reg,offset);
     return us?ULONGLONG:LONGLONG;
 }
 #endif
@@ -2534,8 +2543,10 @@
     /* used regsister var */
     int i;
     int offset=0;
+    int min = reg_var_num(max_reg_var);
+    int max = reg_var_num(0);
     for(i=0;i<32;i++) {
-	if (i==28||i==31||(reg_var_num(0)>i&&i>reg_var_num(max_reg_var))) {
+	if (i==28||i==31||(max>i&&i>=min)) {
 	    offset++;
 	}
     }
@@ -2549,8 +2560,10 @@
     /* used regsister var */
     int i;
     unsigned int mask=0;
+    int min = reg_var_num(max_reg_var);
+    int max = reg_var_num(0);
     for(i=0;i<32;i++) {
-	if (i==28||i==31||(reg_var_num(0)>i&&i>reg_var_num(max_reg_var))) {
+	if (i==28||i==31||(max>i&&i>=min)) {
 	    mask |= (1<<i);
 	}
     }
@@ -2561,19 +2574,15 @@
 code_register_save(int reg_save,int freg_save,int disp)
 {
     int i;
-    for(i=0;i<32;i++) {
-	if (reg_var_num(0)>i&&i>reg_var_num(reg_save)) {
-	    printf("\tsw    %s,$L_%d+%d($sp)\n",register_name(i),
-		r1_offset_label,disp);
-	    disp -= SIZE_OF_INT;
-	}
+    for (i=reg_var_num(0);i>reg_var_num(reg_save);i--) {
+	printf("\tsw    %s,$L_%d-%d($sp)\n",register_name(i),
+	    r1_offset_label,-disp);
+	disp -= SIZE_OF_INT;
     }
-    for(i=0;i<32;i++) {
-	if (freg_var_num(0)>i&&i>freg_var_num(freg_save)) {
-	    printf("\ts.s    %s,$L_%d+%d($sp)\n",register_name(i),
-		r1_offset_label,disp);
-	    disp -= SIZE_OF_FLOAT;
-	}
+    for (i=freg_var_num(0);i>freg_var_num(freg_save);i--) {
+	printf("\ts.s    %s,$L_%d-%d($sp)\n",register_name(i),
+	    r1_offset_label,-disp);
+	disp -= SIZE_OF_FLOAT;
     }
     return disp;
 }
@@ -2582,19 +2591,15 @@
 code_register_restore(int reg_save,int freg_save,int disp)
 {
     int i;
-    for(i=0;i<32;i++) {
-	if (reg_var_num(0)>i&&i>reg_var_num(reg_save)) {
-	    printf("\tlw    %s,$L_%d+%d($sp)\n",register_name(i),
-		r1_offset_label,disp);
-	    disp -= SIZE_OF_INT;
-	}
+    for (i=reg_var_num(0);i>reg_var_num(reg_save);i--) {
+	printf("\tlw    %s,$L_%d-%d($sp)\n",register_name(i),
+	    r1_offset_label,-disp);
+	disp -= SIZE_OF_INT;
     }
-    for(i=0;i<32;i++) {
-	if (freg_var_num(0)>i&&i>freg_var_num(freg_save)) {
-	    printf("\tl.s    %s,$L_%d+%d($sp)\n",register_name(i),
-		r1_offset_label,disp);
-	    disp -= SIZE_OF_FLOAT;
-	}
+    for (i=freg_var_num(0);i>freg_var_num(freg_save);i--) {
+	printf("\tl.s    %s,$L_%d-%d($sp)\n",register_name(i),
+	    r1_offset_label,-disp);
+	disp -= SIZE_OF_FLOAT;
     }
     return disp;
 }
@@ -2604,8 +2609,10 @@
 {
     int i;
     int offset=0;
+    int min = freg_var_num(max_reg_var);
+    int max = freg_var_num(0);
     for(i=0;i<32;i++) {
-	if (freg_var_num(0)>i&&i>freg_var_num(max_reg_var)) {
+	if (i==28||i==31||(max>i&&i>=min)) {
 	    offset++;
 	}
     }
@@ -2618,9 +2625,10 @@
 {
     int i;
     unsigned int mask=0;
-    /* used fregsister var */
+    int min = freg_var_num(max_reg_var);
+    int max = freg_var_num(0);
     for(i=0;i<32;i++) {
-	if (freg_var_num(0)>i&&i>freg_var_num(max_reg_var)) {
+	if (i==28||i==31||(max>i&&i>=min)) {
 	    mask |= (1<<i);
 	}
     }
@@ -2702,9 +2710,9 @@
     printf("\t.cpload $25\n");
     printf("\t.set reorder\n");
     printf("\tsubu $sp,$sp,$L_%d\n",r1_offset_label);
-    printf("\tsw      $31,$L_%d+%d($sp)\n",r1_offset_label,r1_offset);
-    printf("\tsw      $fp,$L_%d+%d($sp)\n",r1_offset_label,r1_offset-SIZE_OF_INT);
     printf("\t.cprestore $L_%d\n",cprestore_label=fwdlabel());
+    printf("\tsw      $31,$L_%d-%d($sp)\n",r1_offset_label,arg_offset);
+    printf("\tsw      $fp,$L_%d-%d($sp)\n",r1_offset_label,arg_offset+SIZE_OF_INT);
     printf("\tj $L_%d\n",register_save_label=fwdlabel());
     register_save_return_label = backdef();
     printf("\tmove  $fp,$sp\n");
@@ -2762,21 +2770,30 @@
 	fwddef(retcont1);
     }
 
-
+/*
+                      <-------r1_offset------------------------------>
+                                      <------------lvar_offset------->
+ r+  +-----------+----+---------------+----------+--- ----------+----+    -
+       callee arg xxx  register save   local      caller arg     xxx
+                       ($fp) reg_save   disp          max_func_args*SIZE_OF_INT
+        lvar>0                         lvar<0          lvar>0x1000 0000
+                      prev $sp=$fp                                   $sp=$fp
+ */
+ 
     disp &= -SIZE_OF_INT;
     lvar_offsetv = round16(-disp) +
-	round16(max_func_args)+r1_offset;
-    r1_offsetv = lvar_offsetv +
+	round16((max_func_args<2?2:max_func_args)*SIZE_OF_INT);
+    r1_offsetv = lvar_offsetv + arg_offset + SIZE_OF_INT*2 +
 	max_reg_var*SIZE_OF_INT+max_freg_var*SIZE_OF_FLOAT+2*SIZE_OF_INT;
 	
     fprintf(asi,"$L_%d=%d\n",r1_offset_label,r1_offsetv);
     fprintf(asi,"$L_%d=%d\n",lvar_offset_label,lvar_offsetv);
 
     printf("\tmove    $sp,$fp\n");
-    printf("\tlw      $31,$L_%d+%d($sp)\n",r1_offset_label,r1_offset);
-    printf("\tlw      $fp,$L_%d+%d($sp)\n",r1_offset_label,r1_offset-SIZE_OF_INT);
+    printf("\tlw      $31,$L_%d-%d($sp)\n",r1_offset_label,arg_offset);
+    printf("\tlw      $fp,$L_%d-%d($sp)\n",r1_offset_label,arg_offset+SIZE_OF_INT);
     if (max_reg_var+max_freg_var)
-	code_register_restore(max_reg_var,max_freg_var,r1_offset-SIZE_OF_INT*2);
+	code_register_restore(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2);
     printf("\taddu    $sp,$sp,%d\n",r1_offsetv);
     printf("\tj       $31\n");
 
@@ -2784,23 +2801,39 @@
 	round16(-disp),
 	max_reg_var+2,
 	max_freg_var,
-	round16(max_func_args),
+	round16(max_func_args*SIZE_OF_INT),
 	0
 );
     fprintf(asi,"$L_%d=0x%x\n",mask_label,code_mask());
     fprintf(asi,"$L_%d=%d\n",mask_offset_label,code_mask_offset());
     fprintf(asi,"$L_%d=0x%x\n",fmask_label,code_fmask());
     fprintf(asi,"$L_%d=%d\n",fmask_offset_label,code_fmask_offset());
-    fprintf(asi,"$L_%d=%d\n",cprestore_label ,round16(max_func_args));
+    fprintf(asi,"$L_%d=%d\n",cprestore_label ,round16(max_func_args*SIZE_OF_INT));
 
     if (max_reg_var+max_freg_var==0) {
 	fprintf(asi,"$L_%d=$L_%d\n",
 		register_save_label,register_save_return_label);
     } else {
 	code_label(register_save_label);
-	code_register_save(max_reg_var,max_freg_var,r1_offset-SIZE_OF_INT*2);
+	code_register_save(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2);
 	jmp(register_save_return_label);
     }
+#if 1
+   printf("#\n");
+   printf("# callee arg top=\t%d\n",CALLEE_ARG(0)+r1_offsetv);
+   printf("# r1_offset=\t\t%d\n",r1_offsetv);
+   printf("# reg_save_top=\t\t%d\n",r1_offsetv);
+   printf("# reg_save_end=\t\t%d\n",
+	-max_reg_var*SIZE_OF_INT-max_freg_var*SIZE_OF_FLOAT-2*SIZE_OF_INT+
+	r1_offsetv);
+   printf("# lvar_offset=\t\t%d\n",lvar_offsetv);
+   printf("# min local var=\t%d\n",FUNC_LVAR(0)+lvar_offsetv);
+   printf("# max local var=\t%d\n",FUNC_LVAR(disp)+lvar_offsetv);
+   printf("# min caller arg var=\t%d\n",
+	CALLER_ARG(round16(max_func_args*SIZE_OF_INT)));
+   printf("# max caller arg var=\t%d\n",CALLER_ARG(0));
+   printf("#\n");
+#endif
 
     local_table();
     printf("\t.end    %s\n",name);
@@ -3569,19 +3602,19 @@
 code_dpreinc(int e1,int e2,int d,int reg) {
     char *frn;
     char *crn;
-    char *xrn;
-    int  g,xreg;
+    int  g,xreg,creg0;
     char *grn;
     int dir=caddr(e1);
 
     if (!d) {
       if (car(e2)==FREGISTER) {
-	crn=register_name(cadr(e2));
+	creg0=cadr(e2);
       } else {
 	g_expr(e2);
 	if (!is_int_reg(creg)) error(-1);
-	crn=register_name(ireg);
+	creg0=ireg;
       }
+      crn=register_name(creg0);
 
       use_float(d,reg);
 
@@ -3590,7 +3623,8 @@
       printf("\tli.s %s,1.0\n",grn);
 
       if (car(e2)==FREGISTER) {
-	printf("\tmov.s %s,%s\n",crn,frn);
+	if (creg0!=reg)
+	    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);
@@ -3613,22 +3647,17 @@
       } 
       g_expr(e2);
       if(!is_int_reg(creg)) error(-1);
+      creg0=creg;
       emit_push();
       code_save_stacks();
       clear_ptr_cache();
+      lload(creg0,DREGISTER_OPERAND,0);
       set_dreg(RET_DREGISTER,0);
-      xreg = emit_pop(1);
-      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);
+      if (reg!=USE_CREG) error(-1);
       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);
+      xreg = emit_pop(1);
+      code_lassign(xreg,RET_DREGISTER);
       emit_pop_free(xreg);
     }
 }
@@ -3637,18 +3666,19 @@
 code_dpostinc(int e1,int e2,int d,int reg) {
     char *frn;
     char *crn;
-    int  g,xreg;
-    char *grn,*xrn;
+    int  g,xreg,creg0;
+    char *grn;
     int dir=caddr(e1);
 
     if (!d) {
 	if (car(e2)==FREGISTER) {
-	    crn=register_name(cadr(e2));
+	    creg0=cadr(e2);
 	} else {
 	    g_expr(e2);
 	    if (!is_int_reg(creg)) error(-1);
-	    crn=register_name(creg);
+	    creg0=creg;
 	}
+	crn=register_name(creg0);
 
 	use_float(d,reg);
 
@@ -3682,29 +3712,37 @@
       } 
       g_expr(e2);
       if(!is_int_reg(creg)) error(-1);
+      creg0=creg;
       emit_push();
       code_save_stacks();
       clear_ptr_cache();
       set_dreg(RET_LREGISTER,0);
-      xreg = emit_pop(0);
-      xrn = register_name(xreg);
-      printf("\tlw $4,%d(%s)\n",SIZE_OF_INT,xrn);
-      printf("\tlw $5,0(%s)\n",xrn);
+      lload(creg0,DREGISTER_OPERAND,0);
       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);
+      if (use) {
+	if (reg!=USE_CREG) {
+	    use_float(d,reg);
+	    lload(xreg,reg,0);
+	} else {
+	    reg = get_dregister(1);
+	    xreg = emit_pop(0);
+	    lload(xreg,reg,0);
+            code_lassign(xreg,RET_DREGISTER);
+	    set_dreg(reg,0);
+            emit_pop_free(xreg);
+            return;
+	}
+      }
+      xreg = emit_pop(0);
+      code_lassign(xreg,RET_DREGISTER);
       emit_pop_free(xreg);
-      if (use) {
-        use_float(d,reg);
-	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,int cond)
 {
+    int op1;
     if (!cond) {
 	switch(op) {
 	    case FOP+GT:
@@ -3726,22 +3764,22 @@
 	}
     }
     switch(op) {
-    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;
+    case FOP+GT: op1=FOP+CMP; break;
+    case DOP+GT: op1=DOP+CMP; break;
+    case FOP+GE: op1=FOP+CMPGE; break;
+    case DOP+GE: op1=DOP+CMPGE; break;
+    case FOP+EQ: op1=FOP+CMPEQ; break;
+    case DOP+EQ: op1=DOP+CMP; break;
+    case FOP+NEQ: op1=FOP+CMPEQ; break;
+    case DOP+NEQ: op1=DOP+CMP; break;
     default: error(-1);
     }
-    g_expr(list3(op,e2,e1));
+    g_expr(list3(op1,e2,e1));
     switch(op) {
 	case DOP+GT:	printf("\tbgez\t$2,$L_%d\n",l1);break;
 	case FOP+GT:	printf("\tbc1t\t$L_%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 FOP+GE:	printf("\tbc1t\t$L_%d\n",l1);break;
 	case DOP+EQ:	printf("\tbeq\t$2,$0,$L_%d\n",l1);break;
 	case FOP+EQ:	printf("\tbc1t\t$L_%d\n",l1);break;
 	case DOP+NEQ:	printf("\tbne\t$2,$0,$L_%d\n",l1);break;
@@ -3820,6 +3858,8 @@
 lmove(int to,int from)
 {
     int tmp;
+    if (regv_h(to)==regv_h(from)&&(regv_l(to)==regv_l(from))) 
+	return;
     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));
@@ -4665,7 +4705,6 @@
 void
 code_lpreinc(int e1,int e2,int reg)
 {
-    char *xrn,*drn_h,*drn_l;
     int dreg=-1,xreg=-1;
     int dir=caddr(e1);
     if (car(e2)==LREGISTER) {
@@ -4681,20 +4720,14 @@
     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);
+        dreg = reg;
     }
     xreg = emit_pop(0);
-    xrn = register_name(xreg);
-    printf("\tlw %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn);
-    printf("\tlw %s,0(%s)\n",drn_h,xrn);
+    lload(xreg,dreg,0);
     ladd(dreg,dir);
-    printf("\tsw %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn);
-    printf("\tsw %s,0(%s)\n",drn_h,xrn);
+    code_lassign(xreg,dreg);
     emit_pop_free(xreg);
     if (dreg!=-1) free_register(dreg);
 }
@@ -4702,8 +4735,6 @@
 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) {
@@ -4716,25 +4747,16 @@
     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);
 	dreg = reg;
     }
     xreg = emit_pop(0);
-    xrn = register_name(xreg);
-    printf("\tlw %s,%d(%s)\n",drn_l,SIZE_OF_INT,xrn);
-    printf("\tlw %s,0(%s)\n",drn_h,xrn);
+    lload(xreg,dreg,0);
     ladd(dreg,dir);
-    printf("\tsw %s,%d(%s)\n",nrn_l,SIZE_OF_INT,xrn);
-    printf("\tsw %s,0(%s)\n",nrn_h,xrn);
+    code_lassign(xreg,nreg);
     emit_pop_free(xreg);
     free_register(nreg);
 }
@@ -4757,18 +4779,15 @@
 	       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);
+    lload(edx0=edx,reg,0);
+    // free_register(edx); don't do this, it will free pushed register
     ltosop(op,reg,xreg);
+    use_reg(reg);
     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));
+    code_lassign(edx,reg);
     free_register(edx);
+    if (edx0!=-1)
+	free_register(edx0);
     emit_lpop_free(xreg);
 }
 
--- a/mc-code-powerpc.c	Tue May 18 14:20:46 2004 +0900
+++ b/mc-code-powerpc.c	Wed May 19 09:56:53 2004 +0900
@@ -1648,7 +1648,7 @@
 {
     return e3==FUNCTION||e3==CONV||e3==RSTRUCT||e3==STASS|| 
 	e3==LLSHIFT||e3==LULSHIFT||e3==LRSHIFT||e3==LURSHIFT||
-	e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD;
+	e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD||e3==LASSOP;
 }
 
 static int
@@ -2123,6 +2123,19 @@
 }
 #endif
 
+static void
+lload(int creg,int reg,int offset)
+{
+    char *crn = register_name(creg);
+    if (creg!=regv_h(reg)) {
+	printf("\tlwz %s,%d(%s)\n",lregister_name_high(reg),offset,crn);
+	printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn);
+    } else {
+	printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn);
+	printf("\tlwz %s,%d(%s)\n",lregister_name_high(reg),offset,crn);
+    }
+}
+
 #if LONGLONG_CODE
 int
 code_lrindirect(int e1, int reg, int offset, int us)
@@ -2134,13 +2147,7 @@
     if (!is_int_reg(creg)) error(-1);
     crn=register_name(creg0=creg);
     use_longlong(reg);
-    if (creg0!=regv_h(reg)) {
-	printf("\tlwz %s,%d(%s)\n",lregister_name_high(reg),offset,crn);
-	printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn);
-    } else {
-	printf("\tlwz %s,%d(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn);
-	printf("\tlwz %s,%d(%s)\n",lregister_name_high(reg),offset,crn);
-    }
+    lload(creg0,reg,offset);
     return us?ULONGLONG:LONGLONG;
 }
 #endif
@@ -4338,7 +4345,7 @@
 void
 code_lpreinc(int e1,int e2,int reg)
 {
-    char *xrn,*drn_h,*drn_l;
+    char *drn_h,*drn_l;
     int dreg,xreg;
     int dir=caddr(e1);
     if (car(e2)==LREGISTER) {
@@ -4357,28 +4364,24 @@
     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);
+        dreg = 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);
+    lload(xreg,dreg,0);
+    drn_l = lregister_name_low(dreg);
+    drn_h = lregister_name_high(dreg);
     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);
+    code_lassign(xreg,dreg);
     emit_pop_free(xreg);
 }
 
 void
 code_lpostinc(int e1,int e2,int reg)
 {
-    char *xrn,*drn_h,*drn_l;
+    char *drn_h,*drn_l;
     char *nrn_h,*nrn_l;
     int dreg,nreg,xreg;
     int dir=caddr(e1);
@@ -4399,21 +4402,17 @@
     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);
+        dreg = reg;
     }
+    drn_l = lregister_name_low(dreg);
+    drn_h = lregister_name_high(dreg);
     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);
+    lload(xreg,dreg,0);
     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);
+    code_lassign(xreg,nreg);
     emit_pop_free(xreg);
     free_register(nreg);
 }
@@ -4435,18 +4434,14 @@
 	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);
+    lload(edx0=edx,reg,0);
     ltosop(op,reg,xreg);
+    use_reg(reg);
     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);
+    code_lassign(edx,reg);
+    if (edx0!=-1)
+	free_register(edx0);
+    emit_pop_free(edx);
     emit_lpop_free(xreg);
 }
 
--- a/mc-codegen.c	Tue May 18 14:20:46 2004 +0900
+++ b/mc-codegen.c	Wed May 19 09:56:53 2004 +0900
@@ -1000,7 +1000,7 @@
 #if DEBUG_PARALLEL_ASSIGN
 printf("# remove same memory %d ty %d+%d sz %d\n",car(t0),ty,cadr(t0),sz);
 #endif
-                /* we should check size also (but currently useless */
+                /* we should check size also (but currently useless) */
                 remove0(&target,t0);
                 /* still we have source to avoid overwrite */
 	    }
@@ -1138,6 +1138,10 @@
     e3 = cadr(e2);  /* offset of the variable (distination) */
     e4 = caddr(e1); /* right value (source) */
     sz = cadddr(e1);  /* size of struct or union */
+    if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) {
+	if (use) g_expr(e4);
+	return;
+    }
     g_expr(e4);
     emit_push();
     g_expr(e2);
@@ -1156,7 +1160,7 @@
     return;
 }
 
-void
+static void
 assign_opt(int e5,int e2,int e4,int byte)
 {
     int reg;
@@ -1208,6 +1212,10 @@
     /*    e2=e4 */
     e2 = cadr(e1);
     e4 = caddr(e1);e5=car(e4);
+    if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) {
+	if (use) g_expr(e4);
+	return;
+    }
     if (!use && (
 	    (e5==REGISTER) ||
 	    (car(e2)==REGISTER&&(
@@ -1246,7 +1254,7 @@
 
 #if FLOAT_CODE
 
-void
+static void
 dassign_opt(int e5,int e2,int e4,int d)
 {
     int reg;
@@ -1293,6 +1301,10 @@
     e2 = cadr(e1);
     e3 = cadr(e2);
     e4 = caddr(e1); e5=car(e4);
+    if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) {
+	if (use) g_expr(e4);
+	return;
+    }
     if (car(e1)==DASS) d=1;
     else if (car(e1)==FASS) d=0;
     else error(-1); 
@@ -1375,6 +1387,10 @@
     e2 = cadr(e1);
     e3 = cadr(e2);
     e4 = caddr(e1); e5=car(e4);
+    if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) {
+	if (use) g_expr(e4);
+	return;
+    }
     if (!use && (
 	    (e5==LREGISTER) ||
 	    (car(e2)==LREGISTER&&(e5==LRGVAR||e5==LRLVAR||e5==LCONST))