changeset 273:87b9cfc86a10

*** empty log message ***
author kono
date Fri, 21 May 2004 00:57:27 +0900
parents 40266d044d97
children 3ae68af07fce
files Changes mc-code-mips.c mc-code-powerpc.c mc-codegen.c mc-parse.c test/code-gen.c
diffstat 6 files changed, 671 insertions(+), 464 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Wed May 19 23:44:38 2004 +0900
+++ b/Changes	Fri May 21 00:57:27 2004 +0900
@@ -4344,3 +4344,10 @@
 
 しかし、がんがんバグは取れていくわけだけど、なんか、
 微妙にわけわからないバグが残っているな。
+
+MIPSってconst のかけ算ないんだよね。だったら、*4ぐらい
+はshiftした方が良いかも。
+
+Thu May 20 21:46:17 JST 2004
+
+register_dassop をテストしてなくて、コードも間違ってる。
--- a/mc-code-mips.c	Wed May 19 23:44:38 2004 +0900
+++ b/mc-code-mips.c	Fri May 21 00:57:27 2004 +0900
@@ -23,6 +23,7 @@
 static void local_table(void);
 static void shift(char *op, int creg,int reg);
 static int struct_push(int e4,int t,int arg);
+static void register_usage(char *s);
 
 static int creg;
 
@@ -141,9 +142,12 @@
 
 static int *regs  = mips_regs;
 
-#define CREG_REGISTER  (MAX_TMP_REG)
-#define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET)
-#define LREG_LREGISTER (MAX_TMP_REG+LREG_OFFSET)
+// #define CREG_REGISTER  (MAX_TMP_REG)
+#define CREG_REGISTER  REGISTER_OPERAND
+// #define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET)
+#define FREG_FREGISTER FREGISTER_OPERAND
+// #define LREG_LREGISTER (MAX_TMP_REG+LREG_OFFSET)
+#define LREG_LREGISTER LREGISTER_OPERAND
 #define DREG_DREGISTER LREG_LREGISTER
 #define CMP_C1T (-1)
 
@@ -268,12 +272,18 @@
 static void    set_freg(int,int);
 static void    set_lreg(int,int);
 
-// static FILE *asi;
-
 static int max_func_args;
 static int my_func_args;
+static unsigned int code_mask();
+static int code_mask_offset();
+static unsigned int code_fmask();
+static int code_fmask_offset();
+
 #define ARG_LVAR_OFFSET 0x10000000
 
+#define round16(i)   ((i+0xf)&~0xf)
+#define round4(i)   ((i+3)&~3)
+
 /*          
 
      Reorder is automatically done in assembler.
@@ -302,7 +312,17 @@
                               *SIZE_OF_INT                  *SIZE_OF_INT
                  prev $sp=$fp                 $fp                        $sp
 
+
+                      <-------r1_offset------------------------------>
+                                      <------------lvar_offset------->
+                                                              <-arg_offset->
+ r+  +-----------+----+---------------+----------+--- ----------+----+
+       callee arg xxx  register save   local      caller arg     xxx
+                 ($r31)($fp) reg_save   disp          max_func_args*SIZE_OF_INT
+        lvar>0                         lvar<0          lvar>0x1000 0000
+                      prev $sp=$fp                                   $sp=$fp
  */
+
 #define arg_offset 8
 #define arg_offset1 0
 #define disp_offset  0
@@ -317,37 +337,60 @@
 #define CALLER_ARG(l) ((l)+arg_offset1)
 #define CALLEE_ARG(l) ((l)+arg_offset)
 
-#if 0
-void
-code_offset_set()
+static void
+code_offset_set(int *lvar_offsetv_p,int *r1_offsetv_p)
 {
-#if 0
-    int l;
+    int lvar_offsetv,r1_offsetv;
+
+    disp &= -SIZE_OF_INT;
+    lvar_offsetv = round16(-disp) +
+	round16((max_func_args<2?2:max_func_args)*SIZE_OF_INT) +
+	2*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 ;
+    lvar_offsetv += round16(r1_offsetv)-r1_offsetv;
+    r1_offsetv = round16(r1_offsetv);
+
+#if 1
+printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
+	round16(-disp),
+	max_reg_var+2,
+	max_freg_var,
+	round16(max_func_args*SIZE_OF_INT),
+	0
+);
+    printf("# mask_label $L_%d=0x%x\n",mask_label,code_mask());
+    printf("# mask_offset$L_%d=%d\n",mask_offset_label,code_mask_offset());
+    printf("#fmask_label $L_%d=0x%x\n",fmask_label,code_fmask());
+    printf("#fmask_offset$L_%d=%d\n",fmask_offset_label,code_fmask_offset());
+    printf("# cprestore  $L_%d=%d\n",cprestore_label ,round16(max_func_args*SIZE_OF_INT));
+   printf("#\n");
+   printf("# callee arg top=\t%d\n",CALLEE_ARG(0)+r1_offsetv);
+   printf("# r1_offset=\t\t%d %d\n",r1_offsetv,r1_offsetv%16);
+   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 %d\n",lvar_offsetv,lvar_offsetv%16);
+   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
-    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;
-    fprintf(asi,"$L_%d=%d\n",lvar_offset_label,lvar_offsetv);
+    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>2?max_func_args:2)*SIZE_OF_INT));
     fprintf(asi,"$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(l),max_func_args*SIZE_OF_INT);
-    l = disp;
-printf("# offset lvarn\t%d %d\n",FUNC_LVAR(l)+lvar_offsetv,disp);
-    l = 0;
-printf("# offset lvar0\t%d\n",FUNC_LVAR(l)+lvar_offsetv);
-    l = -reg_save;
-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(l)+r1_offsetv);
-    l = my_func_args;
-printf("# offset cargn\t%d %d\n",CALLEE_ARG(l)+r1_offsetv,my_func_args);
-#endif
-}
-#endif
+    fprintf(asi,"$L_%d=%d\n",lvar_offset_label,lvar_offsetv);
+
+    *lvar_offsetv_p=lvar_offsetv;
+    *r1_offsetv_p= r1_offsetv;
+}
 
 static void
 lvar(int l)
@@ -430,6 +473,7 @@
 void
 code_gexpr(int e){
      if (is_int_reg(creg) && creg!=ireg) error(-1);
+// register_usage("code_gexpr");
 }
 
 
@@ -833,8 +877,9 @@
 register_usage(char *s)
 {
 #if 1
-    int i;
+    int i,j;
 #endif
+#define USAGE_MAX 4
     if (chk) return;
     if (!lsrc) return;
     printf("# %d: %s:",lineno,s);
@@ -843,34 +888,56 @@
     if (lreg) printf(" lreg=%s,%s",lregister_name_high(lreg),
 	lregister_name_low(lreg));
 #if 1
-    printf("\n# regs:");
-    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]));
+    for(j=0,i=0;i<MAX_REGISTER;i++) if (regs[i]) j++;
+    if (j>USAGE_MAX) {
+	printf("\n# regs:");
+	for(i=0;i<MAX_REGISTER;i++) {  printf("%d",regs[i]); }
+    }
+    if (reg_sp>0) {
+	printf(" stack ");
+	for(i=reg_sp;i>0;i--) {
+	    if(reg_stack[i-1]>=0) {
+		printf(" %s",register_name(reg_stack[i-1]));
+            } else 
+		printf(",%d",reg_stack[i-1]);
+	}
+    }
+    for(j=0,i=0;i<MAX_FREGISTER;i++) if (regs[i+FREG_OFFSET]) j++;
+    if (j>USAGE_MAX) {
+	printf("\n# freg:");
+	for(i=0;i<MAX_FREGISTER;i++) {  printf("%d",regs[i+FREG_OFFSET]); }
     }
