This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Committed, CRIS: fix varying-size operand support for sym2-sym1 expressions.


Two bugs, one (at least) that has always been there.  The bogus
now corrected md_convert_frag code has obviously never executed;
relaxation results were always complete in
md_estimate_size_before_relax.  The SIMPLE_EXPR change was
driven by misassembling unary minus expressions.  (BTW, I found
that DIFF_EXPR_OK had little to do with this.)

gas/testsuite:

	* gas/cris/rd-pcrel1.d, gas/cris/rd-pcrel1.s,
	gas/cris/rd-pcrel2.d, gas/cris/rd-pcrel2.s: New tests.

gas:
	* config/tc-cris.c (SIMPLE_EXPR): New macro.
	(cris_relax_frag): New function.
	(md_estimate_size_before_relax) <case ENCODE_RELAX
	(STATE_BASE_PLUS_DISP_PREFIX, STATE_UNDF)>: Pass on unresolved
	expressions that will become absolute expressions to relaxation.
	(md_convert_frag) <case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX,
	STATE_WORD)>: Expect only absolute expressions.  Use the symbol
	value, not distance to symbol.
	<case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE)>:
	Ditto.  Correct placement of fixup.
	(md_assemble): Use SIMPLE_EXPR when dissecting expressions.
	(gen_bdap): Ditto.
	* config/tc-cris.h (cris_relax_frag): Declare.
	(md_relax_frag): Define.


