2 Rewrite FP pseudo-registers to use real stack registers
3 Copyright (C) 2001 Justin David Smith, Caltech
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 NOTE: this code assumes no transients are atop the
23 stack upon entering any block, i.e. on entering the
24 block the stack ONLY contains the allocated registers
44 Classifies this instruction. Only used internally, see the
45 next two functions for a general (and better) overview. *)
46 let fpclassify = function
54 (* Normal store operations *)
60 (* Arithmetic operations *)
82 (* Comparison pops nil, once, or twice *)
90 (* Misc. floating-point ops *)
97 (* FSTSW doesn't use the stack *)
104 (* Non-FP operations *)
157 Returns true if the given instruction uses registers from the
158 floating-point stack (either explicitly or implicitly). These
159 instructions cannot be so easily moved around. *)
160 let inst_uses_fpstack inst
=
161 let fpstack, _
= fpclassify inst
in
166 This instruction returns the change in the TOS pointer after
167 executing the named floating-point instruction. If the value
168 is zero, no change is made; if positive, values are pushed on
169 to the stack; if negative, the stack is popped. *)
170 let fpstack_tos_delta inst
=
171 let _, delta
= fpclassify inst
in
175 (*** Rewrite FP Pseudo-regs as FPStack ***)
179 Rewrites the stack pseudo-registers with real FPStack
180 operands that are adjusted to consider temporary values
181 pushed onto the top of the stack.
183 let rewrite_operand tos op
=
186 let sym_eq (reg
, _) = Symbol.eq reg r
in
187 if List.exists
sym_eq fpmap
then
188 let index = Int32.of_int
(tos
+ (snd
(List.find
sym_eq fpmap
))) in
205 Rewrite operands in an instruction. This function
206 returns the revised instruction as well as the new
207 TOS, or new number of temporaries sitting at the top
208 of the floating-point stack after this operation. *)
209 let rec rewrite_insts tos insts
=
210 let modify_tos delta tos insts
=
212 let tos = tos + delta
in
213 let inst = CommentString
(sprintf
"Modified TOS: now %d" tos) in
214 inst :: rewrite_insts tos insts
216 rewrite_insts tos insts
222 let inst = map_operands
(rewrite_operand tos) inst in
223 let delta = fpstack_tos_delta inst in
224 inst :: modify_tos delta tos insts
228 Rewrites a block of instructions. The block is assumed to
229 start out with tos = 0, or no temporary values on the floating
230 point stack (only the permanent values). *)
231 let rewrite_block block
=
232 let insts = block
.block_code
in
233 let insts = rewrite_insts 0 insts in
234 { block
with block_code
= insts }
238 This function expands out FMOV and FMOVP instructions into
239 FLD and FST/FSTP instructions. This is important to run
240 /before/ we rewrite since we currently assume the TOS ptr
241 is revised at most once per instruction in the above code. *)
242 let rec expand_fmov_insts = function
243 FMOVP
(dpre
, dst
, spre
, src
) :: insts ->
244 FLD
(spre
, src
) :: FSTP
(dpre
, dst
) :: expand_fmov_insts insts
245 | FMOV
(dpre
, dst
, spre
, src
) :: insts ->
246 FLD
(spre
, src
) :: FST
(dpre
, dst
) :: expand_fmov_insts insts
248 inst :: expand_fmov_insts insts
254 See above, this works on a block at a time. *)
255 let expand_fmov_block block
=
256 let insts = block
.block_code
in
257 let insts = expand_fmov_insts insts in
258 { block
with block_code
= insts }
262 Rewrites the entire program. *)
263 let rewrite_prog prog
=
264 let blocks = prog
.asm_blocks
in
265 let blocks = Trace.map
expand_fmov_block blocks in
266 let blocks = Trace.map
rewrite_block blocks in
267 { prog
with asm_blocks
= blocks }
269 let rewrite_prog = Fir_state.profile
"X86_fpstack.rewrite_prog" rewrite_prog