From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ian Dall To: raeburn@cygnus.com Cc: gas2@cygnus.com Subject: How best to put machine dependant bits in frags and fixes? Date: Sun, 27 Aug 1995 20:48:00 -0000 Message-id: <199508280347.NAA00388@hfrd015.dsto.gov.au> References: <199508162020.QAA13437@kr-laptop.cygnus.com> <199508180053.KAA01743@hfrd015.dsto.gov.au> <199508180147.VAA00583@kr-laptop.cygnus.com> <199508212328.IAA04600@hfrd015.dsto.gov.au> <199508220148.VAA28233@kr-laptop.cygnus.com> <199508220148.VAA28233@kr-laptop.cygnus.com> X-SW-Source: 1995/msg00158.html 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