--- /dev/null	Tue Jan  1 05:00:00 1980
+++ gas/cris/rd-pcrel1.d	Tue Oct 22 23:33:04 2002
@@ -0,0 +1,45 @@
+#objdump: -dr
+
+.*:     file format .*-cris
+
+Disassembly of section \.text:
+#...
+[ 	]+28:[ 	]+6fae 6e00 0000[ 	]+move.d 6e <y03\+0xa>,r10
+[ 	]+2e:[ 	]+6fae dcff ffff[ 	]+move.d 0xffffffdc,r10
+[ 	]+34:[ 	]+6fae 5c00 0000[ 	]+move.d 5c <y01>,r10
+[ 	]+3a:[ 	]+6fae caff ffff[ 	]+move.d 0xffffffca,r10
+[ 	]+40:[ 	]+6fae 5000 0000[ 	]+move.d 50 <xx\+0x28>,r10
+[ 	]+46:[ 	]+6fae beff ffff[ 	]+move.d 0xffffffbe,r10
+[ 	]+4c:[ 	]+3ef1 633a[ 	]+move.d \[pc\+62\],r3
+[ 	]+50:[ 	]+b8f1 633a[ 	]+move.d \[pc-72\],r3
+[ 	]+54:[ 	]+40f1 633a[ 	]+move.d \[pc\+64\],r3
+0+58 <y00>:
+[ 	]+58:[ 	]+b0f1 633a[ 	]+move.d \[pc-80\],r3
+0+5c <y01>:
+[ 	]+5c:[ 	]+38f1 633a[ 	]+move.d \[pc\+56\],r3
+0+60 <y02>:
+[ 	]+60:[ 	]+a8f1 633a[ 	]+move.d \[pc-88\],r3
+0+64 <y03>:
+#...
+[ 	]+480:[ 	]+5ffd 0a04 633a[ 	]+move.d \[pc\+1034\],r3
+[ 	]+486:[ 	]+5ffd 82fb 633a[ 	]+move.d \[pc-1150\],r3
+[ 	]+48c:[ 	]+5ffd fc03 633a[ 	]+move.d \[pc\+1020\],r3
+0+492 <yy00>:
+[ 	]+492:[ 	]+5ffd 74fb 633a[ 	]+move.d \[pc-1164\],r3
+0+498 <yy01>:
+[ 	]+498:[ 	]+5ffd f003 633a[ 	]+move.d \[pc\+1008\],r3
+0+49e <yy02>:
+[ 	]+49e:[ 	]+5ffd 68fb 633a[ 	]+move.d \[pc-1176\],r3
+#...
+[ 	]+18f2e:[ 	]+6ffd ce86 0100 633a[ 	]+move.d \[pc\+186ce <yy\+0x17e42>\],r3
+[ 	]+18f36:[ 	]+6ffd d270 feff 633a[ 	]+move.d \[pc\+fffe70d2 <z\+0xfffb5ad4>\],r3
+[ 	]+18f3e:[ 	]+6ffd ba86 0100 633a[ 	]+move.d \[pc\+186ba <yy\+0x17e2e>\],r3
+0+18f46 <z00>:
+[ 	]+18f46:[ 	]+6ffd be70 feff 633a[ 	]+move.d \[pc\+fffe70be <z\+0xfffb5ac0>\],r3
+0+18f4e <z01>:
+[ 	]+18f4e:[ 	]+6ffd aa86 0100 633a[ 	]+move.d \[pc\+186aa <yy\+0x17e1e>\],r3
+0+18f56 <z02>:
+[ 	]+18f56:[ 	]+6ffd ae70 feff 633a[ 	]+move.d \[pc\+fffe70ae <z\+0xfffb5ab0>\],r3
+#...
+0+315fe <z>:
+[ 	]+315fe:[ 	]+0f05[ 	]+nop 
--- /dev/null	Tue Jan  1 05:00:00 1980
+++ gas/cris/rd-pcrel1.s	Wed Oct 23 00:28:25 2002
@@ -0,0 +1,55 @@
+; Test that pc-relative expressions give expected results for
+; various expressions.
+ .text
+ .space 10
+x:
+ .space 30
+xx:
+ move.d y-.,r10
+ move.d x-.,r10
+ move.d y-(.+6),r10
+ move.d x-(.+6),r10
+ move.d y-.-6,r10
+ move.d x-.-6,r10
+ move.d [pc+y-(.+12)],r3
+ move.d [pc+x-(.+2)],r3
+ move.d [pc+y-(y00-2)],r3
+y00:
+ move.d [pc+x-(y01-2)],r3
+y01:
+ move.d [pc+y-y02+2],r3
+y02:
+ move.d [pc+x-y03+2],r3
+y03:
+ .space 50
+y:
+ nop
+ .space 1000
+ move.d [pc+yy-(.+2)],r3
+ move.d [pc+x-(.+2)],r3
+ move.d [pc+yy-(yy00-2)],r3
+yy00:
+ move.d [pc+x-(yy01-2)],r3
+yy01:
+ move.d [pc+yy-yy02+2],r3
+yy02:
+ move.d [pc+x-yy03+2],r3
+yy03:
+ .space 1000
+yy:
+ nop
+ .space 100000
+ move.d [pc+z-(.+2)],r3
+ move.d [pc+x-(.+2)],r3
+ move.d [pc+z-(z00-2)],r3
+z00:
+ move.d [pc+x-(z01-2)],r3
+z01:
+ move.d [pc+z-z02+2],r3
+z02:
+ move.d [pc+x-z03+2],r3
+z03:
+ .space 100000
+z:
+ nop
+
--- /dev/null	Tue Jan  1 05:00:00 1980
+++ gas/cris/rd-pcrel2.d	Tue Oct 22 23:33:04 2002
@@ -0,0 +1,40 @@
+#objdump: -dr
+
+.*:     file format .*-cris
+
+Disassembly of section \.text:
+
+0+ <z>:
+[ 	]+0:[ 	]+80f1 688a[ 	]+move.d \[pc-128\],r8
+[ 	]+4:[ 	]+5ffd 7dff 688a[ 	]+move.d \[pc-131\],r8
+[ 	]+a:[ 	]+7ff1 688a[ 	]+move.d \[pc\+127\],r8
+[ 	]+e:[ 	]+5ffd 8200 688a[ 	]+move.d \[pc\+130\],r8
+[ 	]+14:[ 	]+5ffd 0080 688a[ 	]+move.d \[pc-32768\],r8
+[ 	]+1a:[ 	]+6ffd fd7f ffff 688a[ 	]+move.d \[pc\+ffff7ffd <x8\+0xffff7f9d>\],r8
+[ 	]+22:[ 	]+5ffd ff7f 688a[ 	]+move.d \[pc\+32767\],r8
+[ 	]+28:[ 	]+6ffd 0280 0000 688a[ 	]+move.d \[pc\+8002 <x8\+0x7fa2>\],r8
+0+30 <x>:
+[ 	]+30:[ 	]+80f1 688a[ 	]+move.d \[pc-128\],r8
+0+34 <x1>:
+[ 	]+34:[ 	]+5ffd 7dff 688a[ 	]+move.d \[pc-131\],r8
+0+3a <x2>:
+[ 	]+3a:[ 	]+7ff1 688a[ 	]+move.d \[pc\+127\],r8
+0+3e <x3>:
+[ 	]+3e:[ 	]+5ffd 8200 688a[ 	]+move.d \[pc\+130\],r8
+0+44 <x4>:
+[ 	]+44:[ 	]+5ffd 0080 688a[ 	]+move.d \[pc-32768\],r8
+0+4a <x5>:
+[ 	]+4a:[ 	]+6ffd fd7f ffff 688a[ 	]+move.d \[pc\+ffff7ffd <x8\+0xffff7f9d>\],r8
+0+52 <x6>:
+[ 	]+52:[ 	]+5ffd ff7f 688a[ 	]+move.d \[pc\+32767\],r8
+0+58 <x7>:
+[ 	]+58:[ 	]+6ffd 0280 0000 688a[ 	]+move.d \[pc\+8002 <x8\+0x7fa2>\],r8
+0+60 <x8>:
+[ 	]+60:[ 	]+80f1 688a[ 	]+move.d \[pc-128\],r8
+[ 	]+64:[ 	]+5ffd 7dff 688a[ 	]+move.d \[pc-131\],r8
+[ 	]+6a:[ 	]+7ff1 688a[ 	]+move.d \[pc\+127\],r8
+[ 	]+6e:[ 	]+5ffd 8200 688a[ 	]+move.d \[pc\+130\],r8
+[ 	]+74:[ 	]+5ffd 0080 688a[ 	]+move.d \[pc-32768\],r8
+[ 	]+7a:[ 	]+6ffd fd7f ffff 688a[ 	]+move.d \[pc\+ffff7ffd <x8\+0xffff7f9d>\],r8
+[ 	]+82:[ 	]+5ffd ff7f 688a[ 	]+move.d \[pc\+32767\],r8
+[ 	]+88:[ 	]+6ffd 0280 0000 688a[ 	]+move.d \[pc\+8002 <x8\+0x7fa2>\],r8
--- /dev/null	Tue Jan  1 05:00:00 1980
+++ gas/cris/rd-pcrel2.s	Tue Oct 22 23:33:04 2002
@@ -0,0 +1,60 @@
+; Test border-cases for relaxation of pc-relative expressions.
+
+ .macro relaxcode
+ .endm
+
+ .text
+
+; Region of relaxation is after insn, same segment 
+z:
+ move.d [pc-(x1-x+128-4)],r8 ; 4
+ move.d [pc-(x2-x+129-8)],r8 ; 6
+ move.d [pc+x3-x+127-14],r8 ; 4
+ move.d [pc+x4-x+128-18],r8 ; 6
+ move.d [pc-(x5-x+32768-26)],r8 ; 6
+ move.d [pc-(x6-x+32769-32)],r8 ; 8
+ move.d [pc+x7-x+32767-40],r8 ; 6
+ move.d [pc+x8-x+32768-46],r8 ; 8
+
+ .p2align 1
+
+; Region of relaxation is around insn, same segment 
+x:
+ move.d [pc-(x1-x+128-4)],r8 ; 4
+x1:
+ move.d [pc-(x2-x+129-8)],r8 ; 6
+x2:
+ move.d [pc+x3-x+127-14],r8 ; 4
+x3:
+ move.d [pc+x4-x+128-18],r8 ; 6
+x4:
+ move.d [pc-(x5-x+32768-26)],r8 ; 6
+x5:
+ move.d [pc-(x6-x+32769-32)],r8 ; 8
+x6:
+ move.d [pc+x7-x+32767-40],r8 ; 6
+x7:
+ move.d [pc+x8-x+32768-46],r8 ; 8
+x8:
+
+; Region of relaxation is before insn, same segment.
+ move.d [pc-(x1-x+128-4)],r8 ; 4
+ move.d [pc-(x2-x+129-8)],r8 ; 6
+ move.d [pc+x3-x+127-14],r8 ; 4
+ move.d [pc+x4-x+128-18],r8 ; 6
+ move.d [pc-(x5-x+32768-26)],r8 ; 6
+ move.d [pc-(x6-x+32769-32)],r8 ; 8
+ move.d [pc+x7-x+32767-40],r8 ; 6
+ move.d [pc+x8-x+32768-46],r8 ; 8
+
+; Region of relaxation is in other segment.
+ .section .text.other
+y:
+ move.d [pc-(x1-x+128-4)],r8 ; 4
+ move.d [pc-(x2-x+129-8)],r8 ; 6
+ move.d [pc+x3-x+127-14],r8 ; 4
+ move.d [pc+x4-x+128-18],r8 ; 6
+ move.d [pc-(x5-x+32768-26)],r8 ; 6
+ move.d [pc-(x6-x+32769-32)],r8 ; 8
+ move.d [pc+x7-x+32767-40],r8 ; 6
+ move.d [pc+x8-x+32768-46],r8 ; 8

