changeset 398:bf583e04936f

ARM continue... calling sequence, float/duble arg function
author kono
date Fri, 15 Oct 2004 13:33:03 +0900
parents 33a09aa401ba
children 9d0015a1fa54
files .gdbinit Changes mc-code-arm.c mc-code-mips.c
diffstat 4 files changed, 135 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Fri Oct 15 02:08:06 2004 +0900
+++ b/.gdbinit	Fri Oct 15 13:33:03 2004 +0900
@@ -5,8 +5,8 @@
 # run  -s nkf203/nkf.c
 # run  -s -ob01.s mc-switch.c
 # run  -s l.c
-run  -s test/const.c
-# run  -s test/basic.c
+# run  -s test/const.c
+run  -s test/basic.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
--- a/Changes	Fri Oct 15 02:08:06 2004 +0900
+++ b/Changes	Fri Oct 15 13:33:03 2004 +0900
@@ -6023,3 +6023,24 @@
 (gdb) quit
 
 うーむ。
+
+Fri Oct 15 08:46:59 JST 2004
+
+        mov     ip, sp
+        stmfd   sp!, {fp, ip, lr, pc}
+        sub     fp, ip, #4
+        sub     sp, sp, #16
+        str     r0, [fp, #-16]    引数1
+        str     r1, [fp, #-20]    引数2
+        str     r2, [fp, #-24]    引数3
+        str     r3, [fp, #-28]    引数4
+           ...
+        ldr     r2, [fp, #4]      引数5
+        add     r3, r3, r2
+        ldr     r2, [fp, #8]      引数6
+
+そうか。レジスタの引数分はメモリには取られないで、局所変数側
+におかれるらしい。spは、stmfd で自動的に調製されるから、sub sp
+は局所変数分だけ。fp の#4は戻り番地だけ?
+
+でも、それだと va_next が困るんだけど。
--- a/mc-code-arm.c	Fri Oct 15 02:08:06 2004 +0900
+++ b/mc-code-arm.c	Fri Oct 15 13:33:03 2004 +0900
@@ -46,13 +46,15 @@
 static void code_float_lib_c(char *lib,int from,int to,double value);
 static void code_double_lib(char *lib,int to,int reg,int oreg);
 static void code_double_lib_c(char *lib,int from,int to,double value);
+static void dconst(int l,int h,double value);
+
 #endif
 
 static int creg;
 static int output_mode = TEXT_EMIT_MODE;
 static int register_save_return_label;
 
-static int r1_offset_label;
+// static int r1_offset_label;
 static int lvar_offset_label;
 static int    max_func_args = 0;
 
@@ -105,8 +107,8 @@
 
 int MAX_INPUT_REGISTER_VAR = 4;
 int MAX_CODE_INPUT_REGISTER_VAR = 9-MIN_TMP_REG;
-int MAX_INPUT_DREGISTER_VAR = 0;
-int MAX_INPUT_FREGISTER_VAR = 0;
+int MAX_INPUT_DREGISTER_VAR = 4;
+int MAX_INPUT_FREGISTER_VAR = 4;
 int MAX_CODE_INPUT_DREGISTER_VAR = 3-MIN_TMP_FREG;
 int MAX_CODE_INPUT_FREGISTER_VAR = 7-MIN_TMP_FREG;
 
@@ -302,12 +304,14 @@
 
 code segment stack frame
 
+register_save is done by callee
+
                  * gotoを呼び出した関数のr1 ! r1(goto前のr1)
-   #             *                           $fp <---r1_offset---------> $sp
-r+ +----------+--+----------+----------------+-----------+----------+----+
-    cousin arg xx  reg save !callee arg      !code local  caller arg  xx
-              ($fp)r20-r29     lvar>0         lvar<0      lvar>0x1000 000
-                   f20-f31  <-my_func_args--><--disp-----><-max_func_arg->
+   #             *             $fp <-----------------r1_offset---------> $sp
+r+ +----------+-------------+--------+-------+-----------+----------+----+
+    cousin arg!  callee arg !reg_save!reg_arg!code local  caller arg  xx
+                    (arg4..)  lvar>0 (arg0.3) lvar<0      lvar>0x1000 000
+                  <-----------my_func_args--><--disp-----><-max_func_arg->
                               *SIZE_OF_INT                  *SIZE_OF_INT
                  prev $sp=$fp                 $fp                        $sp
 
@@ -322,9 +326,9 @@
                       prev $sp=$fp                                   $sp=$fp
  */
 
-#define arg_offset 0
+#define arg_offset (-12)
 #define arg_offset1 (-16)
-int disp_offset = 0;
+int disp_offset=0;    // fore mc-codegen.c
 #define disp_offset  0
 
 #define func_disp_offset 8
@@ -340,25 +344,16 @@
 static int
 code_offset_set(NMTBL *fnptr)
 {
-    int lvar_offsetv,r1_offsetv;
+    int lvar_offsetv;
     // int code_f = (fnptr->sc==CODE);
 
     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);
-
+    lvar_offsetv = 
+	-12 - max_reg_var*SIZE_OF_INT-max_freg_var*SIZE_OF_FLOAT;
 // printf("        @ args = %d, pretend = %d, frame = %d\n",
 // 	max_func_args,0,round16(-disp));
 // printf("        @ frame_needed = 1, current_function_anonymous_args = 0\n");
-// printf("\t.set .L%d, %d\n",lvar_offset_label,lvar_offsetv);
-printf("\t.set .L%d, %d\n",lvar_offset_label,-16);
-printf("\t.set .L%d, %d\n",r1_offset_label,r1_offsetv);
-
+    printf("\t.set .L%d, %d\n",lvar_offset_label,lvar_offsetv);
 
 #if 0
 printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
@@ -368,8 +363,7 @@
 	round16(max_func_args*SIZE_OF_INT),
 	0
 );
-   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("# callee arg top=\t%d\n",CALLEE_ARG(0));
    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+
@@ -383,7 +377,7 @@
    printf("#\n");
 #endif
 
-    return r1_offsetv;
+    return 0;
 }
 
 #define LARGE_OFFSET(l) (l<-511||l>511)
@@ -430,12 +424,10 @@
             printf("[fp, #%d]%s\n",CODE_LVAR(l),cext);
     } else if (l<0) {  /* local variable */
         printf("[fp, #%d+.L%d]%s\n",FUNC_LVAR(l),lvar_offset_label,cext);
-//        printf("[fp, #%d]%s\n",FUNC_LVAR(l),cext);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
         printf("[sp, #%d]%s\n",CALLER_ARG(l-ARG_LVAR_OFFSET),cext);
     } else { /* callee's arguments */
-        printf("[fp, #%d+.L%d]%s\n",CALLEE_ARG(l),r1_offset_label,cext);
-//        printf("[fp, #%d]%s\n",CALLEE_ARG(l),cext);
+        printf("[fp, #%d]%s\n",CALLEE_ARG(l),cext);
     }
 }
 
@@ -460,12 +452,7 @@
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
 	code_add(creg,CALLER_ARG(l-ARG_LVAR_OFFSET),REG_sp);
     } else { /* callee's arguments */
-//        printf("\tsub\t%s, fp, #%d+.L%d\n",
-//		register_name(creg),CALLEE_ARG(l),r1_offset_label);
-	trn = register_name(tmp = get_register());
-	disp = search_const(LVAR,glist2(r1_offset_label,CALLEE_ARG(l)),&label);
-        printf("\tldr\t%s, .L%d+%d\n",trn,label,disp);
-	printf("\tsub\t%s, fp, %s\n",register_name(creg),trn);
+	code_add(creg,CALLEE_ARG(l),REG_fp);
     }
     if (tmp!=-1) free_register(tmp);
 }