-    printf("\n# freg:");
-    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]));
+    if (freg_sp>0) {
+	printf(" fstack ");
+	for(i=freg_sp;i>0;i--) {
+	    if(freg_stack[i-1]>=0) {
+		printf(" %s",fregister_name(freg_stack[i-1]));
+            } else 
+		printf(",%d",freg_stack[i-1]);
+	}
     }
-    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]));
+
+    for(j=0,i=0;i<REAL_MAX_LREGISTER;i++) if (regs[i+LREG_OFFSET]) j++;
+    if (j>USAGE_MAX) {
+	printf("\n# lreg:");
+	for(i=0;i<REAL_MAX_LREGISTER;i++) {  printf("%d",regs[i+LREG_OFFSET]); }
+    }
+    if (lreg_sp>0) {
+	printf(" lstack ");
+	for(i=lreg_sp;i>0;i--) {
+	    if(lreg_stack[i-1]>=0) {
+		printf(" %s",lregister_name_high(lreg_stack[i-1]));
+		printf(",%s",lregister_name_low(lreg_stack[i-1]));
+            } else 
+		printf(",%d",lreg_stack[i-1]);
+	}
     }
 #endif
     printf("\n");
 }
 
+
 void
-
 gexpr_init(void)
 {
     while(reg_sp > 0) {
@@ -885,7 +952,7 @@
     use_int0();
     text_mode(2);
     gexpr_code_init();
-    register_usage("gexpr_init");
+    register_usage("");
 }
 
 
@@ -1394,7 +1461,6 @@
 #define MAX_COPY_LEN 20
 
 void
-
 emit_copy(int from,int  to,int length,int offset,int value,int det)
 {
     char *frn;
@@ -1472,7 +1538,7 @@
     free_register(dreg);
 }
 
-int
+static int
 struct_push(int e4,int t,int arg) 
 {
     int length,count;
@@ -1508,7 +1574,7 @@
     return length/SIZE_OF_INT;
 }
 
-void
+static void
 set_ireg(int reg,int mode)
 {
     if (!is_int_reg(reg)) error(-1);
@@ -1526,7 +1592,7 @@
     creg = ireg = reg;
 }
 
-void
+static void
 set_freg(int reg,int mode)
 {
     if (!is_float_reg(reg)) error(-1);
@@ -1543,7 +1609,7 @@
     creg = freg = reg;
 }
 
-void
+static void
 set_lreg0(int reg,int mode)
 {
     if (reg!=creg) {
@@ -1569,14 +1635,14 @@
     creg = lreg = reg;
 }
 
-void
+static void
 set_lreg(int reg,int mode)
 {
     if (!is_longlong_reg(reg)) error(-1);
     set_lreg0(reg,mode);
 }
 
-void
+static void
 set_dreg(int reg,int mode)
 {
     if (reg==RET_DREGISTER) {
@@ -1594,12 +1660,29 @@
     regs[regv_h(reg)]=USING_DREG;
 }
 
-void
+static void
 set_lreg_operand(int reg,int mode)
 {
     // save_stack,clear_ptr_cache is assumed    
     if (!is_longlong_reg(reg)) { error(-1); return; }
     if (mode) {
+	if (regv_h(reg)!=DREGISTER_OPERAND_H) {
+	    printf("\tmove %s,%s\n", 
+	    lregister_name_high(DREGISTER_OPERAND),lregister_name_high(reg));
+	}
+	if (regv_l(reg)!=DREGISTER_OPERAND_L) {
+	    printf("\tmove %s,%s\n", 
+	    lregister_name_low(DREGISTER_OPERAND),lregister_name_low(reg));
+	}
+    }
+}
+
+static void
+set_lreg_operand1(int reg,int mode)
+{
+    // save_stack,clear_ptr_cache is assumed    
+    if (!is_longlong_reg(reg)) { error(-1); return; }
+    if (mode) {
 	if (regv_h(reg)!=DREGISTER_OPERAND_1_H) {
 	    printf("\tmove %s,%s\n", 
 	    lregister_name_high(DREGISTER_OPERAND_1),lregister_name_high(reg));
@@ -1611,12 +1694,18 @@
     }
 }
 
-void
+static void
 set_dreg_operand(int reg,int mode)
 {
      set_lreg_operand(reg,mode);
 }
 
+static void
+set_dreg_operand1(int reg,int mode)
+{
+     set_lreg_operand1(reg,mode);
+}
+
 void
 use_reg(int arg)
 {
@@ -1810,8 +1899,6 @@
     return reg_arg_list;
 }
 
-#define round4(i)   ((i+(SIZE_OF_INT-1))&~(SIZE_OF_INT-1))
-
 static void
 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
     int nargs=0,reg_arg=0,freg_arg=0;
@@ -1887,7 +1974,7 @@
 int
 function(int e1)
 {
-    int e2,e3,e4,e5,nargs,t,r0;
+    int e2,e3,e4,e5,nargs,t;
     int arg,reg_arg,freg_arg,arg_assign;
     int dots;
     int reg_arg_list=0,ret_type,special_lvar;
@@ -2007,16 +2094,6 @@
 	arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg);
 	if (car(arg)!=LVAR) continue;
 	g_expr_u(assign_expr0(arg,e4,t,t));
-	if (t==LONGLONG||t==ULONGLONG||t==DOUBLE) {
-	    if (reg_arg+1==MAX_INPUT_REGISTER_VAR) {
-		// half register, half memory case
-		arg_assign = list2(
-		    assign_expr0(r0=get_input_register_var(reg_arg,0,0),
-			arg,INT,INT),
-		    arg_assign);
-		use_input_reg(cadr(r0),1);
-	    }
-	}
 	car(e3)=0;  // done
     }
     nargs = reg_arg = freg_arg = 0;
@@ -2033,17 +2110,8 @@
 		use_input_reg(cadr(arg),1);
 	    g_expr_u(assign_expr0(arg,e4,t,t));
 	} else if (t==LONGLONG||t==ULONGLONG) {
-	    if (reg_arg+1==MAX_INPUT_REGISTER_VAR) { 
-		// half register, half memory case
-		// put whole long long anyway
-		arg_assign = list2(
-		    assign_expr0(r0=get_input_register_var(reg_arg,0,0),
-			arg,INT,INT),
-		    arg_assign);
-		use_input_reg(cadr(r0),1);
-	    } else {
-		if (car(arg)==LREGISTER)
-		    use_input_reg(cadr(arg),1);
+	    if (car(arg)==LREGISTER) {
+		use_input_reg(cadr(arg),1);
 	    }
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    g_expr_u(assign_expr0(arg,e4,t,t));
@@ -2763,7 +2831,6 @@
 }
 
 
-#define round16(i)   ((i+0xf)&~0xf)
 void
 leave(int control, char *name)
 {
@@ -2805,25 +2872,7 @@
 	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<2?2:max_func_args)*SIZE_OF_INT) +
-	2*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);
+    code_offset_set(&lvar_offsetv,&r1_offsetv);
 
     printf("\tmove    $sp,$fp\n");
     printf("\tlw      $31,$L_%d-%d($sp)\n",r1_offset_label,arg_offset);
@@ -2833,18 +2882,9 @@
     printf("\taddu    $sp,$sp,%d\n",r1_offsetv);
     printf("\tj       $31\n");
 
-printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
-	round16(-disp),
-	max_reg_var+2,
-	max_freg_var,
-	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*SIZE_OF_INT));
+//  leave part end
+
+//  entry part  (save register)
 
     if (max_reg_var+max_freg_var==0) {
 	fprintf(asi,"$L_%d=$L_%d\n",
@@ -2854,22 +2894,6 @@
 	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);
@@ -3505,28 +3529,33 @@
 }
 
 static void
