changeset 377:b23568be1155

ARM continue (const table)
author kono
date Tue, 13 Jul 2004 21:43:58 +0900
parents d81e1be4036f
children b3c6c479c522
files Changes mc-code-arm.c mc-parse.c test/offset.c
diffstat 4 files changed, 206 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Mon Jul 12 12:37:18 2004 +0900
+++ b/Changes	Tue Jul 13 21:43:58 2004 +0900
@@ -5772,12 +5772,74 @@
 とするのは、PowerPC では変更が大きすぎる。レジスタセーブする場所
 が良くわからないし。
 
-もしかして、register save 領域は固定?!
+もしかして、register save 領域は固定?! 
+
 
 Mon Jul 12 05:35:33 JST 2004
 
 うーん、やっぱり、難しいよな... 何故か、printf が local variable
 を壊してしまう。
 
+register save 領域は固定なわけきゃないだろ。最初からやり直して、
+
+ function call stack frame
+                      <-------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
+        lvar>0                         lvar<0       lvar>0x1000 0000
+
+ということになりました。frame の設定のところだけ無条件に32bit add
+になったが仕方ないな。これだと、callee arg は不定オフセットにならざる
+を得ない。reg_save が最後まで決まらないから。
+
 はぁ。大変なのはPowerPCだけで、MIPSとia32 は、そのまま動くというのが
 わかりました。
+
+Mon Jul 12 12:54:14 JST 2004
+
+が、結局、MIPSを $fp からの裸オフセットにするのは苦労したね。
+  .frame $fp じゃなくて、 .frame $sp にすると動くのか。
+あと、goto 関連は、
+    code_environment
+    code_fix_frame_pointer
+    leave
+の三つを直さないとだめなのね。
+
+この変更は、ARMのオフセット計算を固定オフセットで行うために
+やっているんだけど、ARMのレジスタセーブを固定領域にすれば、
+あるいは、どこかに追いやれば、callee arg も含めて固定に出来
+るはず。
+
+
+なんか浮動小数点レジスタは f4 だけみたいね。
+
+	    mov	ip, sp
+	    stmfd	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
+	    sub     fp, ip, #4
+	    sub     sp, sp, #12
+    .L3:
+	    ldmea	fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
+    .Lfe1:
+
+まるで、6809 の PSHS X,Y,D だね。PULS X,PC とか。
+
+なんだけど、これだと、
+
+                      <-------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
+        lvar>0                         lvar<0       lvar>0x1000 0000
+
+にならざるを得ない。となると、どっちかは、不定オフセットだな。
+ま、callee 側でしょう。ま、これに習うか。あるいは、ポインタ
+で指してもいいんだよね。ていうか、reg_save に関わらず決まった領域
+をとっちゃえばいいんじゃない? 大した量じゃないし。浮動小数点
+レジスタも一つだしね。
+
+もう少しかかりそうだね。
--- a/mc-code-arm.c	Mon Jul 12 12:37:18 2004 +0900
+++ b/mc-code-arm.c	Tue Jul 13 21:43:58 2004 +0900
@@ -1030,7 +1030,7 @@
 void
 gexpr_init(void)
 {
-    gvar_ref_list();
+    const_list();
     while(reg_sp > 0) {
 	error(-1);
 	free_register(reg_stack[--reg_sp]);
@@ -1135,29 +1135,55 @@
     return xreg;
 }
 
-static int gvar_ref_list;
-static int gvar_ref_disp;
+static int const_list;
+static int const_list_label;
+static int prev_const_list;
+static int prev_const_list_label;
+
+/*
+     constant table
+        glist3( tag, next, value )
+		GVAR       	nptr
+		CONST		value
+		LABEL		value
+     nth element has offset n * SIZE_OF_INT
+ */
+
+#define new_const(e,v) (const_list = glist3(e,const_list,v))
 
 static int
-new_gvar_ref(NMTBL *nptr)
-{
-    return
-	gvar_ref_list =
-	    glist3((int)nptr,gvar_ref_list,gvar_ref_disp+=SIZE_OF_INT);
-}
-
-static int
-search_gvar_ref(NMTBL *nptr)
-{
-    int p;
-    for(p = gvar_ref_list;
-	p && neqname(((NMTBL *)car(p))->nm,nptr->nm);p=cadr(p));
-    if (p) return caddr(p);
-    return caddr(new_gvar_ref(nptr));
+search_const(int tag,int value,int *label)
+{
+    int p,i,j,list;
+
+    for(j=0;j<2;j++) {
+	i = 0;
+	if(j==1) {
+	    if (!const_list_label) const_list_label = fwdlabel();
+	    list = const_list; *label = const_list_label;
+	} else {
+	    list = prev_const_list; *label = prev_const_list_label;
+	}
+	for(p = list; p ;p=cadr(p),i+=SIZE_OF_INT) {
+	    if (car(p)!=tag) continue;
+	    switch(tag) {
+	    case GVAR:
+		if (neqname(((char *)caddr(p)),
+			    ((NMTBL *)value)->nm)) continue;
+		return i;
+	    case CONST: case LABEL:
+		if (caddr(p)!=value) continue;
+		return i;
+	    default: error(-1);
+	    }
+	}
+    }
+    new_const(tag,cadr(e));
+    return i+SIZE_OF_INT;
 }
 
 static void
-gvar_ref_list()
+const_list()
 {
     int p,next,lb;
     if (control) {
@@ -1165,25 +1191,44 @@
 	jmp(lb);
 	printf("\t.align\t2\n");
     }
-    gvar_ref_list = reverse0(gvar_ref_list);
-    fwddef(gvar_ref_label);
-    for(p = gvar_ref_list; p ;) {
-	printf("\t.word\t%s\n",((NMTBL *)car(p))->nm);
-	next = cadr(p);
-	free_glist3(p);
-	p = next;
+    const_list = reverse0(const_list);
+    fwddef(const_list_label);
+    for(p = const_list; p ; p = cadr(p)) {
+	switch(car(p)) {
+	case GVAR:	printf("\t.word\t%s\n",((NMTBL *)caddr(p))->nm); break;
+	case CONST:	printf("\t.word\t%d\n",caddr(p)); break;
+	case LABEL:	printf("\t.word\t.L%d\n",caddr(p)); break;
+	default: error(-1);
+	}
     }
     if (lb) {
 	fwddef(lb);
     }
+    free_glist3_a(pconst_list);
+    prev_const_list=const_list;
+    prev_const_list_label=const_list_label;
+    const_list = 0;
+}
+
+#define CONST_TBL_COUNT 300
+
+static void
+inc_inst(int count)
+{
+    static int inst_count;
+    if ((inst_count+=count)>CONST_TBL_COUNT) {
+	inst_count = 0;
+	const_list();
+    }
 }
 
 extern void
 code_ptr_cache_def(int r, NMTBL *nptr)
 {
+    int label,disp;
     char *rrn = register_name(r);
-    printf("\tldr %s, .L%d+%d\n",rrn,gvar_ref_label,
-	search_gvar_ref(nptr));
+    disp = search_const(GVAR,(int)nptr,&label);
+    printf("\tldr %s, .L%d+%d\n",rrn,label,disp);
 }
 
 #define mask8(d,bit)   (d & (255 << bit))
@@ -1239,22 +1284,47 @@
 }
 
 static void 
+code_const(int e2,int reg)
+{
+    char *crn,*add,*mov;
+    int s,p1,p2,p3;
+    int label,disp;
+
+    use_int(reg);
+    crn = register_name(reg);
+    if ((s=make_const(e2,&p1,&p2,&p3))) {
+	add = s>0?"add":"sub";
+	mov = s>0?"mov":"mvn";
+	if (p1) printf("\t%s\t%s, %s, #%d\n",mov,crn,rrn,p1);
+	if (p2) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,p2);
+	if (p3) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,p3);
+    } else {
+	disp = search_const(CONST,e2,&label);
+	printf("\tldr\t%s, .L%d+%d\n",crn,label,disp);
+    }
+}
+
+static void 
 code_add(int reg,int offset,int r)
 {
     char *crn = register_name(reg);
     char *rrn = register_name(r);
     int s,p1,p2,p3;
+    char *add;
+    int label,disp;
     if (offset==0) {
         if(r!=reg)
             printf("\tmov %s,%s\n",crn,rrn);
+    }
     if ((s=make_const(offset,&p1,&p2,&p3))) {
 	add = s>0?"add":"sub";
-	if (p1) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,offset);
-	if (p2) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,offset);
-	if (p3) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,offset);
+	if (p1) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,p1);
+	if (p2) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,p2);
+	if (p3) printf("\t%s\t%s, %s, #%d\n",add,crn,rrn,p3);
     } else {
-	printf("\tldr\t%s, .L%d\n",crn,new_const_ref(r,offset));
-	printf("\tadd\t%s, %s, %s\n",add,crn,crn,rrn);
+	disp = search_const(CONST,offset,&label);
+	printf("\tldr\t%s, .L%d+%d\n",crn,label,disp);
+	printf("\tadd\t%s, %s, %s\n",crn,crn,rrn);
     }
 }
 