@@ -591,7 +578,7 @@
 		}
 	    } else {
 		if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) {
-		    n->sc = REGISTER;
+		    n->sc = FREGISTER;
 		    n->dsp = cadr(reg);
 		    regs[n->dsp]= INPUT_REG;
 		    freg_var++;
@@ -863,7 +850,6 @@
 	}
     }
     if (d) {
-	// if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0;
 	j = get_input_lregister_var(i,n,is_code);
 	return j;
     } else {
@@ -880,14 +866,13 @@
 {
     int ll;
     ll = get_lregister0();
-    if (i!=-1) {
+    if (ll!=-1) {
 	if (is_code) {
 	    if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0;
 	    i = REG_VAR_BASE-i;
 	} else {
 	    if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0;
-	    i = i+MIN_TMP_REG;
-            if (i%2==1) i++;
+	    i++;
 	}
 #if ENDIAN==0
 	regv_l(ll)=i;
@@ -2146,13 +2131,13 @@
 	if (!n||n==&null_nptr) error(REG_ERR);
 	if (tag==REGISTER) {
 	    /* regs[reg]==INPUT_REG case should be considered */
-	    n->dsp = offset;
+	    n->dsp = new_lvar(SIZE_OF_INT);
 	    offset+=SIZE_OF_INT;
 	    t = INT;
 	    reg_var++;
 	} else if (tag==LREGISTER) {
 	    /* regs[reg]==INPUT_REG case should be considered */
-	    n->dsp = offset;
+	    n->dsp = new_lvar(SIZE_OF_LONGLONG);
 	    // t = n->ty;
 	    t = LONGLONG;
 	    offset+=SIZE_OF_LONGLONG; reg_offset+=2;
@@ -2202,6 +2187,7 @@
     return ARG_LVAR_OFFSET+arg*SIZE_OF_INT;
 }
 
+
 void
 use_input_reg(int reg,int mode)
 {
@@ -2248,6 +2234,64 @@
     if (mode) use_reg(reg);
 }
 
+static void
+code_assign_input_float_int(int e1,int e2) {
+    int r,tmp=-1;
+    float f;
+    char *frn;
+    //  e1 = e2;
+    if (car(e1)!=REGISTER) { error(-1); return; }
+    frn = register_name(r=cadr(e1));
+    switch(car(e2)) {
+    case FCONST:
+        f = dcadr(e2);
+	code_const(*((int*)&f),r);
+        break;
+    case FRGVAR:
+	code_rgvar(e2,r);
+        break;
+    case FRLVAR:
+	code_rlvar(cadr(e2),r);
+	break;
+    default:
+        g_expr(e2);
+    case FREGISTER:
+	tmp = new_lvar(SIZE_OF_INT);
+	code_dassign_lvar(tmp, (car(e2)==FREGISTER)?cadr(e2):freg,0);
+	code_rlvar(tmp,r);
+	if (tmp!=-1) free_lvar(tmp);
+    }
+}
+
+static void
+code_assign_input_double_long(int e1,int e2) {
+    int r,tmp=-1,reg;
+    double value;
+    //  e1 = e2;
+    if (car(e1)!=LREGISTER) { error(-1); return; }
+    r=cadr(e1);
+    switch(car(e2)) {
+    case DCONST:
+        value = dcadr(e2);
+	dconst(regv_l(r),regv_h(r),value);
+        break;
+    case DRGVAR:
+	code_lrgvar(e2,r);
+        break;
+    case DRLVAR:
+	code_lrlvar(cadr(e2),r);
+	break;
+    default:
+        g_expr(e2);
+	reg = freg;
+    case DREGISTER:
+	if (car(e2)==DREGISTER) reg = cadr(e2);
+        printf("\tstfd\t%s, [sp, #-8]!\n",fregister_name(reg));
+        printf("\tldmfd\tsp!, {%s, %s}\n",lregister_name_low(r),lregister_name_high(r));
+    }
+    if (tmp!=-1) free_lvar(tmp);
+}
+
 static int
 compute_complex_arg(int e3,int reg_arg_list,int arg) {
     int t=caddr(e3);
@@ -2256,7 +2300,12 @@
     if (car(arg)==REGISTER||car(arg)==DREGISTER||
 	car(arg)==FREGISTER||car(arg)==LREGISTER)
 	use_input_reg(cadr(arg),1);
-    g_expr_u(assign_expr0(arg,e4,t,t));
+    if (t==FLOAT&&car(arg)==REGISTER)
+	code_assign_input_float_int(arg, e4);
+    else if (t==DOUBLE&&car(arg)==LREGISTER)
+	code_assign_input_double_long(arg, e4);
+    else
+	g_expr_u(assign_expr0(arg,e4,t,t));
     car(e3) = arg;
     return reg_arg_list;
 }
@@ -2316,8 +2365,6 @@
 	} else
 	    return get_input_dregister_var(freg_arg,0,0,0);
     } else if (t==DOUBLE) {
-        if (reg_arg%2==1) reg_arg++;  // alignment
-        if (nargs%2==1) nargs++;  // alignment
 	if (mode==AS_SAVE) {
 	    return get_dregister_var(0,1);
 	} else if (reg_arg+1>=MAX_INPUT_DREGISTER_VAR) {
@@ -2498,17 +2545,17 @@
 	    g_expr_u(assign_expr0(arg,e4,t,t));
 	} else if (t==DOUBLE) {
 	    reg_arg_list = list2(arg,reg_arg_list);
-	    if (car(arg)==DREGISTER)
+	    if (car(arg)==LREGISTER) {
 		use_input_reg(cadr(arg),1);
-	    g_expr_u(assign_expr0(arg,e4,t,t));
+                code_assign_input_double_long(arg, e4);
+	    } else {
+		g_expr_u(assign_expr0(arg,e4,t,t));
+	    }
 	} else if (t==FLOAT) {
 	    reg_arg_list = list2(arg,reg_arg_list);
-            if (car(arg)==FREGISTER) {
+            if (car(arg)==REGISTER) {
                 use_input_reg(cadr(arg),1);/* protect from input register free */
-                g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */
-
-
-
+                code_assign_input_float_int(arg, e4);
             } else {
                 g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */
             }
@@ -3198,7 +3245,7 @@
     max_func_args = 0;
 
     lvar_offset_label = fwdlabel();
-    r1_offset_label = fwdlabel();
+    // r1_offset_label = fwdlabel();
     printf("\t.type\t%s,function\n",name);
     if (stmode!=STATIC)
 	printf("\t.globl\t%s\n",name);
@@ -3222,7 +3269,6 @@
 leave(int control, char *name)
 {
     int retcont1=0,sz;
-    int r1_offsetv;
 
     if (control) {
 	code_set_return_register(1);
@@ -3263,18 +3309,20 @@
     }
     fwddef(retlabel);
 
-    r1_offsetv = code_offset_set(fnptr);
-    code_register_restore(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2);
+    code_offset_set(fnptr);
+    code_register_restore(max_reg_var,max_freg_var,0);
 
 //  leave part end
 
 //  entry part  (save register)
 
     fwddef(entry_label);
-    code_register_save(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2);
-
-    code_add(REG_fp,-4,REG_ip);
-    code_add(REG_sp,disp,REG_sp);
+    code_register_save(max_reg_var,max_freg_var,0);
+
+    // code_add(REG_fp,-4,REG_ip);
+    printf("\tsub\tfp, ip, #4\n");
+
+    code_add(REG_sp,disp-max_func_args*SIZE_OF_INT,REG_sp);
     jmp(register_save_return_label);
     local_table();
 
@@ -3606,8 +3654,6 @@
 #define  set_double(freg) if (regs[freg]) {regs[freg]=USING_DREG;}
 #define  set_float(freg) if (regs[freg]) {regs[freg]=USING_DREG;}
 
-static void dconst(int l,int h,double value);
-
 void
 code_cmp_dregister(int e2,int d,int label,int cond)
 {
--- a/mc-code-mips.c	Fri Oct 15 02:08:06 2004 +0900
+++ b/mc-code-mips.c	Fri Oct 15 13:33:03 2004 +0900
@@ -1962,7 +1962,10 @@
     if (car(arg)==REGISTER||car(arg)==DREGISTER||
 	car(arg)==FREGISTER||car(arg)==LREGISTER)
 	use_input_reg(cadr(arg),1);
-    g_expr_u(assign_expr0(arg,e4,t,t));
+    if (t==FLOAT&&car(arg)==REGISTER)
+	code_assign_input_float_int(list3(FASS_INPUT, arg, e4));
+    else
+	g_expr_u(assign_expr0(arg,e4,t,t));
     car(e3) = arg;
     return reg_arg_list;
 }