diff mc-code-powerpc.c @ 258:22949117768f

Complex function argments. Struct is done. Long long is odd.
author kono
date Sat, 15 May 2004 20:07:24 +0900
parents e2f5671c413d
children 18837238e306
line wrap: on
line diff
--- a/mc-code-powerpc.c	Sat May 15 12:05:17 2004 +0900
+++ b/mc-code-powerpc.c	Sat May 15 20:07:24 2004 +0900
@@ -127,6 +127,8 @@
     "f30","f31"
 }; 
 
+#define round4(i)   ((i+3)&~3)
+
 #define register_name(i)  reg_name[i]
 #define fregister_name(i) reg_name[i]
 #define lregister_name_low(i) reg_name[regv_l(i)]
@@ -1405,14 +1407,16 @@
 	printf("\tstw %s,%d(%s)\n",drn,offset,trn);
 	break;
     default:
-	if (-MAX_COPY_LEN<length && length <0) {
-	    for(;length<=4;length+=4,offset-=4)
-		emit_copy(from,to,4,offset,0,det);
-	    for(;length<=2;length+=2,offset-=2)
-		emit_copy(from,to,2,offset,0,det);
-	    if(length>0)
-		emit_copy(from,to,length,offset,0,det);
-	    break;
+	if (length <0) {
+	    if (length > -MAX_COPY_LEN) {
+		for(;length<=-4;length+=4,offset-=4)
+		    emit_copy(from,to,-4,offset-4,0,det);
+		for(;length<=-2;length+=2,offset-=2)
+		    emit_copy(from,to,-2,offset-2,0,det);
+		if(length<0)
+		    emit_copy(from,to,length,offset-1,0,det);
+		break;
+	    }
 	} else if (length <=MAX_COPY_LEN) {
 	    for(;length>=4;length-=4,offset+=4)
 		emit_copy(from,to,4,offset,0,det);
@@ -1466,22 +1470,20 @@
     if (length<MAX_COPY_LEN) {
 	sreg = get_register(); if (!sreg) error(-1);
 	srn = register_name(sreg);
-	code_lvar(cadr(arg),sreg);
-	for(count=0;length<MAX_COPY_LEN;count++,length-=SIZE_OF_INT) {
-	    if (length==0) {
-		free_register(sreg);
-		free_register(dreg);
-		return count;
-	    } else {
-		printf("\tlwz %s,%d(%s)\n",drn,length-SIZE_OF_INT,crn);
-		printf("\tstwu %s,%d(%s)\n",drn,-SIZE_OF_INT,srn);
-	    }
+	code_lvar(cadr(arg),dreg);
+	for(count=0;count<length;count+=SIZE_OF_INT) {
+	    printf("\tlwz %s,%d(%s)\n",srn,count,crn);
+	    printf("\tstwu %s,%d(%s)\n",srn,count,drn);
 	}
+	free_register(sreg);
+	free_register(dreg);
+	return length/SIZE_OF_INT;
+    } else {
+	code_lvar(cadr(arg),dreg);
+	/* downward direction copy */
+	emit_copy(creg,dreg,length,0,0,1);
     }
-    code_lvar(cadr(arg),dreg);
-    /* downward direction copy */
-    emit_copy(creg,dreg,length,0,0,1);
-    if (dreg) free_register(dreg);
+    free_register(dreg);
     return length/SIZE_OF_INT;
 }
 
@@ -1648,10 +1650,10 @@
 	e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD;
 }
 
-int
-simple_args(int e3)
+static int
+simple_arg(int e3)
 {
-    return !contains_in_list_p(e3,not_simple_p);
+    return !contains_p(e3,not_simple_p);
 }
 
 int
@@ -1697,6 +1699,89 @@
     if (mode) use_reg(reg);
 }
 