-longlong_lib(char *opc,int reg,int e1)
+code_double_lib(char *lib,int to,int reg,int oreg)
 {
-    use_longlong(reg);
     code_save_stacks();
     clear_ptr_cache();
-    set_lreg(LREGISTER_OPERAND,1);
-    if (e1!=-1) {
-      set_lreg(e1,0);
-      set_lreg(LREGISTER_OPERAND_1,1);
+    set_dreg_operand(reg,1);
+    set_dreg_operand1(oreg,1);
+    extern_conv(lib);
+    set_dreg(RET_DREGISTER,0);
+    if (to!=RET_DREGISTER) {
+	lmove(to,RET_DREGISTER);
     }
-    set_lreg(RET_LREGISTER,0);
-    extern_define(opc,0,FUNCTION,1);
-    printf("\tjal %s\n",opc);
-    lib_args(16);
 }
 
 static void
-double_lib(char *opc,int reg,int e1)
+code_dconst_op(char *lib,int from,int to,double value)
 {
-    longlong_lib(opc,reg,e1);
+    code_save_stacks();
+    clear_ptr_cache();
+    set_dreg_operand(from,1);
+    printf("\tli.d $6,%g\n",value);
+    extern_conv(lib);
     set_dreg(RET_DREGISTER,0);
-}
+    if (to!=RET_DREGISTER) {
+	lmove(to,RET_DREGISTER);
+    }
+}
+
 
 void
 dtosop(int op,int reg,int e1)
@@ -3550,7 +3579,7 @@
 	default:
 	    error(-1); return;
 	}
-        double_lib(opc,reg,e1);
+        code_double_lib(opc,RET_DREGISTER,reg,e1);
     } else {
 	switch(op) {
 	case FADD: opn="add.s"; break;
@@ -3581,7 +3610,7 @@
     int  xreg;
     char *crn;
     char *frn;
-    int edx,edx0;
+    int edx,edx0=-1;
 
     if (!d) {
       xreg=emit_dpop(d);
@@ -3605,11 +3634,12 @@
 	edx = edx0;
       }
       lload(edx,reg,0);
-      free_register(edx);
       dtosop(op,reg,xreg);
       edx = emit_pop(0);
-      code_lassign(edx,lreg);
-      free_register(edx);
+      code_lassign(edx,reg);
+      if (edx0!=-1)
+	free_register(edx0);
+      emit_pop_free(edx);
       emit_lpop_free(xreg);
       set_double(reg);
     }
@@ -3631,77 +3661,73 @@
     }
 }   
 
-
-static void
-double_lib_c(char *opc,double value)
+static int
+code_dload_1(int d)
 {
-      extern_define(opc,0,FUNCTION,1);
-      lib_args(16);
-      printf("\tli.d $6,%g\n",value);
-      printf("\tjal %s\n",opc);
+    int g = get_dregister(d);
+    if (d)
+	error(-1);
+    else
+	printf("\tli.s %s,1.0\n",fregister_name(g));
+    return g;
 }
 
 void
 code_dpreinc(int e1,int e2,int d,int reg) {
     char *frn;
     char *crn;
-    int  g,xreg,creg0;
+    int  g,xreg,dreg;
     char *grn;
     int dir=caddr(e1);
 
     if (!d) {
-      if (car(e2)==FREGISTER) {
-	creg0=cadr(e2);
-      } else {
-	g_expr(e2);
-	if (!is_int_reg(creg)) error(-1);
-	creg0=ireg;
-      }
-      crn=register_name(creg0);
-
-      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) {
-	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);
-	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);
+	if (car(e2)==FREGISTER) {
+	    crn=register_name(cadr(e2));
+	    grn=fregister_name(g=code_dload_1(d));
+	    if (reg==USE_CREG) {
+		reg=get_dregister(d); if (!reg) error(-1);
+		set_freg(reg,0);
+	    }
+	    frn=fregister_name(reg);
+	    printf("\t%s %s,%s,%s\n",dir>0?"add.s":"sub.s",crn,crn,grn);
+	    if (use && reg!=cadr(e2))
+		printf("\tmov.s %s,%s\n",crn,frn);
+	} else {
+	    g_expr(e2);
+	    if (!is_int_reg(creg)) error(-1);
+	    crn=register_name(ireg);
+	    if (reg==USE_CREG) {
+		reg=get_dregister(d); if (!reg) error(-1);
+		set_freg(reg,0);
+	    }
+	    frn=fregister_name(reg);
+	    grn = fregister_name(g = code_dload_1(d));
+	    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();
-	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));
+	if (car(e2)==DREGISTER) {
+	    use_float(d,reg);
+	    code_dconst_op("dpadd",cadr(e2),cadr(e2),dir);
+	    if (reg!=cadr(e2)) lmove(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);
+	    set_dreg(dreg,0);  // free old lreg==creg
+	} else {
+	    dreg = reg;
 	}
-        return;
-      } 
-      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);
-      double_lib_c(dir>0?"dpadd":"dpsub",1.0);
-      if (reg!=USE_CREG) error(-1);
-      use_float(d,reg);
-      xreg = emit_pop(1);
-      code_lassign(xreg,RET_DREGISTER);
-      emit_pop_free(xreg);
+	xreg = emit_pop(0);
+	lload(xreg,dreg,0);
+	code_dconst_op("dpadd",dreg,dreg,dir);
+	code_lassign(xreg,dreg);
+	emit_pop_free(xreg);
     }
 }
 
