changeset 372:81345636387d

arm continue...
author kono
date Sat, 10 Jul 2004 21:46:21 +0900
parents 238c3704ee3d
children a9bc85fe6702
files Changes mc-code-arm.c mc-parse.c test/code-gen.c
diffstat 4 files changed, 292 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Changes	Fri Jul 09 14:47:40 2004 +0900
+++ b/Changes	Sat Jul 10 21:46:21 2004 +0900
@@ -5586,3 +5586,117 @@
 LDECL は、disp < 0
 
 const も実装しないといけないんだよな〜
+
+arm は、大域変数を、
+        ldr     r3, .L28+88
+    ....
+.L29:
+        .align  2
+.L28:
+        .word   i1
+        .word   i2
+        .word   s1
+        .word   s2
+        .word   us1
+
+みたいな形で間接参照するわけだけど、参照した順にリストに格納しないと
+だめ? 変数表に格納したい所だが... make scope で出来ないかな?
+linear list で持ってもいいんだけど。
+
+ptr_cache の方でリストを持てば?
+
+なんか、add # の意味が良くわからないよ。別に常にメモリ
+参照で問題はないんでしょ?
+
+良くわからないけど、
+      8bit 幅の定数で、シフトが2ずつ
+みたいな感じ?
+
+でいいけど、どんなアルゴリズムで生成するんだよ。
+
+    8bit mask を2ずつシフトして、
+      残りが取れるかどうかをみる
+
+えーと、16x8x8 ぐらいのオーダ?
+    for(sign=-1;sign<=1;sign+=2) {
+	if (sign==1) d = c; else d = -c;
+	for(i=0;i<32;i+=2) {
+	    if (!(im=mask8(d,i)))  continue;
+	    id = d - im;
+	    if (id==0) goto found;
+	    for(j=i+8;j<32;i+=2) {
+		if (!(jm=mask8(id,j)))  continue;
+		jd = id - jm;
+		if (jm==0) goto found;
+		for(k=i+8;k<32;k+=2) {
+		    if (!(km=mask8(jd,j)))  continue;
+		    kd = jd - km;
+		    if (km==0) goto found;
+		}
+	    }
+	}
+    }
+	emit_const(c);
+    found:
+	if (sign==1) emit_add(im,jm,km);
+	else emit_sub(im,jm,km)
+ですかね。1024 ループか。。。 const 毎に?
+
+しかも、その中で、もっとも短い命令を探さないとだめなのか。
+
+pointer offset も、そうなのかな? (その可能性はあると思う)
+
+12*8*4 = 384 ぐらいか(最悪で)
+
+    sub mask8 {
+	my ($d,$bit) = @_;
+	$d & (255 << $bit);
+    }
+
+    sub make_const {
+	my ($c) = @_;
+	my ($sign,$im,$jm,$km);
+	my ($min_stage) = 4;
+	my ($msign,$mim,$mjm,$mkm);
+	for($sign=1;$sign>=-1;$sign-=2) {
+	    my $d;
+	    if ($sign==1) { $d = $c; } else { $d = -$c; }
+	    last if ($min_stage==1);
+	    for(my $i=24;$i>=0;$i-=2) {
+		$jm = $km = 0;
+		next if (!($im=mask8($d,$i)));
+		my $id = $d - $im;
+		if ($id==0) { 
+		    $min_stage=1; $msign = $sign;
+		    $mim = $im;$mjm = $jm;$mkm = $km;
+		    last;
+		}
+		next if ($min_stage<=2);
+		for(my $j=$i-8;$j>=0;$j-=2) {
+		    $km = 0;
+		    next if (!($jm=mask8($id,$j)));
+		    $jd = $id - $jm;
+		    if ($jd==0) {
+			$min_stage=2; $msign = $sign;
+			$mim = $im;$mjm = $jm;$mkm = $km;
+			last;
+		    }
+		    next if ($min_stage<=3);
+		    for(my $k=$j-8;$k>=0;$k-=2) {
+			next if (!($km=mask8($jd,$k)));
+			$kd = $jd - $km;
+			if ($kd==0) { 
+			    $min_stage=3; $msign = $sign;
+			    $mim = $im;$mjm = $jm;$mkm = $km;
+			    last;
+			}
+		    }
+		}
+	    }
+	}
+	if ($min_stage<=3) { emit($sign,$im,$jm,$km); }
+	else { print "emit const $c\n"; }
+    }
+
+ぐらいでした。
+
--- a/mc-code-arm.c	Fri Jul 09 14:47:40 2004 +0900
+++ b/mc-code-arm.c	Sat Jul 10 21:46:21 2004 +0900
@@ -11,7 +11,7 @@
 #define Linux_Zaurus 1
 #define GameBoyAdvance 2
 
-int arc_mode = Linux_Zaurus; 
+int arch_mode = Linux_Zaurus; 
 
 char **l_include_path[];
 