@@ -1283,7 +1353,7 @@
     } else {
 	orn = register_name(reg=get_register());
 	code_add(reg,offset,r);
-	printf("\t%s\t%s, [%s, #%d]%s\n",ld,crn,orn,offset,cext);
+	printf("\t%s\t%s, [%s, #0]%s\n",ld,crn,orn,cext);
 	free_register(reg);
     }
 }
@@ -3502,7 +3572,9 @@
 {
     NMTBL *n;
     int init;
-    gvar_ref_list();
+    const_list();
+    free_glist3_a(pconst_list); pconst_list = 0;
+
     init=0;
     /* static local variables */
     for(n=local_static_list;n;n=n->next) {
--- a/mc-parse.c	Mon Jul 12 12:37:18 2004 +0900
+++ b/mc-parse.c	Tue Jul 13 21:43:58 2004 +0900
@@ -3853,6 +3853,24 @@
     }
 }
 
+extern void
+free_glist3_a(int e1)
+{
+    int next;
+    while(e1) {
+	if (e1>gfree) continue;  /* freeing local heap */
+	next = cadr(e1);
+	if (e1==gfree) {
+	    gfree-=3;
+	} else {
+	    cadr(e1) = free_glist3_list;
+	    free_glist3_list = e1;
+	}
+	e1 = next;
+    }
+}
+
+
 extern int
 length(int list)
 {
--- a/test/offset.c	Mon Jul 12 12:37:18 2004 +0900
+++ b/test/offset.c	Tue Jul 13 21:43:58 2004 +0900
@@ -80,9 +80,27 @@
    printf("%x\n", p[-(BIT12-1)]);
    printf("%x\n", p[-(BIT16-1)]);
 
+   p = large+BIT16;
+
+   p[-1] = 0xaa;
+   p[-BIT8] = 0xbb;
+   p[-BIT10] = 0xcc;
+   p[-(BIT12-1)] = 0xdd;
+   p[-(BIT16-1)] = 0xee;
+
+   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)]);
+
+
     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;
 
+    for(p=midium;p<&midium[BIT12];p++) *p = p-midium;
+    for(p=large;p<&large[BIT16];p++) *p = p-large;
+
 }
 
 main(int ac,char *av[])