changeset 375:91849fdeea60

PowerPC large offset.
author kono
date Mon, 12 Jul 2004 07:33:23 +0900
parents 9bc42f69f653
children d81e1be4036f
files Changes mc-code-powerpc.c mc-codegen.c test/basic.c test/offset.c
diffstat 5 files changed, 161 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Sun Jul 11 20:59:52 2004 +0900
+++ b/Changes	Mon Jul 12 07:33:23 2004 +0900
@@ -5761,3 +5761,20 @@
 
 ん、だが....
 
+                       <------r1_offset------------------------------>
+                                                 <-lvar_offset------->
+ r+  +------------+---+-------+------------------+--------------+----+    -
+      callee arg   xx   local   register save       caller arg     xx
+                        disp      reg_save          max_func_args*SIZE_OF_INT
+        lvar>0          lvar<0                      lvar>0x1000 0000
+                      r30                                            r1
+                                       
+とするのは、PowerPC では変更が大きすぎる。レジスタセーブする場所
+が良くわからないし。
+
+もしかして、register save 領域は固定?!
+
+Mon Jul 12 05:35:33 JST 2004
+
+うーん、やっぱり、難しいよな... 何故か、printf が local variable
+を壊してしまう。
--- a/mc-code-powerpc.c	Sun Jul 11 20:59:52 2004 +0900
+++ b/mc-code-powerpc.c	Mon Jul 12 07:33:23 2004 +0900
@@ -263,8 +263,9 @@
      f24-f31 saved register variable
 
  function call stack frame
-                       <------r1_offset------------------------------>
-                                      <------------lvar_offset------->
+                      <-------r1_offset------------------------------>
+                                      <------------lvar_offset0------>
+                      <--lvar_offset-->
  r+  +------------+---+---------------+----------+--------------+----+    -
       callee arg   xx   register save   local      caller arg     xx
                           reg_save      disp       max_func_args*SIZE_OF_INT
@@ -299,14 +300,16 @@
     int l;
 #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;
-    printf(".set L_%d,%d\n",lvar_offset_label,lvar_offsetv);
+    // int r1_offsetv = -disp+max_func_args*SIZE_OF_INT-reg_save+r1_offset;
+    int r1_offsetv = lvar_offsetv-reg_save+12;
+    printf(".set L_%d,%d\n",lvar_offset_label,r1_offsetv-lvar_offsetv);
     printf(".set L_%d,%d\n",r1_offset_label,r1_offsetv);
     if (max_func_arg_label) {
 	printf(".set L_%d,%d\n",max_func_arg_label,max_func_args*SIZE_OF_INT+24);
 	max_func_arg_label = 0;
     }
 
+printf("# reg_save %d\n",reg_save);
 #if 0
 printf("# function %s\n",fnptr->nm);
     l = ARG_LVAR_OFFSET;
@@ -327,21 +330,40 @@
 #endif
 }
 
+static int large_offset_reg;
 
 static void
-lvar8(int l)
+lvar(int l)
 {
-    if (fnptr->sc==CODE) {
-	if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	    printf("lo16(%d)(r1)\n",CODE_CALLER_ARG);
-	} else
-	    printf("lo16(%d)(r30)\n",CODE_LVAR);
-    } else if (l<0) {  /* local variable */
-	printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
-    } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	printf("lo16(%d)(r1)\n",CALLER_ARG);
-    } else { /* callee's arguments */
-	printf("lo16(%d+L_%d)(r30)\n",CALLEE_ARG,r1_offset_label);
+    char *rn;
+    if (!large_offset_reg) {
+	if (fnptr->sc==CODE) {
+	    if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
+		printf("lo16(%d)(r1)\n",CODE_CALLER_ARG);
+	    } else
+		printf("lo16(%d)(r30)\n",CODE_LVAR);
+	} else if (l<0) {  /* local variable */
+	    printf("lo16(%d)(r30)\n",FUNC_LVAR);
+	} else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
+	    printf("lo16(%d)(r1)\n",CALLER_ARG);
+	} else { /* callee's arguments */
+	    printf("lo16(%d+L_%d)(r30)\n",CALLEE_ARG,lvar_offset_label);
+	}
+    } else {
+        rn = register_name(large_offset_reg);
+        if (fnptr->sc==CODE) {
+            if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
+                printf("lo16(%d)(%s)\n",CODE_CALLER_ARG,rn);
+            } else
+                printf("lo16(%d)(%s)\n",CODE_LVAR,rn);
+        } else if (l<0) {  /* local variable */
+            printf("lo16(%d)(%s)\n",FUNC_LVAR,rn);
+        } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
+            printf("lo16(%d)(%s)\n",CALLER_ARG,rn);
+        } else { /* callee's arguments */
+            printf("lo16(%d+L_%d)(%s)\n",CALLEE_ARG,lvar_offset_label,rn);
+        }
+        free_register(large_offset_reg);
     }
 }
 