Index: gas/config/tc-cris.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-cris.c,v
retrieving revision 1.22
diff -p -c -r1.22 tc-cris.c
*** gas/config/tc-cris.c	5 Sep 2002 00:01:17 -0000	1.22
--- gas/config/tc-cris.c	22 Oct 2002 22:48:37 -0000
***************
*** 43,48 ****
--- 43,55 ----
  #define SYNTAX_USER_SYM_NO_LEADING_UNDERSCORE "no_leading_underscore"
  #define REGISTER_PREFIX_CHAR '$'
  
+ /* True for expressions where getting X_add_symbol and X_add_number is
+    enough to get the "base" and "offset"; no need to make_expr_symbol.
+    It's not enough to check if X_op_symbol is NULL; that misses unary
+    operations like O_uminus.  */
+ #define SIMPLE_EXPR(EXP) \
+  ((EXP)->X_op == O_constant || (EXP)->X_op == O_symbol)
+ 
  /* Like in ":GOT", ":GOTOFF" etc.  Other ports use '@', but that's in
     line_separator_chars for CRIS, so we avoid it.  */
  #define PIC_SUFFIX_CHAR ':'
*************** cris_target_format ()
*** 330,335 ****
--- 337,434 ----
      }
  }
  
+ /* We need a port-specific relaxation function to cope with sym2 - sym1
+    relative expressions with both symbols in the same segment (but not
+    necessarily in the same frag as this insn), for example:
+      move.d [pc+sym2-(sym1-2)],r10
+     sym1:
+    The offset can be 8, 16 or 32 bits long.  */
+ 
+ long
+ cris_relax_frag (seg, fragP, stretch)
+      segT seg ATTRIBUTE_UNUSED;
+      fragS *fragP;
+      long stretch ATTRIBUTE_UNUSED;
+ {
+   long growth;
+   offsetT aim = 0;
+   symbolS *symbolP;
+   const relax_typeS *this_type;
+   const relax_typeS *start_type;
+   relax_substateT next_state;
+   relax_substateT this_state;
+   const relax_typeS *table = TC_GENERIC_RELAX_TABLE;
+ 
+   /* We only have to cope with frags as prepared by
+      md_estimate_size_before_relax.  The dword cases may geet here
+      because of the different reasons that they aren't relaxable.  */
+   switch (fragP->fr_subtype)
+     {
+     case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_DWORD):
+     case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_DWORD):
+       /* When we get to these states, the frag won't grow any more.  */
+       return 0;
+ 
+     case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_WORD):
+     case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE):
+       if (fragP->fr_symbol == NULL
+ 	  || S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
+ 	as_fatal (_("internal inconsistency problem in %s: fr_symbol %lx"),
+ 		  __FUNCTION__, (long) fragP->fr_symbol);
+       symbolP = fragP->fr_symbol;
+       if (symbol_resolved_p (symbolP))
+ 	as_fatal (_("internal inconsistency problem in %s: resolved symbol"),
+ 		  __FUNCTION__);
+       aim = S_GET_VALUE (symbolP);
+       break;
+ 
+     default:
+       as_fatal (_("internal inconsistency problem in %s: fr_subtype %d"),
+ 		  __FUNCTION__, fragP->fr_subtype);
+     }
+ 
+   /* The rest is stolen from relax_frag.  There's no obvious way to
+      share the code, but fortunately no requirement to keep in sync as
+      long as fragP->fr_symbol does not have its segment changed.  */
+ 
+   this_state = fragP->fr_subtype;
+   start_type = this_type = table + this_state;
+ 
+   if (aim < 0)
+     {
+       /* Look backwards.  */
+       for (next_state = this_type->rlx_more; next_state;)
+ 	if (aim >= this_type->rlx_backward)
+ 	  next_state = 0;
+ 	else
+ 	  {
+ 	    /* Grow to next state.  */
+ 	    this_state = next_state;
+ 	    this_type = table + this_state;
+ 	    next_state = this_type->rlx_more;
+ 	  }
+     }
+   else
+     {
+       /* Look forwards.  */
+       for (next_state = this_type->rlx_more; next_state;)
+ 	if (aim <= this_type->rlx_forward)
+ 	  next_state = 0;
+ 	else
+ 	  {
+ 	    /* Grow to next state.  */
+ 	    this_state = next_state;
+ 	    this_type = table + this_state;
+ 	    next_state = this_type->rlx_more;
+ 	  }
+     }
+ 
+   growth = this_type->rlx_length - start_type->rlx_length;
+   if (growth != 0)
+     fragP->fr_subtype = this_state;
+   return growth;
+ }
+ 
  /* Prepare machine-dependent frags for relaxation.
  
     Called just before relaxation starts. Any symbol that is now undefined
*************** md_estimate_size_before_relax (fragP, se
*** 386,391 ****
--- 485,501 ----
  	    = ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_DWORD);
  	  fragP->fr_var = md_cris_relax_table[fragP->fr_subtype].rlx_length;
  	}
+       else if (!symbol_resolved_p (fragP->fr_symbol))
+ 	{
+ 	  /* The symbol will eventually be completely resolved as an
+ 	     absolute expression, but right now it depends on the result
+ 	     of relaxation and we don't know anything else about the
+ 	     value.  We start relaxation with the assumption that it'll
+ 	     fit in a byte.  */
+ 	  fragP->fr_subtype
+ 	    = ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE);
+ 	  fragP->fr_var = md_cris_relax_table[fragP->fr_subtype].rlx_length;
+ 	}
        else
  	{
  	  /* Absolute expression.  */
*************** md_convert_frag (abfd, sec, fragP)
*** 526,532 ****
        break;
  
      case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE):