@@ -3709,76 +3735,60 @@
 code_dpostinc(int e1,int e2,int d,int reg) {
     char *frn;
     char *crn;
-    int  g,xreg,creg0;
+    int  g,xreg,dreg,nreg;
     char *grn;
     int dir=caddr(e1);
 
     if (!d) {
 	if (car(e2)==FREGISTER) {
-	    creg0=cadr(e2);
+	    crn=register_name(cadr(e2));
+	    grn=fregister_name(g=code_dload_1(d));
+	    if (reg==USE_CREG) {
+		reg=get_dregister(d); if (!reg) error(-1);
+		set_freg(reg,0);
+	    }
+	    frn=fregister_name(reg);
+	    printf("\t%s %s,%s,%s\n",dir>0?"add.s":"sub.s",crn,crn,grn);
+	    if (use && reg!=cadr(e2))
+		printf("\tmov.s %s,%s\n",crn,frn);
 	} else {
 	    g_expr(e2);
 	    if (!is_int_reg(creg)) error(-1);
-	    creg0=creg;
-	}
-	crn=register_name(creg0);
-
-	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 {
+	    crn=register_name(ireg);
+	    if (reg==USE_CREG) {
+		reg=get_dregister(d); if (!reg) error(-1);
+		set_freg(reg,0);
+	    }
+	    frn=fregister_name(reg);
+	    grn = fregister_name(g = code_dload_1(d));
 	    printf("\tl.s %s,0(%s)\n",frn,crn);
-	    printf("\t%s %s,%s,%s\n",(dir>0)?"add.s":"sub.s",grn,frn,grn);
+	    printf("\t%s %s,%s,%s\n",dir>0?"add.s":"sub.s",grn,frn,grn);
 	    printf("\ts.s %s,0(%s)\n",grn,crn);
 	}
 	free_register(g);
     } else {
-      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);
+	if (car(e2)==DREGISTER) {
+	    use_float(d,reg);
+	    if (reg!=cadr(e2)) lmove(reg,cadr(e2));
+	    code_dconst_op("dpadd",cadr(e2),cadr(e2),dir);
+	    return;
+	} 
+	g_expr(e2);
+	if(!is_int_reg(creg)) error(-1);
+	emit_push();
+	nreg=get_dregister(1); if (!nreg) error(-1);
+	if (reg==USE_CREG) {
+	    dreg=get_lregister(); if (!dreg) error(-1);
+	    set_dreg(dreg,0);  // free old lreg==creg
+	} else {
+	    dreg = reg;
 	}
-        return;
-      } 
-      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);
-      lload(creg0,DREGISTER_OPERAND,0);
-      double_lib_c(dir>0?"dpadd":"dpsub",1.0);
-      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);
+	xreg = emit_pop(0);
+	lload(xreg,dreg,0);
+	code_dconst_op("dpadd",nreg,dreg,dir);
+	code_lassign(xreg,nreg);
+	emit_pop_free(xreg);
+	free_register(nreg);
     }
 }
 
@@ -4202,13 +4212,13 @@
 
 
 static void
-code_asld_lib(int oreg)
+code_asld_lib(int reg,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);
+    ch = lregister_name_high(reg);
+    cl = lregister_name_low(reg);
     oh = lregister_name_high(oreg);
     ol = lregister_name_low(oreg);
     dh = lregister_name_high(dreg);
@@ -4238,7 +4248,7 @@
 }
 
 static void
-code_asrd_lib(int oreg) // ___ashrdi3$stub
+code_asrd_lib(int reg,int oreg) // ___ashrdi3$stub
 {
     char *ch,*cl,*oh,*ol,*dh,*dl;
     //    5   4   2   3   9   8
@@ -4274,13 +4284,13 @@
 }
 
 static void
-code_lsrd_lib(int oreg) // ___lshrdi3$stub
+code_lsrd_lib(int reg,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);
+    ch = lregister_name_high(reg);
+    cl = lregister_name_low(reg);
     oh = lregister_name_high(oreg);
     ol = lregister_name_low(oreg);
     dh = lregister_name_high(dreg);
@@ -4312,50 +4322,22 @@
 }
 
 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");
-    set_lreg(RET_LREGISTER,0);
-}
-
-static void
-code_ludiv_lib(int oreg) // ___udivdi3$stub
+code_longlong_lib(char *lib,int reg,int oreg) // ___divdi3$stub
 {
     code_save_stacks();
     clear_ptr_cache();
-    set_lreg(LREGISTER_OPERAND,1);
-    set_lreg_operand(oreg,1);
-    extern_conv("__udivdi3");
-    set_lreg(RET_LREGISTER,0);
-}
-
-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");
+    set_lreg_operand(reg,1);
+    set_lreg_operand1(oreg,1);
+    extern_conv(lib);
     set_lreg(RET_LREGISTER,0);
 }
 
-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");
-    set_lreg(RET_LREGISTER,0);
-}
-
-#define check_lreg(reg) if (use && reg!=lreg) { lmove(reg,lreg); }
+#define code_ldiv_lib(reg,oreg)  code_longlong_lib("__divdi3",reg,oreg)
+#define code_ludiv_lib(reg,oreg) code_longlong_lib("__udivdi3",reg,oreg)
+#define code_lmod_lib(reg,oreg)  code_longlong_lib("__moddi3",reg,oreg)
+#define code_lumod_lib(reg,oreg) code_longlong_lib("__umoddi3",reg,oreg)
+
+#define check_lreg(reg) if (reg!=lreg) { lmove(reg,lreg); }
 
 void
 ltosop(int op,int reg,int oreg)
@@ -4365,7 +4347,7 @@
     char *orn_h,*crn_h,*drn_h;
     char *orn_l,*crn_l,*drn_l;
     char *drn;
