FreeBSD/contrib/binutils/gas/config/tc-arm.c
/* Parse a directive saving iWMMXt data registers.  */
Parse a directive saving iWMMXt data registers.
Parse a directive saving iWMMXt data registers .
static void
s_arm_unwind_save_mmxwr (void)
{
  int reg;
  int hi_reg;
  int i;
  unsigned mask = 0;
  valueT op;
  if (*input_line_pointer == '{')
    input_line_pointer++;
  do
    {
      reg = arm_reg_parse (&input_line_pointer, REG_TYPE_MMXWR);
      if (reg == FAIL)
	{
	  as_bad (_(reg_expected_msgs[REG_TYPE_MMXWR]));
	  goto error;
	}
      if (mask >> reg)
	as_tsktsk (_("register list not in ascending order"));
      mask |= 1 << reg;
      if (*input_line_pointer == '-')
	{
	  input_line_pointer++;
	  hi_reg = arm_reg_parse (&input_line_pointer, REG_TYPE_MMXWR);
	  if (hi_reg == FAIL)
	    {
	      as_bad (_(reg_expected_msgs[REG_TYPE_MMXWR]));
	      goto error;
	    }
	  else if (reg >= hi_reg)
	    {
	      as_bad (_("bad register range"));
	      goto error;
	    }
	  for (; reg < hi_reg; reg++)
	    mask |= 1 << reg;
	}
    }
  while (skip_past_comma (&input_line_pointer) != FAIL);
  if (*input_line_pointer == '}')
    input_line_pointer++;
  demand_empty_rest_of_line ();
  flush_pending_unwind ();
  for (i = 0; i < 16; i++)
    {
      if (mask & (1 << i))
	unwind.frame_size += 8;
    }
  if (unwind.opcode_count > 0)
    {
      i = unwind.opcodes[unwind.opcode_count - 1];
      if ((i & 0xf8) == 0xc0)
	{
	  i &= 7;
	  if (i < 6)
	    {
	      if ((mask & 0xfe00) == (1 << 9))
		{
		  mask |= ((1 << (i + 11)) - 1) & 0xfc00;
		  unwind.opcode_count--;
		}
	    }
	  else if (i == 6 && unwind.opcode_count >= 2)
	    {
	      i = unwind.opcodes[unwind.opcode_count - 2];
	      reg = i >> 4;
	      i &= 0xf;
	      op = 0xffff << (reg - 1);
	      if (reg > 0
		  && ((mask & op) == (1u << (reg - 1))))
		{
		  op = (1 << (reg + i + 1)) - 1;
		  op &= ~((1 << reg) - 1);
		  mask |= op;
		  unwind.opcode_count -= 2;
		}
	    }
	}
    }
  hi_reg = 15;
  for (reg = 15; reg >= -1; reg--)
    {
      if (reg < 0
	  || !(mask & (1 << reg)))
	{
	  if (reg != hi_reg)
	    {
	      if (reg == 9)
		{
		  op = 0xc0 | (hi_reg - 10);
		  add_unwind_opcode (op, 1);
		}
	      else
		{
		  op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
		  add_unwind_opcode (op, 2);
		}
	    }
	  hi_reg = reg - 1;
	}
    }
  return;
error:
  ignore_rest_of_line ();
}
static void s_arm_unwind_save_mmxwr ( void ) { int reg ; int hi_reg ; int i ; unsigned mask = 0 ; valueT op ; if ( * input_line_pointer == ' ' ) input_line_pointer ++ ; do { reg = arm_reg_parse ( & input_line_pointer , REG_TYPE_MMXWR ) ; if ( reg == FAIL ) { as_bad ( _ ( reg_expected_msgs [ REG_TYPE_MMXWR ] ) ) ; goto error ; } if ( mask >> reg ) as_tsktsk ( _ ( " " ) ) ; mask |= 1 << reg ; if ( * input_line_pointer == ' ' ) { input_line_pointer ++ ; hi_reg = arm_reg_parse ( & input_line_pointer , REG_TYPE_MMXWR ) ; if ( hi_reg == FAIL ) { as_bad ( _ ( reg_expected_msgs [ REG_TYPE_MMXWR ] ) ) ; goto error ; } else if ( reg >= hi_reg ) { as_bad ( _ ( " " ) ) ; goto error ; } for ( ; reg < hi_reg ; reg ++ ) mask |= 1 << reg ; } } while ( skip_past_comma ( & input_line_pointer ) != FAIL ) ; if ( * input_line_pointer == ' ' ) input_line_pointer ++ ; demand_empty_rest_of_line ( ) ; flush_pending_unwind ( ) ; for ( i = 0 ; i < 16 ; i ++ ) { if ( mask & ( 1 << i ) ) unwind . frame_size += 8 ; } if ( unwind . opcode_count > 0 ) { i = unwind . opcodes [ unwind . opcode_count - 1 ] ; if ( ( i & 0xf8 ) == 0xc0 ) { i &= 7 ; if ( i < 6 ) { if ( ( mask & 0xfe00 ) == ( 1 << 9 ) ) { mask |= ( ( 1 << ( i + 11 ) ) - 1 ) & 0xfc00 ; unwind . opcode_count -- ; } } else if ( i == 6 && unwind . opcode_count >= 2 ) { i = unwind . opcodes [ unwind . opcode_count - 2 ] ; reg = i >> 4 ; i &= 0xf ; op = 0xffff << ( reg - 1 ) ; if ( reg > 0 && ( ( mask & op ) == ( 1u << ( reg - 1 ) ) ) ) { op = ( 1 << ( reg + i + 1 ) ) - 1 ; op &= ~ ( ( 1 << reg ) - 1 ) ; mask |= op ; unwind . opcode_count -= 2 ; } } } } hi_reg = 15 ; for ( reg = 15 ; reg >= -1 ; reg -- ) { if ( reg < 0 || ! ( mask & ( 1 << reg ) ) ) { if ( reg != hi_reg ) { if ( reg == 9 ) { op = 0xc0 | ( hi_reg - 10 ) ; add_unwind_opcode ( op , 1 ) ; } else { op = 0xc600 | ( ( reg + 1 ) << 4 ) | ( ( hi_reg - reg ) - 1 ) ; add_unwind_opcode ( op , 2 ) ; } } hi_reg = reg - 1 ; } } return ; error : ignore_rest_of_line ( ) ; }
Parse a directive saving iWMMXt data registers.
Parse a directive saving iWMMXt data registers .
/* Generate any deferred opcodes because we're going to be looking at
     the list.	*/ /* Attempt to combine with a previous opcode.	 We do this because gcc
     likes to output separate unwind directives for a single block of
     registers.	 */ /* Only merge if the blocks are contiguous.  */ /* We want to generate opcodes in the order the registers have been
     saved, ie. descending order.  */ /* Save registers in blocks.  */ /* We found an unsaved reg.  Generate opcodes to save the
	     preceeding block.	*/ /* Short form.  */ /* Long form.	 */