@@ -45,8 +45,6 @@
 
 static int output_mode = TEXT_EMIT_MODE;
 
-static FILE *asi;
-
 static int cprestore_label;
 static int fmask_label;
 static int fmask_offset_label;
@@ -131,12 +129,12 @@
 #define RET_LREGISTER (LREG_OFFSET+REAL_MAX_LREGISTER)
 #define LREGISTER_OPERAND  (LREG_OFFSET +REAL_MAX_LREGISTER +1)
 #define LREGISTER_OPERAND_1  (LREG_OFFSET +REAL_MAX_LREGISTER +2)
-#define RET_LREGISTER_L 2    /* low word */
-#define RET_LREGISTER_H 3    /* high word */
-#define LREGISTER_OPERAND_L  4    /* low word */
-#define LREGISTER_OPERAND_H  5    /* high word */
-#define LREGISTER_OPERAND_1_L  6    /* low word */
-#define LREGISTER_OPERAND_1_H  7    /* high word */
+#define RET_LREGISTER_L 0    /* low word */
+#define RET_LREGISTER_H 1    /* high word */
+#define LREGISTER_OPERAND_L  0    /* low word */
+#define LREGISTER_OPERAND_H  1    /* high word */
+#define LREGISTER_OPERAND_1_L  2    /* low word */
+#define LREGISTER_OPERAND_1_H  3    /* high word */
 
 #define RET_DREGISTER RET_LREGISTER 
 #define DREGISTER_OPERAND LREGISTER_OPERAND
@@ -181,7 +179,7 @@
 #define is_int_reg(i)  (0<i&&i<REAL_MAX_REGISTER)
 #define is_float_reg(i)  (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER)
 #define is_longlong_reg(i)  (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER+LREG_V)
-#define is_double_reg(i)  is_longlong_reg(i)
+#define is_double_reg(i)  (arch_mode==GameBoyAdvance?is_longlong_reg(i):is_float_reg(i))
 
 #define  use_int(reg) if (reg==USE_CREG) reg=use_int0()
 static
@@ -224,7 +222,7 @@
 
 
 #if FLOAT_CODE
-#define  use_float(d,reg) if (reg==USE_CREG) reg=d?use_double0():use_float0()
+#define  use_float(d,reg) if (reg==USE_CREG) arch_mode==GameBoyAdvance?(reg=d?use_double0():use_float0()):use_float0()
 static
 int use_float0() { 
     int i = creg;
@@ -297,17 +295,17 @@
      delayed slot done within .set noreorder.
 
      r0    return value etc.
-     $2,$3 return value. (dpcmp return value on $2)
-     $0  special register
-     $4-$7  input register
-     r18-r24 saved register variable (input register for code segment)
-     $25    jump register
-     $31    stack pointer
-     $fp    frame pointer
-
-     $f0       return value etc.
-     $f14,$f12 input register
-     $f20-$f31 saved register variable
+     r0,r1 return value. (dpcmp return value on $2)
+     00  special register
+     r0-r3  input register
+     r7-r9 saved register variable (input register for code segment)
+         jump register
+     sp    stack pointer
+     fp    frame pointer
+
+     f0       return value etc.
+     r0-r3    input register
+     f20-f31 saved register variable
 
 code segment stack frame
 
@@ -361,6 +359,11 @@
     lvar_offsetv += round16(r1_offsetv)-r1_offsetv;
     r1_offsetv = round16(r1_offsetv);
 
+printf("        @ args = %d, pretend = %d, frame = %d\n",
+	max_func_args,0,round16(-disp));
+printf("        @ frame_needed = 1, current_function_anonymous_args = 0\n");
+
+
 #if 0
 printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
 	round16(-disp),
@@ -389,14 +392,6 @@
    printf("# max caller arg var=\t%d\n",CALLER_ARG(0));
    printf("#\n");
 #endif
-    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);
-    fprintf(asi,"$L_%d=%d\n",lvar_offset_label,lvar_offsetv);
 
     return r1_offsetv;
 }