-    // creg = creg op oreg
+    // reg = reg op oreg
 
     use_longlong(reg);
     if(oreg==-1) {
@@ -4380,17 +4362,17 @@
     switch(op) {
     case LLSHIFT:
     case LULSHIFT:
-	code_asld_lib(oreg); // ___ashldi3$stub
+	code_asld_lib(reg,oreg); // ___ashldi3$stub
 	check_lreg(reg);
 	if(ox!=-1) free_register(ox);
 	return;
     case LRSHIFT:
-	code_asrd_lib(oreg); // ___ashrdi3$stub
+	code_asrd_lib(reg,oreg); // ___ashrdi3$stub
 	check_lreg(reg);
 	if(ox!=-1) free_register(ox);
 	return;
     case LURSHIFT:
-	code_lsrd_lib(oreg); // ___lshrdi3$stub
+	code_lsrd_lib(reg,oreg); // ___lshrdi3$stub
 	check_lreg(reg);
 	if(ox!=-1) free_register(ox);
 	return;
@@ -4431,8 +4413,6 @@
 	break;
     case LMUL:
     case LUMUL:
-	code_save_stacks();
-	clear_ptr_cache();
 	dx=get_lregister();
 	use_reg(dx);
 	drn_l = lregister_name_low(dx);
@@ -4457,20 +4437,16 @@
 	printf("\tmove    %s,%s\n",crn_l,drn_l);
 	break;
     case LDIV:
-	code_ldiv_lib(oreg); // ___divdi3$stub
-	check_lreg(reg);
+	code_ldiv_lib(reg,oreg); // ___divdi3$stub
 	break;
     case LUDIV:
-	code_ludiv_lib(oreg); // ___udivdi3$stub
-	check_lreg(reg);
+	code_ludiv_lib(reg,oreg); // ___udivdi3$stub
 	break;
     case LMOD:
-	code_lmod_lib(oreg); // ___moddi3$stub
-	check_lreg(reg);
+	code_lmod_lib(reg,oreg); // ___moddi3$stub
 	break;
     case LUMOD:
-	code_lumod_lib(oreg); // ___umoddi3$stub
-	check_lreg(reg);
+	code_lumod_lib(reg,oreg); // ___umoddi3$stub
 	break;
     default:
 	error(-1);
@@ -4558,20 +4534,18 @@
     case LSUB:
 	v = -v;
     case LADD:
+	drn = register_name(dx = get_register());
 	if (v<0) {
-	    drn = register_name(dx = get_register());
-	    printf("\tsubu %s,%s,%d\n",crn_l,crn_l,v);
-	    printf("\tsltu %s,%s,%d\n",drn,crn_l,-v);
+	    printf("\tsubu %s,%s,%d\n",crn_l,crn_l,-v);
+	    printf("\tsltu %s,%s,%d\n",drn,crn_l,v);
 	    printf("\tsubu %s,%s,1\n",crn_h,crn_h);
 	    printf("\taddu %s,%s,%s\n",crn_h,crn_h,drn);
-	    break;
 	} else {
-	    drn = register_name(dx = get_register());
 	    printf("\tsltu %s,%s,%d\n",drn,crn_l,v);
 	    printf("\taddu %s,%s,%d\n",crn_l,crn_l,v);
 	    printf("\taddu %s,%s,%s\n",crn_h,crn_h,drn);
-	    break;
 	}
+	break;
     case LBOR:
 	printf("\tori %s,%s,lo16(%d)\n",crn_l,crn_l,v);
 	break;
@@ -4675,7 +4649,7 @@
 code_d2ll(int reg)
 {
     // fixdfdi$stub
-    set_freg(RET_FREGISTER,1);
+    set_dreg(DREGISTER_OPERAND,1);
     extern_conv("__fixdfdi");
     set_lreg(RET_LREGISTER,0);
     if (reg!=USE_CREG&&reg!=RET_LREGISTER)
@@ -4695,8 +4669,8 @@
 void
 code_f2ll(int reg)
 {
-    set_freg(RET_FREGISTER,1);
-    extern_conv("__fixdfdi");
+    set_freg(FREGISTER_OPERAND,1);
+    extern_conv("__fixsfdi");
     set_lreg(RET_LREGISTER,0);
     if (reg!=USE_CREG&&reg!=RET_LREGISTER)
 	use_longlong(reg);
@@ -4705,8 +4679,8 @@
 void
 code_f2ull(int reg)
 {
-    set_freg(RET_FREGISTER,1);
-    extern_conv("__fixsfdi");
+    set_freg(FREGISTER_OPERAND,1);
+    extern_conv("__fixunssfdi");
     set_lreg(RET_LREGISTER,0);
     if (reg!=USE_CREG&&reg!=RET_LREGISTER)
 	use_longlong(reg);
@@ -4748,23 +4722,25 @@
 #endif
 
 static void
-ladd(int dreg,int dir)
+ladd(int dreg,int rreg,int v)   //   rreg = dreg + v
 {
-  int xreg;
-  char *dl=lregister_name_low(dreg);
-  char *dh=lregister_name_high(dreg);
-  char *xrn=register_name(xreg=get_register());
-  if (dir>0) {
-    printf("\tsltu %s,%s,1\n", xrn,dl);
-    printf("\taddu %s,%s,%d\n", dl,dl,dir);
-    printf("\taddu %s,%s,%s\n", dh,dh,xrn);
-  } else {
-    printf("\tsltu %s,%s,1\n", xrn,dl);
-    printf("\tsubu %s,%s,%d\n", dl,dl,-dir);
-    printf("\tsubu %s,%s,1\n", dh,dh);
-    printf("\taddu %s,%s,%s\n", dh,dh,xrn);
-  }
-  free_register(xreg);
+  int dx;
+  char *crn_l=lregister_name_low(dreg);
+  char *crn_h=lregister_name_high(dreg);
+  char *rrn_l=lregister_name_low(rreg);
+  char *rrn_h=lregister_name_high(rreg);
+  char *drn = register_name(dx = get_register());
+    if (v<0) {
+        printf("\tsubu %s,%s,%d\n",rrn_l,crn_l,-v);
+        printf("\tsltu %s,%s,%d\n",drn,rrn_l,v);
+        printf("\tsubu %s,%s,1\n",rrn_h,crn_h);
+        printf("\tsubu %s,%s,%s\n",rrn_h,rrn_h,drn);
+    } else {
+        printf("\taddu %s,%s,%d\n",rrn_l,crn_l,v);
+        printf("\tsltu %s,%s,%d\n",drn,rrn_l,v);
+        printf("\taddu %s,%s,%s\n",rrn_h,crn_h,drn);
+    }
+    free_register(dx);
 }
 
 void
@@ -4774,7 +4750,7 @@
     int dir=caddr(e1);
     if (car(e2)==LREGISTER) {
         use_longlong(reg);
-	ladd(cadr(e2),dir);
+	ladd(cadr(e2),cadr(e2),dir);
         if (cadr(reg)!=cadr(e2)) {
 	    lmove(cadr(reg),cadr(e2));
 	}
@@ -4791,7 +4767,7 @@
     }
     xreg = emit_pop(0);
     lload(xreg,dreg,0);
-    ladd(dreg,dir);
+    ladd(dreg,dreg,dir);
     code_lassign(xreg,dreg);
     emit_pop_free(xreg);
     if (dreg!=-1) free_register(dreg);
@@ -4805,7 +4781,7 @@
     if (car(e2)==LREGISTER) {
 	use_longlong(reg);
 	lmove(cadr(reg),cadr(e2));
-	ladd(cadr(e2),dir);
+	ladd(cadr(e2),cadr(e2),dir);
         return;
     } 
     g_expr(e2);
@@ -4820,7 +4796,7 @@
     }
     xreg = emit_pop(0);
     lload(xreg,dreg,0);
-    ladd(dreg,dir);
+    ladd(dreg,nreg,dir);
     code_lassign(xreg,nreg);
     emit_pop_free(xreg);
     free_register(nreg);
@@ -4844,16 +4820,16 @@
 	       register_name(edx));
 	edx = edx0;
     }
-    lload(edx0=edx,reg,0);
+    lload(edx,reg,0);
     // free_register(edx); don't do this, it will free pushed register
-    ltosop(op,reg,xreg);
+    ltosop(op,reg,xreg);    // loprtc?
+    emit_lpop_free(xreg);
     use_reg(reg);
     edx = emit_pop(0);
     code_lassign(edx,reg);
-    free_register(edx);
+    emit_pop_free(edx);
     if (edx0!=-1)
 	free_register(edx0);
-    emit_lpop_free(xreg);
 }
 
 void
--- a/mc-code-powerpc.c	Wed May 19 23:44:38 2004 +0900
+++ b/mc-code-powerpc.c	Fri May 21 00:57:27 2004 +0900
@@ -808,6 +808,70 @@
 register_usage(char *s)
 {
 #if 1
+    int i,j;
+#endif
+#define USAGE_MAX 4
+    if (chk) return;
+    if (!lsrc) return;
+    printf("# %d: %s:",lineno,s);
+    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
+    for(j=0,i=0;i<MAX_REGISTER;i++) if (regs[i]) j++;
+    if (j>USAGE_MAX) {
+	printf("\n# regs:");
+	for(i=0;i<MAX_REGISTER;i++) {  printf("%d",regs[i]); }
+    }
+    if (reg_sp>0) {
+	printf(" stack ");
+	for(i=reg_sp;i>0;i--) {
+	    if(reg_stack[i-1]>=0) {
+		printf(" %s",register_name(reg_stack[i-1]));
+            } else 
+		printf(",%d",reg_stack[i-1]);
+	}
+    }
+    for(j=0,i=0;i<MAX_FREGISTER;i++) if (regs[i+FREG_OFFSET]) j++;
+    if (j>USAGE_MAX) {
+	printf("\n# freg:");
+	for(i=0;i<MAX_FREGISTER;i++) {  printf("%d",regs[i+FREG_OFFSET]); }
+    }
+    if (freg_sp>0) {
+	printf(" fstack ");
+	for(i=freg_sp;i>0;i--) {
+	    if(freg_stack[i-1]>=0) {
+		printf(" %s",fregister_name(freg_stack[i-1]));
+            } else 
+		printf(",%d",freg_stack[i-1]);
+	}
+    }
+
+    for(j=0,i=0;i<REAL_MAX_LREGISTER;i++) if (regs[i+LREG_OFFSET]) j++;
+    if (j>USAGE_MAX) {
+	printf("\n# lreg:");
+	for(i=0;i<REAL_MAX_LREGISTER;i++) {  printf("%d",regs[i+LREG_OFFSET]); }
+    }
+    if (lreg_sp>0) {
+	printf(" lstack ");
+	for(i=lreg_sp;i>0;i--) {
+	    if(lreg_stack[i-1]>=0) {
+		printf(" %s",lregister_name_high(lreg_stack[i-1]));
+		printf(",%s",lregister_name_low(lreg_stack[i-1]));
+            } else 
+		printf(",%d",lreg_stack[i-1]);
+	}
+    }
+#endif
+    printf("\n");
+}
+
+#if 0
+void
+register_usage(char *s)
+{
+#if 1
     int i;
 #endif
     if (chk) return;
@@ -843,6 +907,7 @@
 #endif
     printf("\n");
 }
+#endif
 
 void
 
@@ -1158,8 +1223,8 @@
 	use_int(reg);
 	printf("\taddi %s,%s,%d\n", 
 		register_name(cadr(e2)),register_name(cadr(e2)), dir);
-	if (cadr(reg)!=e2)
-	    printf("\tmr %s,%s\n",register_name(cadr(reg)),register_name(e2));
+	if (cadr(e2)!=reg)
+	    printf("\tmr %s,%s\n",register_name(reg),register_name(cadr(e2)));
 	return;
     } 
     g_expr(e2);
