changeset 424:485bf7dde96a non-aligned-bit-field

ARM non-aligned bitfield
author kono
date Fri, 29 Oct 2004 20:34:08 +0900
parents 8b9136a06f56
children 7851023f5af1
files .gdbinit Changes mc-code-arm.c mc-codegen.c test/bitfield.c
diffstat 5 files changed, 116 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Fri Oct 29 14:20:19 2004 +0900
+++ b/.gdbinit	Fri Oct 29 20:34:08 2004 +0900
@@ -1,5 +1,5 @@
 tb main
-run  -s test/bitfield1.c
+run  -s test/bitfield.c
 # run  -s mc-parse.c
 # run  -s mc-codegen.c
 # run  -s nkf203/nkf.c
--- a/Changes	Fri Oct 29 14:20:19 2004 +0900
+++ b/Changes	Fri Oct 29 20:34:08 2004 +0900
@@ -6355,4 +6355,17 @@
 この手のbit-field って、本来なら、inline で *C* で記述されるべき
 ものだよね。
 
-
+Fri Oct 29 20:30:41 JST 2004
+
+できたけど.... bassign の中のsassignでアドレスが狂うバグが
+あるらしい。本来は、余計なコピーがあっても、害はないはず
+なんだが、
+diff test/bitfield.gcc.out test/bitfield.mc-arm.out
+1058c1058
+< 2:00000000 00000000 00000000 def00000 56789abc 00000234 00000000 00000000
+---
+> 2:00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+と言う形で、上書きしてしまう。
+
+dum()をはさむと直ったしするのでレジスタのメンテナンスの
+問題らしいが...
--- a/mc-code-arm.c	Fri Oct 29 14:20:19 2004 +0900
+++ b/mc-code-arm.c	Fri Oct 29 20:34:08 2004 +0900
@@ -5994,43 +5994,41 @@
     } else if (l==2) {
 	use_int(reg);
 	lreg = get_lregister();
-#if LENDIAN_L==0
-	code_ld(cload(0,0),regv_l(lreg),0,reg,cext_at(0,0));
-	code_ld(cload(0,0),regv_h(lreg),SIZE_OF_INT,reg,cext_at(0,0));
-#else
-	code_ld(cload(0,0),regv_l(lreg),0,reg,cext_at(0,0));
-	code_ld(cload(0,0),regv_h(lreg),SIZE_OF_INT,reg,cext_at(0,0));
-#endif
-	code_ld(cload(0,0),reg,SIZE_OF_INT*2,reg,cext_at(0,0));
    /*
-       111111  222222222222  0000000000
-      |------||------------||----------|
-			    |-------||-------|
-			     1111111  0000000
-      <------bitsize---------------><a->        a = bitsz-bitsize
-				     <---b-->   b = 64+32-bitsize-bitbpos
-
+
+                        <-----bitsize--------------->
+                        hhhhhh  mmmmmmmmmmmm  lllllll
+   lllll  00000000000  mmmmmmmmmmmm  0000000  hhhhhhh 
+  |-----||-----------||------------||-------||-------|
+         <-bitpos--->
+  <----------------bitsz----------------------------->
+  <-----32----------> <---32------> <----32---------->
       (r0:r1) <<= bitsz-bitsize-bitbos
       rest >> =  b;
       rest << =  a;   (b>a)   ==>    rest >> (b-a)
                   (64+32-bitsize -bitpos - (bitsz-bitsize))
                  = 64+32 -bitsz -bitbpos
    */
-	if ((i=bitpos)) 
-	    loprtc(LLSHIFT,lreg,list2(CONST,i));
+	/* load hhhhh */
+	code_ld(cload(0,0),regv_h(lreg),SIZE_OF_INT*2,reg,cext_at(0,0));
+	/* load mmmmmm */
+	code_ld(cload(0,0),regv_l(lreg),SIZE_OF_INT,reg,cext_at(0,0));
+	i = 64-(bitsize-(32-bitpos));
+	loprtc(LLSHIFT,lreg,list2(CONST,i));
 	if (i<0||64<=i) error(-1);
-	/* shift right */
-	if ((i=SIZE_OF_LONGLONG*8-bitsize)) 
-	    loprtc(sign?LRSHIFT:LURSHIFT,lreg,list2(CONST,i));
-	if (i<0||64<=i) error(-1);
-	if ((i=bitsz-bitsize-bitpos)) 
-	    oprtc(RSHIFT,reg,list2(CONST,i));
+	/* load lllll */
+	code_ld(cload(0,0),reg,0,reg,cext_at(0,0));
+	i = (bitsize-(32-bitpos))-32;
+	oprtc(URSHIFT,reg,list2(CONST,i));
 	if (i<0||32<=i) error(-1);
 	inc_inst(1);
 	printf("\tadd\t%s,%s,%s\n",
-			    register_name(regv_h(lreg)),
-			    register_name(regv_h(lreg)),
+			    register_name(regv_l(lreg)),
+			    register_name(regv_l(lreg)),
 			    register_name(reg));
+	i = 64-bitsize;
+	loprtc(sign?LRSHIFT:LURSHIFT,lreg,list2(CONST,i));
+	if (i<0||64<=i) error(-1);
 	set_lreg(lreg,1);
     } else {
 	use_int(reg);
@@ -6097,37 +6095,45 @@
         tmpvar=new_lvar(SIZE_OF_LONGLONG);
 	code_lassign_lvar(tmpvar,value);
 	use_int(lvalue);
-	lrn = register_name(tmp = get_register());
-
-	i=bitsz-bitpos-bitsize;
+	trn = register_name(tmp = get_register());
+
+        /* make and-mask upper */
+	i=bitpos;
 	if (i) 
-	    oprtc(RSHIFT,regv_l(value),list2(CONST,i));
+	    oprtc(LSHIFT,regv_l(value),list2(CONST,i));
 	if (i<0||32<=i) error(-1);
 	crn = lregister_name_low(value);
-	code_ld(cload(0,0),tmp,0,lvalue,cext_at(0,0));
-	trn = lregister_name_high(value);
-	mask = make_mask(bitsz-bitpos-bitsize,31);
-	make_mask_and_or(mask,regv_h(value),trn,crn,lrn);
+	code_ld(cload(0,0),regv_h(value),0,lvalue,cext_at(0,0));
+	lrn = lregister_name_high(value);
+        mask = make_mask(0,31-bitpos);
+	make_mask_and_or(mask,tmp,trn,crn,lrn);
 	inc_inst(1);
 	printf("\t%s\t%s, [%s, #0]\n",cstore(0),crn,register_name(lvalue));
 /*
-                        111111  222222222222  1111111
-   0000000000  111111  222222222222  1111111  0000000 
-  |----------||------||------------||-------||-------|
+                        <-----bitsize--------------->
+                        hhhhhh  mmmmmmmmmmmm  lllllll
+   lllll  00000000000  mmmmmmmmmmmm  0000000  hhhhhhh 
+  |-----||-----------||------------||-------||-------|
+         <-bitpos--->
+  <----------------bitsz----------------------------->
+  <-----32----------> <---32------> <----32---------->
  */
+        /* store middle */
 	code_lrlvar(tmpvar,value);
-	i=bitsz-bitsize-bitpos;
+	i=32-bitpos;
 	if (i)
-	    loprtc(LLSHIFT,value,list2(CONST,i));
+	    loprtc(LRSHIFT,value,list2(CONST,i));
 	if (i<0||64<=i) error(-1);
 	inc_inst(1);
-	printf("\t%s\t%s, [%s, #4]\n",cstore(0),trn,register_name(lvalue));
-
-	code_ld(cload(0,0),tmp,SIZE_OF_INT*2,lvalue,cext_at(0,0));
-	mask = make_mask(0,31-i);
-	make_mask_and_or(mask,regv_h(value),trn,crn,lrn);
+	printf("\t%s\t%s, [%s, #4]\n",cstore(0),crn,register_name(lvalue));
+
+        /* make and-mask lower */
+	code_ld(cload(0,0),regv_l(value),SIZE_OF_INT*2,lvalue,cext_at(0,0));
+	if (i<0||64<=i) error(-1);
+	mask = make_mask(bitsz-bitpos-bitsize,31);
+	make_mask_and_or(mask,tmp,trn,lrn,crn);
 	inc_inst(1);
-	printf("\t%s\t%s, [%s, #8]\n",cstore(0),crn,register_name(lvalue));
+	printf("\t%s\t%s, [%s, #8]\n",cstore(0),lrn,register_name(lvalue));
 	free_lvar(tmpvar);
 	set_ireg(lvalue,0);
     } else {
@@ -6214,28 +6220,30 @@
 	    make_mask_and_or_const(mask,crn,(int)lc);
 	}
     } else if (l==2) {
+/*
+                        hhhhhh  mmmmmmmmmmmm  lllllll
+   lllll  00000000000  mmmmmmmmmmmm  0000000  hhhhhhh 
+  |-----||-----------||------------||-------||-------|
+ */
 	use_int(lvalue);
 	crn = register_name(lvalue);
 	trn = register_name(tmp = get_register());
 	/* shift right */
 	lc = lcadr(value);
-	lc >>= 32-bitpos;
 	/* make and-mask upper */
 	code_ld(cload(0,0),tmp,0,lvalue,cext_at(0,0));
-	mask = make_mask(bitsz-bitpos-bitsize,bitsz-bitpos);
-	make_mask_and_or_const(mask,trn,(int)(lc>>32));
+	mask = make_mask(0,31-bitpos);
+	make_mask_and_or_const(mask,trn,(int)(lc<<bitpos));
 	inc_inst(1);
 	printf("\t%s\t%s, [%s, #0]\n",cstore(0),trn,crn);
 	/* store middle */
-	code_const((int)lc,tmp);
+	code_const((int)(lc>>(32-bitpos)),tmp);
 	inc_inst(1);
 	printf("\t%s\t%s, [%s, #4]\n",cstore(0),trn,crn);
 	/* make and-mask lower */
-	lc = lcadr(value);
-	lc <<= bitpos;
 	code_ld(cload(0,0),tmp,SIZE_OF_INT*2,lvalue,cext_at(0,0));
-	mask = make_mask(0,31-bitpos);
-	make_mask_and_or_const(mask,trn,(int)lc);
+	mask = make_mask(bitsz-bitpos-bitsize,31);
+	make_mask_and_or_const(mask,trn,(int)(lc>>(64-bitpos)));
 	inc_inst(1);
 	printf("\t%s\t%s, [%s, #8]\n",cstore(0),trn,crn);
 #endif
--- a/mc-codegen.c	Fri Oct 29 14:20:19 2004 +0900
+++ b/mc-codegen.c	Fri Oct 29 20:34:08 2004 +0900
@@ -1309,9 +1309,11 @@
     if (car(e4)==RSTRUCT) {
 	e4 = cadr(e4);
     }
-    if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) {
-	if (use) g_expr(e4);
-	return;
+    if (is_same_type(e2,e4)) {
+	if (cadr(e2)==cadr(e4)) {
+	    if (use) g_expr(e4);
+	    return;
+	}
     }
     g_expr(e4);
     emit_push();
@@ -3522,21 +3524,29 @@
     }
     if (car(e2)==LREGISTER||car(e2)==REGISTER||car(e2)==LVAR||car(e2)==GVAR) {
 	e4 = rvalue_t(e2,stype);
-	g_expr(assign_expr0(e2, list4(BFD_REPL,e4,e3,t), stype,stype));
+	if (stype>0 && car(stype)==STRUCT)
+	    g_expr(list4(BFD_REPL,e4,e3,t));
+	else
+	    g_expr(assign_expr0(e2, list4(BFD_REPL,e4,e3,t), stype,stype));
 	if (use)
 	    code_bit_field(t, cadr(caddr(t))  /* bit offset */, USE_CREG);
 	return type;
     }
     /*  new = &e2 */
     /*  *new = *new bit_repl e3 */