+static void
+compute_complex_arg(int e3,int reg_arg_list,int arg) {
+    int t=caddr(e3);
+    int e4 = car(e3);
+    reg_arg_list = list2(arg,reg_arg_list);
+    g_expr_u(assign_expr0(arg,e4,t,t));
+    if (car(arg)==REGISTER||car(arg)==DREGISTER||
+	car(arg)==FREGISTER||car(arg)==LREGISTER)
+	use_input_reg(cadr(arg),1);
+    car(e3) = arg;
+}
+
+static void
+increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
+    int nargs=0,reg_arg=0,freg_arg=0;
+    int t=caddr(e3);
+    if(scalar(t)) {
+	nargs ++ ; reg_arg++;
+    } else if (t==LONGLONG||t==ULONGLONG) {
+	nargs ++ ; reg_arg++;
+	nargs ++ ; reg_arg++;
+    } else if (t==DOUBLE||t==FLOAT) {
+	if (*preg_arg<MAX_INPUT_REGISTER_VAR) {
+	    reg_arg += 2;
+	}
+	freg_arg++;
+	nargs += size(t)/SIZE_OF_INT;
+    } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
+	nargs += round4(size(t))/SIZE_OF_INT;
+    } else {
+	error(TYERR);
+	nargs ++ ;
+    }
+    *pnargs += nargs;
+    *preg_arg += reg_arg;
+    *pfreg_arg += freg_arg;
+}
+
+#define AS_SAVE 1
+#define AS_ARG  0
+
+static int
+get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) 
+{
+    if(scalar(t)) {
+	if (mode==AS_SAVE) {
+	    return get_register_var(0);
+	} else if (reg_arg>=MAX_INPUT_REGISTER_VAR) {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else 
+	    return get_input_register_var(reg_arg,0,0);
+    } else if (t==LONGLONG||t==ULONGLONG) {
+	if (mode==AS_SAVE) {
+	    return get_lregister_var(0);
+	} else if (reg_arg>=MAX_INPUT_REGISTER_VAR)  {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else
+	    return get_input_lregister_var(reg_arg,0,0);
+    } else if (t==FLOAT) {
+	if (mode==AS_SAVE) {
+	    return get_dregister_var(0,0);
+	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else
+	    return get_input_dregister_var(freg_arg,0,0,0);
+    } else if (t==DOUBLE) {
+	if (mode==AS_SAVE) {
+	    return get_dregister_var(0,1);
+	} else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+	} else
+	    return get_input_dregister_var(freg_arg,0,0,1);
+    } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
+	if (mode==AS_SAVE) {
+	    return get_register_var(0);
+	} else
+	    return list2(LVAR,caller_arg_offset_v(nargs));
+    } else {
+	error(-1);
+	return get_register_var(0);
+    }
+}
+
 int
 function(int e1)
 {
@@ -1707,6 +1792,9 @@
     NMTBL *fn = 0;
     int jmp = 0;
     char *jrn;
+    int complex_;
+    int pnargs,preg_arg,pfreg_arg;
+    int stargs;
 
     special_lvar = -1;
     ret_type = cadr(cadddr(e1));
@@ -1734,6 +1822,42 @@
 	code_register(creg,cadr(jmp));
         /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */
     }
+    /* first we execute complex argument to avoid interaction with
+       input variables */
+    stargs = 0;
+    complex_ = 0;
+    nargs = reg_arg = freg_arg = arg_assign = 0;
+    for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {	
+	t=caddr(e3);
+	if ((e5= !simple_arg(car(e3)))) {
+	    if (complex_) {
+		arg = get_input_arg(caddr(complex_),AS_SAVE,
+					pnargs,preg_arg,pfreg_arg);
+		compute_complex_arg(complex_,reg_arg_list,arg);
+	    }
+	    pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg;
+	    complex_ = e3;
+	}
+	if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
+	    // The struct should be pushed after complex arguments.
+	    if (e5) { // compute address only, complex_ is me now. Clear it.
+		complex_ = 0;
+		e4 = car(e3);
+		if (car(e4)!=RSTRUCT) error(-1);
+		if (!simple_arg(cadr(e4))) {
+		    // Calculate complex struct address here.
+		    // If simple, leave it.
+		    arg = get_register_var(0);
+		    g_expr_u(assign_expr0(arg,list2(ADDRESS,car(e3)),INT,INT));
+		    car(e3)=arg;
+		    reg_arg_list = list2(arg,reg_arg_list);
+		    if (car(arg)==REGISTER) use_input_reg(cadr(arg),1);
+		}
+	    }
+	    stargs = list4(e3,stargs,nargs,reg_arg);
+	}
+	increment_function_arg(e3,&nargs,&reg_arg,&freg_arg);
+    }
 
     /* now all input register vars are free */
     code_save_stacks();
@@ -1741,71 +1865,48 @@
     set_freg(FREG_FREGISTER,0);
     set_ireg(CREG_REGISTER,0);
 
+    if (complex_) {
+	arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg);
+	compute_complex_arg(complex_,reg_arg_list,arg);
+    }
+    for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) {
+	e3 = car(stargs);
+	e4 = car(e3);
+	t  = caddr(e3);
+	arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0);
+	struct_push(e4,t,arg);
+    }
+
     nargs = reg_arg = freg_arg = arg_assign = 0;