@@ -352,49 +374,44 @@
    smaller offset. But who cares who use very large local variables?
  */
 
-#define LARGE_LVAR (disp<-32765||max_func_args>32765)
-
-static void
-lvar16ha(int l)
-{
-    if (fnptr->sc==CODE) {
-	if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	    printf("la r0,ha16(%d)(r1)\n",CODE_CALLER_ARG);
-	} else
-	    printf("la r0,ha16(%d)(r30)\n",CODE_LVAR);
-    } else if (l<0) {  /* local variable */
-	printf("la r0,ha16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
-    } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	if (CALLER_ARG>32765)
-	    printf("la r0,ha16(%d)(r1)\n",CALLER_ARG);
-    } else { /* callee's arguments */
-	printf("la r0,ha16(%d+L_%d)(r30)\n",CALLEE_ARG,r1_offset_label);
-    }
-}
+#define LARGE_OFFSET(l) (l<-32000||l>32000)
 
 static void
-lvar16lo(int l)
+lvar_intro(int l)
 {
+    char *rn;
+    large_offset_reg=0;
     if (fnptr->sc==CODE) {
-	if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	    printf("lo16(%d)(r0)\n",CODE_CALLER_ARG);
-	} else
-	    printf("lo16(%d)(r0)\n",CODE_LVAR);
+        if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
+            if (LARGE_OFFSET(CODE_CALLER_ARG)) {
+                rn=register_name(large_offset_reg=get_register());
+                printf("\taddis %s,r1,ha16(%d)\n",rn,CODE_CALLER_ARG);
+            }
+        } else {
+            if (LARGE_OFFSET(CODE_LVAR)) {
+                rn=register_name(large_offset_reg=get_register());
+                printf("\taddis %s,r30,ha16(%d)\n",rn,CODE_LVAR);
+            }
+        }
     } else if (l<0) {  /* local variable */
-	printf("lo16(%d+L_%d)(r0)\n",FUNC_LVAR,lvar_offset_label);
+        if (LARGE_OFFSET(FUNC_LVAR)) {
+            rn=register_name(large_offset_reg=get_register());
+            printf("\taddis %s,r30,ha16(%d)\n",rn,FUNC_LVAR);
+        }
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-	if (CALLER_ARG>32765)
-	    printf("lo16(%d)(r0)\n",CALLER_ARG);
-	else
-	    printf("lo16(%d)(r1)\n",CALLER_ARG);
+        if (LARGE_OFFSET(CALLER_ARG)) {
+            rn=register_name(large_offset_reg=get_register());
+            printf("\taddis %s,r1,ha16(%d)\n",rn,CALLER_ARG);
+        }
     } else { /* callee's arguments */
-	printf("lo16(%d+L_%d)(r0)\n",CALLEE_ARG,r1_offset_label);
+        if (LARGE_OFFSET(CALLEE_ARG)) {
+            rn=register_name(large_offset_reg=get_register());
+            printf("\taddis %s,r30,lo16(%d+L_%d)\n",
+		rn,CALLEE_ARG,lvar_offset_label);
+        }
     }
 }
 