-    n = list2(LVAR,new_lvar(size_of_int));
     //  n = get_register_var(0);
-    g_expr_u(assign_expr0(n,list2(ADDRESS,cadr(e2)),INT,INT));
-    e4 = rvalue_t(list2(INDIRECT,rvalue_t(n,INT)),stype);
-    g_expr(assign_expr0(list2(INDIRECT,rvalue_t(n,INT)),
-	list4(BFD_REPL,e4,e3,t),
-	stype,stype));
-    free_lvar(cadr(n));
+    if (stype>0 && car(stype)==STRUCT) {
+	e4 = rvalue_t(list2(INDIRECT,rvalue_t(n,INT)),stype);
+	g_expr(list4(BFD_REPL,list2(ADDRESS,cadr(e2)),e3,t));
+    } else {
+	n = list2(LVAR,new_lvar(size_of_int));
+	g_expr_u(assign_expr0(n,list2(ADDRESS,cadr(e2)),INT,INT));
+	e4 = rvalue_t(list2(INDIRECT,rvalue_t(n,INT)),stype);
+	g_expr(assign_expr0(list2(INDIRECT,rvalue_t(n,INT)),
+	    list4(BFD_REPL,e4,e3,t),
+	    stype,stype));
+	free_lvar(cadr(n));
+    }
     if (use)
 	code_bit_field(t, cadr(caddr(t))  /* bit offset */, USE_CREG);
     return type;
