changeset 421:ab58eea5e032

Non aligned bit field (not yet complete)
author kono
date Fri, 29 Oct 2004 04:18:39 +0900
parents efbd420386c5
children 83a7f9426a55
files mc-code-arm.c mc-codegen.c
diffstat 2 files changed, 128 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/mc-code-arm.c	Thu Oct 28 21:20:52 2004 +0900
+++ b/mc-code-arm.c	Fri Oct 29 04:18:39 2004 +0900
@@ -647,6 +647,14 @@
 	regs[i]=USING_REG;      /* そのレジスタを使うことを宣言し */
 	return i;   /* その場所を表す番号を返す */
     }
+    for(i=0;i<REG_VAR_MAX-REG_VAR_MIN;i++) {
+        reg =REG_VAR_BASE+i;
+        if (! regs[reg]) {       /* 使われていないなら */
+            regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
+	    if (i+1>max_reg_var) max_reg_var=i+1;
+	    return reg;   /* その場所を表す番号を返す */
+        }
+    }
     /* search register stack */
     for(i=0;i<reg_sp;i++) {
 	if ((reg=reg_stack[i])>0) {
@@ -668,14 +676,6 @@
 	}
     }
 #endif
-    for(i=0;i<REG_VAR_MAX-REG_VAR_MIN;i++) {
-        reg =REG_VAR_BASE+i;
-        if (! regs[reg]) {       /* 使われていないなら */
-            regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
-	    if (i+1>max_reg_var) max_reg_var=i+1;
-	    return reg;   /* その場所を表す番号を返す */
-        }
-    }
     /* PTR_CACHE をつぶす */
     for(i=MAX_TMP_REG;i>=MIN_TMP_REG;i--) {
 	if (regs[i]==PTRC_REG) {
@@ -5870,7 +5870,7 @@
     }
     if (car(caddr(type))>0) { /* store type */
 	if (car(car(caddr(type)))==STRUCT) {
-	    bitsz=64+32; align=4;l=1;
+	    bitsz=64+32; l=2;
 	} else error(-1);
     } else {
 	switch(car(caddr(type))) { 
@@ -5880,8 +5880,8 @@
 	case UCHAR: 	    bitsz= 8; break; 
 	case SHORT:         bitsz=16; break; 
 	case USHORT:        bitsz=16; break; 
-	case LONGLONG:      bitsz=64; break; 
-	case ULONGLONG:     bitsz=64; break; 
+	case LONGLONG:      bitsz=64; l=1; break; 
+	case ULONGLONG:     bitsz=64; l=1; break; 
 	default: error(-1);
 	}
     }
@@ -5904,7 +5904,6 @@
     int bitpos = *bfd;
     int offset = *poffset;
     int l;
-    int stype;
     int bitsize = caddr(caddr(type));
     set_bitsz(type,&sign,&bitsz,&align,&l);
 
@@ -5914,7 +5913,10 @@
     if (bitpos) {
 	/* previous field is bit field and spaces may remain */
 	/* calc previsous offset */
-	if (bitpos+bitsize > bitsz) {
+#if 1
+	int stype;
+	/* code for non-aligned non-hole bit-field */
+	if (bitpos!=bitsz && bitpos+bitsize > bitsz) {
 	    switch(car(caddr(type))) { 
 	    case INT:	 	stype=ULONGLONG;    break;
 	    case UNSIGNED:	stype=ULONGLONG; break;
@@ -5926,9 +5928,10 @@
 	    case ULONGLONG: 	stype=list4(STRUCT,12,0,0); break;
 	    default: error(-1);
 	    }
-	    bitsz = size(stype);
-	    cadr(caddr(type)) = stype;
+	    bitsz = size(stype)*8;
+	    car(caddr(type)) = stype;
 	}
+#endif
 
 	i= offset-(bitpos+7)/8;
 	for(l = bitpos;l>0;l -= 8,i++) {
@@ -5936,8 +5939,12 @@
 		/* alignment is correct and space remains */
 		*poffset=offset=i;
 		i = l+bitsize;
-		*bfd = i;
-		*sz = (i+7)/8;
+		if (i==bitsz) {
+		    *bfd = 0;
+		} else {
+		    *bfd = i;
+		}
+	        *sz = (i+7)/8;
  printf("# bitpos=%d bitsize=%d bitsz=%d offset=%d\n",l,bitsize,bitsz,*poffset);
 		return l;
 	    } 
@@ -5977,6 +5984,45 @@
 	/* shift right */
 	if ((i=bitsz-bitsize)) 
 	    loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i));
+    } 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
+
+      (r0:r1) <<= bitsz-bitsize-bitbos
+      rest >> =  b;
+      rest << =  a;   (b>a)   ==>    rest >> (b-a)
+                  (64+32-bitsize -bitpos - (bitsz-bitsize))
+                 = 64+32 -bitsz -bitbpos
+   */
+	/* shift left */
+	if ((i=bitsz-SIZE_OF_LONGLONG*8-bitpos)) 
+	    oprtc(LSHIFT,reg,list2(CONST,i));
+	if ((i=SIZE_OF_LONGLONG*8-bitsize-bitpos)) 
+	    loprtc(LLSHIFT,lreg,list2(CONST,i));
+	inc_inst(1);
+	printf("\tadd\t%s,%s,%s\n",
+			    register_name(regv_l(lreg)),
+			    register_name(regv_l(lreg)),
+			    register_name(reg));
+	set_lreg(lreg,1);
+	/* shift right */
+	if ((i=SIZE_OF_LONGLONG*8-bitsize)) 
+	    loprtc(sign?LRSHIFT:LURSHIFT,lreg,list2(CONST,i));
     } else {
 	use_int(reg);
 	/* shift left */
@@ -6013,10 +6059,11 @@
     int bitsize = caddr(caddr(type));
     int mask = 0;
     int tmp = -1;
+    int tmpvar = -1;
     char *crn,*lrn,*trn;
     set_bitsz(type,&sign,&bitsz,&align,&l);
 // printf("# %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
-    if (l) {
+    if (l==1) {
 	use_longlong(value);
 	crn = lregister_name_high(value);
 	lrn = lregister_name_high(lvalue);
@@ -6036,6 +6083,35 @@
 	    mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos);
 	    make_mask_and_or(mask,tmp,trn,crn,lrn);
 	}
+    } else if (l==2) {
+	use_longlong(value);
+        tmpvar=new_lvar(SIZE_OF_LONGLONG);
+	code_lassign_lvar(tmpvar,value);
+	use_int(lvalue);
+	lrn = register_name(tmp = get_register());
+
+	if (bitsz-bitpos-bitsize) 
+	    oprtc(RSHIFT,regv_l(value),list2(CONST,bitsz-bitpos-bitsize));
+	crn = lregister_name_low(value);
+	code_ld(cload(0,0),regv_l(value),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);
+	inc_inst(1);
+	printf("\t%s\t%s, [%s, #0]\n",cstore(0),crn,register_name(lvalue));
+
+	code_lrlvar(list2(LVAR,tmpvar),value);
+	loprtc(LLSHIFT,value,list2(CONST,64-(bitsize-bitpos)));
+	inc_inst(1);
+	printf("\t%s\t%s, [%s, #4]\n",cstore(0),crn,register_name(lvalue));
+
+	code_ld(cload(0,0),regv_h(value),SIZE_OF_INT*2,lvalue,cext_at(0,0));
+	mask = make_mask(0,31-(bitsz-bitpos-bitsize));
+	make_mask_and_or(mask,regv_h(value),trn,crn,lrn);
+	inc_inst(1);
+	printf("\t%s\t%s, [%s, #8]\n",cstore(0),crn,register_name(lvalue));
+	free_lvar(tmpvar);
+	set_ireg(lvalue,0);
     } else {
 	use_int(value);
 	crn = register_name(value);
@@ -6096,11 +6172,12 @@
     int c;
 #if LONGLONG_CODE
     long long lc;
+    int tmp;
 #endif
-    char *crn;
+    char *crn,*trn;
     set_bitsz(type,&sign,&bitsz,&align,&l);
 // printf("# %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
-    if (l) {
+    if (l==1) {
 #if LONGLONG_CODE
 	use_longlong(lvalue);
 	crn = lregister_name_high(lvalue);
@@ -6118,6 +6195,31 @@
 	    mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos);
 	    make_mask_and_or_const(mask,crn,(int)lc);
 	}
+    } else if (l==2) {
+	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,value,cext_at(0,0));
+	mask = make_mask(bitsz-bitpos-bitsize,bitsz-bitpos);
+	make_mask_and_or_const(mask,trn,(int)(lc>>32));
+	inc_inst(1);
+	printf("\t%s\t%s, [%s, #0]\n",cstore(0),trn,crn);
+	/* store middle */
+	code_const((int)lc,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,value,cext_at(0,0));
+	mask = make_mask(0,31-bitpos);
+	make_mask_and_or_const(mask,trn,(int)lc);
+	inc_inst(1);
+	printf("\t%s\t%s, [%s, #8]\n",cstore(0),trn,crn);
 #endif
     } else {
 	use_int(lvalue);
--- a/mc-codegen.c	Thu Oct 28 21:20:52 2004 +0900
+++ b/mc-codegen.c	Fri Oct 29 04:18:39 2004 +0900
@@ -1875,8 +1875,7 @@
 	case BIT_FIELD:
             //        type = list4(BIT_FIELD,type,
             //            list3(type /*store type*/,0 /*bit offset*/,symval));
-	    e2 = correct_type(e2,car(caddr(t))); /* store type */
-	    type = cadr(t); /* value type */
+	    e2 = correct_type(e2,cadr(t)); /* value type */
 	    return(list4(BASS,e1,e2,list2(BASS,t)));
 	case STRUCT:case UNION:
 	    if (size(t)!=size(type)) error(TYERR);
@@ -3494,20 +3493,21 @@
 bit_field_repl(int e1,int e2,int t)
 {
     /* e1 = e2 */
-    int lo = is_long_type(car(caddr(t))); /* store type  */
+    int stype = car(caddr(t));   /* store type */
+    int lo = is_long_type(stype);
     if ((car(e2)==CONST||car(e2)==LCONST)) {
 	g_expr(e1);
 	code_bit_replace_const(e2,USE_CREG,
 	    t /* type */,cadr(caddr(t)) /* bit offset */);
-	return cadr(t);
+	return stype;
     }
     g_expr(e1);
     if (lo) emit_lpush(); else emit_push();
     g_expr(e2);
-    code_bit_replace(USE_CREG,(e2=lo?emit_lpop():pop_register()),
+    code_bit_replace(USE_CREG,(e2=lo?emit_lpop():emit_pop(0)),
 	t /* type */,cadr(caddr(t)) /* bit offset */);
     if (lo) emit_lpop_free(e2); else emit_pop_free(e2);
-    return cadr(t);
+    return stype;
 }
 
 static int