Go to the first, previous, next, last section, table of contents.


Relaxation

Relaxation is a generic term used when the size of some instruction or data depends upon the value of some symbol or other data.

GAS knows to relax a particular type of PC relative relocation using a table. You can also define arbitrarily complex forms of relaxation yourself.

Relaxing with a table

If you do not define md_relax_frag, and you do define TC_GENERIC_RELAX_TABLE, GAS will relax rs_machine_dependent frags based on the frag subtype and the displacement to some specified target address. The basic idea is that several machines have different addressing modes for instructions that can specify different ranges of values, with successive modes able to access wider ranges, including the entirety of the previous range. Smaller ranges are assumed to be more desirable (perhaps the instruction requires one word instead of two or three); if this is not the case, don't describe the smaller-range, inferior mode.

The fr_subtype field of a frag is an index into a CPU-specific relaxation table. That table entry indicates the range of values that can be stored, the number of bytes that will have to be added to the frag to accomodate the addressing mode, and the index of the next entry to examine if the value to be stored is outside the range accessible by the current addressing mode. The fr_symbol field of the frag indicates what symbol is to be accessed; the fr_offset field is added in.

If the fr_pcrel_adjust field is set, which currently should only happen for the NS32k family, the TC_PCREL_ADJUST macro is called on the frag to compute an adjustment to be made to the displacement.

The value fitted by the relaxation code is always assumed to be a displacement from the current frag. (More specifically, from fr_fix bytes into the frag.)

The end of the relaxation sequence is indicated by a "next" value of 0. This means that the first entry in the table can't be used.

For some configurations, the linker can do relaxing within a section of an object file. If call instructions of various sizes exist, the linker can determine which should be used in each instance, when a symbol's value is resolved. In order for the linker to avoid wasting space and having to insert no-op instructions, it must be able to expand or shrink the section contents while still preserving intra-section references and meeting alignment requirements.

For the i960 using b.out format, no expansion is done; instead, each `.align' directive causes extra space to be allocated, enough that when the linker is relaxing a section and removing unneeded space, it can discard some or all of this extra padding and cause the following data to be correctly aligned.

For the H8/300, I think the linker expands calls that can't reach, and doesn't worry about alignment issues; the cpu probably never needs any significant alignment beyond the instruction size.

The relaxation table type contains these fields:

long rlx_forward
Forward reach, must be non-negative.
long rlx_backward
Backward reach, must be zero or negative.
rlx_length
Length in bytes of this addressing mode.
rlx_more
Index of the next-longer relax state, or zero if there is no next relax state.

The relaxation is done in relax_segment in `write.c'. The difference in the length fields between the original mode and the one finally chosen by the relaxing code is taken as the size by which the current frag will be increased in size. For example, if the initial relaxing mode has a length of 2 bytes, and because of the size of the displacement, it gets upgraded to a mode with a size of 6 bytes, it is assumed that the frag will grow by 4 bytes. (The initial two bytes should have been part of the fixed portion of the frag, since it is already known that they will be output.) This growth must be effected by md_convert_frag; it should increase the fr_fix field by the appropriate size, and fill in the appropriate bytes of the frag. (Enough space for the maximum growth should have been allocated in the call to frag_var as the second argument.)

If relocation records are needed, they should be emitted by md_estimate_size_before_relax. This function should examine the target symbol of the supplied frag and correct the fr_subtype of the frag if needed. When this function is called, if the symbol has not yet been defined, it will not become defined later; however, its value may still change if the section it is in gets relaxed.

Usually, if the symbol is in the same section as the frag (given by the sec argument), the narrowest likely relaxation mode is stored in fr_subtype, and that's that.

If the symbol is undefined, or in a different section (and therefore moveable to an arbitrarily large distance), the largest available relaxation mode is specified, fix_new is called to produce the relocation record, fr_fix is increased to include the relocated field (remember, this storage was allocated when frag_var was called), and frag_wane is called to convert the frag to an rs_fill frag with no variant part. Sometimes changing addressing modes may also require rewriting the instruction. It can be accessed via fr_opcode or fr_fix.

Sometimes fr_var is increased instead, and frag_wane is not called. I'm not sure, but I think this is to keep fr_fix referring to an earlier byte, and fr_subtype set to rs_machine_dependent so that md_convert_frag will get called.

General relaxing

If using a simple table is not suitable, you may implement arbitrarily complex relaxation semantics yourself. For example, the MIPS backend uses this to emit different instruction sequences depending upon the size of the symbol being accessed.

When you assemble an instruction that may need relaxation, you should allocate a frag using frag_var or frag_variant with a type of rs_machine_dependent. You should store some sort of information in the fr_subtype field so that you can figure out what to do with the frag later.

When GAS reaches the end of the input file, it will look through the frags and work out their final sizes.

GAS will first call md_estimate_size_before_relax on each rs_machine_dependent frag. This function must return an estimated size for the frag.

GAS will then loop over the frags, calling md_relax_frag on each rs_machine_dependent frag. This function should return the change in size of the frag. GAS will keep looping over the frags until none of the frags changes size.


Go to the first, previous, next, last section, table of contents.