--- a/test/bitfield.c	Fri Oct 29 14:20:19 2004 +0900
+++ b/test/bitfield.c	Fri Oct 29 20:34:08 2004 +0900
@@ -534,7 +534,7 @@
     } b;
 } ii;
 
-int m1 = -1;
+long long m1 = 0x123456789abcdefLL;
 int p1 = 1;
 int zero = 0;
 
@@ -543,60 +543,68 @@
      ii.b.a = -1;
      printf("m5c-00:%d\n",ii.b.a);
 
-     ll1.b.v = -1;
+     ll1.b.v = 0x123456789abcdefLL;
      printf("m5c-01:%llx\n",ll1.b.v);
      printf("m5c-02:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll1.a[0],ll1.a[1],ll1.a[2],ll1.a[3],
 	ll1.a[4],ll1.a[5],ll1.a[6],ll1.a[7]
       );
      ll1.b.v = 0;
-     ll1.b.w = -1;
+     printf("m5c-01:%llx\n",
+	 ll1.b.w = 0x123456789abcdefLL);
      printf("m5c-02:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll1.a[0],ll1.a[1],ll1.a[2],ll1.a[3],
 	ll1.a[4],ll1.a[5],ll1.a[6],ll1.a[7]
       );
      ll1.b.w = 0;
