]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/sframe-opt.c
1 /* sframe-opt.c - optimize FRE and FDE information in SFrame.
2 Copyright (C) 2022 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
24 /* The function estimates the size of a rs_sframe variant frag based on
25 the current values of the symbols. It is called before the
26 relaxation loop. We set fr_subtype{0:2} to the expected length. */
29 sframe_estimate_size_before_relax (fragS
*frag
)
36 /* We are dealing with two different kind of fragments here which need
38 - first, FRE start address in each FRE, and
39 - second, Function info in each FDE (function info stores the FRE type)
40 The two kind of fragments can be differentiated based on the opcode
42 exp
= symbol_get_value_expression (frag
->fr_symbol
);
43 gas_assert ((exp
->X_op
== O_subtract
) || (exp
->X_op
== O_absent
));
44 /* Fragment for function info in an SFrame FDE will always write
46 if (exp
->X_op
== O_subtract
)
48 /* Fragment for the start address in an SFrame FRE may write out
49 1/2/4 bytes depending on the value of the diff. */
52 /* Get the width expression from the symbol. */
53 widthS
= exp
->X_op_symbol
;
54 width
= resolve_symbol_value (widthS
);
58 else if (width
< 0x10000)
64 frag
->fr_subtype
= (frag
->fr_subtype
& ~7) | (ret
& 7);
69 /* This function relaxes a rs_sframe variant frag based on the current
70 values of the symbols. fr_subtype{0:2} is the current length of
71 the frag. This returns the change in frag length. */
74 sframe_relax_frag (fragS
*frag
)
78 oldsize
= frag
->fr_subtype
& 7;
81 newsize
= sframe_estimate_size_before_relax (frag
);
82 return newsize
- oldsize
;
85 /* This function converts a rs_sframe variant frag into a normal fill
86 frag. This is called after all relaxation has been done.
87 fr_subtype{0:2} will be the desired length of the frag. */
90 sframe_convert_frag (fragS
*frag
)
95 unsigned char func_info
= SFRAME_FRE_TYPE_ADDR4
;
97 symbolS
*fsizeS
, *diffS
;
99 /* We are dealing with two different kind of fragments here which need
101 - first, FRE start address in each FRE, and
102 - second, Function info in each FDE (function info stores the FRE type)
103 The two kind of fragments can be differentiated based on the opcode
105 exp
= symbol_get_value_expression (frag
->fr_symbol
);
106 gas_assert ((exp
->X_op
== O_subtract
) || (exp
->X_op
== O_absent
));
107 /* Fragment for function info in an SFrame FDE. */
108 if (exp
->X_op
== O_subtract
)
110 fsizeS
= frag
->fr_symbol
;
111 fsize
= resolve_symbol_value (fsizeS
);
113 func_info
= SFRAME_FRE_TYPE_ADDR1
;
114 else if (fsize
< 0x10000)
115 func_info
= SFRAME_FRE_TYPE_ADDR2
;
117 func_info
= SFRAME_FRE_TYPE_ADDR4
;
120 frag
->fr_literal
[frag
->fr_fix
] = value
;
122 /* Fragment for the start address in an SFrame FRE. */
125 /* Get the fsize expression from the symbol. */
126 fsizeS
= exp
->X_op_symbol
;
127 fsize
= resolve_symbol_value (fsizeS
);
128 /* Get the diff expression from the symbol. */
129 diffS
= exp
->X_add_symbol
;
130 diff
= resolve_symbol_value (diffS
);
133 switch (frag
->fr_subtype
& 7)
136 gas_assert (fsize
< 0x100);
137 frag
->fr_literal
[frag
->fr_fix
] = diff
;
140 gas_assert (fsize
< 0x10000);
141 md_number_to_chars (frag
->fr_literal
+ frag
->fr_fix
, diff
, 2);
144 md_number_to_chars (frag
->fr_literal
+ frag
->fr_fix
, diff
, 4);
151 frag
->fr_fix
+= frag
->fr_subtype
& 7;
152 frag
->fr_type
= rs_fill
;
153 frag
->fr_subtype
= 0;
155 /* FIXME do this now because we have evaluated and fixed up the fragments