-#define lvar_intro(i) if (LARGE_LVAR) lvar16ha(i)
-
-#define lvar(i) if (LARGE_LVAR) lvar16lo(i); else lvar8(i)
 
 void
 code_lvar(int e2,int reg) {
@@ -1116,7 +1133,7 @@
     if (offset==0) {
 	if(r!=reg)
 	    printf("\tmr %s,%s\n",crn,rrn);
-    } else if (offset<-32768||32767<offset) {
+    } else if (LARGE_OFFSET(offset)) {
 	printf("\tla   %s,ha16(%d)(%s)\n",crn,offset,rrn);
 	printf("\taddi %s,%s,lo16(%d)\n",crn,crn,offset);
     } else
@@ -1128,7 +1145,7 @@
 {
     char *crn = register_name(reg);
     char *rrn = register_name(r);
-    if (offset<-32768||32767<offset) {
+    if (LARGE_OFFSET(offset)) {
 	printf("\tla   %s,ha16(%d)(%s)\n",crn,offset,rrn);
 	printf("\t%s %s,%s,lo16(%d)\n",ld,crn,crn,offset);
     } else
@@ -2239,7 +2256,7 @@
 code_fix_frame_pointer(int disp_offset) {
     int l = 0;
     printf("\tla r30,");
-    printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label);
+    printf("lo16(%d)(r30)\n",FUNC_LVAR);
 }
 
 void
@@ -2270,7 +2287,10 @@
     crn=register_name(creg);
     use_int(reg);
     rrn=register_name(reg);
-    printf("\t%s %s,%d(%s)\n",cload(sz),rrn,offset,crn);
+    if (LARGE_OFFSET(offset)) {
+        printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset);
+    }
+    printf("\t%s %s,lo16(%d)(%s)\n",cload(sz),rrn,offset,crn);
     cext(sign,sz,reg);
 }
 
@@ -2283,8 +2303,12 @@
     if (!is_int_reg(creg)) error(-1);
     crn=register_name(creg);
     use_float(d,reg);
-    printf("\t%s %s,%d(%s)\n",fload(d),
+    if (LARGE_OFFSET(offset)) {
+        printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset);
+    }
+    printf("\t%s %s,lo16(%d)(%s)\n",fload(d),
 	fregister_name(reg),offset,crn);
+
     return d?DOUBLE:FLOAT;
 }
 #endif
@@ -2293,12 +2317,15 @@
 lload(int creg,int reg,int offset)
 {
     char *crn = register_name(creg);
+    if (LARGE_OFFSET(offset)) {
+	printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset);
+    }
     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);
+	printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset,crn);
+	printf("\tlwz %s,lo16(%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);
+	printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn);
+	printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset,crn);
     }
 }
 
@@ -2762,8 +2789,16 @@
     fwddef(code_base);
     r1_offset_label = fwdlabel();
     lvar_offset_label = fwdlabel();
+#if 0
+    printf("\taddi r30,r1,lo16(-L_%d)\n",lvar_offset_label);
     printf("\tstwu r1,lo16(-L_%d)(r1)\n",r1_offset_label);
-    printf("\tmr r30,r1\n");
+    // printf("\tmr r30,r1\n");
+#else
+    printf("\taddi r30,r1,lo16(-L_%d)\n",lvar_offset_label);
+    printf("\tlis r31,ha16(-L_%d)\n",r1_offset_label);
+    printf("\taddi r31,r31,lo16(-L_%d)\n",r1_offset_label);
+    printf("\tstwux r1,r1,r31\n");
+#endif
     printf("\tmflr r31\n");
     max_func_args = 0;
 }
@@ -3384,10 +3419,10 @@
 "        mflr r10",
 "        mtlr r0",
 "        xoris r3,r3,0x8000",
-"        stw r3,-28(r30)",
+"        stw r3,-28(r1)",
 "        lis r0,0x4330",
-"        stw r0,-32(r30)",
-"        lfd f0,-32(r30)",
+"        stw r0,-32(r1)",
+"        lfd f0,-32(r1)",
 "        addis r9,r10,ha16(__i2dLC0-__i2dL1$pb)",
 "        lfd f1,lo16(__i2dLC0-__i2dL1$pb)(r9)",
 "        fsub f1,f0,f1",
@@ -3427,16 +3462,16 @@
 "        cror 2,1,2",
 "        beq- cr0,__d2uL2",
 "        fctiwz f0,f1",
-"        stfd f0,-32(r30)",
-"        lwz r3,-28(r30)",
+"        stfd f0,-32(r1)",
+"        lwz r3,-28(r1)",
 "        blr",
 "__d2uL2:",
 "        addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)",
 "        lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)",
 "        fsub f0,f1,f0",
 "        fctiwz f0,f0",
-"        stfd f0,-24(r30)",
-"        lwz r3,-20(r30)",
+"        stfd f0,-24(r1)",
+"        lwz r3,-20(r1)",
 "        xoris r3,r3,0x8000",
 "        blr",
 0
@@ -3469,10 +3504,10 @@
 "__u2dL2$pb:",
 "        mflr r10",
 "        mtlr r0",