-     ll1.b.x = -1;
+     printf("m5c-01:%llx\n",
+	 ll1.b.x = 0x123456789abcdefLL);
      printf("m5c-02:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll1.a[0],ll1.a[1],ll1.a[2],ll1.a[3],
 	ll1.a[4],ll1.a[5],ll1.a[6],ll1.a[7]
       );
      ll1.b.x = 0;
 
-     ll0.b.v = -1;
+     printf("m5c-01:%llx\n",
+	 ll0.b.v = 0x123456789abcdefLL);
      printf("m5c-01:%llx\n",ll0.b.v);
      printf("m5c-02:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll0.a[0],ll0.a[1],ll0.a[2],ll0.a[3],
 	ll0.a[4],ll0.a[5],ll0.a[6],ll0.a[7]
       );
      ll0.b.v = 0;
-     ll0.b.w = -1;
+     printf("m5c-01:%llx\n",
+	 ll0.b.w = 0x123456789abcdefLL);
      printf("m5c-02:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll0.a[0],ll0.a[1],ll0.a[2],ll0.a[3],
 	ll0.a[4],ll0.a[5],ll0.a[6],ll0.a[7]
       );
      ll0.b.w = 0;
-     ll0.b.x = -1;
+     printf("m5c-01:%llx\n",
+	 ll0.b.x = 0x123456789abcdefLL);
      printf("m5c-02:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll0.a[0],ll0.a[1],ll0.a[2],ll0.a[3],
 	ll0.a[4],ll0.a[5],ll0.a[6],ll0.a[7]
       );
      ll0.b.x = 0;
 
-     ll.b.v = -1;
+     printf("m5c-01:%llx\n",
+	 ll.b.v = 0x123456789abcdefLL);
      printf("m5c-1:%llx\n",ll.b.v);
      printf("m5c-2:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll.a[0],ll.a[1],ll.a[2],ll.a[3],
 	ll.a[4],ll.a[5],ll.a[6],ll.a[7]
       );
      ll.b.v = 0;
-     ll.b.w = -1;
+     printf("m5c-01:%llx\n",
+	 ll.b.w = 0x123456789abcdefLL);
      printf("m5c-2:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll.a[0],ll.a[1],ll.a[2],ll.a[3],
 	ll.a[4],ll.a[5],ll.a[6],ll.a[7]
       );
      ll.b.w = 0;
-     ll.b.x = -1;
+     printf("m5c-01:%llx\n",
+	 ll.b.x = 0x123456789abcdefLL);
      printf("m5c-2:%08x %08x %08x %08x %08x %08x %08x %08x\n",
 	ll.a[0],ll.a[1],ll.a[2],ll.a[3],
 	ll.a[4],ll.a[5],ll.a[6],ll.a[7]
@@ -604,6 +612,7 @@
      ll.b.x = 0;
 
      printf("m5c-char a:1; char b:4; char c:7; char d:4; char e:4; char f:4;\n");
+     cc.a = 0;
      cc.b.a = -1;
      printf("m5c-a:%08x\n",cc.a);
      cc.b.b = -1;
@@ -735,6 +744,7 @@
       );
      ll.b.x = zero;
 
+     cc.a = zero;
      printf("char a:1; char b:4; char c:7; char d:4; char e:4; char f:4;\n");
      cc.b.a = m1;
      printf("a:%08x\n",cc.a);