@@ -3266,13 +3331,23 @@
 }
 
 void
-dtosop(int op,int reg,int e1)
+dtosop(int op,int reg,int oreg)
 { 
     char *opn="";
     char *frn;
-    char *grn=fregister_name(e1);
+    char *grn;
+    int ox = -1;
 
     use_float(1,reg);
+    if(oreg==-1) {
+        error(-1);
+    } else if (oreg<= -REG_LVAR_OFFSET) {
+        ox = get_dregister(1); if (ox<0) error(-1);
+        use_reg(ox);
+        code_drlvar(oreg+REG_LVAR_OFFSET,1,ox);
+        oreg = ox;
+    }
+    grn=fregister_name(oreg);
     frn=fregister_name(reg);
     switch(op) {
     case FADD:
@@ -3286,17 +3361,18 @@
     case FCMP:
     case DCMP: 
 	printf("\tfcmpu cr7,%s,%s\n",frn,grn);
-	free_register(e1);
+	if (ox!=-1) free_register(ox);
 	return;
     case FCMPGE: 
     case DCMPGE: 
 	printf("\tfcmpu cr7,%s,%s\n",frn,grn);
-	free_register(e1);
+	if (ox!=-1) free_register(ox);
 	return;
     default:
 	error(-1); return;
     }
     printf("\t%s %s,%s,%s\n",opn,frn,frn,grn);
+    if (ox!=-1) free_register(ox);
 }
 
 void
@@ -3325,36 +3401,46 @@
     emit_dpop_free(xreg,d);
 }   
 
+static int
+code_dload_1(int d)
+{
+    int r,g;
+    char *drn,*grn;
+    // load 1
+    float_one_lib_used=1;
+    r = get_ptr_cache(&float_one);
+    drn=register_name(r);
+    grn=fregister_name(g=get_dregister(d));
+    printf("\tlfs %s,0(%s)\n",grn,drn);
+    return g;
+}
+
 void
 code_dpreinc(int e1,int e2,int d,int reg) {
-    char *frn;
-    char *crn;
+    char *frn,*crn,*grn;
     int  g;
-    char *grn,*drn;
-    int r;
 
     if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
 	crn=register_name(cadr(e2));
+        grn = fregister_name(g = code_dload_1(d));
+	if (reg==USE_CREG) {
+	    reg=get_dregister(d); if (!reg) error(-1);
+	    set_freg(reg,0);
+	}
+	frn=fregister_name(reg);
+	printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn);
+	if (use && reg!=cadr(e2))
+	    printf("\tfmr %s,%s\n",frn,crn);
     } else {
 	g_expr(e2);
 	if (!is_int_reg(creg)) error(-1);
 	crn=register_name(ireg);
-    }
-
-    float_one_lib_used=1;
-    r = get_ptr_cache(&float_one);
-    drn=register_name(r);
-
-    use_float(d,reg);
-
-    frn=fregister_name(reg);
-    grn=fregister_name(g=get_dregister(d));
-    printf("\tlfs %s,0(%s)\n",grn,drn);
-
-    if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
-	printf("\tfmr %s,%s\n",crn,frn);
-	printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,frn,grn);
-    } else {
+	if (reg==USE_CREG) {
+	    reg=get_dregister(d); if (!reg) error(-1);
+	    set_freg(reg,0);
+	}
+	frn=fregister_name(reg);
+        grn = fregister_name(g = code_dload_1(d));
 	printf("\t%s %s,0(%s)\n",fload(d),frn,crn);
 	printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",frn,frn,grn);
 	printf("\t%s %s,0(%s)\n",fstore(d),frn,crn);
@@ -3364,34 +3450,30 @@
 
 void
 code_dpostinc(int e1,int e2,int d,int reg) {
-    char *frn;
-    char *crn;
+    char *frn,*crn,*grn;
     int  g;
-    char *grn,*drn;
-    int r;
 
     if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
 	crn=register_name(cadr(e2));
+        grn = fregister_name(g = code_dload_1(d));
+	if (reg==USE_CREG) {
+	    reg=get_dregister(d); if (!reg) error(-1);
+	    set_freg(reg,0);
+	}
+	frn=fregister_name(reg);
+	if (use && reg!=cadr(e2))
+	    printf("\tfmr %s,%s\n",frn,crn);
+	printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn);
     } else {
 	g_expr(e2);
 	if (!is_int_reg(creg)) error(-1);
-	crn=register_name(creg);
-    }
-
-    float_one_lib_used=1;
-    r = get_ptr_cache(&float_one);
-    drn=register_name(r);
-
-    use_float(d,reg);
-
-    frn=fregister_name(reg);
-    grn=fregister_name(g=get_dregister(d));
-    printf("\tlfs %s,0(%s)\n",grn,drn);
-
-    if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
-	printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",frn,crn,grn);
-	printf("\tfmr %s,%s\n",frn,crn);
-    } else {
+	crn=register_name(ireg);
+	if (reg==USE_CREG) {
+	    reg=get_dregister(d); if (!reg) error(-1);
+	    set_freg(reg,0);
+	}
+	frn=fregister_name(reg);
+        grn = fregister_name(g = code_dload_1(d));
 	printf("\t%s %s,0(%s)\n",fload(d),frn,crn);
 	printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",grn,frn,grn);
 	printf("\t%s %s,0(%s)\n",fstore(d),grn,crn);
@@ -3483,7 +3565,7 @@
 
 /* 64bit int part */
 static void
-lmove(int to,int from)
+lmove(int to,int from)   //   to = from
 {
     int tmp;
     if (regv_h(to)==regv_l(from)&&(regv_l(to)==regv_h(from))) {
@@ -3975,7 +4057,7 @@
     } else if (oreg<= -REG_LVAR_OFFSET) {
 	ox = get_lregister(); if (ox<0) error(-1);
 	use_reg(ox);
-        code_rlvar(oreg+REG_LVAR_OFFSET,ox);
+        code_lrlvar(oreg+REG_LVAR_OFFSET,ox);
 	oreg = ox;
     }
 
@@ -4027,8 +4109,8 @@
 	break;
     case LMUL:
     case LUMUL:
-	code_save_stacks();
-	clear_ptr_cache();
+	// code_save_stacks();
+	// clear_ptr_cache();
 	dx=get_lregister();
 	use_reg(dx);
 	drn_l = lregister_name_low(dx);
@@ -4332,26 +4414,25 @@
 
 #endif
 
-static char *
-addze(int dir)
+static void
+ladd(int creg,int reg,int dir)   // creg=reg+dir
 {
-    return dir>0?"ze":"me";
+    printf("\taddic %s,%s,%d\n", 
+	    lregister_name_low(creg),lregister_name_low(reg), dir);
+    printf("\tadd%s %s,%s\n", dir>0?"ze":"me",
+	    lregister_name_high(creg),lregister_name_high(reg));
 }
 
 void
 code_lpreinc(int e1,int e2,int reg)
 {
-    char *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));
+	ladd(cadr(e2),cadr(e2),dir);
+        if (reg!=cadr(e2)) {
+	    lmove(reg,cadr(e2));
 	}
         return;
     } 
