home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / GDB / GDB-4.13 / GDB-4 / gdb-4.13 / bfd / aout-ns32k.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-14  |  10.5 KB  |  311 lines

  1. /* Written by Ian Dall
  2.  *            5-Jun-94
  3.  * HISTORY
  4.  * 05-Jun-94  Ian Dall (idall@eleceng.adelaide.edu.au) at University of Adelaide
  5.  *    This code was formerly in aout-pc532-mach.c. This organisations
  6.  *    is intended to allow multiple format support more easilly.
  7.  *
  8.  */
  9.  
  10. #define BYTES_IN_WORD 4
  11.  
  12. #include "bfd.h"
  13. #include "aout/aout64.h"
  14. #include "aout-ns32k.h"
  15. #define MY(OP) MYNS(OP)
  16.  
  17.  
  18. #define MY_swap_std_reloc_in MY(swap_std_reloc_in)
  19. #define MY_swap_std_reloc_out MY(swap_std_reloc_out)
  20.  
  21. static void
  22. MY_swap_std_reloc_in PARAMS ((bfd *abfd, struct reloc_std_external *bytes,
  23.                   arelent *cache_ptr, asymbol **symbols));
  24.  
  25. static void
  26. MY_swap_std_reloc_out PARAMS((bfd *abfd, arelent *g,
  27.                   struct reloc_std_external *natptr));
  28.  
  29.  
  30. /* The ns32k series is ah, unusual, when it comes to relocation.
  31.  * There are three storage methods for relocateable objects.  There
  32.  * are displacements, immediate operands and ordinary twos complement
  33.  * data. Of these, only the last fits into the standard relocation
  34.  * scheme.  Immediate operands are stored huffman encoded and
  35.  * immediate operands are stored big endian (where as the natural byte
  36.  * order is little endian for this achitecture).
  37.  
  38.  * Note that the ns32k displacement storage method is orthogonal to
  39.  * whether the relocation is pc relative or not. The "displacement"
  40.  * storage scheme is used for essentially all address constants. The
  41.  * displacement can be relative to zero (absolute displacement),
  42.  * relative to the pc (pc relative), the stack pointer, the frame
  43.  * pointer, the static base register and general purpose register etc.
  44.  
  45.  * For example:
  46.  *
  47.  *  sym1: .long .    # pc relative 2's complement
  48.  *  sym1: .long foo    # 2's complement not pc relative
  49.  *
  50.  *  self:  movd @self, r0 # pc relative displacement
  51.  *       movd foo, r0 # non pc relative displacement
  52.  *
  53.  *  self:  movd self, r0 # pc relative immediate
  54.  *         movd foo, r0 # non pc relative immediate
  55.  *
  56.  * In addition, for historical reasons the encoding of the relocation types
  57.  * in the a.out format relocation entries is such that even the relocation
  58.  * methods which are standard are not encoded the standard way.
  59.  *
  60.  */
  61.  
  62.  
  63. bfd_reloc_status_type
  64.  ns32k_reloc_disp(bfd *abfd, arelent *reloc_entry,
  65.           struct symbol_cache_entry *symbol,
  66.           PTR data,
  67.           asection *input_section,
  68.           bfd *output_bfd,
  69.           char **error_message);
  70. bfd_reloc_status_type
  71.   ns32k_reloc_imm (bfd *abfd,
  72.            arelent *reloc_entry,
  73.            struct symbol_cache_entry *symbol,
  74.            PTR data,
  75.            asection *input_section,
  76.            bfd *output_bfd,
  77.            char **error_message);
  78. bfd_reloc_status_type
  79.   ns32k_reloc_contents_disp (const reloc_howto_type *howto,
  80.             bfd *input_bfd,
  81.             bfd_vma relocation,
  82.             bfd_byte *location);
  83. bfd_reloc_status_type
  84.   ns32k_reloc_contents_imm (const reloc_howto_type *howto,
  85.             bfd *input_bfd,
  86.             bfd_vma relocation,
  87.             bfd_byte *location);
  88.  
  89. reloc_howto_type MY(howto_table)[] = 
  90. {
  91. /* ns32k immediate operands */
  92. HOWTO2(BFD_RELOC_NS32K_IMM_8, 0, 0, 8, false, 0, true,
  93.        ns32k_reloc_imm, ns32k_reloc_contents_imm,"NS32K_IMM_8",
  94.        true, 0x000000ff,0x000000ff, false),
  95. HOWTO2(BFD_RELOC_NS32K_IMM_16, 0, 1, 16, false, 0, true,
  96.        ns32k_reloc_imm, ns32k_reloc_contents_imm, "NS32K_IMM_16",
  97.        true, 0x0000ffff,0x0000ffff, false),
  98. HOWTO2(BFD_RELOC_NS32K_IMM_32, 0, 2, 32, false, 0, true,
  99.        ns32k_reloc_imm, ns32k_reloc_contents_imm,"NS32K_IMM_32",
  100.        true, 0xffffffff,0xffffffff, false),
  101. HOWTO2(BFD_RELOC_NS32K_IMM_8_PCREL, 0, 0, 8, true, 0, false,
  102.        ns32k_reloc_imm, ns32k_reloc_contents_imm,"PCREL_NS32K_IMM_8",
  103.        true, 0x000000ff, 0x000000ff, false),
  104. HOWTO2(BFD_RELOC_NS32K_IMM_16_PCREL, 0, 1, 16, true, 0, false,
  105.        ns32k_reloc_imm, ns32k_reloc_contents_imm,"PCREL_NS32K_IMM_16",
  106.        true, 0x0000ffff,0x0000ffff, false),
  107. HOWTO2(BFD_RELOC_NS32K_IMM_32_PCREL, 0, 2, 32, true, 0, false,
  108.        ns32k_reloc_imm, ns32k_reloc_contents_imm,"PCREL_NS32K_IMM_32",
  109.        true, 0xffffffff,0xffffffff, false),
  110.  
  111. /* ns32k displacements */
  112. HOWTO2(BFD_RELOC_NS32K_DISP_8, 0, 0, 8, false, 0, true,
  113.        ns32k_reloc_disp, ns32k_reloc_contents_disp,"NS32K_DISP_8",
  114.        true, 0x000000ff,0x000000ff, false),
  115. HOWTO2(BFD_RELOC_NS32K_DISP_16, 0, 1, 16, false, 0, true,
  116.        ns32k_reloc_disp, ns32k_reloc_contents_disp,"NS32K_DISP_16",
  117.        true, 0x0000ffff, 0x0000ffff, false),
  118. HOWTO2(BFD_RELOC_NS32K_DISP_32, 0, 2, 32, false, 0, true,
  119.        ns32k_reloc_disp, ns32k_reloc_contents_disp,"NS32K_DISP_32",
  120.        true, 0xffffffff, 0xffffffff, false),
  121. HOWTO2(BFD_RELOC_NS32K_DISP_8_PCREL, 0, 0, 8, true, 0, false,
  122.        ns32k_reloc_disp, ns32k_reloc_contents_disp,"PCREL_NS32K_DISP_8",
  123.        true, 0x000000ff,0x000000ff, false),
  124. HOWTO2(BFD_RELOC_NS32K_DISP_16_PCREL, 0, 1, 16, true, 0, false,
  125.        ns32k_reloc_disp, ns32k_reloc_contents_disp,"PCREL_NS32K_DISP_16",
  126.        true, 0x0000ffff,0x0000ffff, false),
  127. HOWTO2(BFD_RELOC_NS32K_DISP_32_PCREL, 0, 2, 32, true, 0, false,
  128.        ns32k_reloc_disp, ns32k_reloc_contents_disp,"PCREL_NS32K_DISP_32",
  129.        true, 0xffffffff,0xffffffff, false),
  130.  
  131. /* Normal 2's complement */
  132. HOWTO(BFD_RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,
  133.       "8", true, 0x000000ff,0x000000ff, false),
  134. HOWTO(BFD_RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,
  135.       "16", true, 0x0000ffff,0x0000ffff, false),
  136. HOWTO(BFD_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,
  137.       "32", true, 0xffffffff,0xffffffff, false),
  138. HOWTO(BFD_RELOC_8_PCREL, 0, 0, 8, true, 0, complain_overflow_signed, 0,
  139.       "PCREL_8", true, 0x000000ff,0x000000ff, false),
  140. HOWTO(BFD_RELOC_16_PCREL, 0, 1, 16, true, 0, complain_overflow_signed, 0,
  141.       "PCREL_16", true, 0x0000ffff,0x0000ffff, false),
  142. HOWTO(BFD_RELOC_32_PCREL, 0, 2, 32, true, 0, complain_overflow_signed, 0,
  143.       "PCREL_32", true, 0xffffffff,0xffffffff, false),
  144. };
  145.  
  146. #define MY_reloc_howto(BFD,REL,IN,EX,PC) ({ \
  147.   unsigned int r_length; \
  148.   int r_ns32k_type; \
  149.   BFD_ASSERT((BFD)->xvec->header_byteorder_big_p == false); \
  150.   IN =  ((REL)->r_index[2] << 16) \
  151.     | ((REL)->r_index[1] << 8) \
  152.       |  (REL)->r_index[0]; \
  153.   EX  = (0 != ((REL)->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE)); \
  154.   PC   = (0 != ((REL)->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); \
  155.   r_length  =       ((REL)->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE) \
  156.     >> RELOC_STD_BITS_LENGTH_SH_LITTLE; \
  157.   r_ns32k_type  =    ((REL)->r_type[0] & RELOC_STD_BITS_NS32K_TYPE_LITTLE) \
  158.     >> RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE; \
  159.   MY(howto_table) + r_length + 3 * (PC) + 6 * r_ns32k_type;})
  160.  
  161. #define MY_put_reloc(BFD, EXT, IDX, VAL, HOWTO, RELOC) {  \
  162.   unsigned int r_length; \
  163.   int r_pcrel; \
  164.   int r_ns32k_type; \
  165.   PUT_WORD ((BFD), (VAL), (RELOC)->r_address); \
  166.   r_length = (HOWTO)->size ;    /* Size as a power of two */ \
  167.   r_pcrel  = (int) (HOWTO)->pc_relative; /* Relative to PC? */ \
  168.   r_ns32k_type = ((HOWTO) - MY(howto_table) )/6; \
  169.   BFD_ASSERT ((BFD)->xvec->header_byteorder_big_p == false); \
  170.   (RELOC)->r_index[2] = (IDX) >> 16; \
  171.   (RELOC)->r_index[1] = (IDX) >> 8; \
  172.   (RELOC)->r_index[0] = (IDX); \
  173.   (RELOC)->r_type[0] = \
  174.     ((EXT)?    RELOC_STD_BITS_EXTERN_LITTLE: 0) \
  175.       | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0) \
  176.     | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE) \
  177.       | (r_ns32k_type <<  RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);}
  178.  
  179.  
  180. #define RELOC_STD_BITS_NS32K_TYPE_BIG 0x06
  181. #define RELOC_STD_BITS_NS32K_TYPE_LITTLE 0x60
  182. #define RELOC_STD_BITS_NS32K_TYPE_SH_BIG 1
  183. #define RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE 5
  184.  
  185. #define STAT_FOR_EXEC
  186. #include <aoutx.h>
  187.  
  188. CONST struct reloc_howto_struct *
  189. DEFUN(MY(bfd_reloc_type_lookup),(abfd,code),
  190.       bfd *abfd AND
  191.       bfd_reloc_code_real_type code)
  192. {
  193. #define ENTRY(i,j)    case i: return &MY(howto_table)[j]
  194.   int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
  195.   BFD_ASSERT(ext == 0);
  196.   if (code == BFD_RELOC_CTOR)
  197.     switch (bfd_get_arch_info (abfd)->bits_per_address)
  198.       {
  199.       case 32:
  200.     code = BFD_RELOC_32;
  201.     break;
  202.       }
  203.   switch (code)
  204.     {
  205.       ENTRY(BFD_RELOC_NS32K_IMM_8, 0);
  206.       ENTRY(BFD_RELOC_NS32K_IMM_16, 1);
  207.       ENTRY(BFD_RELOC_NS32K_IMM_32, 2);
  208.       ENTRY(BFD_RELOC_NS32K_IMM_8_PCREL, 3);
  209.       ENTRY(BFD_RELOC_NS32K_IMM_16_PCREL, 4);
  210.       ENTRY(BFD_RELOC_NS32K_IMM_32_PCREL, 5);
  211.       ENTRY(BFD_RELOC_NS32K_DISP_8, 6);
  212.       ENTRY(BFD_RELOC_NS32K_DISP_16, 7);
  213.       ENTRY(BFD_RELOC_NS32K_DISP_32, 8);
  214.       ENTRY(BFD_RELOC_NS32K_DISP_8_PCREL, 9);
  215.       ENTRY(BFD_RELOC_NS32K_DISP_16_PCREL, 10);
  216.       ENTRY(BFD_RELOC_NS32K_DISP_32_PCREL, 11);
  217.       ENTRY(BFD_RELOC_8, 12);
  218.       ENTRY(BFD_RELOC_16, 13);
  219.       ENTRY(BFD_RELOC_32, 14);
  220.       ENTRY(BFD_RELOC_8_PCREL, 15);
  221.       ENTRY(BFD_RELOC_16_PCREL, 16);
  222.       ENTRY(BFD_RELOC_32_PCREL, 17);
  223.     default: return (CONST struct reloc_howto_struct *) 0;
  224.     }
  225. #undef ENTRY
  226. }
  227.  
  228.  
  229. static void
  230. DEFUN(MY_swap_std_reloc_in, (abfd, bytes, cache_ptr, symbols),
  231.   bfd *abfd AND
  232.   struct reloc_std_external *bytes AND
  233.   arelent *cache_ptr AND
  234.   asymbol **symbols)
  235. {
  236.   int r_index;
  237.   int r_extern;
  238.   unsigned int r_length;
  239.   int r_pcrel;
  240.   int r_ns32k_type;
  241.   struct aoutdata  *su = &(abfd->tdata.aout_data->a);
  242.  
  243.   cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
  244.  
  245.   /* now the fun stuff */
  246.  
  247.   cache_ptr->howto = MY_reloc_howto(abfd, bytes, r_index, r_extern, r_pcrel);
  248.  
  249.   MOVE_ADDRESS(0);
  250. }
  251.  
  252.  
  253. static void
  254. DEFUN(MY_swap_std_reloc_out,(abfd, g, natptr),
  255.       bfd *abfd AND
  256.       arelent *g AND
  257.       struct reloc_std_external *natptr)
  258. {
  259.   int r_index;
  260.   asymbol *sym = *(g->sym_ptr_ptr);
  261.   int r_extern;
  262.   unsigned int r_length;
  263.   int r_pcrel;
  264.   int r_ns32k_type;
  265.   unsigned int r_addend;
  266.   asection *output_section = sym->section->output_section;
  267.  
  268.  
  269.   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
  270.     
  271.   /* name was clobbered by aout_write_syms to be symbol index */
  272.  
  273.   /* If this relocation is relative to a symbol then set the 
  274.      r_index to the symbols index, and the r_extern bit.
  275.  
  276.      Absolute symbols can come in in two ways, either as an offset
  277.      from the abs section, or as a symbol which has an abs value.
  278.      check for that here
  279.      */
  280.      
  281.  
  282.   if (bfd_is_com_section (output_section)
  283.       || output_section == &bfd_abs_section
  284.       || output_section == &bfd_und_section) 
  285.     {
  286.       if (bfd_abs_section.symbol == sym)
  287.       {
  288.     /* Whoops, looked like an abs symbol, but is really an offset
  289.        from the abs section */
  290.     r_index = 0;
  291.     r_extern = 0;
  292.        }
  293.       else 
  294.       {
  295.     /* Fill in symbol */
  296.     r_extern = 1;
  297. #define KEEPIT flags
  298.     r_index =  stoi((*(g->sym_ptr_ptr))->KEEPIT);
  299. #undef KEEPIT     
  300.       }
  301.     }
  302.   else 
  303.     {
  304.       /* Just an ordinary section */
  305.       r_extern = 0;
  306.       r_index  = output_section->target_index;      
  307.     }
  308.  
  309.   MY_put_reloc(abfd, r_extern, r_index, g->address, g->howto, natptr);
  310. }
  311.