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]

Re: Merging of various patches for d10v gas


On Tue, 18 Dec 2001, Nick Clifton wrote:

> Hi Alan,
> 
> > The following patches are from various fixes that have been
> > floating around and have not been merged back into the head.
> 
Here we are. 

2001-12-17 Alan Matsuoka <alanm@redhat.com>

	From Jeff Knaggs <jknaggs@redhat.com>
	* config/tc-d10v.c (check_resource_conflict): New function to 
	check for resource conflicts.

	From Jason Eckhardt  <jle@redhat.com>
        * config/tc-d10v.c (build_insn): Check for unresolved imm4 or
        imm3 fields.
        * config/tc-d10v.c (find_opcode): Emit a warning if one of the
        reserved control registers is used.
        * config/tc-d10v.c (build_insn): Check for unresolved imm4 or
        imm3 fields.

	From 2001-03-28  Diego Novillo  <dnovillo@redhat.com>
        * tc-d10v.c (parallel_ok): Prevent packing only if the first
        instruction cannot be packed.

	From 2001-03-30  Diego Novillo  <dnovillo@redhat.com>
        * gas/config/tc-d10v.c (check_resource_conflict): Only check
        write-write conflicts.
        (md_assemble): Reformat introductory comment.
        * opcodes/d10v-opc.c (d10v_opcodes): `btsti' does not modify its
        arguments.


Index: tc-d10v.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gas/config/tc-d10v.c,v
retrieving revision 1.79
diff -d -c -p -3 -r1.79 tc-d10v.c
*** tc-d10v.c	2001/12/12 07:41:28	1.79
--- tc-d10v.c	2001/12/18 15:03:28
***************
*** 25,31 ****
  #include "subsegs.h"
  #include "opcode/d10v.h"
  #include "elf/ppc.h"
- //#include "read.h"
  
  const char comment_chars[] = ";";
  const char line_comment_chars[] = "#";
--- 25,30 ----
*************** static unsigned long d10v_insert_operand
*** 99,104 ****
--- 98,105 ----
  static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
  				struct d10v_opcode *opcode2, unsigned long insn2,
  				packing_type exec_type));
+ static void check_resource_conflict PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1, 
+ 				struct d10v_opcode *opcode2, unsigned long insn2));
  static symbolS * find_symbol_matching_register PARAMS ((expressionS *));
  
  struct option md_longopts[] =
*************** build_insn (opcode, opers, insn)
*** 630,636 ****
  
  	  if (AT_WORD_P (&opers[i]))
  	    {
! 	      /* Reconize XXX>>1+N aka XXX@word+N as special (AT_WORD).  */
  	      fixups->fix[fixups->fc].reloc = BFD_RELOC_D10V_18;
  	      opers[i].X_op = O_symbol;
  	      opers[i].X_op_symbol = NULL; /* Should free it.  */
--- 631,637 ----
  
  	  if (AT_WORD_P (&opers[i]))
  	    {
! 	      /* Recognize XXX>>1+N aka XXX@word+N as special (AT_WORD).  */
  	      fixups->fix[fixups->fc].reloc = BFD_RELOC_D10V_18;
  	      opers[i].X_op = O_symbol;
  	      opers[i].X_op_symbol = NULL; /* Should free it.  */
*************** build_insn (opcode, opers, insn)
*** 642,649 ****
  	      opers[i].X_add_number = number;
  	    }
  	  else
! 	    fixups->fix[fixups->fc].reloc =
! 	      get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
  
  	  if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 ||
  	      fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18)
--- 643,656 ----
  	      opers[i].X_add_number = number;
  	    }
  	  else
!             {
! 	      fixups->fix[fixups->fc].reloc =
! 	        get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
!               if ((bits == 3 || bits == 4)
!                   && fixups->fix[fixups->fc].reloc == 0
!                   && (flags & OPERAND_NUM))
!                 as_bad (_("imm4/imm3 field unresolved (undefined symbol?)"));
!             }
  
  	  if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 ||
  	      fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18)
*************** write_2_short (opcode1, insn1, opcode2, 
*** 833,838 ****
--- 840,846 ----
  	}
        else
  	insn = FM00 | (insn1 << 15) | insn2;
+       check_resource_conflict (opcode1, insn1, opcode2, insn2);
        break;
  
      case PACK_LEFT_RIGHT:
*************** parallel_ok (op1, insn1, op2, insn2, exe
*** 938,945 ****
  
    /* If this is auto parallization, and either instruction is a branch,
       don't parallel.  */
!   if (exec_type == PACK_UNSPEC
!       && (op1->exec_type & ALONE || op2->exec_type & ALONE))
      return 0;
  
    /* The idea here is to create two sets of bitmasks (mod and used)
--- 946,952 ----
  
    /* If this is auto parallization, and either instruction is a branch,
       don't parallel.  */
!   if (exec_type == PACK_UNSPEC && (op1->exec_type & (ALONE|BRANCH)))
      return 0;
  
    /* The idea here is to create two sets of bitmasks (mod and used)
*************** parallel_ok (op1, insn1, op2, insn2, exe
*** 1042,1053 ****
    return 0;
  }
  
- /* This is the main entry point for the machine-dependent assembler.
-    STR points to a machine-dependent instruction.  This function is
-    supposed to emit the frags/bytes it assembles to.  For the D10V, it
-    mostly handles the special VLIW parsing and packing and leaves the
-    difficult stuff to do_assemble().  */
  
  static unsigned long prev_insn;
  static struct d10v_opcode *prev_opcode = 0;
  static subsegT prev_subseg;
--- 1049,1210 ----
    return 0;
  }
  
  
+ /* Determine if there are any resource conflicts among two manually
+    parallelized instructions.  Some of this was lifted from parallel_ok.  */
+ static void 
+ check_resource_conflict (op1, insn1, op2, insn2)
+      struct d10v_opcode *op1, *op2;
+      unsigned long insn1, insn2;
+ {
+   int i, j, flags, mask, shift, regno;
+   unsigned long ins, mod[2], used[2];
+   struct d10v_opcode *op;
+ 
+   if ((op1->exec_type & SEQ)
+       || ! ((op1->exec_type & PAR) || (op1->exec_type & PARONLY)))
+     {
+       as_warn (_("packing conflict: %s must dispatch sequentially"),
+ 	      op1->name);
+       return;
+     }
+ 
+   if ((op2->exec_type & SEQ)
+       || ! ((op2->exec_type & PAR) || (op2->exec_type & PARONLY)))
+     {
+       as_warn (_("packing conflict: %s must dispatch sequentially"),
+ 	      op2->name);
+       return;
+     }
+ 
+ 
+   /* The idea here is to create two sets of bitmasks (mod and used)
+      which indicate which registers are modified or used by each
+      instruction.  The operation can only be done in parallel if
+      instruction 1 and instruction 2 modify different registers, and
+      the first instruction does not modify registers that the second
+      is using (The second instruction can modify registers that the
+      first is using as they are only written back after the first
+      instruction has completed).  Accesses to control registers
+      and memory are treated as accesses to a single register.  So if
+      both instructions write memory or if the first instruction writes
+      memory and the second reads, then they cannot be done in
+      parallel. We treat reads to the PSW (which includes C, F0, and F1)
+      in isolation. So simultaneously writing C and F0 in two different
+      sub-instructions is permitted.  */
+ 
+   /* the bitmasks (mod and used) look like this (bit 31 = MSB) */
+   /* r0-r15	  0-15  */
+   /* a0-a1	  16-17 */
+   /* cr (not psw) 18    */
+   /* psw(other)   19    */
+   /* mem	  20    */
+   /* psw(C flag)  21    */
+   /* psw(F0 flag) 22    */
+ 
+ 
+   for (j = 0; j < 2; j++)
+     {
+       if (j == 0)
+ 	{
+ 	  op = op1;
+ 	  ins = insn1;
+ 	}
+       else
+ 	{
+ 	  op = op2;
+ 	  ins = insn2;
+ 	}
+       mod[j] = used[j] = 0;
+       if (op->exec_type & BRANCH_LINK)
+ 	mod[j] |= 1 << 13;
+ 
+       for (i = 0; op->operands[i]; i++)
+ 	{
+ 	  flags = d10v_operands[op->operands[i]].flags;
+ 	  shift = d10v_operands[op->operands[i]].shift;
+ 	  mask = 0x7FFFFFFF >> (31 - d10v_operands[op->operands[i]].bits);
+ 	  if (flags & OPERAND_REG)
+ 	    {
+ 	      regno = (ins >> shift) & mask;
+ 	      if (flags & (OPERAND_ACC0 | OPERAND_ACC1))
+ 		regno += 16;
+ 	      else if (flags & OPERAND_CONTROL)	/* mvtc or mvfc */
+ 		{ 
+ 		  if (regno == 0)
+ 		    regno = 19;
+ 		  else
+ 		    regno = 18; 
+ 		}
+ 	      else if (flags & OPERAND_FFLAG)
+ 		regno = 22;
+ 	      else if (flags & OPERAND_CFLAG)
+ 		regno = 21;
+ 	      
+             if ( flags & OPERAND_DEST )
+ 		{
+ 		  mod[j] |= 1 << regno;
+ 		  if (flags & OPERAND_EVEN)
+ 		    mod[j] |= 1 << (regno + 1);
+ 		}
+             else
+               {
+                 used[j] |= 1 << regno ;
+                 if (flags & OPERAND_EVEN)
+                   used[j] |= 1 << (regno + 1);
+ 
+                 /* Auto inc/dec also modifies the register.  */
+                 if (op->operands[i+1] != 0
+                     && (d10v_operands[op->operands[i+1]].flags
+                         & (OPERAND_PLUS | OPERAND_MINUS)) != 0)
+                   mod[j] |= 1 << regno;
+               }
+ 	    }
+ 	  else if (flags & OPERAND_ATMINUS)
+ 	    {
+             /* SP implicitly used/modified */
+ 	      mod[j] |= 1 << 15;
+             used[j] |= 1 << 15;
+ 	    }
+ 	}
+       if (op->exec_type & RMEM)
+       used[j] |= 1 << 20;
+       else if (op->exec_type & WMEM)
+ 	mod[j] |= 1 << 20;
+       else if (op->exec_type & RF0)
+       used[j] |= 1 << 22;
+       else if (op->exec_type & WF0)
+ 	mod[j] |= 1 << 22;
+       else if (op->exec_type & WCAR)
+ 	mod[j] |= 1 << 21;
+     }
+   if ((mod[0] & mod[1]) == 0)
+     return;
+   else
+     {
+       unsigned long x;
+       x = mod[0] & mod[1];
+ 
+       for (j = 0; j <= 15; j++)
+ 	if (x & (1 << j))
+ 	  as_warn (_("resource conflict (R%d)"), j);
+       for (j = 16; j <= 17; j++)
+ 	if (x & (1 << j))
+ 	  as_warn (_("resource conflict (A%d)"), j - 16);
+       if (x & (1 << 19))
+ 	as_warn (_("resource conflict (PSW)"));
+       if (x & (1 << 21))
+ 	as_warn (_("resource conflict (C flag)"));
+       if (x & (1 << 22))
+ 	as_warn (_("resource conflict (F flag)"));
+     }
+ }
+ /* This is the main entry point for the machine-dependent assembler.  str  points to a
+    machine-dependent instruction.  This function is supposed to emit the  frags/bytes
+    it assembles to.  For the D10V, it mostly handles the special VLIW parsing and packing
+    and leaves the difficult stuff to do_assemble().
+  */
+ 
  static unsigned long prev_insn;
  static struct d10v_opcode *prev_opcode = 0;
  static subsegT prev_subseg;
*************** find_opcode (opcode, myops)
*** 1468,1485 ****
  	  if (!(d10v_operands[opcode->operands[i]].flags & OPERAND_REG))
  	    {
  	      myops[i].X_op = O_symbol;
! 	      myops[i].X_add_symbol =
! 		symbol_find_or_make ((char *) myops[i].X_op_symbol);
  	      myops[i].X_add_number = 0;
  	      myops[i].X_op_symbol = NULL;
  	    }
  	}
      }
    return opcode;
  }
  
! /* If while processing a fixup, a reloc really needs to be created.
!    Then it is done here.  */
  
  arelent *
  tc_gen_reloc (seg, fixp)
--- 1625,1650 ----
  	  if (!(d10v_operands[opcode->operands[i]].flags & OPERAND_REG))
  	    {
  	      myops[i].X_op = O_symbol;
! 	      myops[i].X_add_symbol = symbol_find_or_make ((char *)myops[i].X_op_symbol);
  	      myops[i].X_add_number = 0;
  	      myops[i].X_op_symbol = NULL;
  	    }
  	}
+       if ((d10v_operands[opcode->operands[i]].flags & OPERAND_CONTROL)
+         && (myops[i].X_add_number == OPERAND_CONTROL + 4
+             || myops[i].X_add_number == OPERAND_CONTROL + 5
+             || myops[i].X_add_number == OPERAND_CONTROL + 6
+             || myops[i].X_add_number == OPERAND_CONTROL + 12
+             || myops[i].X_add_number == OPERAND_CONTROL + 13
+             || myops[i].X_add_number == OPERAND_CONTROL + 15))
+       as_warn (_("cr%d is a reserved control register"),
+                myops[i].X_add_number - OPERAND_CONTROL);
      }
    return opcode;
  }
  
! /* If while processing a fixup, a reloc really needs to be created
!    Then it is done here. */
  
  arelent *
  tc_gen_reloc (seg, fixp)
*************** md_apply_fix3 (fixP, valP, seg)
*** 1595,1601 ****
--- 1760,1780 ----
      case BFD_RELOC_D10V_10_PCREL_L:
      case BFD_RELOC_D10V_10_PCREL_R:
      case BFD_RELOC_D10V_18_PCREL:
+       /* If the fix is relative to a global symbol, not a section
+ 	 symbol, then ignore the offset.
+          XXX - Do we have to worry about branches to a symbol + offset ?  */
+       if (fixP->fx_addsy != NULL
+ 	  && S_IS_EXTERN (fixP->fx_addsy) )
+         {
+           segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
+           segment_info_type *segf = seg_info(fseg);
+ 
+ 	  if ( segf && segf->sym != fixP->fx_addsy)
+ 	    value = 0;
+         }
+       /* Drop through.  */
      case BFD_RELOC_D10V_18:
+ 
        /* Instruction addresses are always right-shifted by 2.  */
        value >>= AT_WORD_RIGHT_SHIFT;
        if (fixP->fx_size == 2)
Index: tc-d10v.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gas/config/tc-d10v.h,v
retrieving revision 1.19
diff -d -c -p -3 -r1.19 tc-d10v.h
*** tc-d10v.h	2001/11/25 23:42:22	1.19
--- tc-d10v.h	2001/12/18 15:03:28
***************
*** 34,39 ****
--- 34,41 ----
  
  #define TARGET_FORMAT "elf32-d10v"
  
+ #define MD_APPLY_FIX3
+ 
  /* Call md_pcrel_from_section, not md_pcrel_from.  */
  #define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
  long md_pcrel_from_section PARAMS ((fixS *, segT));
Alan Matsuoka
GCC Engineering
Red Hat Canada, Ltd
mailto:alanm@redhat.com Tel: (416) 482-2661 x250 / Fax: (416) 482-6299


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