@@ -4366,10 +4447,7 @@
     }
     xreg = emit_pop(0);
     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);
+    ladd(dreg,dreg,dir);
     code_lassign(xreg,dreg);
     emit_pop_free(xreg);
 }
@@ -4377,37 +4455,28 @@
 void
 code_lpostinc(int e1,int e2,int reg)
 {
-    char *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)));
+	if (reg!=cadr(e2))
+	    lmove(reg,cadr(e2));
+	ladd(cadr(e2),cadr(e2),dir);
         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);
 	set_lreg(dreg,0);  // free old lreg==creg
     } else {
         dreg = reg;
     }
-    drn_l = lregister_name_low(dreg);
-    drn_h = lregister_name_high(dreg);
     xreg = emit_pop(0);
     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);
+    ladd(nreg,dreg,dir);
     code_lassign(xreg,nreg);
     emit_pop_free(xreg);
     free_register(nreg);
--- a/mc-codegen.c	Wed May 19 23:44:38 2004 +0900
+++ b/mc-codegen.c	Fri May 21 00:57:27 2004 +0900
@@ -1491,10 +1491,11 @@
 
     g_expr(e3);
     if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
+        emit_dpush(d);
 	code_register_dassop(cadr(e2),op,d);
-	if (use)
-	    code_dregister(cadr(e2),USE_CREG,d);
-	return;
+        if (use)
+            code_dregister(cadr(e2),USE_CREG,d);
+        return;
     }
     emit_dpush(d);
     g_expr(e2);
--- a/mc-parse.c	Wed May 19 23:44:38 2004 +0900
+++ b/mc-parse.c	Fri May 21 00:57:27 2004 +0900
@@ -2049,13 +2049,16 @@
 float_value(int e2,int type)
 {
 #if FLOAT_CODE
+#if LONGLONG_CODE
+    if (car(e2)==LCONST)  return  dlist2(FCONST,(double)lcadr(e2));
+    if(type==LONGLONG) return list3(CONV,rvalue_t(e2,type),LL2F);
+    if(type==ULONGLONG) return list3(CONV,rvalue_t(e2,type),ULL2F);
+#endif
     if (car(e2)==CONST)  return dlist2(FCONST,(double)cadr(e2));
     if (car(e2)==DCONST)  return dlist2(FCONST,dcadr(e2));
     if(type==FLOAT) return e2;
     if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2F);
     if(type==UNSIGNED) return list3(CONV,rvalue_t(e2,type),U2F);
-    if(type==LONGLONG) return list3(CONV,rvalue_t(e2,type),LL2F);
-    if(type==ULONGLONG) return list3(CONV,rvalue_t(e2,type),ULL2F);
     if(integral(type)) return list3(CONV,rvalue_t(e2,type),I2F);
     error(TYERR); return dlist2(DCONST,1.0);
 #else
@@ -2070,7 +2073,8 @@
     if (car(e2)==CONST)  return llist2(LCONST,(long long)cadr(e2));
     if (car(e2)==LCONST)  return e2;
 #if FLOAT_CODE
-    if (car(e2)==DCONST)  return llist2(LCONST,(long long)dcadr(e2));
+    if (car(e2)==DCONST||car(e2)==FCONST) 
+	return llist2(LCONST,(long long)dcadr(e2));
     if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2LL);
     if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2LL);
 #endif
@@ -2091,7 +2095,8 @@
     if (car(e2)==CONST)  return llist2(LCONST,(unsigned long long)cadr(e2));
     if (car(e2)==LCONST)  return e2;
 #if FLOAT_CODE
-    if (car(e2)==DCONST)  return llist2(LCONST,(unsigned long long)dcadr(e2));
+    if (car(e2)==DCONST||car(e2)==FCONST) 
+	return llist2(LCONST,(unsigned long long)dcadr(e2));
     if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2ULL);
     if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2ULL);
 #endif
@@ -2114,6 +2119,7 @@
     if(type==FLOAT||type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2I);
 #endif
 #if LONGLONG_CODE
+    if (car(e2)==LCONST)  return list2(CONST,(int)lcadr(e2));
     if(type==LONGLONG) return list3(CONV,rvalue_t(e2,type),LL2I);
     if(type==ULONGLONG) return list3(CONV,rvalue_t(e2,type),ULL2I);
 #endif
--- a/test/code-gen.c	Wed May 19 23:44:38 2004 +0900
+++ b/test/code-gen.c	Fri May 21 00:57:27 2004 +0900
@@ -142,7 +142,8 @@
 {
     int i,j;
     i = 123123123;j = 0;
-    printf("code_preinc i %d %d\n",++i,--j);
+    printf("code_preinc i %d %d",++i,--j);
+    printf(" %d %d\n",i,j);
 }
 
 // code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) 
@@ -151,7 +152,8 @@
 {
     unsigned int i,j;
     i = 123123123;j = 0;
-    printf("code_upreinc u %d %d\n",i++,j--);
+    printf("code_upreinc u %d %d",i++,j--);
+    printf(" %d %d\n",i,j);
 }
 
 // code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) 
@@ -160,7 +162,8 @@
 {
     int i,j;
     i = 123123123;j = 0;
-    printf("code_postinc i %d %d\n",i++,j--);
+    printf("code_postinc i %d %d",i++,j--);
+    printf(" %d %d\n",i,j);
 }
 
 // code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) 
@@ -169,7 +172,48 @@
 {
     unsigned int i,j;
     i = 123123123;j = 0;
-    printf("code_upreinc u %d %d\n",++i,--j);
+    printf("code_upreinc u %d %d",++i,--j);
+    printf(" %d %d\n",i,j);
+}
+
+// code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) 
+void
+code_register_preinc()
+{
+    register int i,j;
+    i = 123123123;j = 0;
+    printf("code_preinc i r %d %d",++i,--j);
+    printf(" %d %d\n",i,j);
+}
+
+// code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) 
+void
+code_register_upostinc()
+{
+    register unsigned int i,j;
+    i = 123123123;j = 0;
+    printf("code_upreinc u r %d %d",i++,j--);
+    printf(" %d %d\n",i,j);
+}
+
+// code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) 
+void
+code_register_postinc()
+{
+    register int i,j;
+    i = 123123123;j = 0;
+    printf("code_postinc i r %d %d",i++,j--);
+    printf(" %d %d\n",i,j);
+}
+
+// code_register_preinc(int e1,int e2,int dir,int sign,int sz,int reg) 
+void
+code_register_upreinc()
+{
+    register unsigned int i,j;
+    i = 123123123;j = 0;
+    printf("code_upreinc u r %d %d",++i,--j);
+    printf(" %d %d\n",i,j);
 }
 
 // code_return(int creg) 
