How best to put machine dependant bits in frags and fixes?

Ian Dall dall@hfrd.dsto.gov.au
Sun Aug 27 20:48:00 GMT 1995


I have working a new scheme where the ns32k backend uses fr_machdep to
attach a note, instead of having multiple machine dependant fields in
the frag structure. I removed the fr_pcrel_adjust and fr_bsr fields
which are only used by the ns32k port. The new ns32k scheme keeps a
pointer to the frag containing the relavant opcode and an offset in
that frag. From this, it is possible to calculate the address of the
opcode and hence the difference between the address of the opcode and
the address of the displacement field (which is the correct amount to
adjust the pcrel amount by). This works even though frags may grow or
shrink or change fr_address during the relax phase.

A similar thing needs to be done for fixes. I attached a note to the
tc_fix_data field in the fix structure which contains a pointer to the
opcode frag and the offset in that frag. I also have tried folding
various machine dependent fields in the fix structure into the
tc_fix_data. I grepped around to find out where these fields are used
and note that the comments against these fields weren't always correct.

Anyway, one certainly can do the folding, but it isn't a clear win.

The relevant fields seems to be:

fx_pcrel_adjust is used by i860, i960, m68k. (No longer used by the
ns32k).

fx_im_disp is used by i860, i960 and ns32k. i860 asserts it is always
zero, i960 and ns32k sometimes put 2 in here which wont fit in 1
bit. This was one bit unless building for TC_NS32K in which case it
was 2 bits.  However, it should be two bits or else not needed at
all.

fx_bsr  used by i960, ns32k (sequent only).

fx_tcbit ?

fx_bit_fixP i860, i960-coff and ns32k use this. i960-coff stores an
integer.  This could be folded into tc_fix_data, except there is
machine independent code in write.c which refers to it.

It is a pity the fx_bit_fixP is referenced in write.c. I guess one
could use some new TC_... macro to do return the required info, but if
it is just TC_BITFIXP, then this doesn't seem like a win in terms of
decluttering the machine independent code.

Folding the small fields into tc_fix_data doesn't save any space on
most machines because of the alignment restrictions. Also there is
some penalty in accessing them (an extra dereference plus typically
code to test for the case of tc_fix_data == 0.

One goal is to not waste space for fields a particular machine does not
need. Another goal would be to eliminate machine dependent code
in the machine independant parts. Finally, one could want to select
the target machine at run time. I don't see the last goal as being very
relevant (multiple simultaneous target support is a long way off if
ever).

The first two goals could be supported by having (optional) target
dependent macros to do the *declaration* and initialization of the
target dependent fix fields. The macros might be called
TC_FIX_DECL_SMALL (for target dependent bitfields), TC_FIX_DECL (for
other fields), and TC_FIX_INIT which would be called whenever a new
fix is created, just after the machine independant initialization. The
only bad thing about this is that having a macro containing just
declarations of fields within a structure is a bit unusual and might
trip up programmers.

For example, the fix struct would become:

    struct fix
    {
      unsigned fx_pcrel : 1;
      unsigned fx_plt : 1;

      unsigned fx_done : 1;

    #ifdef TC_FIX_DECL_SMALL
      TC_FIX_DECL_SMALL;
    #else
    #ifdef TC_NS32K
      unsigned fx_im_disp : 2;
    #else
      unsigned fx_im_disp : 1;
    #endif
      unsigned fx_bsr : 1;

      unsigned fx_tcbit : 1;

      char fx_pcrel_adjust;
    #endif /* TC_FIX_DECL_SMALL */

      unsigned fx_no_overflow : 1;

      short int fx_size;

      fragS *fx_frag;

      long fx_where;

      symbolS *fx_addsy;

      symbolS *fx_subsy;

      valueT fx_offset;

      struct fix *fx_next;

      bit_fixS *fx_bit_fixP;

    #ifdef BFD_ASSEMBLER
      bfd_reloc_code_real_type fx_r_type;
    #else
    #ifdef NEED_FX_R_TYPE
      int fx_r_type;
    #endif
    #endif

      valueT fx_addnumber;

      char *fx_file;
      unsigned fx_line;

    #ifdef TC_FIX_DECL
      TC_FIX_DECL;
    #else
      PTR tc_fix_data;
    #endif /* TC_FIX_DECL */
    };



I'd be happy to make the changes to write.h, write.c and the ns32k backend
if you think it is on the right track.

Ian













More information about the Gas2 mailing list