FreeBSD/contrib/binutils/gas/config/tc-arm.c
/* Start an unwind table entry.	 HAVE_DATA is nonzero if we have additional
   personality routine data.  Returns zero, or the index table value for
   and inline entry.  */
Start an unwind table entry.    HAVE_DATA is nonzero if we have additional
personality routine data.  Returns zero, or the index table value for
and inline entry.
Start an unwind table entry . HAVE_DATA is nonzero if we have additional personality routine data . Returns zero or the index table value for and inline entry .
static valueT
create_unwind_entry (int have_data)
{
  int size;
  addressT where;
  char *ptr;
  valueT data;
  int n;
  finish_unwind_opcodes ();
  unwind.saved_seg = now_seg;
  unwind.saved_subseg = now_subseg;
  start_unwind_section (now_seg, 0);
  if (unwind.personality_routine == NULL)
    {
      if (unwind.personality_index == -2)
	{
	  if (have_data)
	    as_bad (_("handerdata in cantunwind frame"));
	  return 1; 
	}
      if (unwind.personality_index == -1)
	{
	  if (unwind.opcode_count > 3)
	    unwind.personality_index = 1;
	  else
	    unwind.personality_index = 0;
	}
      if (unwind.personality_index == 0)
	{
	  if (unwind.opcode_count > 3)
	    as_bad (_("too many unwind opcodes for personality routine 0"));
	  if (!have_data)
	    {
	      data = 0x80;
	      n = 3;
	      while (unwind.opcode_count > 0)
		{
		  unwind.opcode_count--;
		  data = (data << 8) | unwind.opcodes[unwind.opcode_count];
		  n--;
		}
	      while (n--)
		data = (data << 8) | 0xb0;
	      return data;
	    }
	  size = 0;
	}
      else
	size = unwind.opcode_count - 2;
    }
  else
    size = unwind.opcode_count + 1;
  size = (size + 3) >> 2;
  if (size > 0xff)
    as_bad (_("too many unwind opcodes"));
  frag_align (2, 0, 0);
  record_alignment (now_seg, 2);
  unwind.table_entry = expr_build_dot ();
  ptr = frag_more ((size << 2) + 4);
  memset(ptr, 0, (size << 2) + 4);
  where = frag_now_fix () - ((size << 2) + 4);
  switch (unwind.personality_index)
    {
    case -1:
      fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
	       BFD_RELOC_ARM_PREL31);
      where += 4;
      ptr += 4;
      data = size - 1;
      n = 3;
      break;
    case 0:
      data = 0x80;
      n = 3;
      break;
    case 1:
    case 2:
      data = ((0x80 + unwind.personality_index) << 8) | size;
      n = 2;
      break;
    default:
      abort ();
    }
  while (unwind.opcode_count > 0)
    {
      if (n == 0)
	{
	  md_number_to_chars (ptr, data, 4);
	  ptr += 4;
	  n = 4;
	  data = 0;
	}
      unwind.opcode_count--;
      n--;
      data = (data << 8) | unwind.opcodes[unwind.opcode_count];
    }
  if (n < 4)
    {
      while (n--)
	data = (data << 8) | 0xb0;
      md_number_to_chars (ptr, data, 4);
    }
  if (!have_data)
    {
      ptr = frag_more (4);
      md_number_to_chars (ptr, 0, 4);
    }
  return 0;
}
static valueT create_unwind_entry ( int have_data ) { int size ; addressT where ; char * ptr ; valueT data ; int n ; finish_unwind_opcodes ( ) ; unwind . saved_seg = now_seg ; unwind . saved_subseg = now_subseg ; start_unwind_section ( now_seg , 0 ) ; if ( unwind . personality_routine == NULL ) { if ( unwind . personality_index == -2 ) { if ( have_data ) as_bad ( _ ( " " ) ) ; return 1 ; } if ( unwind . personality_index == -1 ) { if ( unwind . opcode_count > 3 ) unwind . personality_index = 1 ; else unwind . personality_index = 0 ; } if ( unwind . personality_index == 0 ) { if ( unwind . opcode_count > 3 ) as_bad ( _ ( " " ) ) ; if ( ! have_data ) { data = 0x80 ; n = 3 ; while ( unwind . opcode_count > 0 ) { unwind . opcode_count -- ; data = ( data << 8 ) | unwind . opcodes [ unwind . opcode_count ] ; n -- ; } while ( n -- ) data = ( data << 8 ) | 0xb0 ; return data ; } size = 0 ; } else size = unwind . opcode_count - 2 ; } else size = unwind . opcode_count + 1 ; size = ( size + 3 ) >> 2 ; if ( size > 0xff ) as_bad ( _ ( " " ) ) ; frag_align ( 2 , 0 , 0 ) ; record_alignment ( now_seg , 2 ) ; unwind . table_entry = expr_build_dot ( ) ; ptr = frag_more ( ( size << 2 ) + 4 ) ; memset ( ptr , 0 , ( size << 2 ) + 4 ) ; where = frag_now_fix ( ) - ( ( size << 2 ) + 4 ) ; switch ( unwind . personality_index ) { case -1 : fix_new ( frag_now , where , 4 , unwind . personality_routine , 0 , 1 , BFD_RELOC_ARM_PREL31 ) ; where += 4 ; ptr += 4 ; data = size - 1 ; n = 3 ; break ; case 0 : data = 0x80 ; n = 3 ; break ; case 1 : case 2 : data = ( ( 0x80 + unwind . personality_index ) << 8 ) | size ; n = 2 ; break ; default : abort ( ) ; } while ( unwind . opcode_count > 0 ) { if ( n == 0 ) { md_number_to_chars ( ptr , data , 4 ) ; ptr += 4 ; n = 4 ; data = 0 ; } unwind . opcode_count -- ; n -- ; data = ( data << 8 ) | unwind . opcodes [ unwind . opcode_count ] ; } if ( n < 4 ) { while ( n -- ) data = ( data << 8 ) | 0xb0 ; md_number_to_chars ( ptr , data , 4 ) ; } if ( ! have_data ) { ptr = frag_more ( 4 ) ; md_number_to_chars ( ptr , 0 , 4 ) ; } return 0 ; }
Start an unwind table entry.
Start an unwind table entry .
/* The current word of data.	*/ /* The number of bytes left in this word.  */ /* Remember the current text section.	 */ /* EXIDX_CANTUNWIND.  */ /* Use a default personality routine if none is specified.  */ /* Space for the personality routine entry.  */ /* All the data is inline in the index table.  */ /* Pad with "finish" opcodes.  */ /* We get two opcodes "free" in the first word.	 */ /* An extra byte is required for the opcode count.	*/ /* Allocate the table entry.	*/ /* ??? Should this be a PLT generating relocation?  */ /* Custom personality routine.  */ /* Set the first byte to the number of additional words.	*/ /* ABI defined personality routines.  */ /* Three opcodes bytes are packed into the first word.  */ /* The size and first two opcode bytes go in the first word.  */ /* Should never happen.  */ /* Pack the opcodes into words (MSB first), reversing the list at the same
     time.  */ /* Finish off the last word.	*/ /* Pad with "finish" opcodes.  */ /* Add an empty descriptor if there is no user-specified data.   */