@@ -844,7 +888,7 @@
     register double d0,d1;
     f0 = 0.0; f1 = 0.2;
     d0 = 10; d1 = 10e10;
-    printf("code_lvar float %f %f %g %g\n",f0,f1,d0,d1);
+    printf("code_lvar float r %f %f %g %g\n",f0,f1,d0,d1);
 }
 
 // code_dassign_gvar(int e2,int freg,int d)
@@ -976,10 +1020,10 @@
 {
     f0 = 0.0; f1 = 0.2;
     d0 = 10; d1 = 10e10;
-    printf("code_gvar float %f %f %g %g\n",f0,f1,d0,d1);
+    printf("code_gvar float 1 %f %f %g %g\n",f0,f1,d0,d1);
     s_f0 = 0.0; s_f1 = 0.2;
     s_d0 = 10; s_d1 = 10e10;
-    printf("code_gvar float %f %f %g %g\n",s_f0,s_f1,s_d0,s_d1);
+    printf("code_gvar float 2 %f %f %g %g\n",s_f0,s_f1,s_d0,s_d1);
 }
 
 // code_drlvar(int e2,int d,int freg)
@@ -1081,6 +1125,34 @@
     printf("code_dassop 4 %g\n",ui1);
 }
 
+// code_dassop(int op,int d) 
+void
+code_register_dassop()
+{
+    register double i1,i2; 
+    register float ui1,ui2; 
+    i1 = -555; i2= 555;
+    ui1 = 632423423; ui2= 32394234;
+
+    i1 += 3;
+    printf("code_dassop r 1 %g\n",i1);
+    i1 -= 3;
+    printf("code_dassop r 2 %g\n",i1);
+    i1 /= 3;
+    printf("code_dassop r 3 %g\n",i1);
+    i1 *= 3;
+    printf("code_dassop r 4 %g\n",i1);
+
+    ui1 += 3;
+    printf("code_dassop r 1 %g\n",ui1);
+    ui1 -= 3;
+    printf("code_dassop r 2 %g\n",ui1);
+    ui1 /= 3;
+    printf("code_dassop r 3 %g\n",ui1);
+    ui1 *= 3;
+    printf("code_dassop r 4 %g\n",ui1);
+}
+
 
 // code_dpreinc(int e1,int e2,int d,int reg) 
 void
@@ -1089,9 +1161,11 @@
     double i,j;
     float ui,uj;
     i = 123123123;j = 0;
-    printf("code_dpreinc d %g %g\n",++i,--j);
+    printf("code_dpreinc d %g %g",++i,--j);
+    printf(" %g %g\n",i,j);
     ui = 123123123;uj = 0;
-    printf("code_dpreinc f %g %g\n",++ui,--uj);
+    printf("code_dpreinc f %g %g",++ui,--uj);
+    printf(" %g %g\n",ui,uj);
 }
 
 // code_dpostinc(int e1,int e2,int d,int reg) 
@@ -1101,9 +1175,39 @@
     double i,j;
     float ui,uj;
     i = 123123123;j = 0;
-    printf("code_dpostinc d %g %g\n",i--,j--);
+    printf("code_dpostinc d %g %g",i--,j--);
+    printf(" %g %g\n",i,j);
+    ui = 123123123;uj = 0;
+    printf("code_dpostinc f %g %g",ui++,uj--);
+    printf(" %g %g\n",ui,uj);
+}
+
+// code_dpreinc(int e1,int e2,int d,int reg) 
+void
+code_register_dpreinc()
+{
+    register double i,j;
+    register float ui,uj;
+    i = 123123123;j = 0;
+    printf("code_dpreinc r d %g %g",++i,--j);
+    printf(" %g %g\n",i,j);
     ui = 123123123;uj = 0;
-    printf("code_dpostinc f %g %g\n",ui++,uj--);
+    printf("code_dpreinc r f %g %g",++ui,--uj);
+    printf(" %g %g\n",ui,uj);
+}
+
+// code_dpostinc(int e1,int e2,int d,int reg) 
+void
+code_register_dpostinc()
+{
+    register double i,j;
+    register float ui,uj;
+    i = 123123123;j = 0;
+    printf("code_dpostinc r d %g %g",i--,j--);
+    printf(" %g %g\n",i,j);
+    ui = 123123123;uj = 0;
+    printf("code_dpostinc r f %g %g",ui++,uj--);
+    printf(" %g %g\n",ui,uj);
 }
 
 // drexpr(int e1, int e2,int l1, int op)
@@ -1640,7 +1744,8 @@
 {
     long long i,j;
     i = 123123123;j = 0;
-    printf("code_preinc l %lld %lld\n",++i,--j);
+    printf("code_preinc l %lld %lld",++i,--j);
+    printf(" %lld %lld\n",i,j);
 }
 
 // code_lpostinc(int e1,int e2,int reg)
@@ -1649,25 +1754,68 @@
 {
     long long i,j;
     i = 123123123;j = 0;
-    printf("code_postinc l %lld %lld\n",i++,j--);
+    printf("code_postinc l %lld %lld",i++,j--);
+    printf(" %lld %lld\n",i,j);
 }
 
 // code_lpreinc(int e1,int e2,int reg)
 void
 code_lupreinc()
 {
-    unsigned long long i,j;
+    register unsigned long long i,j;
     i = 123123123;j = 0;
-    printf("code_preinc l %llu %llu\n",++i,--j);
+    printf("code_preinc l %llu %llu",++i,--j);
+    printf(" %lld %lld\n",i,j);
 }
 
 // code_lpostinc(int e1,int e2,int reg)
 void
 code_lupostinc()
 {
-    unsigned long long i,j;
+    register unsigned long long i,j;
+    i = 123123123;j = 0;
+    printf("code_postinc lu %llu %llu",i++,j--);
+    printf(" %lld %lld\n",i,j);
+}
+
+// code_lpreinc(int e1,int e2,int reg)
+void
+code_register_lpreinc()
+{
+    register long long i,j;
+    i = 123123123;j = 0;
+    printf("code_preinc l r %lld %lld",++i,--j);
+    printf(" %lld %lld\n",i,j);
+}
+
+// code_lpostinc(int e1,int e2,int reg)
+void
+code_register_lpostinc()
+{
+    register long long i,j;
     i = 123123123;j = 0;
-    printf("code_postinc lu %llu %llu\n",i++,j--);
+    printf("code_postinc l r %lld %lld",i++,j--);
+    printf(" %lld %lld\n",i,j);
+}
+
+// code_lpreinc(int e1,int e2,int reg)
+void
+code_register_lupreinc()
+{
+    register unsigned long long i,j;
+    i = 123123123;j = 0;
+    printf("code_preinc l r %llu %llu",++i,--j);
+    printf(" %lld %lld\n",i,j);
+}
+
+// code_lpostinc(int e1,int e2,int reg)
+void
+code_register_lupostinc()
+{
+    register unsigned long long i,j;
+    i = 123123123;j = 0;
+    printf("code_postinc lu r %llu %llu",i++,j--);
+    printf(" %lld %lld\n",i,j);
 }
 
 // code_lassop(int op)