@@ -406,15 +401,15 @@
 {
     if (fnptr->sc==CODE) {
         if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-            printf("%d($sp)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
+            printf("[sp, #%d]\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
         } else
-            printf("%d($fp)\n",CODE_LVAR(l));
+            printf("[fp, #%d]\n",CODE_LVAR(l));
     } else if (l<0) {  /* local variable */
-        printf("%d+$L_%d($fp)\n",FUNC_LVAR(l),lvar_offset_label);
+        printf("[fp, #%d+.L%d]\n",FUNC_LVAR(l),lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-        printf("%d($sp)\n",CALLER_ARG(l-ARG_LVAR_OFFSET));
+        printf("[sp, #%d]\n",CALLER_ARG(l-ARG_LVAR_OFFSET));
     } else { /* callee's arguments */
-        printf("%d+$L_%d($fp)\n",CALLEE_ARG(l),r1_offset_label);
+        printf("[fp, #%d+.L%d]\n",CALLEE_ARG(l),r1_offset_label);
     }
 }
 
@@ -423,18 +418,18 @@
 {
     if (fnptr->sc==CODE) {
         if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-            printf("\taddu\t%s,$sp,%d\n",
+            printf("\tadd\t%s, sp, #%d\n",
 		register_name(creg),CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
         } else
-            printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR(l));
+            printf("\tadd\t%s, fp,#%d\n",register_name(creg),CODE_LVAR(l));
     } else if (l<0) {  /* local variable */
-        printf("\taddu\t%s,$fp,%d+$L_%d\n",register_name(creg),
+        printf("\tsub\t%s, fp, #%d+$L_%d\n",register_name(creg),
 		FUNC_LVAR(l),lvar_offset_label);
     } else if (l>=ARG_LVAR_OFFSET) {  /* caller's arguments */
-        printf("\taddu\t%s,$sp,%d\n",
+        printf("\tadd\t%s, $sp, #%d\n",
 		register_name(creg),CALLER_ARG(l-ARG_LVAR_OFFSET));
     } else { /* callee's arguments */
-        printf("\taddu\t%s,$fp,%d+$L_%d\n",
+        printf("\tsub\t%s, fp, #%d+$L_%d\n",
 		register_name(creg),CALLEE_ARG(l),r1_offset_label);
     }
 }
@@ -652,7 +647,7 @@
 get_dregister(int d)
 {    /* 使われていないレジスタを調べる */
     int i,reg;
-    if (d) {
+    if (arch_mode==GameBoyAdvance) {
       i = get_lregister();
       if (i!=-1) regs[i]=USING_DREG;
       return i;
@@ -1141,11 +1136,105 @@
     return xreg;
 }
 
+static int gvar_ref_list;
+static int gvar_ref_disp;
+
+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));
+}
+
+static void
+gvar_ref_list()
+{
+    int p,next,lb;
+    if (control) {
+	lb = fwdlabel();
+	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;
+    }
+    if (lb) {
+	fwddef(lb);
+    }
+}
+
 extern void
 code_ptr_cache_def(int r, NMTBL *nptr)
 {
     char *rrn = register_name(r);
-    printf("\tla %s,%s\n",rrn,nptr->nm);
+    printf("\tldr %s, .L%d+%d\n",rrn,gvar_ref_label,
+	search_gvar_ref(nptr));
+}
+
+#define mask8(d,bit)   (d & (255 << bit))
+
+static void
+make_const(int c)
+{
+    int sign,im,jm,km;
+    int min_stage = 4;
+    int msign,mim,mjm,mkm;
+    int id,jd,kd;
+    int i,j,k;
+    for(sign=1;sign>=-1;sign-=2) {
+	int d;
+        if (sign==1) { d = c; } else { d = -c; }
+	if (min_stage==1) break;
+        for(i=24;i>=0;i-=2) {
+	    jm = km = 0;
+            if (!(im=mask8(d,i))) continue;
+            id = d - im;
+            if (id==0) { 
+		min_stage=1; msign = sign;
+		mim = im;mjm = jm;mkm = km;
+		break;
+	    }
+	    if (min_stage<=2) continue;
+            for(j=i-8;j>=0;j-=2) {
+		km = 0;
+                if (!(jm=mask8(id,j))) continue;
+                jd = id - jm;
+		if (jd==0) {
+		    min_stage=2; msign = sign;
+		    mim = im;mjm = jm;mkm = km;
+		    break;
+		}
+		if (min_stage<=3) continue;
+                for(k=j-8;k>=0;k-=2) {
+                    if (!(km=mask8(jd,k))) continue;
+                    kd = jd - km;
+		    if (kd==0) { 
+			min_stage=3; msign = sign;
+			mim = im;mjm = jm;mkm = km;
+			break;
+		    }
+                }
+            }
+        }
+    }
+    if (min_stage<=3) { emit(sign,im,jm,km); }
+    else { print "emit const c\n"; }
 }
 
 static void 
@@ -1155,9 +1244,12 @@
     char *rrn = register_name(r);
     if (offset==0) {
         if(r!=reg)
-            printf("\tmove %s,%s\n",crn,rrn);
-    } else
-        printf("\taddu %s,%s,%d\n",crn,rrn,offset);
+            printf("\tmov %s,%s\n",crn,rrn);
+    } else if (offset > 0) {
+	if (offset>
+        printf("\tadd %s, %s, #%d\n",crn,rrn,offset);
+    } else {
+    }
 }
 
 
@@ -2749,20 +2841,10 @@
 code_opening(char *filename)
 {
     static int count=0;
-    char *asi_name;
     /* this is called once per file */
     printf("\t.file %d \"%s\"\n",count++,filename);
-    printf(".abicalls\n");
     printf(".text\n");
 
-    if (asi) {
-        fclose(asi);
-        asi = 0;
-    }
-    asi_name = make_filename_with_extension(filename,"i");
-    if ( (asi = fopen(asi_name,"w")) == NULL ) error(FILERR);
-    if (!asi) error(-1);
-    printf(".include \"%s\"\n",asi_name);
 }
 
 // should have pcond_const
@@ -3148,8 +3230,6 @@
 //  entry part  (save register)
 
     if (max_reg_var+max_freg_var==0) {
-	fprintf(asi,"$L_%d=$L_%d\n",
-		register_save_label,register_save_return_label);
     } else {
 	code_label(register_save_label);
 	code_register_save(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2);
@@ -3399,6 +3479,7 @@
 {
     NMTBL *n;
     int init;
+    gvar_ref_list();
     init=0;
     /* static local variables */
     for(n=local_static_list;n;n=n->next) {
@@ -5214,7 +5295,6 @@
 {
     global_table();
     /* printf("\t.ident \"Micro-C compiled\"\n"); */
-    fclose(asi); asi=0;
 }
 
 #if CASE_CODE
--- a/mc-parse.c	Fri Jul 09 14:47:40 2004 +0900
+++ b/mc-parse.c	Sat Jul 10 21:46:21 2004 +0900
@@ -3157,7 +3157,9 @@
 	*cheap->ptr = '.'; /* .0 case */
 	cheap = increment_cheap(cheap,&num);
     } else if (ch == '0') {
+	*cheap->ptr = ch; cheap = increment_cheap(cheap,&num);
 	if (getch() == 'x' || ch == 'X') {
+	    *cheap->ptr = ch; cheap = increment_cheap(cheap,&num);
 	    /* hexadicimal */
 	    while(1) {
 		getch(); *cheap->ptr = ch;
@@ -3172,8 +3174,7 @@
 	    }
 	    if (is_ll()) {
 #if LONGLONG_CODE
-		*cheap->ptr = 0;
-		cheap = increment_cheap(cheap,&num);
+		cheap->ptr[-1] = 0;
 		lsymval = strtoll(num,0,0);
 		// we should keep this value? like string?
 		cheap = reset_cheap(&scheap);
@@ -3192,7 +3193,7 @@
 	    }
 	    if (is_ll()) {
 #if LONGLONG_CODE
-		*cheap->ptr = 0;
+		cheap->ptr[-1] = 0;
 		cheap = increment_cheap(cheap,&num);
 		lsymval = strtoll(num,0,0);
 		cheap = reset_cheap(&scheap);
--- a/test/code-gen.c	Fri Jul 09 14:47:40 2004 +0900
+++ b/test/code-gen.c	Sat Jul 10 21:46:21 2004 +0900
@@ -9,6 +9,24 @@
 extern int printf(const char *fmt,...);
 
 void
+code_endian()
+{
+    union {
+	unsigned char a[8];
+	unsigned short s;
+	unsigned int i;
+	unsigned long long l;
+    } u;
+    u.s = 0x0123;
+    printf("endian s : %02x %02x\n",u.a[0],u.a[1]);
+    u.i = 0x01234567;
+    printf("endian i : %02x %02x %02x %02x\n",u.a[0],u.a[1],u.a[2],u.a[3]);
+    u.l = 0x0123456789abcdefULL;
+    printf("endian l : %02x %02x %02x %02x\n",u.a[0],u.a[1],u.a[2],u.a[3]);
+    printf("endian l : %02x %02x %02x %02x\n",u.a[4],u.a[5],u.a[6],u.a[7]);
+}
+
+void
 code_lvar()
 {
     char c1,c2;
@@ -24,6 +42,24 @@
     printf("code_lvar %d %d %u %u\n",c1,c2,uc1,uc2);
 }
 
+void
+code_lvar_address()
+{
+    char c1,c2,*p;
+    unsigned char uc1,uc2,*up;
+    int i1,i2,*ip; 
+    short s1,s2,*sp; 
+    unsigned short us1,us2,*usp; 
+
+    ip = &i1; *ip = 1; ip = &i2 ; *ip = -2; 
+    sp = &s1 ; *sp = -1; sp = &s2 ; *sp = -3; 
+    usp = &us1 ; *usp = 65535; usp = &us2 ; *usp = 65535;
+    printf("code_lvar %d %d %d %d %u %u\n",i1,i2,s1,s2,us1,us2);
+    p = &c1;
+    *p = -1; p = &c2; *p = -3; up = &uc1; *up = 200; up=&uc2; *up = 202;
+    printf("code_lvar %d %d %u %u\n",c1,c2,uc1,uc2);
+}
+
 // code_label(int labelno)
 void
 code_label()