!       var_partp[0] = target_address - (address_of_var_part + 1);
        var_part_size = 0;
        break;
  
--- 636,645 ----
        break;
  
      case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE):
!       if (symbolP == NULL)
! 	as_fatal (_("internal inconsistency in %s: bdapq no symbol"),
! 		    __FUNCTION__);
!       opcodep[0] = S_GET_VALUE (symbolP);
        var_part_size = 0;
        break;
  
*************** md_convert_frag (abfd, sec, fragP)
*** 536,542 ****
        opcodep[0] = BDAP_PC_LOW + (1 << 4);
        opcodep[1] &= 0xF0;
        opcodep[1] |= BDAP_INCR_HIGH;
!       md_number_to_chars (var_partp, (long) (target_address), 2);
        var_part_size = 2;
        break;
  
--- 649,658 ----
        opcodep[0] = BDAP_PC_LOW + (1 << 4);
        opcodep[1] &= 0xF0;
        opcodep[1] |= BDAP_INCR_HIGH;
!       if (symbolP == NULL)
! 	as_fatal (_("internal inconsistency in %s: bdap.w with no symbol"),
! 		  __FUNCTION__);
!       md_number_to_chars (var_partp, S_GET_VALUE (symbolP), 2);
        var_part_size = 2;
        break;
  