-    for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {	
+    for (e3 = e1; e3; 
+		increment_function_arg(e3,&nargs,&reg_arg,&freg_arg),
+		e3 = cadr(e3)) {	
+	if (!(e4=car(e3))) continue;
 	t=caddr(e3);
-	e4 = car(e3);
+	arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg);
 	if(scalar(t)) {
-	    if (reg_arg>=MAX_INPUT_REGISTER_VAR) { 
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
-	    } else if (!simple_args(e3) && cadr(e3)) {
-		arg = get_register_var(0); 
-		arg_assign = list2(
-		    assign_expr0(get_input_register_var(reg_arg,0,0),
-			arg,t,t),
-		    arg_assign);
-	    } else {
-		arg = get_input_register_var(reg_arg,0,0); 
-	    }
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    /* protect from input register free */
 	    if (car(arg)==REGISTER)
 		use_input_reg(cadr(arg),1);
 	    g_expr_u(assign_expr0(arg,e4,t,t));
-	    nargs ++ ; reg_arg++;
 	    continue;
 	} else if (t==LONGLONG||t==ULONGLONG) {
 	    if (reg_arg>=MAX_INPUT_REGISTER_VAR) { 
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
 	    } else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR) { 
 		// half register, half memory case
 		// put whole long long anyway
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
 		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 (!simple_args(e3) && cadr(e3)) {
-		arg = get_lregister_var(0); 
-		if (car(arg)==LREGISTER) {
-		    // r0=get_input_lregiste... is not preserved
-		    // we cannot mark r0 used, it consumes unused register
-		    // but get_input_register is preserved.
-		    arg_assign = list2(
-			assign_expr0(get_input_register_var(reg_arg,0,0),
-			    list2(REGISTER,regv_h(cadr(arg))),INT,INT), 
-			list2(
-			assign_expr0(get_input_register_var(reg_arg+1,0,0),
-			    list2(REGISTER,regv_l(cadr(arg))),INT,INT), 
-			arg_assign));
-		} else {
-		    arg_assign = list2(
-			assign_expr0(get_input_register_var(reg_arg,0,0),
-			    list2(LVAR,cadr(arg)+SIZE_OF_INT),INT,INT), 
-			list2(
-			assign_expr0(get_input_register_var(reg_arg+1,0,0),
-			    list2(LVAR,cadr(arg)),INT,INT), 
-			arg_assign));
-		}
 	    } else {
-		arg = get_input_lregister_var(reg_arg,0,0); 
-		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));
-	    nargs ++ ; reg_arg++;
-	    nargs ++ ; reg_arg++;
 	    continue;
 	} else if (t==DOUBLE||t==FLOAT) {
 	    if (reg_arg<MAX_INPUT_REGISTER_VAR) {
@@ -1839,7 +1940,6 @@
 			    list2(LVAR,special_lvar+SIZE_OF_INT),
 			    INT,INT), arg_assign);
 		}
-		reg_arg += 2;
 	    }
 	    if (dots && freg_arg>=4 && freg_arg<MAX_INPUT_DREGISTER_VAR) { 
 		/* oh my god! 
@@ -1851,32 +1951,16 @@
 			    get_input_dregister_var(freg_arg,0,0,1),t,t),
 		    arg_assign);
 	    }
-	    if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
-		arg = list2(LVAR,caller_arg_offset_v(nargs));
-	    } else if (!simple_args(e3) && cadr(e3)) {
-		arg = get_dregister_var(0,1); 
-		arg_assign = list2(
-		    assign_expr0(get_input_dregister_var(freg_arg,0,0,1),
-			arg,t,t),
-		    arg_assign);
-	    } else {
-		arg = get_input_dregister_var(freg_arg,0,0,1); 
-	    }
 	    reg_arg_list = list2(arg,reg_arg_list);
 	    if (car(arg)==DREGISTER)
 		use_input_reg(cadr(arg),1); /* protect from input register free */
 	    g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */
-	    freg_arg++;
-	    nargs += size(t)/SIZE_OF_INT;
 	    continue;
 	} else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
-	    arg = list2(LVAR,caller_arg_offset_v(nargs));
-	    nargs += struct_push(e4,t,arg);
 	    continue;
 	} else {
 	    error(TYERR);
 	}
-	++nargs;
     }
     if (max_func_args<nargs) max_func_args=nargs;
     for(;arg_assign;arg_assign=cadr(arg_assign)) {