-"        stw r3,-28(r30)",
+"        stw r3,-28(r1)",
 "        lis r0,0x4330",
-"        stw r0,-32(r30)",
-"        lfd f0,-32(r30)",
+"        stw r0,-32(r1)",
+"        lfd f0,-32(r1)",
 "        addis r9,r10,ha16(__u2dLC1-__u2dL2$pb)",
 "        lfd f1,lo16(__u2dLC1-__u2dL2$pb)(r9)",
 "        fsub f1,f0,f1",
--- a/mc-codegen.c	Sun Jul 11 20:59:52 2004 +0900
+++ b/mc-codegen.c	Mon Jul 12 07:33:23 2004 +0900
@@ -3601,7 +3601,7 @@
 extern int
 new_lvar0(int sz)
 {
-    return disp -= sz;
+    return disp-=sz;
 }
 
 extern int
--- a/test/basic.c	Sun Jul 11 20:59:52 2004 +0900
+++ b/test/basic.c	Mon Jul 12 07:33:23 2004 +0900
@@ -1,3 +1,5 @@
+#define ARG_ADDRESS 0
+
 double ggg = 0.134;
 float fff = 0.0;
 
@@ -62,6 +64,9 @@
 int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8,int a9,int a10,int a11,int a12,int a13,int a14,int a15,int a16,int a17,int a18,int a19,int a20,int a21,int a22,int a23,int a24,int a25,int a26,int a27,int a28,int a29,int a30,int a31,int a32,int a33,int a34,int a35,int a36,int a37,int a38,int a39,int a40,int a41,int a42,int a43,int a44,int a45,int a46,int a47,int a48,int a49
 )
 {
+#if ARG_ADDRESS
+    printf("i50: a0 %x a49 %x\n",&a0,&a49);
+#endif
     printf("i50: %d\n",
 a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22+a23+a24+a25+a26+a27+a28+a29+a30+a31+a32+a33+a34+a35+a36+a37+a38+a39+a40+a41+a42+a43+a44+a45+a46+a47+a48+a49
     );
@@ -111,6 +116,10 @@
 
 void 
 tmp1 () { 
+#if ARG_ADDRESS
+    int a0;
+    printf("tmp1: a0 %x\n",&a0);
+#endif
 
     printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \n",
 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49
--- a/test/offset.c	Sun Jul 11 20:59:52 2004 +0900
+++ b/test/offset.c	Mon Jul 12 07:33:23 2004 +0900
@@ -7,12 +7,25 @@
 int midium[BIT12];
 int large[BIT16];
 
-main()
+
+main0(int ac,char *av[])
 {
 int *p;
 int local_midium[BIT12];
 int local_large[BIT16];
 
+#if 0
+    printf("int ac =\t%x\n",&ac);
+    printf("int midium[0] =\t%x\n",&midium[0]);
+    printf("int midium[BIT12] =\t%x\n",&midium[BIT12]);
+    printf("int large[0] =\t%x\n",&large[0]);
+    printf("int large[BIT16] =\t%x\n",&large[BIT16]);
+    printf("int local_midium[0] =\t%x\n",&local_midium[0]);
+    printf("int local_midium[BIT12] =\t%x\n",&local_midium[BIT12]);
+    printf("int local_large[0] =\t%x\n",&local_large[0]);
+    printf("int local_large[BIT16] =\t%x\n",&local_large[BIT16]);
+#endif
+
   midium[0]=0x55;
   large[0]=0x55;
   local_midium[0]=0x55;
@@ -64,7 +77,21 @@
    printf("%x\n", p[-1]);
    printf("%x\n", p[-BIT8]);
    printf("%x\n", p[-BIT10]);
-   printf("%x\n", p[BIT12-1]);
-   printf("%x\n", p[BIT16-1]);
+   printf("%x\n", p[-(BIT12-1)]);
+   printf("%x\n", p[-(BIT16-1)]);
+
+    for(p=local_midium;p<&local_midium[BIT12];p++) *p = p-local_midium;
+    for(p=local_large;p<&local_large[BIT16];p++) *p = p-local_large;
 
 }
+
+main(int ac,char *av[])
+{
+    int i=-1,j=-2,k=-3;
+    
+    main0(ac,av);
+
+    printf("%d %d %d %d\n",ac,i,j,k);
+    return 0;
+}
+