*************** md_assemble (str)
*** 813,824 ****
  	{
  	  /* Handle complex expressions.  */
  	  valueT addvalue
! 	    = (output_instruction.expr.X_op_symbol != NULL
! 	       ? 0 : output_instruction.expr.X_add_number);
  	  symbolS *sym
! 	    = (output_instruction.expr.X_op_symbol != NULL
! 	       ? make_expr_symbol (&output_instruction.expr)
! 	       : output_instruction.expr.X_add_symbol);
  
  	  /* If is_undefined, then the expression may BECOME now_seg.  */
  	  length_code = is_undefined ? STATE_UNDF : STATE_BYTE;
--- 929,941 ----
  	{
  	  /* Handle complex expressions.  */
  	  valueT addvalue
! 	    = (SIMPLE_EXPR (&output_instruction.expr)
! 	       ? output_instruction.expr.X_add_number
! 	       : 0);
  	  symbolS *sym
! 	    = (SIMPLE_EXPR (&output_instruction.expr)
! 	       ? output_instruction.expr.X_add_symbol
! 	       : make_expr_symbol (&output_instruction.expr));
  
  	  /* If is_undefined, then the expression may BECOME now_seg.  */
  	  length_code = is_undefined ? STATE_UNDF : STATE_BYTE;
*************** gen_bdap (base_regno, exprP)
*** 2386,2395 ****
      {
        /* Handle complex expressions.  */
        valueT addvalue
! 	= exprP->X_op_symbol != NULL ? 0 : exprP->X_add_number;
        symbolS *sym
! 	= (exprP->X_op_symbol != NULL
! 	   ? make_expr_symbol (exprP) : exprP->X_add_symbol);
  
        /* The expression is not defined yet but may become absolute.  We
  	 make it a relocation to be relaxed.  */
--- 2503,2512 ----
      {
        /* Handle complex expressions.  */
        valueT addvalue
! 	= SIMPLE_EXPR (exprP) ? exprP->X_add_number : 0;
        symbolS *sym
! 	= (SIMPLE_EXPR (exprP)
! 	   ? exprP->X_add_symbol : make_expr_symbol (exprP));
  
        /* The expression is not defined yet but may become absolute.  We
  	 make it a relocation to be relaxed.  */
Index: tc-cris.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-cris.h,v
retrieving revision 1.7
diff -p -c -r1.7 tc-cris.h
*** tc-cris.h	5 Sep 2002 00:01:17 -0000	1.7
--- tc-cris.h	22 Oct 2002 22:40:13 -0000
*************** extern const int md_long_jump_size;
*** 75,80 ****
--- 75,90 ----
  extern const struct relax_type md_cris_relax_table[];
  #define TC_GENERIC_RELAX_TABLE md_cris_relax_table
  
+ long cris_relax_frag PARAMS ((segT, fragS *, long));
+ 
+ /* GAS only handles relaxations for pc-relative data targeting addresses
+    in the same segment, so we have to handle the rest on our own.  */
+ #define md_relax_frag(SEG, FRAGP, STRETCH)		\
+  ((FRAGP)->fr_symbol != NULL				\
+   && S_GET_SEGMENT ((FRAGP)->fr_symbol) == (SEG)	\
+   ? relax_frag (SEG, FRAGP, STRETCH)			\
+   : cris_relax_frag (SEG, FRAGP, STRETCH))
+ 
  #define TC_FORCE_RELOCATION(FIX) md_cris_force_relocation (FIX)
  extern int md_cris_force_relocation PARAMS ((struct fix *));
  
brgds, H-P


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]