blob: 716b426466cbeb288836a787400a92dd11b3fe70 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- The JITter proper: register allocation & code improvement ---*/
4/*--- vg_translate.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
nethercotebb1c9912004-01-04 16:43:23 +000011 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
32#include "vg_include.h"
33
sewardjde4a1d02002-03-22 01:27:54 +000034/*------------------------------------------------------------*/
35/*--- Renamings of frequently-used global functions. ---*/
36/*------------------------------------------------------------*/
37
njn25e49d8e72002-09-23 09:36:25 +000038#define dis VG_(print_codegen)
sewardjde4a1d02002-03-22 01:27:54 +000039
nethercotebee3fd92004-08-02 15:17:43 +000040/*------------------------------------------------------------*/
41/*--- Reg-alloc stats ---*/
42/*------------------------------------------------------------*/
43
44static UInt n_uinstrs_prealloc; // # uinstrs input to reg-alloc
45static UInt n_uinstrs_spill; // # uinstrs added due to spill code
46static UInt n_translations_needing_spill; // # bbs requiring spill code
47static UInt n_total_reg_rank; // total of register ranks over all translations
48
49void VG_(print_reg_alloc_stats)(void)
50{
51 VG_(message)(Vg_DebugMsg,
52 "reg-alloc: %d t-req-spill, "
53 "%d+%d orig+spill uis, %d total-reg-r.",
54 n_translations_needing_spill,
55 n_uinstrs_prealloc, n_uinstrs_spill, n_total_reg_rank );
56}
sewardje1042472002-09-30 12:33:11 +000057
sewardjde4a1d02002-03-22 01:27:54 +000058/*------------------------------------------------------------*/
59/*--- Basics ---*/
60/*------------------------------------------------------------*/
61
nethercote85cdd342004-08-01 22:36:40 +000062#define VG_IS_FLAG_SUBSET(set1,set2) \
63 (( ((FlagSet)set1) & ((FlagSet)set2) ) == ((FlagSet)set1) )
64
65#define VG_UNION_FLAG_SETS(set1,set2) \
66 ( ((FlagSet)set1) | ((FlagSet)set2) )
67
njn810086f2002-11-14 12:42:47 +000068/* This one is called by the core */
njn4ba5a792002-09-30 10:23:54 +000069UCodeBlock* VG_(alloc_UCodeBlock) ( void )
sewardjde4a1d02002-03-22 01:27:54 +000070{
njn25e49d8e72002-09-23 09:36:25 +000071 UCodeBlock* cb = VG_(arena_malloc)(VG_AR_CORE, sizeof(UCodeBlock));
sewardjde4a1d02002-03-22 01:27:54 +000072 cb->used = cb->size = cb->nextTemp = 0;
73 cb->instrs = NULL;
74 return cb;
75}
76
nethercote996901a2004-08-03 13:29:09 +000077/* This one is called by tools */
njn810086f2002-11-14 12:42:47 +000078UCodeBlock* VG_(setup_UCodeBlock) ( UCodeBlock* cb_in )
79{
80 UCodeBlock* cb = VG_(arena_malloc)(VG_AR_CORE, sizeof(UCodeBlock));
sewardj22854b92002-11-30 14:00:47 +000081 cb->orig_eip = cb_in->orig_eip;
njn810086f2002-11-14 12:42:47 +000082 cb->used = cb->size = 0;
83 cb->nextTemp = cb_in->nextTemp;
84 cb->instrs = NULL;
85 return cb;
86}
sewardjde4a1d02002-03-22 01:27:54 +000087
njn4ba5a792002-09-30 10:23:54 +000088void VG_(free_UCodeBlock) ( UCodeBlock* cb )
sewardjde4a1d02002-03-22 01:27:54 +000089{
njn25e49d8e72002-09-23 09:36:25 +000090 if (cb->instrs) VG_(arena_free)(VG_AR_CORE, cb->instrs);
91 VG_(arena_free)(VG_AR_CORE, cb);
sewardjde4a1d02002-03-22 01:27:54 +000092}
93
94
95/* Ensure there's enough space in a block to add one uinstr. */
daywalkerb18d2532003-09-27 20:15:01 +000096static
sewardjde4a1d02002-03-22 01:27:54 +000097void ensureUInstr ( UCodeBlock* cb )
98{
99 if (cb->used == cb->size) {
100 if (cb->instrs == NULL) {
101 vg_assert(cb->size == 0);
102 vg_assert(cb->used == 0);
103 cb->size = 8;
njn25e49d8e72002-09-23 09:36:25 +0000104 cb->instrs = VG_(arena_malloc)(VG_AR_CORE, 8 * sizeof(UInstr));
sewardjde4a1d02002-03-22 01:27:54 +0000105 } else {
106 Int i;
njn25e49d8e72002-09-23 09:36:25 +0000107 UInstr* instrs2 = VG_(arena_malloc)(VG_AR_CORE,
sewardjde4a1d02002-03-22 01:27:54 +0000108 2 * sizeof(UInstr) * cb->size);
109 for (i = 0; i < cb->used; i++)
110 instrs2[i] = cb->instrs[i];
111 cb->size *= 2;
njn25e49d8e72002-09-23 09:36:25 +0000112 VG_(arena_free)(VG_AR_CORE, cb->instrs);
sewardjde4a1d02002-03-22 01:27:54 +0000113 cb->instrs = instrs2;
114 }
115 }
116
117 vg_assert(cb->used < cb->size);
118}
119
120
121__inline__
njn4ba5a792002-09-30 10:23:54 +0000122void VG_(new_NOP) ( UInstr* u )
sewardjde4a1d02002-03-22 01:27:54 +0000123{
124 u->val1 = u->val2 = u->val3 = 0;
125 u->tag1 = u->tag2 = u->tag3 = NoValue;
126 u->flags_r = u->flags_w = FlagsEmpty;
sewardj2e93c502002-04-12 11:12:52 +0000127 u->jmpkind = JmpBoring;
njn25e49d8e72002-09-23 09:36:25 +0000128 u->signed_widen = u->has_ret_val = False;
129 u->regs_live_after = ALL_RREGS_LIVE;
sewardjde4a1d02002-03-22 01:27:54 +0000130 u->lit32 = 0;
njn25e49d8e72002-09-23 09:36:25 +0000131 u->opcode = NOP;
sewardjde4a1d02002-03-22 01:27:54 +0000132 u->size = 0;
133 u->cond = 0;
134 u->extra4b = 0;
njn25e49d8e72002-09-23 09:36:25 +0000135 u->argc = u->regparms_n = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000136}
137
138
139/* Add an instruction to a ucode block, and return the index of the
140 instruction. */
141__inline__
njn4ba5a792002-09-30 10:23:54 +0000142void VG_(new_UInstr3) ( UCodeBlock* cb, Opcode opcode, Int sz,
sewardjde4a1d02002-03-22 01:27:54 +0000143 Tag tag1, UInt val1,
144 Tag tag2, UInt val2,
145 Tag tag3, UInt val3 )
146{
147 UInstr* ui;
148 ensureUInstr(cb);
149 ui = & cb->instrs[cb->used];
150 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000151 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000152 ui->val1 = val1;
153 ui->val2 = val2;
154 ui->val3 = val3;
155 ui->opcode = opcode;
156 ui->tag1 = tag1;
157 ui->tag2 = tag2;
158 ui->tag3 = tag3;
159 ui->size = sz;
160 if (tag1 == TempReg) vg_assert(val1 != INVALID_TEMPREG);
161 if (tag2 == TempReg) vg_assert(val2 != INVALID_TEMPREG);
162 if (tag3 == TempReg) vg_assert(val3 != INVALID_TEMPREG);
163}
164
165
166__inline__
njn4ba5a792002-09-30 10:23:54 +0000167void VG_(new_UInstr2) ( UCodeBlock* cb, Opcode opcode, Int sz,
sewardjde4a1d02002-03-22 01:27:54 +0000168 Tag tag1, UInt val1,
169 Tag tag2, UInt val2 )
170{
171 UInstr* ui;
172 ensureUInstr(cb);
173 ui = & cb->instrs[cb->used];
174 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000175 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000176 ui->val1 = val1;
177 ui->val2 = val2;
178 ui->opcode = opcode;
179 ui->tag1 = tag1;
180 ui->tag2 = tag2;
181 ui->size = sz;
182 if (tag1 == TempReg) vg_assert(val1 != INVALID_TEMPREG);
183 if (tag2 == TempReg) vg_assert(val2 != INVALID_TEMPREG);
184}
185
186
187__inline__
njn4ba5a792002-09-30 10:23:54 +0000188void VG_(new_UInstr1) ( UCodeBlock* cb, Opcode opcode, Int sz,
sewardjde4a1d02002-03-22 01:27:54 +0000189 Tag tag1, UInt val1 )
190{
191 UInstr* ui;
192 ensureUInstr(cb);
193 ui = & cb->instrs[cb->used];
194 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000195 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000196 ui->val1 = val1;
197 ui->opcode = opcode;
198 ui->tag1 = tag1;
199 ui->size = sz;
200 if (tag1 == TempReg) vg_assert(val1 != INVALID_TEMPREG);
201}
202
203
204__inline__
njn4ba5a792002-09-30 10:23:54 +0000205void VG_(new_UInstr0) ( UCodeBlock* cb, Opcode opcode, Int sz )
sewardjde4a1d02002-03-22 01:27:54 +0000206{
207 UInstr* ui;
208 ensureUInstr(cb);
209 ui = & cb->instrs[cb->used];
210 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000211 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000212 ui->opcode = opcode;
213 ui->size = sz;
214}
215
sewardjde4a1d02002-03-22 01:27:54 +0000216/* Copy an instruction into the given codeblock. */
njn4f9c9342002-04-29 16:03:24 +0000217__inline__
njn4ba5a792002-09-30 10:23:54 +0000218void VG_(copy_UInstr) ( UCodeBlock* cb, UInstr* instr )
sewardjde4a1d02002-03-22 01:27:54 +0000219{
220 ensureUInstr(cb);
221 cb->instrs[cb->used] = *instr;
222 cb->used++;
223}
224
sewardjde4a1d02002-03-22 01:27:54 +0000225/* Set the lit32 field of the most recent uinsn. */
njn4ba5a792002-09-30 10:23:54 +0000226void VG_(set_lit_field) ( UCodeBlock* cb, UInt lit32 )
sewardjde4a1d02002-03-22 01:27:54 +0000227{
228 LAST_UINSTR(cb).lit32 = lit32;
229}
230
231
njn25e49d8e72002-09-23 09:36:25 +0000232/* Set the C call info fields of the most recent uinsn. */
njn4ba5a792002-09-30 10:23:54 +0000233void VG_(set_ccall_fields) ( UCodeBlock* cb, Addr fn, UChar argc, UChar
234 regparms_n, Bool has_ret_val )
njn25e49d8e72002-09-23 09:36:25 +0000235{
236 vg_assert(argc < 4);
237 vg_assert(regparms_n <= argc);
238 LAST_UINSTR(cb).lit32 = fn;
239 LAST_UINSTR(cb).argc = argc;
240 LAST_UINSTR(cb).regparms_n = regparms_n;
241 LAST_UINSTR(cb).has_ret_val = has_ret_val;
242}
243
njn810086f2002-11-14 12:42:47 +0000244/* For the last uinsn inserted into cb, set the read, written and
245 undefined flags. Undefined flags are counted as written, but it
246 seems worthwhile to distinguish them.
247*/
248__inline__
249void VG_(set_flag_fields) ( UCodeBlock* cb,
250 FlagSet rr, FlagSet ww, FlagSet uu )
251{
252 FlagSet uw = VG_UNION_FLAG_SETS(ww,uu);
253
254 vg_assert(rr == (rr & FlagsALL));
255 vg_assert(uw == (uw & FlagsALL));
256 LAST_UINSTR(cb).flags_r = rr;
257 LAST_UINSTR(cb).flags_w = uw;
258}
259
nethercote911cc372004-04-18 12:23:02 +0000260void VG_(set_cond_field) ( UCodeBlock* cb, Condcode cond )
261{
262 LAST_UINSTR(cb).cond = cond;
263}
264
265void VG_(set_widen_fields) ( UCodeBlock* cb, UInt szs, Bool is_signed )
266{
267 LAST_UINSTR(cb).extra4b = szs;
268 LAST_UINSTR(cb).signed_widen = is_signed;
269}
270
njn810086f2002-11-14 12:42:47 +0000271
njn4ba5a792002-09-30 10:23:54 +0000272Bool VG_(any_flag_use) ( UInstr* u )
sewardjde4a1d02002-03-22 01:27:54 +0000273{
274 return (u->flags_r != FlagsEmpty
275 || u->flags_w != FlagsEmpty);
276}
277
njn25e49d8e72002-09-23 09:36:25 +0000278#if 1
279# define BEST_ALLOC_ORDER
280#endif
sewardjde4a1d02002-03-22 01:27:54 +0000281
282/* Convert a rank in the range 0 .. VG_MAX_REALREGS-1 into an Intel
283 register number. This effectively defines the order in which real
284 registers are allocated. %ebp is excluded since it is permanently
njn25e49d8e72002-09-23 09:36:25 +0000285 reserved for pointing at VG_(baseBlock).
sewardjde4a1d02002-03-22 01:27:54 +0000286
njn25e49d8e72002-09-23 09:36:25 +0000287 Important! This function must correspond with the value of
288 VG_MAX_REALREGS (actually, VG_MAX_REALREGS can be reduced without
289 a problem, except the generated code will obviously be worse).
sewardjde4a1d02002-03-22 01:27:54 +0000290*/
njn25e49d8e72002-09-23 09:36:25 +0000291__inline__
njn4ba5a792002-09-30 10:23:54 +0000292Int VG_(rank_to_realreg) ( Int rank )
sewardjde4a1d02002-03-22 01:27:54 +0000293{
294 switch (rank) {
njn25e49d8e72002-09-23 09:36:25 +0000295# ifdef BEST_ALLOC_ORDER
sewardjde4a1d02002-03-22 01:27:54 +0000296 /* Probably the best allocation ordering. */
297 case 0: return R_EAX;
298 case 1: return R_EBX;
299 case 2: return R_ECX;
300 case 3: return R_EDX;
301 case 4: return R_ESI;
njn25e49d8e72002-09-23 09:36:25 +0000302 case 5: return R_EDI;
sewardjde4a1d02002-03-22 01:27:54 +0000303# else
304 /* Contrary; probably the worst. Helpful for debugging, tho. */
njn25e49d8e72002-09-23 09:36:25 +0000305 case 5: return R_EAX;
306 case 4: return R_EBX;
307 case 3: return R_ECX;
308 case 2: return R_EDX;
309 case 1: return R_ESI;
310 case 0: return R_EDI;
sewardjde4a1d02002-03-22 01:27:54 +0000311# endif
njne427a662002-10-02 11:08:25 +0000312 default: VG_(core_panic)("VG_(rank_to_realreg)");
njn25e49d8e72002-09-23 09:36:25 +0000313 }
314}
315
316/* Convert an Intel register number into a rank in the range 0 ..
njn4ba5a792002-09-30 10:23:54 +0000317 VG_MAX_REALREGS-1. See related comments for rank_to_realreg()
njn25e49d8e72002-09-23 09:36:25 +0000318 above. */
319__inline__
njn4ba5a792002-09-30 10:23:54 +0000320Int VG_(realreg_to_rank) ( Int realReg )
njn25e49d8e72002-09-23 09:36:25 +0000321{
322 switch (realReg) {
323# ifdef BEST_ALLOC_ORDER
324 case R_EAX: return 0;
325 case R_EBX: return 1;
326 case R_ECX: return 2;
327 case R_EDX: return 3;
328 case R_ESI: return 4;
329 case R_EDI: return 5;
330# else
331 case R_EAX: return 5;
332 case R_EBX: return 4;
333 case R_ECX: return 3;
334 case R_EDX: return 2;
335 case R_ESI: return 1;
336 case R_EDI: return 0;
337# endif
njne427a662002-10-02 11:08:25 +0000338 default: VG_(core_panic)("VG_(realreg_to_rank)");
sewardjde4a1d02002-03-22 01:27:54 +0000339 }
340}
341
nethercote0973f702004-08-03 15:49:50 +0000342Int VG_(get_num_instrs) ( UCodeBlock* cb )
343{
344 return cb->used;
345}
346
347Int VG_(get_num_temps) ( UCodeBlock* cb )
348{
349 return cb->nextTemp;
350}
351
352UInstr* VG_(get_instr) ( UCodeBlock* cb, Int i )
353{
354 return & cb->instrs[i];
355}
356
357UInstr* VG_(get_last_instr) ( UCodeBlock* cb )
358{
359 return & cb->instrs[cb->used-1];
360}
361
sewardjde4a1d02002-03-22 01:27:54 +0000362
363/*------------------------------------------------------------*/
364/*--- Sanity checking uinstrs. ---*/
365/*------------------------------------------------------------*/
366
367/* This seems as good a place as any to record some important stuff
368 about ucode semantics.
369
370 * TempRegs are 32 bits wide. LOADs of 8/16 bit values into a
371 TempReg are defined to zero-extend the loaded value to 32 bits.
372 This is needed to make the translation of movzbl et al work
373 properly.
374
375 * Similarly, GETs of a 8/16 bit ArchRegs are zero-extended.
376
377 * Arithmetic on TempRegs is at the specified size. For example,
378 SUBW t1, t2 has to result in a real 16 bit x86 subtraction
379 being emitted -- not a 32 bit one.
380
381 * On some insns we allow the cc bit to be set. If so, the
382 intention is that the simulated machine's %eflags register
383 is copied into that of the real machine before the insn,
384 and copied back again afterwards. This means that the
385 code generated for that insn must be very careful only to
386 update %eflags in the intended way. This is particularly
387 important for the routines referenced by CALL insns.
388*/
389
390/* Meaning of operand kinds is as follows:
391
392 ArchReg is a register of the simulated CPU, stored in memory,
393 in vg_m_state.m_eax .. m_edi. These values are stored
394 using the Intel register encoding.
395
396 RealReg is a register of the real CPU. There are VG_MAX_REALREGS
397 available for allocation. As with ArchRegs, these values
398 are stored using the Intel register encoding.
399
400 TempReg is a temporary register used to express the results of
401 disassembly. There is an unlimited supply of them --
402 register allocation and spilling eventually assigns them
403 to RealRegs.
404
405 SpillNo is a spill slot number. The number of required spill
406 slots is VG_MAX_PSEUDOS, in general. Only allowed
407 as the ArchReg operand of GET and PUT.
408
409 Lit16 is a signed 16-bit literal value.
410
411 Literal is a 32-bit literal value. Each uinstr can only hold
412 one of these.
413
414 The disassembled code is expressed purely in terms of ArchReg,
415 TempReg and Literal operands. Eventually, register allocation
416 removes all the TempRegs, giving a result using ArchRegs, RealRegs,
417 and Literals. New x86 code can easily be synthesised from this.
418 There are carefully designed restrictions on which insns can have
419 which operands, intended to make it possible to generate x86 code
420 from the result of register allocation on the ucode efficiently and
421 without need of any further RealRegs.
422
njn25e49d8e72002-09-23 09:36:25 +0000423 Restrictions for the individual UInstrs are clear from the checks below.
424 Abbreviations: A=ArchReg S=SpillNo T=TempReg L=Literal
425 Ls=Lit16 R=RealReg N=NoValue
sewardje1042472002-09-30 12:33:11 +0000426 As=ArchRegS
sewardjde4a1d02002-03-22 01:27:54 +0000427
sewardjde4a1d02002-03-22 01:27:54 +0000428 Before register allocation, S operands should not appear anywhere.
429 After register allocation, all T operands should have been
430 converted into Rs, and S operands are allowed in GET and PUT --
431 denoting spill saves/restores.
432
njn25e49d8e72002-09-23 09:36:25 +0000433 Before liveness analysis, save_e[acd]x fields should all be True.
434 Afterwards, they may be False.
435
sewardjde4a1d02002-03-22 01:27:54 +0000436 The size field should be 0 for insns for which it is meaningless,
437 ie those which do not directly move/operate on data.
438*/
njn25e49d8e72002-09-23 09:36:25 +0000439Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
sewardjde4a1d02002-03-22 01:27:54 +0000440{
njn25e49d8e72002-09-23 09:36:25 +0000441# define LIT0 (u->lit32 == 0)
sewardjb31b06d2003-06-13 00:26:02 +0000442# define LIT8 (((u->lit32) & 0xFFFFFF00) == 0)
njn25e49d8e72002-09-23 09:36:25 +0000443# define LIT1 (!(LIT0))
444# define LITm (u->tag1 == Literal ? True : LIT0 )
sewardj77d30a22003-10-19 08:18:52 +0000445# define SZ16 (u->size == 16)
sewardj3d7c9c82003-03-26 21:08:13 +0000446# define SZ8 (u->size == 8)
njn25e49d8e72002-09-23 09:36:25 +0000447# define SZ4 (u->size == 4)
448# define SZ2 (u->size == 2)
449# define SZ1 (u->size == 1)
450# define SZ0 (u->size == 0)
451# define SZ42 (u->size == 4 || u->size == 2)
sewardjd7971012003-04-04 00:21:58 +0000452# define SZ48 (u->size == 4 || u->size == 8)
sewardjfebaa3b2003-05-25 01:07:34 +0000453# define SZ416 (u->size == 4 || u->size == 16)
nethercoteb1affa82004-01-19 19:14:18 +0000454# define SZ816 (u->size == 8 || u->size == 16)
455# define SZsse2 (u->size == 4 || u->size == 8 || u->size == 16 || u->size == 512)
jsewardfca60182004-01-04 23:30:55 +0000456# define SZsse3 (u->size == 4 || u->size == 8 || u->size == 16)
njn25e49d8e72002-09-23 09:36:25 +0000457# define SZi (u->size == 4 || u->size == 2 || u->size == 1)
458# define SZf ( u->size == 4 || u->size == 8 || u->size == 2 \
459 || u->size == 10 || u->size == 28 || u->size == 108)
460# define SZ4m ((u->tag1 == TempReg || u->tag1 == RealReg) \
nethercoteafa17ef2004-04-26 09:21:25 +0000461 ? (u->size == 4) : SZi)
njn25e49d8e72002-09-23 09:36:25 +0000462
463/* For these ones, two cases:
464 *
465 * 1. They are transliterations of the corresponding x86 instruction, in
466 * which case they should have its flags (except that redundant write
467 * flags can be annulled by the optimisation pass).
468 *
469 * 2. They are being used generally for other purposes, eg. helping with a
470 * 'rep'-prefixed instruction, in which case should have empty flags .
471 */
472# define emptyR (u->flags_r == FlagsEmpty)
473# define emptyW (u->flags_w == FlagsEmpty)
474# define CC0 (emptyR && emptyW)
475# define CCr (u->flags_r == FlagsALL && emptyW)
476# define CCw (emptyR && u->flags_w == FlagsALL)
477# define CCa (emptyR && (u->flags_w == FlagsOSZACP || emptyW))
478# define CCc (emptyR && (u->flags_w == FlagsOC || emptyW))
479# define CCe (emptyR && (u->flags_w == FlagsOSZAP || emptyW))
480# define CCb ((u->flags_r==FlagC || emptyR) && \
481 (u->flags_w==FlagsOSZACP || emptyW))
482# define CCd ((u->flags_r==FlagC || emptyR) && \
483 (u->flags_w==FlagsOC || emptyW))
sewardjc232b212002-12-10 22:24:03 +0000484# define CCf (CC0 || (emptyR && u->flags_w==FlagsZCP) \
485 || (u->flags_r==FlagsZCP && emptyW))
njn25e49d8e72002-09-23 09:36:25 +0000486# define CCg ((u->flags_r==FlagsOSZACP || emptyR) && emptyW)
487# define CCj (u->cond==CondAlways ? CC0 : CCg)
488
sewardjde4a1d02002-03-22 01:27:54 +0000489# define TR1 (beforeRA ? (u->tag1 == TempReg) : (u->tag1 == RealReg))
490# define TR2 (beforeRA ? (u->tag2 == TempReg) : (u->tag2 == RealReg))
491# define TR3 (beforeRA ? (u->tag3 == TempReg) : (u->tag3 == RealReg))
492# define A1 (u->tag1 == ArchReg)
493# define A2 (u->tag2 == ArchReg)
494# define AS1 ((u->tag1 == ArchReg) || ((!beforeRA && (u->tag1 == SpillNo))))
495# define AS2 ((u->tag2 == ArchReg) || ((!beforeRA && (u->tag2 == SpillNo))))
496# define AS3 ((u->tag3 == ArchReg) || ((!beforeRA && (u->tag3 == SpillNo))))
497# define L1 (u->tag1 == Literal && u->val1 == 0)
498# define L2 (u->tag2 == Literal && u->val2 == 0)
499# define Ls1 (u->tag1 == Lit16)
sewardjfebaa3b2003-05-25 01:07:34 +0000500# define Ls2 (u->tag2 == Lit16)
sewardjde4a1d02002-03-22 01:27:54 +0000501# define Ls3 (u->tag3 == Lit16)
njn25e49d8e72002-09-23 09:36:25 +0000502# define TRL1 (TR1 || L1)
503# define TRAL1 (TR1 || A1 || L1)
jsgf5efa4fd2003-10-14 21:49:11 +0000504# define TRA1 (TR1 || A1)
505# define TRA2 (TR2 || A2)
sewardjde4a1d02002-03-22 01:27:54 +0000506# define N1 (u->tag1 == NoValue)
507# define N2 (u->tag2 == NoValue)
508# define N3 (u->tag3 == NoValue)
sewardje1042472002-09-30 12:33:11 +0000509# define Se1 (u->tag1 == ArchRegS)
510# define Se2 (u->tag2 == ArchRegS)
sewardjde4a1d02002-03-22 01:27:54 +0000511
njn25e49d8e72002-09-23 09:36:25 +0000512# define COND0 (u->cond == 0)
513# define EXTRA4b0 (u->extra4b == 0)
nethercote4a12dbd2004-04-16 16:16:34 +0000514# define EXTRA4b12 (u->extra4b == 1 || u->extra4b == 2)
njn25e49d8e72002-09-23 09:36:25 +0000515# define SG_WD0 (u->signed_widen == 0)
516# define JMPKIND0 (u->jmpkind == 0)
517# define CCALL0 (u->argc==0 && u->regparms_n==0 && u->has_ret_val==0 && \
518 ( beforeLiveness \
519 ? u->regs_live_after == ALL_RREGS_LIVE \
520 : True ))
521
522# define XCONDi ( EXTRA4b0 && SG_WD0 && JMPKIND0 && CCALL0)
nethercote4a12dbd2004-04-16 16:16:34 +0000523# define XLEA2 (COND0 && SG_WD0 && JMPKIND0 && CCALL0)
524# define XWIDEN (COND0 && EXTRA4b12 && JMPKIND0 && CCALL0)
njn25e49d8e72002-09-23 09:36:25 +0000525# define XJMP ( SG_WD0 && CCALL0)
526# define XCCALL (COND0 && EXTRA4b0 && SG_WD0 && JMPKIND0 )
527# define XOTHER (COND0 && EXTRA4b0 && SG_WD0 && JMPKIND0 && CCALL0)
528
529 /* 0 or 1 Literal args per UInstr */
sewardjde4a1d02002-03-22 01:27:54 +0000530 Int n_lits = 0;
531 if (u->tag1 == Literal) n_lits++;
532 if (u->tag2 == Literal) n_lits++;
533 if (u->tag3 == Literal) n_lits++;
534 if (n_lits > 1)
535 return False;
536
njn25e49d8e72002-09-23 09:36:25 +0000537 /* Fields not checked: val1, val2, val3 */
538
sewardjde4a1d02002-03-22 01:27:54 +0000539 switch (u->opcode) {
njn25e49d8e72002-09-23 09:36:25 +0000540
541 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
sewardje1042472002-09-30 12:33:11 +0000542 case PUTSEG: return LIT0 && SZ2 && CC0 && TR1 && Se2 && N3 && XOTHER;
543 case GETSEG: return LIT0 && SZ2 && CC0 && Se1 && TR2 && N3 && XOTHER;
544 case USESEG: return LIT0 && SZ0 && CC0 && TR1 && TR2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000545 case NOP: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
sewardj7a5ebcf2002-11-13 22:42:13 +0000546 case LOCK: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000547 case GETF: return LIT0 && SZ42 && CCr && TR1 && N2 && N3 && XOTHER;
548 case PUTF: return LIT0 && SZ42 && CCw && TR1 && N2 && N3 && XOTHER;
549 case GET: return LIT0 && SZi && CC0 && AS1 && TR2 && N3 && XOTHER;
550 case PUT: return LIT0 && SZi && CC0 && TR1 && AS2 && N3 && XOTHER;
551 case LOAD:
552 case STORE: return LIT0 && SZi && CC0 && TR1 && TR2 && N3 && XOTHER;
553 case MOV: return LITm && SZ4m && CC0 && TRL1 && TR2 && N3 && XOTHER;
554 case CMOV: return LIT0 && SZ4 && CCg && TR1 && TR2 && N3 && XCONDi;
njn95bc3862003-09-30 13:22:30 +0000555 case WIDEN: return LIT0 && SZ42 && CC0 && TR1 && N2 && N3 && XWIDEN;
njn25e49d8e72002-09-23 09:36:25 +0000556 case JMP: return LITm && SZ0 && CCj && TRL1 && N2 && N3 && XJMP;
557 case CALLM: return LIT0 && SZ0 /*any*/ && Ls1 && N2 && N3 && XOTHER;
558 case CALLM_S:
559 case CALLM_E:return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
560 case PUSH:
561 case POP: return LIT0 && SZi && CC0 && TR1 && N2 && N3 && XOTHER;
562 case CLEAR: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
563 case AND:
564 case OR: return LIT0 && SZi && CCa && TR1 && TR2 && N3 && XOTHER;
jsgf5efa4fd2003-10-14 21:49:11 +0000565 case MUL: return LIT0 && SZ42 && CCa && TRA1 &&TRA2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000566 case ADD:
567 case XOR:
568 case SUB: return LITm && SZi && CCa &&TRAL1 && TR2 && N3 && XOTHER;
569 case SBB:
570 case ADC: return LITm && SZi && CCb &&TRAL1 && TR2 && N3 && XOTHER;
571 case SHL:
572 case SHR:
573 case SAR: return LITm && SZi && CCa && TRL1 && TR2 && N3 && XOTHER;
574 case ROL:
575 case ROR: return LITm && SZi && CCc && TRL1 && TR2 && N3 && XOTHER;
576 case RCL:
577 case RCR: return LITm && SZi && CCd && TRL1 && TR2 && N3 && XOTHER;
578 case NOT: return LIT0 && SZi && CC0 && TR1 && N2 && N3 && XOTHER;
579 case NEG: return LIT0 && SZi && CCa && TR1 && N2 && N3 && XOTHER;
580 case INC:
581 case DEC: return LIT0 && SZi && CCe && TR1 && N2 && N3 && XOTHER;
582 case CC2VAL: return LIT0 && SZ1 && CCg && TR1 && N2 && N3 && XCONDi;
583 case BSWAP: return LIT0 && SZ4 && CC0 && TR1 && N2 && N3 && XOTHER;
584 case JIFZ: return LIT1 && SZ4 && CC0 && TR1 && L2 && N3 && XOTHER;
585 case FPU_R:
586 case FPU_W: return LIT0 && SZf && CC0 && Ls1 && TR2 && N3 && XOTHER;
587 case FPU: return LIT0 && SZ0 && CCf && Ls1 && N2 && N3 && XOTHER;
588 case LEA1: return /*any*/ SZ4 && CC0 && TR1 && TR2 && N3 && XOTHER;
nethercote4a12dbd2004-04-16 16:16:34 +0000589 case LEA2: return /*any*/ SZ4 && CC0 && TR1 && TR2 && TR3 && XLEA2;
njn25e49d8e72002-09-23 09:36:25 +0000590 case INCEIP: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
591 case CCALL: return LIT1 && SZ0 && CC0 &&
592 (u->argc > 0 ? TR1 : N1) &&
593 (u->argc > 1 ? TR2 : N2) &&
594 (u->argc > 2 || u->has_ret_val ? TR3 : N3) &&
595 u->regparms_n <= u->argc && XCCALL;
thughes96b466a2004-03-15 16:43:58 +0000596 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
sewardj3d7c9c82003-03-26 21:08:13 +0000597 case MMX1:
thughes96b466a2004-03-15 16:43:58 +0000598 case MMX2: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
599 case MMX3: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER;
600 case MMX2_MemRd: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER;
601 case MMX2_MemWr: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER;
602 case MMX2a1_MemRd: return LIT0 && SZ8 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
603 case MMX2_ERegRd: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER;
604 case MMX2_ERegWr: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER;
sewardjfebaa3b2003-05-25 01:07:34 +0000605
606 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
jsewardfca60182004-01-04 23:30:55 +0000607 case SSE2a_MemWr: return LIT0 && SZsse2 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
608 case SSE2a_MemRd: return LIT0 && SZsse2 && CCa && Ls1 && Ls2 && TR3 && XOTHER;
nethercote1018bdd2004-02-11 23:33:29 +0000609 case SSE2a1_MemRd: return LIT0 && SZsse3 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
nethercoteb1affa82004-01-19 19:14:18 +0000610 case SSE2g_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
611 case SSE2g1_RegWr: return LIT8 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
612 case SSE2e1_RegRd: return LIT8 && SZ2 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
jsewardfca60182004-01-04 23:30:55 +0000613 case SSE3a_MemWr: return LIT0 && SZsse3 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
614 case SSE3a_MemRd: return LIT0 && SZsse3 && CCa && Ls1 && Ls2 && TR3 && XOTHER;
615 case SSE3e_RegRd: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
616 case SSE3e_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
nethercoteb1affa82004-01-19 19:14:18 +0000617 case SSE3a1_MemRd: return LIT8 && SZ816 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
jsewardfca60182004-01-04 23:30:55 +0000618 case SSE3g_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
619 case SSE3g1_RegWr: return LIT8 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
620 case SSE3e1_RegRd: return LIT8 && SZ2 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
621 case SSE3: return LIT0 && SZ0 && CCa && Ls1 && Ls2 && N3 && XOTHER;
622 case SSE4: return LIT0 && SZ0 && CCa && Ls1 && Ls2 && N3 && XOTHER;
623 case SSE5: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && Ls3 && XOTHER;
sewardje3891fa2003-06-15 03:13:48 +0000624 case SSE3ag_MemRd_RegWr:
jsewardfca60182004-01-04 23:30:55 +0000625 return SZ48 && CC0 && TR1 && TR2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000626 default:
627 if (VG_(needs).extended_UCode)
njn4ba5a792002-09-30 10:23:54 +0000628 return SK_(sane_XUInstr)(beforeRA, beforeLiveness, u);
njn25e49d8e72002-09-23 09:36:25 +0000629 else {
630 VG_(printf)("unhandled opcode: %u. Perhaps "
631 "VG_(needs).extended_UCode should be set?",
632 u->opcode);
njne427a662002-10-02 11:08:25 +0000633 VG_(core_panic)("VG_(saneUInstr): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000634 }
sewardjde4a1d02002-03-22 01:27:54 +0000635 }
njn25e49d8e72002-09-23 09:36:25 +0000636# undef LIT0
637# undef LIT1
sewardjb31b06d2003-06-13 00:26:02 +0000638# undef LIT8
njn25e49d8e72002-09-23 09:36:25 +0000639# undef LITm
sewardj77d30a22003-10-19 08:18:52 +0000640# undef SZ16
sewardj3d7c9c82003-03-26 21:08:13 +0000641# undef SZ8
sewardjde4a1d02002-03-22 01:27:54 +0000642# undef SZ4
643# undef SZ2
644# undef SZ1
645# undef SZ0
njn25e49d8e72002-09-23 09:36:25 +0000646# undef SZ42
sewardjd7971012003-04-04 00:21:58 +0000647# undef SZ48
sewardjfebaa3b2003-05-25 01:07:34 +0000648# undef SZ416
nethercote4a12dbd2004-04-16 16:16:34 +0000649# undef SZ816
jsewardfca60182004-01-04 23:30:55 +0000650# undef SZsse2
651# undef SZsse3
njn25e49d8e72002-09-23 09:36:25 +0000652# undef SZi
653# undef SZf
654# undef SZ4m
655# undef emptyR
656# undef emptyW
657# undef CC0
658# undef CCr
659# undef CCw
660# undef CCa
661# undef CCb
662# undef CCc
663# undef CCd
664# undef CCe
665# undef CCf
666# undef CCg
667# undef CCj
sewardjde4a1d02002-03-22 01:27:54 +0000668# undef TR1
669# undef TR2
670# undef TR3
671# undef A1
672# undef A2
673# undef AS1
674# undef AS2
675# undef AS3
676# undef L1
sewardjde4a1d02002-03-22 01:27:54 +0000677# undef L2
njn25e49d8e72002-09-23 09:36:25 +0000678# undef Ls1
sewardjfebaa3b2003-05-25 01:07:34 +0000679# undef Ls2
sewardjde4a1d02002-03-22 01:27:54 +0000680# undef Ls3
njn25e49d8e72002-09-23 09:36:25 +0000681# undef TRL1
682# undef TRAL1
nethercote4a12dbd2004-04-16 16:16:34 +0000683# undef TRA1
684# undef TRA2
sewardjde4a1d02002-03-22 01:27:54 +0000685# undef N1
686# undef N2
687# undef N3
sewardje1042472002-09-30 12:33:11 +0000688# undef Se2
689# undef Se1
njn25e49d8e72002-09-23 09:36:25 +0000690# undef COND0
691# undef EXTRA4b0
nethercote4a12dbd2004-04-16 16:16:34 +0000692# undef EXTRA4b12
njn25e49d8e72002-09-23 09:36:25 +0000693# undef SG_WD0
694# undef JMPKIND0
695# undef CCALL0
nethercote4a12dbd2004-04-16 16:16:34 +0000696# undef XCONDi
697# undef XLEA2
njn25e49d8e72002-09-23 09:36:25 +0000698# undef XWIDEN
699# undef XJMP
700# undef XCCALL
701# undef XOTHER
sewardjde4a1d02002-03-22 01:27:54 +0000702}
703
njn25e49d8e72002-09-23 09:36:25 +0000704void VG_(saneUCodeBlock) ( UCodeBlock* cb )
705{
706 Int i;
707
708 for (i = 0; i < cb->used; i++) {
709 Bool sane = VG_(saneUInstr)(True, True, &cb->instrs[i]);
710 if (!sane) {
711 VG_(printf)("Instruction failed sanity check:\n");
njn4ba5a792002-09-30 10:23:54 +0000712 VG_(up_UInstr)(i, &cb->instrs[i]);
njn25e49d8e72002-09-23 09:36:25 +0000713 }
714 vg_assert(sane);
715 }
716}
sewardjde4a1d02002-03-22 01:27:54 +0000717
718/* Sanity checks to do with CALLMs in UCodeBlocks. */
njn25e49d8e72002-09-23 09:36:25 +0000719Bool VG_(saneUCodeBlockCalls) ( UCodeBlock* cb )
sewardjde4a1d02002-03-22 01:27:54 +0000720{
721 Int callm = 0;
722 Int callm_s = 0;
723 Int callm_e = 0;
724 Int callm_ptr, calls_ptr;
725 Int i, j, t;
726 Bool incall = False;
727
728 /* Ensure the number of CALLM, CALLM_S and CALLM_E are the same. */
729
730 for (i = 0; i < cb->used; i++) {
731 switch (cb->instrs[i].opcode) {
732 case CALLM:
733 if (!incall) return False;
734 callm++;
735 break;
736 case CALLM_S:
737 if (incall) return False;
738 incall = True;
739 callm_s++;
740 break;
741 case CALLM_E:
742 if (!incall) return False;
743 incall = False;
744 callm_e++;
745 break;
746 case PUSH: case POP: case CLEAR:
747 if (!incall) return False;
748 break;
749 default:
750 break;
751 }
752 }
753 if (incall) return False;
754 if (callm != callm_s || callm != callm_e) return False;
755
756 /* Check the sections between CALLM_S and CALLM's. Ensure that no
757 PUSH uinsn pushes any TempReg that any other PUSH in the same
758 section pushes. Ie, check that the TempReg args to PUSHes in
759 the section are unique. If not, the instrumenter generates
760 incorrect code for CALLM insns. */
761
762 callm_ptr = 0;
763
764 find_next_CALLM:
765 /* Search for the next interval, making calls_ptr .. callm_ptr
766 bracket it. */
767 while (callm_ptr < cb->used
768 && cb->instrs[callm_ptr].opcode != CALLM)
769 callm_ptr++;
770 if (callm_ptr == cb->used)
771 return True;
772 vg_assert(cb->instrs[callm_ptr].opcode == CALLM);
773
774 calls_ptr = callm_ptr - 1;
775 while (cb->instrs[calls_ptr].opcode != CALLM_S)
776 calls_ptr--;
777 vg_assert(cb->instrs[calls_ptr].opcode == CALLM_S);
778 vg_assert(calls_ptr >= 0);
779
780 /* VG_(printf)("interval from %d to %d\n", calls_ptr, callm_ptr ); */
781
782 /* For each PUSH insn in the interval ... */
783 for (i = calls_ptr + 1; i < callm_ptr; i++) {
784 if (cb->instrs[i].opcode != PUSH) continue;
785 t = cb->instrs[i].val1;
786 /* Ensure no later PUSH insns up to callm_ptr push the same
787 TempReg. Return False if any such are found. */
788 for (j = i+1; j < callm_ptr; j++) {
789 if (cb->instrs[j].opcode == PUSH &&
790 cb->instrs[j].val1 == t)
791 return False;
792 }
793 }
794
795 /* This interval is clean. Keep going ... */
796 callm_ptr++;
797 goto find_next_CALLM;
798}
799
800
801/*------------------------------------------------------------*/
802/*--- Printing uinstrs. ---*/
803/*------------------------------------------------------------*/
804
njn25e49d8e72002-09-23 09:36:25 +0000805/* Global that dictates whether to print generated code at all stages */
806Bool VG_(print_codegen);
807
njn563f96f2003-02-03 11:17:46 +0000808Char* VG_(name_UCondcode) ( Condcode cond )
sewardjde4a1d02002-03-22 01:27:54 +0000809{
810 switch (cond) {
811 case CondO: return "o";
812 case CondNO: return "no";
813 case CondB: return "b";
814 case CondNB: return "nb";
815 case CondZ: return "z";
816 case CondNZ: return "nz";
817 case CondBE: return "be";
818 case CondNBE: return "nbe";
819 case CondS: return "s";
sewardje1042472002-09-30 12:33:11 +0000820 case CondNS: return "ns";
sewardjde4a1d02002-03-22 01:27:54 +0000821 case CondP: return "p";
822 case CondNP: return "np";
823 case CondL: return "l";
824 case CondNL: return "nl";
825 case CondLE: return "le";
826 case CondNLE: return "nle";
827 case CondAlways: return "MP"; /* hack! */
njn563f96f2003-02-03 11:17:46 +0000828 default: VG_(core_panic)("name_UCondcode");
sewardjde4a1d02002-03-22 01:27:54 +0000829 }
830}
831
832
833static void vg_ppFlagSet ( Char* prefix, FlagSet set )
834{
835 VG_(printf)("%s", prefix);
836 if (set & FlagD) VG_(printf)("D");
837 if (set & FlagO) VG_(printf)("O");
838 if (set & FlagS) VG_(printf)("S");
839 if (set & FlagZ) VG_(printf)("Z");
840 if (set & FlagA) VG_(printf)("A");
841 if (set & FlagC) VG_(printf)("C");
842 if (set & FlagP) VG_(printf)("P");
843}
844
845
846static void ppTempReg ( Int tt )
847{
848 if ((tt & 1) == 0)
849 VG_(printf)("t%d", tt);
850 else
851 VG_(printf)("q%d", tt-1);
852}
853
854
njn4ba5a792002-09-30 10:23:54 +0000855void VG_(pp_UOperand) ( UInstr* u, Int operandNo, Int sz, Bool parens )
sewardjde4a1d02002-03-22 01:27:54 +0000856{
857 UInt tag, val;
858 switch (operandNo) {
859 case 1: tag = u->tag1; val = u->val1; break;
860 case 2: tag = u->tag2; val = u->val2; break;
861 case 3: tag = u->tag3; val = u->val3; break;
njne427a662002-10-02 11:08:25 +0000862 default: VG_(core_panic)("VG_(pp_UOperand)(1)");
sewardjde4a1d02002-03-22 01:27:54 +0000863 }
864 if (tag == Literal) val = u->lit32;
865
866 if (parens) VG_(printf)("(");
867 switch (tag) {
sewardje1042472002-09-30 12:33:11 +0000868 case TempReg: ppTempReg(val); break;
869 case RealReg: VG_(printf)("%s",nameIReg(sz==0 ? 4 : sz,val)); break;
870 case Literal: VG_(printf)("$0x%x", val); break;
871 case Lit16: VG_(printf)("$0x%x", val); break;
872 case NoValue: VG_(printf)("NoValue"); break;
873 case ArchReg: VG_(printf)("%S",nameIReg(sz,val)); break;
874 case ArchRegS: VG_(printf)("%S",nameSReg(val)); break;
875 case SpillNo: VG_(printf)("spill%d", val); break;
njne427a662002-10-02 11:08:25 +0000876 default: VG_(core_panic)("VG_(ppUOperand)(2)");
sewardjde4a1d02002-03-22 01:27:54 +0000877 }
878 if (parens) VG_(printf)(")");
879}
880
881
njn4ba5a792002-09-30 10:23:54 +0000882Char* VG_(name_UOpcode) ( Bool upper, Opcode opc )
sewardjde4a1d02002-03-22 01:27:54 +0000883{
884 switch (opc) {
885 case ADD: return (upper ? "ADD" : "add");
886 case ADC: return (upper ? "ADC" : "adc");
887 case AND: return (upper ? "AND" : "and");
888 case OR: return (upper ? "OR" : "or");
889 case XOR: return (upper ? "XOR" : "xor");
890 case SUB: return (upper ? "SUB" : "sub");
891 case SBB: return (upper ? "SBB" : "sbb");
892 case SHL: return (upper ? "SHL" : "shl");
893 case SHR: return (upper ? "SHR" : "shr");
894 case SAR: return (upper ? "SAR" : "sar");
895 case ROL: return (upper ? "ROL" : "rol");
896 case ROR: return (upper ? "ROR" : "ror");
897 case RCL: return (upper ? "RCL" : "rcl");
898 case RCR: return (upper ? "RCR" : "rcr");
jsgf5efa4fd2003-10-14 21:49:11 +0000899 case MUL: return (upper ? "MUL" : "mul");
sewardjde4a1d02002-03-22 01:27:54 +0000900 case NOT: return (upper ? "NOT" : "not");
901 case NEG: return (upper ? "NEG" : "neg");
902 case INC: return (upper ? "INC" : "inc");
903 case DEC: return (upper ? "DEC" : "dec");
904 case BSWAP: return (upper ? "BSWAP" : "bswap");
905 default: break;
906 }
njne427a662002-10-02 11:08:25 +0000907 if (!upper) VG_(core_panic)("vg_name_UOpcode: invalid !upper");
sewardjde4a1d02002-03-22 01:27:54 +0000908 switch (opc) {
sewardjde4a1d02002-03-22 01:27:54 +0000909 case CALLM_S: return "CALLM_S";
910 case CALLM_E: return "CALLM_E";
911 case INCEIP: return "INCEIP";
912 case LEA1: return "LEA1";
913 case LEA2: return "LEA2";
914 case NOP: return "NOP";
sewardj7a5ebcf2002-11-13 22:42:13 +0000915 case LOCK: return "LOCK";
sewardjde4a1d02002-03-22 01:27:54 +0000916 case GET: return "GET";
917 case PUT: return "PUT";
918 case GETF: return "GETF";
919 case PUTF: return "PUTF";
sewardje1042472002-09-30 12:33:11 +0000920 case GETSEG: return "GETSEG";
921 case PUTSEG: return "PUTSEG";
922 case USESEG: return "USESEG";
sewardjde4a1d02002-03-22 01:27:54 +0000923 case LOAD: return "LD" ;
924 case STORE: return "ST" ;
925 case MOV: return "MOV";
926 case CMOV: return "CMOV";
927 case WIDEN: return "WIDEN";
928 case JMP: return "J" ;
929 case JIFZ: return "JIFZ" ;
930 case CALLM: return "CALLM";
njn25e49d8e72002-09-23 09:36:25 +0000931 case CCALL: return "CCALL";
sewardjde4a1d02002-03-22 01:27:54 +0000932 case PUSH: return "PUSH" ;
933 case POP: return "POP" ;
934 case CLEAR: return "CLEAR";
935 case CC2VAL: return "CC2VAL";
936 case FPU_R: return "FPU_R";
937 case FPU_W: return "FPU_W";
938 case FPU: return "FPU" ;
sewardj3d7c9c82003-03-26 21:08:13 +0000939 case MMX1: return "MMX1" ;
940 case MMX2: return "MMX2" ;
sewardjca860012003-03-27 23:52:58 +0000941 case MMX3: return "MMX3" ;
sewardj3d7c9c82003-03-26 21:08:13 +0000942 case MMX2_MemRd: return "MMX2_MRd" ;
943 case MMX2_MemWr: return "MMX2_MWr" ;
thughes96b466a2004-03-15 16:43:58 +0000944 case MMX2a1_MemRd: return "MMX2a1_MRd" ;
sewardj4fbe6e92003-06-15 21:54:34 +0000945 case MMX2_ERegRd: return "MMX2_eRRd" ;
946 case MMX2_ERegWr: return "MMX2_eRWr" ;
sewardjfebaa3b2003-05-25 01:07:34 +0000947 case SSE2a_MemWr: return "SSE2a_MWr";
948 case SSE2a_MemRd: return "SSE2a_MRd";
nethercoteb1affa82004-01-19 19:14:18 +0000949 case SSE2g_RegWr: return "SSE2g_RWr";
sewardj9dd209f2003-06-18 23:30:52 +0000950 case SSE2a1_MemRd: return "SSE2a1_MRd";
nethercoteb1affa82004-01-19 19:14:18 +0000951 case SSE2g1_RegWr: return "SSE2g1_RWr";
952 case SSE2e1_RegRd: return "SSE2e1_RRd";
sewardj4fbe6e92003-06-15 21:54:34 +0000953 case SSE3e_RegRd: return "SSE3e_RRd";
sewardjabf8bf82003-06-15 22:28:05 +0000954 case SSE3e_RegWr: return "SSE3e_RWr";
sewardj02af6bc2003-06-12 00:56:06 +0000955 case SSE3g_RegWr: return "SSE3g_RWr";
sewardj77d30a22003-10-19 08:18:52 +0000956 case SSE3a1_MemRd: return "SSE3a1_MRd";
sewardjb31b06d2003-06-13 00:26:02 +0000957 case SSE3g1_RegWr: return "SSE3g1_RWr";
sewardj4fbe6e92003-06-15 21:54:34 +0000958 case SSE3e1_RegRd: return "SSE3e1_RRd";
sewardja60be0e2003-05-26 08:47:27 +0000959 case SSE3: return "SSE3";
sewardjfebaa3b2003-05-25 01:07:34 +0000960 case SSE4: return "SSE4";
sewardja453fb02003-06-14 13:22:36 +0000961 case SSE5: return "SSE5";
sewardjfebaa3b2003-05-25 01:07:34 +0000962 case SSE3a_MemWr: return "SSE3a_MWr";
963 case SSE3a_MemRd: return "SSE3a_MRd";
sewardje3891fa2003-06-15 03:13:48 +0000964 case SSE3ag_MemRd_RegWr: return "SSE3ag_MemRd_RegWr";
njn25e49d8e72002-09-23 09:36:25 +0000965 default:
966 if (VG_(needs).extended_UCode)
njn4ba5a792002-09-30 10:23:54 +0000967 return SK_(name_XUOpcode)(opc);
njn25e49d8e72002-09-23 09:36:25 +0000968 else {
969 VG_(printf)("unhandled opcode: %u. Perhaps "
970 "VG_(needs).extended_UCode should be set?",
971 opc);
njne427a662002-10-02 11:08:25 +0000972 VG_(core_panic)("name_UOpcode: unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000973 }
sewardjde4a1d02002-03-22 01:27:54 +0000974 }
975}
976
sewardja38e0922002-10-01 00:50:47 +0000977static
njn4ba5a792002-09-30 10:23:54 +0000978void pp_realregs_liveness ( UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +0000979{
980# define PRINT_RREG_LIVENESS(realReg,s) \
njn4ba5a792002-09-30 10:23:54 +0000981 VG_(printf)( IS_RREG_LIVE(VG_(realreg_to_rank)(realReg), \
njn25e49d8e72002-09-23 09:36:25 +0000982 u->regs_live_after) \
983 ? s : "-");
sewardjde4a1d02002-03-22 01:27:54 +0000984
njn25e49d8e72002-09-23 09:36:25 +0000985 VG_(printf)("[");
986 PRINT_RREG_LIVENESS(R_EAX, "a");
987 PRINT_RREG_LIVENESS(R_EBX, "b");
988 PRINT_RREG_LIVENESS(R_ECX, "c");
989 PRINT_RREG_LIVENESS(R_EDX, "d");
990 PRINT_RREG_LIVENESS(R_ESI, "S");
991 PRINT_RREG_LIVENESS(R_EDI, "D");
992 VG_(printf)("]");
993
994# undef PRINT_RREG_LIVENESS
995}
996
997/* Ugly-print UInstr :) */
njn4ba5a792002-09-30 10:23:54 +0000998void VG_(up_UInstr) ( Int i, UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +0000999{
njn4ba5a792002-09-30 10:23:54 +00001000 VG_(pp_UInstr_regs)(i, u);
njn25e49d8e72002-09-23 09:36:25 +00001001
1002 VG_(printf)("opcode: %d\n", u->opcode);
sewardjc1b86882002-10-06 21:43:50 +00001003 VG_(printf)("lit32: 0x%x\n", u->lit32);
njn25e49d8e72002-09-23 09:36:25 +00001004 VG_(printf)("size: %d\n", u->size);
1005 VG_(printf)("val1,val2,val3: %d, %d, %d\n", u->val1, u->val2, u->val3);
1006 VG_(printf)("tag1,tag2,tag3: %d, %d, %d\n", u->tag1, u->tag2, u->tag3);
sewardjc1b86882002-10-06 21:43:50 +00001007 VG_(printf)("flags_r: 0x%x\n", u->flags_r);
1008 VG_(printf)("flags_w: 0x%x\n", u->flags_w);
1009 VG_(printf)("extra4b: 0x%x\n", u->extra4b);
1010 VG_(printf)("cond: 0x%x\n", u->cond);
njn25e49d8e72002-09-23 09:36:25 +00001011 VG_(printf)("signed_widen: %d\n", u->signed_widen);
1012 VG_(printf)("jmpkind: %d\n", u->jmpkind);
1013 VG_(printf)("argc,regparms_n: %d, %d\n", u->argc, u->regparms_n);
1014 VG_(printf)("has_ret_val: %d\n", u->has_ret_val);
1015 VG_(printf)("regs_live_after: ");
njn4ba5a792002-09-30 10:23:54 +00001016 pp_realregs_liveness(u);
njn25e49d8e72002-09-23 09:36:25 +00001017 VG_(printf)("\n");
1018}
1019
sewardja38e0922002-10-01 00:50:47 +00001020static
njn4ba5a792002-09-30 10:23:54 +00001021void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
sewardjde4a1d02002-03-22 01:27:54 +00001022{
1023 VG_(printf)("\t%4d: %s", instrNo,
njn4ba5a792002-09-30 10:23:54 +00001024 VG_(name_UOpcode)(True, u->opcode));
nethercotee00f1ff2004-04-16 11:33:53 +00001025 // For JMP, the condition goes before the size
1026 if (u->opcode == JMP)
njn563f96f2003-02-03 11:17:46 +00001027 VG_(printf)("%s", VG_(name_UCondcode)(u->cond));
sewardjde4a1d02002-03-22 01:27:54 +00001028
1029 switch (u->size) {
1030 case 0: VG_(printf)("o"); break;
1031 case 1: VG_(printf)("B"); break;
1032 case 2: VG_(printf)("W"); break;
1033 case 4: VG_(printf)("L"); break;
1034 case 8: VG_(printf)("Q"); break;
sewardjfebaa3b2003-05-25 01:07:34 +00001035 case 16: VG_(printf)("QQ"); break;
sewardjde4a1d02002-03-22 01:27:54 +00001036 default: VG_(printf)("%d", (Int)u->size); break;
1037 }
1038
nethercotee00f1ff2004-04-16 11:33:53 +00001039 // For CC2VAL and CMOV, the condition goes after the size
1040 if (u->opcode == CC2VAL || u->opcode == CMOV)
1041 VG_(printf)("%s", VG_(name_UCondcode)(u->cond));
1042
nethercotebbcfb582004-04-16 15:39:22 +00001043 // Append extra bits
1044 switch (u->opcode) {
1045 case JMP:
nethercotee00f1ff2004-04-16 11:33:53 +00001046 switch (u->jmpkind) {
1047 case JmpCall: VG_(printf)("-c"); break;
1048 case JmpRet: VG_(printf)("-r"); break;
1049 case JmpSyscall: VG_(printf)("-sys"); break;
1050 case JmpClientReq: VG_(printf)("-cli"); break;
1051 case JmpYield: VG_(printf)("-yld"); break;
1052 default: break;
1053 }
nethercotebbcfb582004-04-16 15:39:22 +00001054 break;
1055
1056 case WIDEN:
1057 VG_(printf)("_%c%c", VG_(toupper)(nameISize(u->extra4b)),
1058 u->signed_widen?'s':'z');
1059 }
sewardjfebaa3b2003-05-25 01:07:34 +00001060 VG_(printf)(" \t");
1061
sewardjde4a1d02002-03-22 01:27:54 +00001062 switch (u->opcode) {
1063
sewardjde4a1d02002-03-22 01:27:54 +00001064 case CALLM_S: case CALLM_E:
1065 break;
1066
1067 case INCEIP:
sewardjfebaa3b2003-05-25 01:07:34 +00001068 VG_(printf)("$%d", u->val1);
sewardjde4a1d02002-03-22 01:27:54 +00001069 break;
1070
1071 case LEA2:
sewardjfebaa3b2003-05-25 01:07:34 +00001072 VG_(printf)("%d(" , u->lit32);
njn4ba5a792002-09-30 10:23:54 +00001073 VG_(pp_UOperand)(u, 1, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001074 VG_(printf)(",");
njn4ba5a792002-09-30 10:23:54 +00001075 VG_(pp_UOperand)(u, 2, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001076 VG_(printf)(",%d), ", (Int)u->extra4b);
njn4ba5a792002-09-30 10:23:54 +00001077 VG_(pp_UOperand)(u, 3, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001078 break;
1079
1080 case LEA1:
sewardjfebaa3b2003-05-25 01:07:34 +00001081 VG_(printf)("%d" , u->lit32);
njn4ba5a792002-09-30 10:23:54 +00001082 VG_(pp_UOperand)(u, 1, 4, True);
sewardjde4a1d02002-03-22 01:27:54 +00001083 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001084 VG_(pp_UOperand)(u, 2, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001085 break;
1086
sewardj7a5ebcf2002-11-13 22:42:13 +00001087 case NOP: case LOCK:
sewardjde4a1d02002-03-22 01:27:54 +00001088 break;
1089
1090 case FPU_W:
sewardjfebaa3b2003-05-25 01:07:34 +00001091 VG_(printf)("0x%x:0x%x, ",
sewardjde4a1d02002-03-22 01:27:54 +00001092 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
njn4ba5a792002-09-30 10:23:54 +00001093 VG_(pp_UOperand)(u, 2, 4, True);
sewardjde4a1d02002-03-22 01:27:54 +00001094 break;
1095
1096 case FPU_R:
sewardjfebaa3b2003-05-25 01:07:34 +00001097 VG_(printf)("");
njn4ba5a792002-09-30 10:23:54 +00001098 VG_(pp_UOperand)(u, 2, 4, True);
sewardjde4a1d02002-03-22 01:27:54 +00001099 VG_(printf)(", 0x%x:0x%x",
1100 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1101 break;
1102
1103 case FPU:
sewardjfebaa3b2003-05-25 01:07:34 +00001104 VG_(printf)("0x%x:0x%x",
sewardjde4a1d02002-03-22 01:27:54 +00001105 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1106 break;
1107
sewardj3d7c9c82003-03-26 21:08:13 +00001108 case MMX1:
sewardjfebaa3b2003-05-25 01:07:34 +00001109 VG_(printf)("0x%x",
sewardj3d7c9c82003-03-26 21:08:13 +00001110 u->val1 & 0xFF );
1111 break;
1112
1113 case MMX2:
sewardjfebaa3b2003-05-25 01:07:34 +00001114 VG_(printf)("0x%x:0x%x",
sewardj3d7c9c82003-03-26 21:08:13 +00001115 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1116 break;
1117
sewardjca860012003-03-27 23:52:58 +00001118 case MMX3:
sewardjfebaa3b2003-05-25 01:07:34 +00001119 VG_(printf)("0x%x:0x%x:0x%x",
sewardjca860012003-03-27 23:52:58 +00001120 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
1121 break;
1122
sewardj4fbe6e92003-06-15 21:54:34 +00001123 case MMX2_ERegWr:
1124 case MMX2_ERegRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001125 VG_(printf)("0x%x:0x%x, ",
sewardjca860012003-03-27 23:52:58 +00001126 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1127 VG_(pp_UOperand)(u, 2, 4, False);
1128 break;
1129
sewardj3d7c9c82003-03-26 21:08:13 +00001130 case MMX2_MemWr:
1131 case MMX2_MemRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001132 VG_(printf)("0x%x:0x%x",
sewardj3d7c9c82003-03-26 21:08:13 +00001133 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1134 VG_(pp_UOperand)(u, 2, 4, True);
1135 break;
1136
thughes96b466a2004-03-15 16:43:58 +00001137 case MMX2a1_MemRd:
1138 VG_(printf)("0x%x:0x%x:0x%x",
1139 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
1140 VG_(pp_UOperand)(u, 3, 4, True);
1141 break;
1142
sewardjfebaa3b2003-05-25 01:07:34 +00001143 case SSE2a_MemWr:
1144 case SSE2a_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001145 case SSE2g_RegWr:
1146 case SSE2g1_RegWr:
1147 case SSE2e1_RegRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001148 VG_(printf)("0x%x:0x%x:0x%x",
1149 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
1150 VG_(pp_UOperand)(u, 3, 4, True);
1151 break;
1152
sewardj9dd209f2003-06-18 23:30:52 +00001153 case SSE2a1_MemRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001154 case SSE3a_MemWr:
1155 case SSE3a_MemRd:
1156 VG_(printf)("0x%x:0x%x:0x%x:0x%x",
1157 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
sewardjde8aecf2003-05-27 00:46:28 +00001158 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
sewardjfebaa3b2003-05-25 01:07:34 +00001159 VG_(pp_UOperand)(u, 3, 4, True);
1160 break;
1161
sewardjabf8bf82003-06-15 22:28:05 +00001162 case SSE3e_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001163 case SSE3e_RegRd:
sewardj02af6bc2003-06-12 00:56:06 +00001164 case SSE3g_RegWr:
sewardjfebaa3b2003-05-25 01:07:34 +00001165 VG_(printf)("0x%x:0x%x:0x%x:0x%x",
1166 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1167 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
1168 VG_(pp_UOperand)(u, 3, 4, True);
1169 break;
1170
sewardjb31b06d2003-06-13 00:26:02 +00001171 case SSE3g1_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001172 case SSE3e1_RegRd:
sewardj77d30a22003-10-19 08:18:52 +00001173 case SSE3a1_MemRd:
sewardjb31b06d2003-06-13 00:26:02 +00001174 VG_(printf)("0x%x:0x%x:0x%x:0x%x:0x%x",
1175 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1176 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF,
1177 u->lit32 );
1178 VG_(pp_UOperand)(u, 3, 4, True);
1179 break;
1180
sewardja60be0e2003-05-26 08:47:27 +00001181 case SSE3:
1182 VG_(printf)("0x%x:0x%x:0x%x",
1183 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1184 u->val2 & 0xFF );
1185 break;
1186
sewardjfebaa3b2003-05-25 01:07:34 +00001187 case SSE4:
1188 VG_(printf)("0x%x:0x%x:0x%x:0x%x",
1189 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1190 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
1191 break;
1192
sewardja453fb02003-06-14 13:22:36 +00001193 case SSE5:
1194 VG_(printf)("0x%x:0x%x:0x%x:0x%x:0x%x",
1195 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1196 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF,
1197 u->val3 & 0xFF );
1198 break;
1199
sewardje3891fa2003-06-15 03:13:48 +00001200 case SSE3ag_MemRd_RegWr:
1201 VG_(printf)("0x%x(addr=", u->lit32 );
1202 VG_(pp_UOperand)(u, 1, 4, False);
1203 VG_(printf)(", dst=");
1204 VG_(pp_UOperand)(u, 2, 4, False);
1205 VG_(printf)(")");
1206 break;
1207
sewardjde4a1d02002-03-22 01:27:54 +00001208 case GET: case PUT: case MOV: case LOAD: case STORE: case CMOV:
sewardje1042472002-09-30 12:33:11 +00001209 case GETSEG: case PUTSEG:
njn4ba5a792002-09-30 10:23:54 +00001210 VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOAD);
sewardjde4a1d02002-03-22 01:27:54 +00001211 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001212 VG_(pp_UOperand)(u, 2, u->size, u->opcode==STORE);
njn25e49d8e72002-09-23 09:36:25 +00001213 break;
1214
1215 case JMP:
njn4ba5a792002-09-30 10:23:54 +00001216 VG_(pp_UOperand)(u, 1, u->size, False);
njn25e49d8e72002-09-23 09:36:25 +00001217 if (CondAlways == u->cond) {
1218 /* Print x86 instruction size if filled in */
1219 if (0 != u->extra4b)
1220 VG_(printf)(" ($%u)", u->extra4b);
1221 }
sewardjde4a1d02002-03-22 01:27:54 +00001222 break;
1223
1224 case GETF: case PUTF:
njn25e49d8e72002-09-23 09:36:25 +00001225 case CC2VAL: case PUSH: case POP: case CLEAR: case CALLM:
1226 case NOT: case NEG: case INC: case DEC: case BSWAP:
njn4ba5a792002-09-30 10:23:54 +00001227 VG_(pp_UOperand)(u, 1, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001228 break;
1229
njn25e49d8e72002-09-23 09:36:25 +00001230 /* Print a "(s)" after args passed on stack */
1231 case CCALL:
njn25e49d8e72002-09-23 09:36:25 +00001232 if (u->has_ret_val) {
njn4ba5a792002-09-30 10:23:54 +00001233 VG_(pp_UOperand)(u, 3, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001234 VG_(printf)(" = ");
sewardj2e93c502002-04-12 11:12:52 +00001235 }
njn25e49d8e72002-09-23 09:36:25 +00001236 VG_(printf)("%p(", u->lit32);
1237 if (u->argc > 0) {
njn4ba5a792002-09-30 10:23:54 +00001238 VG_(pp_UOperand)(u, 1, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001239 if (u->regparms_n < 1)
1240 VG_(printf)("(s)");
1241 }
1242 if (u->argc > 1) {
1243 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001244 VG_(pp_UOperand)(u, 2, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001245 if (u->regparms_n < 2)
1246 VG_(printf)("(s)");
1247 }
1248 if (u->argc > 2) {
1249 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001250 VG_(pp_UOperand)(u, 3, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001251 if (u->regparms_n < 3)
1252 VG_(printf)("(s)");
1253 }
1254 VG_(printf)(") ");
njn6431be72002-07-28 09:53:34 +00001255 break;
1256
sewardje1042472002-09-30 12:33:11 +00001257 case USESEG:
sewardjde4a1d02002-03-22 01:27:54 +00001258 case JIFZ:
sewardjde4a1d02002-03-22 01:27:54 +00001259 case ADD: case ADC: case AND: case OR:
1260 case XOR: case SUB: case SBB:
1261 case SHL: case SHR: case SAR:
jsgf5efa4fd2003-10-14 21:49:11 +00001262 case ROL: case ROR: case RCL: case RCR:
1263 case MUL:
njn4ba5a792002-09-30 10:23:54 +00001264 VG_(pp_UOperand)(u, 1, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001265 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001266 VG_(pp_UOperand)(u, 2, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001267 break;
1268
1269 case WIDEN:
njn4ba5a792002-09-30 10:23:54 +00001270 VG_(pp_UOperand)(u, 1, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001271 break;
1272
njn25e49d8e72002-09-23 09:36:25 +00001273 default:
1274 if (VG_(needs).extended_UCode)
njn4ba5a792002-09-30 10:23:54 +00001275 SK_(pp_XUInstr)(u);
njn25e49d8e72002-09-23 09:36:25 +00001276 else {
1277 VG_(printf)("unhandled opcode: %u. Perhaps "
1278 "VG_(needs).extended_UCode should be set?",
1279 u->opcode);
njne427a662002-10-02 11:08:25 +00001280 VG_(core_panic)("pp_UInstr: unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +00001281 }
sewardjde4a1d02002-03-22 01:27:54 +00001282 }
sewardjde4a1d02002-03-22 01:27:54 +00001283 if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty) {
1284 VG_(printf)(" (");
1285 if (u->flags_r != FlagsEmpty)
1286 vg_ppFlagSet("-r", u->flags_r);
1287 if (u->flags_w != FlagsEmpty)
1288 vg_ppFlagSet("-w", u->flags_w);
1289 VG_(printf)(")");
1290 }
njn25e49d8e72002-09-23 09:36:25 +00001291
1292 if (ppRegsLiveness) {
1293 VG_(printf)("\t\t");
njn4ba5a792002-09-30 10:23:54 +00001294 pp_realregs_liveness ( u );
njn25e49d8e72002-09-23 09:36:25 +00001295 }
1296
sewardjde4a1d02002-03-22 01:27:54 +00001297 VG_(printf)("\n");
1298}
1299
njn4ba5a792002-09-30 10:23:54 +00001300void VG_(pp_UInstr) ( Int instrNo, UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +00001301{
njn4ba5a792002-09-30 10:23:54 +00001302 pp_UInstrWorker ( instrNo, u, /*ppRegsLiveness*/False );
njn25e49d8e72002-09-23 09:36:25 +00001303}
1304
njn4ba5a792002-09-30 10:23:54 +00001305void VG_(pp_UInstr_regs) ( Int instrNo, UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +00001306{
njn4ba5a792002-09-30 10:23:54 +00001307 pp_UInstrWorker ( instrNo, u, /*ppRegsLiveness*/True );
njn25e49d8e72002-09-23 09:36:25 +00001308}
sewardjde4a1d02002-03-22 01:27:54 +00001309
njn4ba5a792002-09-30 10:23:54 +00001310void VG_(pp_UCodeBlock) ( UCodeBlock* cb, Char* title )
sewardjde4a1d02002-03-22 01:27:54 +00001311{
1312 Int i;
njn25e49d8e72002-09-23 09:36:25 +00001313 VG_(printf)("%s\n", title);
sewardjde4a1d02002-03-22 01:27:54 +00001314 for (i = 0; i < cb->used; i++)
njn25e49d8e72002-09-23 09:36:25 +00001315 if (cb->instrs[i].opcode != NOP)
njn4ba5a792002-09-30 10:23:54 +00001316 VG_(pp_UInstr) ( i, &cb->instrs[i] );
sewardjde4a1d02002-03-22 01:27:54 +00001317 VG_(printf)("\n");
1318}
1319
1320
1321/*------------------------------------------------------------*/
1322/*--- uinstr helpers for register allocation ---*/
1323/*--- and code improvement. ---*/
1324/*------------------------------------------------------------*/
1325
njn25e49d8e72002-09-23 09:36:25 +00001326/* Get the temp/reg use of a uinstr, parking them in an array supplied by
njn810086f2002-11-14 12:42:47 +00001327 the caller (regs), which is assumed to be big enough. Return the number
1328 of entries. Written regs are indicated in parallel array isWrites.
1329 Insns which read _and_ write a register wind up mentioning it twice.
1330 Entries are placed in the array in program order, so that if a reg is
1331 read-modified-written, it appears first as a read and then as a write.
1332 'tag' indicates whether we are looking at TempRegs or RealRegs.
sewardjde4a1d02002-03-22 01:27:54 +00001333*/
njn810086f2002-11-14 12:42:47 +00001334Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites )
sewardjde4a1d02002-03-22 01:27:54 +00001335{
njn810086f2002-11-14 12:42:47 +00001336# define RD(ono) VG_UINSTR_READS_REG(ono, regs, isWrites)
1337# define WR(ono) VG_UINSTR_WRITES_REG(ono, regs, isWrites)
sewardjde4a1d02002-03-22 01:27:54 +00001338
1339 Int n = 0;
1340 switch (u->opcode) {
1341 case LEA1: RD(1); WR(2); break;
1342 case LEA2: RD(1); RD(2); WR(3); break;
1343
sewardj77d30a22003-10-19 08:18:52 +00001344 case SSE3a1_MemRd:
sewardj9dd209f2003-06-18 23:30:52 +00001345 case SSE2a1_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001346 case SSE2e1_RegRd:
sewardj4fbe6e92003-06-15 21:54:34 +00001347 case SSE3e_RegRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001348 case SSE3a_MemWr:
1349 case SSE3a_MemRd:
1350 case SSE2a_MemWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001351 case SSE3e1_RegRd:
sewardj02af6bc2003-06-12 00:56:06 +00001352 case SSE2a_MemRd: RD(3); break;
1353
nethercoteb1affa82004-01-19 19:14:18 +00001354 case SSE2g_RegWr:
1355 case SSE2g1_RegWr:
sewardjabf8bf82003-06-15 22:28:05 +00001356 case SSE3e_RegWr:
sewardjb31b06d2003-06-13 00:26:02 +00001357 case SSE3g1_RegWr:
sewardj02af6bc2003-06-12 00:56:06 +00001358 case SSE3g_RegWr: WR(3); break;
sewardjfebaa3b2003-05-25 01:07:34 +00001359
sewardje3891fa2003-06-15 03:13:48 +00001360 case SSE3ag_MemRd_RegWr: RD(1); WR(2); break;
1361
thughes96b466a2004-03-15 16:43:58 +00001362 case MMX2a1_MemRd: RD(3); break;
sewardj4fbe6e92003-06-15 21:54:34 +00001363 case MMX2_ERegRd: RD(2); break;
1364 case MMX2_ERegWr: WR(2); break;
sewardjca860012003-03-27 23:52:58 +00001365
sewardja453fb02003-06-14 13:22:36 +00001366 case SSE4: case SSE3: case SSE5:
sewardjca860012003-03-27 23:52:58 +00001367 case MMX1: case MMX2: case MMX3:
njn25e49d8e72002-09-23 09:36:25 +00001368 case NOP: case FPU: case INCEIP: case CALLM_S: case CALLM_E:
sewardj7a5ebcf2002-11-13 22:42:13 +00001369 case CLEAR: case CALLM: case LOCK: break;
njn25e49d8e72002-09-23 09:36:25 +00001370
1371 case CCALL:
1372 if (u->argc > 0) RD(1);
1373 if (u->argc > 1) RD(2);
1374 if (u->argc > 2) RD(3);
1375 if (u->has_ret_val) WR(3);
1376 break;
1377
sewardj3d7c9c82003-03-26 21:08:13 +00001378 case MMX2_MemRd: case MMX2_MemWr:
sewardjde4a1d02002-03-22 01:27:54 +00001379 case FPU_R: case FPU_W: RD(2); break;
1380
sewardje1042472002-09-30 12:33:11 +00001381 case GETSEG: WR(2); break;
1382 case PUTSEG: RD(1); break;
1383
sewardjde4a1d02002-03-22 01:27:54 +00001384 case GETF: WR(1); break;
1385 case PUTF: RD(1); break;
1386
1387 case GET: WR(2); break;
1388 case PUT: RD(1); break;
1389 case LOAD: RD(1); WR(2); break;
njn25e49d8e72002-09-23 09:36:25 +00001390 case STORE: RD(1); RD(2); break;
sewardjde4a1d02002-03-22 01:27:54 +00001391 case MOV: RD(1); WR(2); break;
1392
1393 case JMP: RD(1); break;
sewardjde4a1d02002-03-22 01:27:54 +00001394
njn25e49d8e72002-09-23 09:36:25 +00001395 case PUSH: RD(1); break;
sewardjde4a1d02002-03-22 01:27:54 +00001396 case POP: WR(1); break;
1397
sewardje1042472002-09-30 12:33:11 +00001398 case USESEG:
sewardjde4a1d02002-03-22 01:27:54 +00001399 case CMOV:
1400 case ADD: case ADC: case AND: case OR:
1401 case XOR: case SUB: case SBB:
jsgf5efa4fd2003-10-14 21:49:11 +00001402 case MUL:
sewardjde4a1d02002-03-22 01:27:54 +00001403 RD(1); RD(2); WR(2); break;
1404
1405 case SHL: case SHR: case SAR:
1406 case ROL: case ROR: case RCL: case RCR:
1407 RD(1); RD(2); WR(2); break;
1408
njn25e49d8e72002-09-23 09:36:25 +00001409 case NOT: case NEG: case INC: case DEC: case BSWAP:
sewardjde4a1d02002-03-22 01:27:54 +00001410 RD(1); WR(1); break;
1411
1412 case WIDEN: RD(1); WR(1); break;
1413
1414 case CC2VAL: WR(1); break;
1415 case JIFZ: RD(1); break;
1416
njn25e49d8e72002-09-23 09:36:25 +00001417 default:
1418 if (VG_(needs).extended_UCode)
njn810086f2002-11-14 12:42:47 +00001419 return SK_(get_Xreg_usage)(u, tag, regs, isWrites);
njn25e49d8e72002-09-23 09:36:25 +00001420 else {
1421 VG_(printf)("unhandled opcode: %u. Perhaps "
1422 "VG_(needs).extended_UCode should be set?",
1423 u->opcode);
njne427a662002-10-02 11:08:25 +00001424 VG_(core_panic)("VG_(get_reg_usage): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +00001425 }
sewardjde4a1d02002-03-22 01:27:54 +00001426 }
1427 return n;
1428
1429# undef RD
1430# undef WR
1431}
1432
1433
njn25e49d8e72002-09-23 09:36:25 +00001434/* Change temp regs in u into real regs, as directed by the
1435 * temps[i]-->reals[i] mapping. */
sewardj56867352003-10-12 10:27:06 +00001436static
njn810086f2002-11-14 12:42:47 +00001437void patchUInstr ( UInstr* u, Int temps[], UInt reals[], Int n_tmap )
sewardjde4a1d02002-03-22 01:27:54 +00001438{
1439 Int i;
1440 if (u->tag1 == TempReg) {
1441 for (i = 0; i < n_tmap; i++)
njn810086f2002-11-14 12:42:47 +00001442 if (temps[i] == u->val1) break;
njne427a662002-10-02 11:08:25 +00001443 if (i == n_tmap) VG_(core_panic)("patchUInstr(1)");
sewardjde4a1d02002-03-22 01:27:54 +00001444 u->tag1 = RealReg;
njn25e49d8e72002-09-23 09:36:25 +00001445 u->val1 = reals[i];
sewardjde4a1d02002-03-22 01:27:54 +00001446 }
1447 if (u->tag2 == TempReg) {
1448 for (i = 0; i < n_tmap; i++)
njn810086f2002-11-14 12:42:47 +00001449 if (temps[i] == u->val2) break;
njne427a662002-10-02 11:08:25 +00001450 if (i == n_tmap) VG_(core_panic)("patchUInstr(2)");
sewardjde4a1d02002-03-22 01:27:54 +00001451 u->tag2 = RealReg;
njn25e49d8e72002-09-23 09:36:25 +00001452 u->val2 = reals[i];
sewardjde4a1d02002-03-22 01:27:54 +00001453 }
1454 if (u->tag3 == TempReg) {
1455 for (i = 0; i < n_tmap; i++)
njn810086f2002-11-14 12:42:47 +00001456 if (temps[i] == u->val3) break;
njne427a662002-10-02 11:08:25 +00001457 if (i == n_tmap) VG_(core_panic)("patchUInstr(3)");
sewardjde4a1d02002-03-22 01:27:54 +00001458 u->tag3 = RealReg;
njn25e49d8e72002-09-23 09:36:25 +00001459 u->val3 = reals[i];
sewardjde4a1d02002-03-22 01:27:54 +00001460 }
1461}
1462
1463
1464/* Tedious x86-specific hack which compensates for the fact that the
1465 register numbers for %ah .. %dh do not correspond to those for %eax
1466 .. %edx. It maps a (reg size, reg no) pair to the number of the
1467 containing 32-bit reg. */
1468static __inline__
1469Int containingArchRegOf ( Int sz, Int aregno )
1470{
1471 switch (sz) {
1472 case 4: return aregno;
1473 case 2: return aregno;
1474 case 1: return aregno >= 4 ? aregno-4 : aregno;
njne427a662002-10-02 11:08:25 +00001475 default: VG_(core_panic)("containingArchRegOf");
sewardjde4a1d02002-03-22 01:27:54 +00001476 }
1477}
1478
1479
1480/* If u reads an ArchReg, return the number of the containing arch
njn25e49d8e72002-09-23 09:36:25 +00001481 reg. Otherwise return -1. Used in redundant-PUT elimination.
nethercote996901a2004-08-03 13:29:09 +00001482 Note that this is not required for tools extending UCode because
njn25e49d8e72002-09-23 09:36:25 +00001483 this happens before instrumentation. */
sewardj56867352003-10-12 10:27:06 +00001484static
sewardjde4a1d02002-03-22 01:27:54 +00001485Int maybe_uinstrReadsArchReg ( UInstr* u )
1486{
1487 switch (u->opcode) {
1488 case GET:
1489 case ADD: case ADC: case AND: case OR:
1490 case XOR: case SUB: case SBB:
1491 case SHL: case SHR: case SAR: case ROL:
1492 case ROR: case RCL: case RCR:
jsgf5efa4fd2003-10-14 21:49:11 +00001493 case MUL:
sewardjde4a1d02002-03-22 01:27:54 +00001494 if (u->tag1 == ArchReg)
1495 return containingArchRegOf ( u->size, u->val1 );
1496 else
1497 return -1;
1498
1499 case GETF: case PUTF:
1500 case CALLM_S: case CALLM_E:
1501 case INCEIP:
1502 case LEA1:
1503 case LEA2:
1504 case NOP:
sewardj7a5ebcf2002-11-13 22:42:13 +00001505 case LOCK:
sewardjde4a1d02002-03-22 01:27:54 +00001506 case PUT:
1507 case LOAD:
1508 case STORE:
1509 case MOV:
1510 case CMOV:
1511 case JMP:
1512 case CALLM: case CLEAR: case PUSH: case POP:
1513 case NOT: case NEG: case INC: case DEC: case BSWAP:
1514 case CC2VAL:
1515 case JIFZ:
1516 case FPU: case FPU_R: case FPU_W:
sewardjca860012003-03-27 23:52:58 +00001517 case MMX1: case MMX2: case MMX3:
thughes96b466a2004-03-15 16:43:58 +00001518 case MMX2_MemRd: case MMX2_MemWr: case MMX2a1_MemRd:
sewardj4fbe6e92003-06-15 21:54:34 +00001519 case MMX2_ERegRd: case MMX2_ERegWr:
sewardj9dd209f2003-06-18 23:30:52 +00001520 case SSE2a_MemWr: case SSE2a_MemRd: case SSE2a1_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001521 case SSE2g_RegWr: case SSE2g1_RegWr: case SSE2e1_RegRd:
sewardj77d30a22003-10-19 08:18:52 +00001522 case SSE3a_MemWr: case SSE3a_MemRd: case SSE3a1_MemRd:
sewardjabf8bf82003-06-15 22:28:05 +00001523 case SSE3e_RegRd: case SSE3g_RegWr: case SSE3e_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001524 case SSE3g1_RegWr: case SSE3e1_RegRd:
sewardje3891fa2003-06-15 03:13:48 +00001525 case SSE4: case SSE3: case SSE5: case SSE3ag_MemRd_RegWr:
sewardjde4a1d02002-03-22 01:27:54 +00001526 case WIDEN:
sewardje1042472002-09-30 12:33:11 +00001527 /* GETSEG and USESEG are to do with ArchRegS, not ArchReg */
1528 case GETSEG: case PUTSEG:
1529 case USESEG:
sewardjde4a1d02002-03-22 01:27:54 +00001530 return -1;
1531
1532 default:
njn4ba5a792002-09-30 10:23:54 +00001533 VG_(pp_UInstr)(0,u);
njne427a662002-10-02 11:08:25 +00001534 VG_(core_panic)("maybe_uinstrReadsArchReg: unhandled opcode");
sewardjde4a1d02002-03-22 01:27:54 +00001535 }
1536}
1537
1538static __inline__
1539Bool uInstrMentionsTempReg ( UInstr* u, Int tempreg )
1540{
1541 Int i, k;
njnf4ce3d32003-02-10 10:17:26 +00001542 Int tempUse[VG_MAX_REGS_USED];
1543 Bool notUsed[VG_MAX_REGS_USED];
njn810086f2002-11-14 12:42:47 +00001544
1545 k = VG_(get_reg_usage) ( u, TempReg, &tempUse[0], &notUsed[0] );
sewardjde4a1d02002-03-22 01:27:54 +00001546 for (i = 0; i < k; i++)
njn810086f2002-11-14 12:42:47 +00001547 if (tempUse[i] == tempreg)
sewardjde4a1d02002-03-22 01:27:54 +00001548 return True;
1549 return False;
1550}
1551
1552
1553/*------------------------------------------------------------*/
1554/*--- ucode improvement. ---*/
1555/*------------------------------------------------------------*/
1556
1557/* Improve the code in cb by doing
1558 -- Redundant ArchReg-fetch elimination
1559 -- Redundant PUT elimination
1560 -- Redundant cond-code restore/save elimination
1561 The overall effect of these is to allow target registers to be
1562 cached in host registers over multiple target insns.
1563*/
1564static void vg_improve ( UCodeBlock* cb )
1565{
1566 Int i, j, k, m, n, ar, tr, told, actual_areg;
1567 Int areg_map[8];
1568 Bool annul_put[8];
njnf4ce3d32003-02-10 10:17:26 +00001569 Int tempUse[VG_MAX_REGS_USED];
1570 Bool isWrites[VG_MAX_REGS_USED];
sewardjde4a1d02002-03-22 01:27:54 +00001571 UInstr* u;
1572 Bool wr;
1573 Int* last_live_before;
1574 FlagSet future_dead_flags;
1575
njn25e49d8e72002-09-23 09:36:25 +00001576 if (dis)
1577 VG_(printf) ("Improvements:\n");
1578
sewardjde4a1d02002-03-22 01:27:54 +00001579 if (cb->nextTemp > 0)
njn25e49d8e72002-09-23 09:36:25 +00001580 last_live_before = VG_(arena_malloc) ( VG_AR_JITTER,
1581 cb->nextTemp * sizeof(Int) );
sewardjde4a1d02002-03-22 01:27:54 +00001582 else
1583 last_live_before = NULL;
1584
1585
1586 /* PASS 1: redundant GET elimination. (Actually, more general than
1587 that -- eliminates redundant fetches of ArchRegs). */
1588
1589 /* Find the live-range-ends for all temporaries. Duplicates code
1590 in the register allocator :-( */
1591
1592 for (i = 0; i < cb->nextTemp; i++) last_live_before[i] = -1;
1593
1594 for (i = cb->used-1; i >= 0; i--) {
1595 u = &cb->instrs[i];
1596
njn810086f2002-11-14 12:42:47 +00001597 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
sewardjde4a1d02002-03-22 01:27:54 +00001598
1599 /* For each temp usage ... bwds in program order. */
1600 for (j = k-1; j >= 0; j--) {
njn810086f2002-11-14 12:42:47 +00001601 tr = tempUse[j];
1602 wr = isWrites[j];
sewardjde4a1d02002-03-22 01:27:54 +00001603 if (last_live_before[tr] == -1) {
1604 vg_assert(tr >= 0 && tr < cb->nextTemp);
1605 last_live_before[tr] = wr ? (i+1) : i;
1606 }
1607 }
1608
1609 }
1610
1611# define BIND_ARCH_TO_TEMP(archreg,tempreg)\
1612 { Int q; \
1613 /* Invalidate any old binding(s) to tempreg. */ \
1614 for (q = 0; q < 8; q++) \
1615 if (areg_map[q] == tempreg) areg_map[q] = -1; \
1616 /* Add the new binding. */ \
1617 areg_map[archreg] = (tempreg); \
1618 }
1619
1620 /* Set up the A-reg map. */
1621 for (i = 0; i < 8; i++) areg_map[i] = -1;
1622
1623 /* Scan insns. */
1624 for (i = 0; i < cb->used; i++) {
1625 u = &cb->instrs[i];
1626 if (u->opcode == GET && u->size == 4) {
1627 /* GET; see if it can be annulled. */
1628 vg_assert(u->tag1 == ArchReg);
1629 vg_assert(u->tag2 == TempReg);
1630 ar = u->val1;
1631 tr = u->val2;
1632 told = areg_map[ar];
1633 if (told != -1 && last_live_before[told] <= i) {
1634 /* ar already has an old mapping to told, but that runs
1635 out here. Annul this GET, rename tr to told for the
1636 rest of the block, and extend told's live range to that
1637 of tr. */
njn4ba5a792002-09-30 10:23:54 +00001638 VG_(new_NOP)(u);
sewardjde4a1d02002-03-22 01:27:54 +00001639 n = last_live_before[tr] + 1;
1640 if (n > cb->used) n = cb->used;
1641 last_live_before[told] = last_live_before[tr];
1642 last_live_before[tr] = i-1;
njn25e49d8e72002-09-23 09:36:25 +00001643 if (dis)
sewardjde4a1d02002-03-22 01:27:54 +00001644 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00001645 " at %2d: delete GET, rename t%d to t%d in (%d .. %d)\n",
sewardjde4a1d02002-03-22 01:27:54 +00001646 i, tr, told,i+1, n-1);
1647 for (m = i+1; m < n; m++) {
1648 if (cb->instrs[m].tag1 == TempReg
1649 && cb->instrs[m].val1 == tr)
1650 cb->instrs[m].val1 = told;
1651 if (cb->instrs[m].tag2 == TempReg
1652 && cb->instrs[m].val2 == tr)
1653 cb->instrs[m].val2 = told;
sewardjfebaa3b2003-05-25 01:07:34 +00001654 if (cb->instrs[m].tag3 == TempReg
1655 && cb->instrs[m].val3 == tr)
1656 cb->instrs[m].val3 = told;
sewardjde4a1d02002-03-22 01:27:54 +00001657 }
1658 BIND_ARCH_TO_TEMP(ar,told);
1659 }
1660 else
1661 BIND_ARCH_TO_TEMP(ar,tr);
1662 }
1663 else if (u->opcode == GET && u->size != 4) {
1664 /* Invalidate any mapping for this archreg. */
1665 actual_areg = containingArchRegOf ( u->size, u->val1 );
1666 areg_map[actual_areg] = -1;
1667 }
1668 else if (u->opcode == PUT && u->size == 4) {
1669 /* PUT; re-establish t -> a binding */
1670 vg_assert(u->tag1 == TempReg);
1671 vg_assert(u->tag2 == ArchReg);
1672 BIND_ARCH_TO_TEMP(u->val2, u->val1);
1673 }
1674 else if (u->opcode == PUT && u->size != 4) {
1675 /* Invalidate any mapping for this archreg. */
1676 actual_areg = containingArchRegOf ( u->size, u->val2 );
1677 areg_map[actual_areg] = -1;
1678 } else {
1679
1680 /* see if insn has an archreg as a read operand; if so try to
1681 map it. */
1682 if (u->tag1 == ArchReg && u->size == 4
1683 && areg_map[u->val1] != -1) {
1684 switch (u->opcode) {
1685 case ADD: case SUB: case AND: case OR: case XOR:
1686 case ADC: case SBB:
1687 case SHL: case SHR: case SAR: case ROL: case ROR:
1688 case RCL: case RCR:
jsgf5efa4fd2003-10-14 21:49:11 +00001689 case MUL:
njn25e49d8e72002-09-23 09:36:25 +00001690 if (dis)
sewardjde4a1d02002-03-22 01:27:54 +00001691 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00001692 " at %2d: change ArchReg %S to TempReg t%d\n",
sewardjde4a1d02002-03-22 01:27:54 +00001693 i, nameIReg(4,u->val1), areg_map[u->val1]);
1694 u->tag1 = TempReg;
1695 u->val1 = areg_map[u->val1];
1696 /* Remember to extend the live range of the TempReg,
1697 if necessary. */
1698 if (last_live_before[u->val1] < i)
1699 last_live_before[u->val1] = i;
1700 break;
1701 default:
1702 break;
1703 }
1704 }
1705
1706 /* boring insn; invalidate any mappings to temps it writes */
njn810086f2002-11-14 12:42:47 +00001707 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
sewardjde4a1d02002-03-22 01:27:54 +00001708
1709 for (j = 0; j < k; j++) {
njn810086f2002-11-14 12:42:47 +00001710 wr = isWrites[j];
sewardjde4a1d02002-03-22 01:27:54 +00001711 if (!wr) continue;
njn810086f2002-11-14 12:42:47 +00001712 tr = tempUse[j];
sewardjde4a1d02002-03-22 01:27:54 +00001713 for (m = 0; m < 8; m++)
1714 if (areg_map[m] == tr) areg_map[m] = -1;
1715 }
1716 }
1717
1718 }
1719
1720# undef BIND_ARCH_TO_TEMP
1721
sewardj05f1aa12002-04-30 00:29:36 +00001722 /* PASS 2: redundant PUT elimination. Don't annul (delay) puts of
1723 %ESP, since the memory check machinery always requires the
1724 in-memory value of %ESP to be up to date. Although this isn't
1725 actually required by other analyses (cache simulation), it's
1726 simplest to be consistent for all end-uses. */
sewardjde4a1d02002-03-22 01:27:54 +00001727 for (j = 0; j < 8; j++)
1728 annul_put[j] = False;
1729
1730 for (i = cb->used-1; i >= 0; i--) {
1731 u = &cb->instrs[i];
1732 if (u->opcode == NOP) continue;
1733
1734 if (u->opcode == PUT && u->size == 4) {
1735 vg_assert(u->tag2 == ArchReg);
1736 actual_areg = containingArchRegOf ( 4, u->val2 );
1737 if (annul_put[actual_areg]) {
sewardj05f1aa12002-04-30 00:29:36 +00001738 vg_assert(actual_areg != R_ESP);
njn4ba5a792002-09-30 10:23:54 +00001739 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001740 if (dis)
1741 VG_(printf)(" at %2d: delete PUT\n", i );
sewardjde4a1d02002-03-22 01:27:54 +00001742 } else {
sewardj05f1aa12002-04-30 00:29:36 +00001743 if (actual_areg != R_ESP)
sewardjde4a1d02002-03-22 01:27:54 +00001744 annul_put[actual_areg] = True;
1745 }
1746 }
1747 else if (u->opcode == PUT && u->size != 4) {
1748 actual_areg = containingArchRegOf ( u->size, u->val2 );
1749 annul_put[actual_areg] = False;
1750 }
1751 else if (u->opcode == JMP || u->opcode == JIFZ
1752 || u->opcode == CALLM) {
1753 for (j = 0; j < 8; j++)
1754 annul_put[j] = False;
1755 }
1756 else {
1757 /* If an instruction reads an ArchReg, the immediately
1758 preceding PUT cannot be annulled. */
1759 actual_areg = maybe_uinstrReadsArchReg ( u );
1760 if (actual_areg != -1)
1761 annul_put[actual_areg] = False;
1762 }
1763 }
1764
1765 /* PASS 2a: redundant-move elimination. Given MOV t1, t2 and t1 is
1766 dead after this point, annul the MOV insn and rename t2 to t1.
1767 Further modifies the last_live_before map. */
1768
1769# if 0
njn4ba5a792002-09-30 10:23:54 +00001770 VG_(pp_UCodeBlock)(cb, "Before MOV elimination" );
sewardjde4a1d02002-03-22 01:27:54 +00001771 for (i = 0; i < cb->nextTemp; i++)
1772 VG_(printf)("llb[t%d]=%d ", i, last_live_before[i]);
1773 VG_(printf)("\n");
1774# endif
1775
1776 for (i = 0; i < cb->used-1; i++) {
1777 u = &cb->instrs[i];
1778 if (u->opcode != MOV) continue;
1779 if (u->tag1 == Literal) continue;
1780 vg_assert(u->tag1 == TempReg);
1781 vg_assert(u->tag2 == TempReg);
1782 if (last_live_before[u->val1] == i) {
njn25e49d8e72002-09-23 09:36:25 +00001783 if (dis)
sewardjde4a1d02002-03-22 01:27:54 +00001784 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00001785 " at %2d: delete MOV, rename t%d to t%d in (%d .. %d)\n",
sewardjde4a1d02002-03-22 01:27:54 +00001786 i, u->val2, u->val1, i+1, last_live_before[u->val2] );
1787 for (j = i+1; j <= last_live_before[u->val2]; j++) {
1788 if (cb->instrs[j].tag1 == TempReg
1789 && cb->instrs[j].val1 == u->val2)
1790 cb->instrs[j].val1 = u->val1;
1791 if (cb->instrs[j].tag2 == TempReg
1792 && cb->instrs[j].val2 == u->val2)
1793 cb->instrs[j].val2 = u->val1;
sewardjfebaa3b2003-05-25 01:07:34 +00001794 if (cb->instrs[j].tag3 == TempReg
1795 && cb->instrs[j].val3 == u->val2)
1796 cb->instrs[j].val3 = u->val1;
sewardjde4a1d02002-03-22 01:27:54 +00001797 }
1798 last_live_before[u->val1] = last_live_before[u->val2];
1799 last_live_before[u->val2] = i-1;
njn4ba5a792002-09-30 10:23:54 +00001800 VG_(new_NOP)(u);
sewardjde4a1d02002-03-22 01:27:54 +00001801 }
1802 }
1803
1804 /* PASS 3: redundant condition-code restore/save elimination.
1805 Scan backwards from the end. future_dead_flags records the set
1806 of flags which are dead at this point, that is, will be written
1807 before they are next read. Earlier uinsns which write flags
1808 already in future_dead_flags can have their writes annulled.
1809 */
1810 future_dead_flags = FlagsEmpty;
1811
1812 for (i = cb->used-1; i >= 0; i--) {
1813 u = &cb->instrs[i];
1814
1815 /* We might never make it to insns beyond this one, so be
1816 conservative. */
1817 if (u->opcode == JIFZ || u->opcode == JMP) {
1818 future_dead_flags = FlagsEmpty;
1819 continue;
1820 }
1821
sewardjfbb6cda2002-07-24 09:33:52 +00001822 /* PUTF modifies the %EFLAGS in essentially unpredictable ways.
1823 For example people try to mess with bit 21 to see if CPUID
1824 works. The setting may or may not actually take hold. So we
1825 play safe here. */
1826 if (u->opcode == PUTF) {
1827 future_dead_flags = FlagsEmpty;
1828 continue;
1829 }
1830
sewardjde4a1d02002-03-22 01:27:54 +00001831 /* We can annul the flags written by this insn if it writes a
1832 subset (or eq) of the set of flags known to be dead after
1833 this insn. If not, just record the flags also written by
1834 this insn.*/
1835 if (u->flags_w != FlagsEmpty
1836 && VG_IS_FLAG_SUBSET(u->flags_w, future_dead_flags)) {
njn25e49d8e72002-09-23 09:36:25 +00001837 if (dis) {
1838 VG_(printf)(" at %2d: annul flag write ", i);
sewardjde4a1d02002-03-22 01:27:54 +00001839 vg_ppFlagSet("", u->flags_w);
1840 VG_(printf)(" due to later ");
1841 vg_ppFlagSet("", future_dead_flags);
1842 VG_(printf)("\n");
1843 }
1844 u->flags_w = FlagsEmpty;
1845 } else {
1846 future_dead_flags
1847 = VG_UNION_FLAG_SETS ( u->flags_w, future_dead_flags );
1848 }
1849
1850 /* If this insn also reads flags, empty out future_dead_flags so
1851 as to force preceding writes not to be annulled. */
1852 if (u->flags_r != FlagsEmpty)
1853 future_dead_flags = FlagsEmpty;
1854 }
1855
1856 if (last_live_before)
njn25e49d8e72002-09-23 09:36:25 +00001857 VG_(arena_free) ( VG_AR_JITTER, last_live_before );
1858
1859 if (dis) {
1860 VG_(printf)("\n");
njn4ba5a792002-09-30 10:23:54 +00001861 VG_(pp_UCodeBlock) ( cb, "Improved UCode:" );
njn25e49d8e72002-09-23 09:36:25 +00001862 }
sewardjde4a1d02002-03-22 01:27:54 +00001863}
1864
njn9b007f62003-04-07 14:40:25 +00001865/*------------------------------------------------------------*/
1866/*--- %ESP-update pass ---*/
1867/*------------------------------------------------------------*/
1868
nethercote996901a2004-08-03 13:29:09 +00001869/* For tools that want to know about %ESP changes, this pass adds
1870 in the appropriate hooks. We have to do it after the tool's
1871 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +00001872 it adds in, and we must do it before register allocation because
1873 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +00001874 Thus we have it as an extra phase between the two.
1875
1876 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
1877 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
1878 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
1879 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
1880 instruction clobbers t_ESP, we don't track it anymore, and fall back to
1881 the delta-is-unknown case. That case is also used when the delta is not
1882 a nice small amount, or an unknown amount.
1883*/
njn9b007f62003-04-07 14:40:25 +00001884static
1885UCodeBlock* vg_ESP_update_pass(UCodeBlock* cb_in)
1886{
1887 UCodeBlock* cb;
1888 UInstr* u;
1889 Int delta = 0;
1890 UInt t_ESP = INVALID_TEMPREG;
sewardj05bcdcb2003-05-18 10:05:38 +00001891 Int i;
njn9b007f62003-04-07 14:40:25 +00001892
1893 cb = VG_(setup_UCodeBlock)(cb_in);
1894
1895 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
1896 u = VG_(get_instr)(cb_in, i);
1897
1898 if (GET == u->opcode && R_ESP == u->val1) {
1899 t_ESP = u->val2;
1900 delta = 0;
1901
1902 } else if (PUT == u->opcode && R_ESP == u->val2 && 4 == u->size) {
1903
fitzhardinge98abfc72003-12-16 02:05:15 +00001904# define DO_GENERIC \
1905 if (VG_(defined_new_mem_stack)() || \
1906 VG_(defined_die_mem_stack)()) { \
1907 uInstr1(cb, CCALL, 0, TempReg, u->val1); \
1908 uCCall(cb, (Addr) VG_(unknown_esp_update), \
1909 1, 1, False); \
njn9b007f62003-04-07 14:40:25 +00001910 }
1911
fitzhardinge98abfc72003-12-16 02:05:15 +00001912# define DO(kind, size) \
1913 if (VG_(defined_##kind##_mem_stack_##size)()) { \
1914 uInstr1(cb, CCALL, 0, TempReg, u->val1); \
1915 uCCall(cb, (Addr) VG_(tool_interface).track_##kind##_mem_stack_##size, \
1916 1, 1, False); \
1917 \
1918 } else \
1919 DO_GENERIC \
njn9b007f62003-04-07 14:40:25 +00001920 break
1921
1922 if (u->val1 == t_ESP) {
1923 /* Known delta, common cases handled specially. */
1924 switch (delta) {
njned619712003-10-01 16:45:04 +00001925 case 0: break;
njn9b007f62003-04-07 14:40:25 +00001926 case 4: DO(die, 4);
1927 case -4: DO(new, 4);
1928 case 8: DO(die, 8);
1929 case -8: DO(new, 8);
1930 case 12: DO(die, 12);
1931 case -12: DO(new, 12);
1932 case 16: DO(die, 16);
1933 case -16: DO(new, 16);
1934 case 32: DO(die, 32);
1935 case -32: DO(new, 32);
1936 default: DO_GENERIC; break;
1937 }
1938 } else {
1939 /* Unknown delta */
1940 DO_GENERIC;
njned619712003-10-01 16:45:04 +00001941
daywalker972a7592003-10-01 10:19:08 +00001942 /* now we know the temp that points to %ESP */
njned619712003-10-01 16:45:04 +00001943 t_ESP = u->val1;
njn9b007f62003-04-07 14:40:25 +00001944 }
1945 delta = 0;
1946
1947# undef DO
1948# undef DO_GENERIC
1949
njned619712003-10-01 16:45:04 +00001950 } else if (ADD == u->opcode && Literal == u->tag1 && t_ESP == u->val2) {
1951 delta += u->lit32;
1952
1953 } else if (SUB == u->opcode && Literal == u->tag1 && t_ESP == u->val2) {
1954 delta -= u->lit32;
njn9b007f62003-04-07 14:40:25 +00001955
1956 } else if (MOV == u->opcode && TempReg == u->tag1 && t_ESP == u->val1 &&
1957 TempReg == u->tag2) {
njned619712003-10-01 16:45:04 +00001958 // t_ESP is transferred
njn9b007f62003-04-07 14:40:25 +00001959 t_ESP = u->val2;
njned619712003-10-01 16:45:04 +00001960
1961 } else {
1962 // Stop tracking t_ESP if it's clobbered by this instruction.
1963 Int tempUse [VG_MAX_REGS_USED];
1964 Bool isWrites[VG_MAX_REGS_USED];
1965 Int j, n = VG_(get_reg_usage)(u, TempReg, tempUse, isWrites);
1966
1967 for (j = 0; j < n; j++) {
1968 if (tempUse[j] == t_ESP && isWrites[j])
1969 t_ESP = INVALID_TEMPREG;
1970 }
njn9b007f62003-04-07 14:40:25 +00001971 }
1972 VG_(copy_UInstr) ( cb, u );
1973 }
1974
1975 VG_(free_UCodeBlock)(cb_in);
1976 return cb;
1977}
sewardjde4a1d02002-03-22 01:27:54 +00001978
1979/*------------------------------------------------------------*/
1980/*--- The new register allocator. ---*/
1981/*------------------------------------------------------------*/
1982
1983typedef
1984 struct {
1985 /* Becomes live for the first time after this insn ... */
1986 Int live_after;
jsewardfa70a8e2004-07-01 11:38:36 +00001987 /* Becomes dead for the last time before this insn ... */
sewardjde4a1d02002-03-22 01:27:54 +00001988 Int dead_before;
1989 /* The "home" spill slot, if needed. Never changes. */
1990 Int spill_no;
1991 /* Where is it? VG_NOVALUE==in a spill slot; else in reg. */
1992 Int real_no;
1993 }
1994 TempInfo;
1995
1996
1997/* Take a ucode block and allocate its TempRegs to RealRegs, or put
1998 them in spill locations, and add spill code, if there are not
1999 enough real regs. The usual register allocation deal, in short.
2000
2001 Important redundancy of representation:
2002
2003 real_to_temp maps real reg ranks (RRRs) to TempReg nos, or
2004 to VG_NOVALUE if the real reg has no currently assigned TempReg.
2005
2006 The .real_no field of a TempInfo gives the current RRR for
2007 this TempReg, or VG_NOVALUE if the TempReg is currently
2008 in memory, in which case it is in the SpillNo denoted by
2009 spillno.
2010
2011 These pieces of information (a fwds-bwds mapping, really) must
2012 be kept consistent!
2013
2014 This allocator uses the so-called Second Chance Bin Packing
2015 algorithm, as described in "Quality and Speed in Linear-scan
2016 Register Allocation" (Traub, Holloway and Smith, ACM PLDI98,
2017 pp142-151). It is simple and fast and remarkably good at
2018 minimising the amount of spill code introduced.
2019*/
2020
2021static
2022UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
2023{
2024 TempInfo* temp_info;
njned619712003-10-01 16:45:04 +00002025 Int real_to_temp [VG_MAX_REALREGS];
sewardjde4a1d02002-03-22 01:27:54 +00002026 Bool is_spill_cand[VG_MAX_REALREGS];
2027 Int ss_busy_until_before[VG_MAX_SPILLSLOTS];
2028 Int i, j, k, m, r, tno, max_ss_no;
2029 Bool wr, defer, isRead, spill_reqd;
njned619712003-10-01 16:45:04 +00002030 UInt realUse [VG_MAX_REGS_USED];
2031 Int tempUse [VG_MAX_REGS_USED];
njnf4ce3d32003-02-10 10:17:26 +00002032 Bool isWrites[VG_MAX_REGS_USED];
sewardjde4a1d02002-03-22 01:27:54 +00002033 UCodeBlock* c2;
2034
2035 /* Used to denote ... well, "no value" in this fn. */
2036# define VG_NOTHING (-2)
2037
2038 /* Initialise the TempReg info. */
2039 if (c1->nextTemp > 0)
njn25e49d8e72002-09-23 09:36:25 +00002040 temp_info = VG_(arena_malloc)(VG_AR_JITTER,
2041 c1->nextTemp * sizeof(TempInfo) );
sewardjde4a1d02002-03-22 01:27:54 +00002042 else
2043 temp_info = NULL;
2044
2045 for (i = 0; i < c1->nextTemp; i++) {
2046 temp_info[i].live_after = VG_NOTHING;
2047 temp_info[i].dead_before = VG_NOTHING;
2048 temp_info[i].spill_no = VG_NOTHING;
2049 /* temp_info[i].real_no is not yet relevant. */
2050 }
2051
2052 spill_reqd = False;
2053
2054 /* Scan fwds to establish live ranges. */
2055
2056 for (i = 0; i < c1->used; i++) {
njn810086f2002-11-14 12:42:47 +00002057 k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
2058 &isWrites[0]);
njnf4ce3d32003-02-10 10:17:26 +00002059 vg_assert(k >= 0 && k <= VG_MAX_REGS_USED);
sewardjde4a1d02002-03-22 01:27:54 +00002060
2061 /* For each temp usage ... fwds in program order */
2062 for (j = 0; j < k; j++) {
njn810086f2002-11-14 12:42:47 +00002063 tno = tempUse[j];
2064 wr = isWrites[j];
sewardjde4a1d02002-03-22 01:27:54 +00002065 if (wr) {
2066 /* Writes hold a reg live until after this insn. */
2067 if (temp_info[tno].live_after == VG_NOTHING)
2068 temp_info[tno].live_after = i;
2069 if (temp_info[tno].dead_before < i + 1)
2070 temp_info[tno].dead_before = i + 1;
2071 } else {
2072 /* First use of a tmp should be a write. */
njnfa0ad422003-02-03 11:07:03 +00002073 if (temp_info[tno].live_after == VG_NOTHING) {
2074 VG_(printf)("At instr %d...\n", i);
2075 VG_(core_panic)("First use of tmp not a write,"
nethercote996901a2004-08-03 13:29:09 +00002076 " probably a tool instrumentation error");
njnfa0ad422003-02-03 11:07:03 +00002077 }
sewardjde4a1d02002-03-22 01:27:54 +00002078 /* Reads only hold it live until before this insn. */
2079 if (temp_info[tno].dead_before < i)
2080 temp_info[tno].dead_before = i;
2081 }
2082 }
2083 }
2084
2085# if 0
2086 /* Sanity check on live ranges. Expensive but correct. */
2087 for (i = 0; i < c1->nextTemp; i++) {
2088 vg_assert( (temp_info[i].live_after == VG_NOTHING
2089 && temp_info[i].dead_before == VG_NOTHING)
2090 || (temp_info[i].live_after != VG_NOTHING
2091 && temp_info[i].dead_before != VG_NOTHING) );
2092 }
2093# endif
2094
2095 /* Do a rank-based allocation of TempRegs to spill slot numbers.
2096 We put as few as possible values in spill slots, but
2097 nevertheless need to have an assignment to them just in case. */
2098
2099 max_ss_no = -1;
2100
2101 for (i = 0; i < VG_MAX_SPILLSLOTS; i++)
2102 ss_busy_until_before[i] = 0;
2103
2104 for (i = 0; i < c1->nextTemp; i++) {
2105
2106 /* True iff this temp is unused. */
2107 if (temp_info[i].live_after == VG_NOTHING)
2108 continue;
2109
2110 /* Find the lowest-numbered spill slot which is available at the
2111 start point of this interval, and assign the interval to
2112 it. */
2113 for (j = 0; j < VG_MAX_SPILLSLOTS; j++)
2114 if (ss_busy_until_before[j] <= temp_info[i].live_after)
2115 break;
2116 if (j == VG_MAX_SPILLSLOTS) {
2117 VG_(printf)("VG_MAX_SPILLSLOTS is too low; increase and recompile.\n");
njne427a662002-10-02 11:08:25 +00002118 VG_(core_panic)("register allocation failed -- out of spill slots");
sewardjde4a1d02002-03-22 01:27:54 +00002119 }
2120 ss_busy_until_before[j] = temp_info[i].dead_before;
2121 temp_info[i].spill_no = j;
2122 if (j > max_ss_no)
2123 max_ss_no = j;
2124 }
2125
nethercotebee3fd92004-08-02 15:17:43 +00002126 n_total_reg_rank += (max_ss_no+1);
sewardjde4a1d02002-03-22 01:27:54 +00002127
2128 /* Show live ranges and assigned spill slot nos. */
2129
njn25e49d8e72002-09-23 09:36:25 +00002130 if (dis) {
2131 VG_(printf)("Live range assignments:\n");
sewardjde4a1d02002-03-22 01:27:54 +00002132
2133 for (i = 0; i < c1->nextTemp; i++) {
2134 if (temp_info[i].live_after == VG_NOTHING)
2135 continue;
2136 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00002137 " LR %d is after %d to before %d\tspillno %d\n",
sewardjde4a1d02002-03-22 01:27:54 +00002138 i,
2139 temp_info[i].live_after,
2140 temp_info[i].dead_before,
2141 temp_info[i].spill_no
2142 );
2143 }
njn25e49d8e72002-09-23 09:36:25 +00002144 VG_(printf)("\n");
sewardjde4a1d02002-03-22 01:27:54 +00002145 }
2146
2147 /* Now that we've established a spill slot number for each used
2148 temporary, we can go ahead and do the core of the "Second-chance
2149 binpacking" allocation algorithm. */
2150
njn25e49d8e72002-09-23 09:36:25 +00002151 if (dis) VG_(printf)("Register allocated UCode:\n");
2152
2153
sewardjde4a1d02002-03-22 01:27:54 +00002154 /* Resulting code goes here. We generate it all in a forwards
2155 pass. */
njn4ba5a792002-09-30 10:23:54 +00002156 c2 = VG_(alloc_UCodeBlock)();
sewardj22854b92002-11-30 14:00:47 +00002157 c2->orig_eip = c1->orig_eip;
sewardjde4a1d02002-03-22 01:27:54 +00002158
2159 /* At the start, no TempRegs are assigned to any real register.
2160 Correspondingly, all temps claim to be currently resident in
2161 their spill slots, as computed by the previous two passes. */
2162 for (i = 0; i < VG_MAX_REALREGS; i++)
2163 real_to_temp[i] = VG_NOTHING;
2164 for (i = 0; i < c1->nextTemp; i++)
2165 temp_info[i].real_no = VG_NOTHING;
2166
sewardjde4a1d02002-03-22 01:27:54 +00002167 /* Process each insn in turn. */
2168 for (i = 0; i < c1->used; i++) {
2169
2170 if (c1->instrs[i].opcode == NOP) continue;
nethercotebee3fd92004-08-02 15:17:43 +00002171 n_uinstrs_prealloc++;
sewardjde4a1d02002-03-22 01:27:54 +00002172
2173# if 0
2174 /* Check map consistency. Expensive but correct. */
2175 for (r = 0; r < VG_MAX_REALREGS; r++) {
2176 if (real_to_temp[r] != VG_NOTHING) {
2177 tno = real_to_temp[r];
2178 vg_assert(tno >= 0 && tno < c1->nextTemp);
2179 vg_assert(temp_info[tno].real_no == r);
2180 }
2181 }
2182 for (tno = 0; tno < c1->nextTemp; tno++) {
2183 if (temp_info[tno].real_no != VG_NOTHING) {
2184 r = temp_info[tno].real_no;
2185 vg_assert(r >= 0 && r < VG_MAX_REALREGS);
2186 vg_assert(real_to_temp[r] == tno);
2187 }
2188 }
2189# endif
2190
njn25e49d8e72002-09-23 09:36:25 +00002191 if (dis)
njn4ba5a792002-09-30 10:23:54 +00002192 VG_(pp_UInstr)(i, &c1->instrs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002193
2194 /* First, free up enough real regs for this insn. This may
2195 generate spill stores since we may have to evict some TempRegs
2196 currently in real regs. Also generates spill loads. */
2197
njn810086f2002-11-14 12:42:47 +00002198 k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
2199 &isWrites[0]);
njnf4ce3d32003-02-10 10:17:26 +00002200 vg_assert(k >= 0 && k <= VG_MAX_REGS_USED);
sewardjde4a1d02002-03-22 01:27:54 +00002201
2202 /* For each ***different*** temp mentioned in the insn .... */
2203 for (j = 0; j < k; j++) {
2204
2205 /* First check if the temp is mentioned again later; if so,
2206 ignore this mention. We only want to process each temp
2207 used by the insn once, even if it is mentioned more than
2208 once. */
2209 defer = False;
njn810086f2002-11-14 12:42:47 +00002210 tno = tempUse[j];
sewardjde4a1d02002-03-22 01:27:54 +00002211 for (m = j+1; m < k; m++)
njn810086f2002-11-14 12:42:47 +00002212 if (tempUse[m] == tno)
sewardjde4a1d02002-03-22 01:27:54 +00002213 defer = True;
2214 if (defer)
2215 continue;
2216
njn810086f2002-11-14 12:42:47 +00002217 /* Now we're trying to find a register for tempUse[j].
sewardjde4a1d02002-03-22 01:27:54 +00002218 First of all, if it already has a register assigned, we
2219 don't need to do anything more. */
2220 if (temp_info[tno].real_no != VG_NOTHING)
2221 continue;
2222
2223 /* No luck. The next thing to do is see if there is a
2224 currently unassigned register available. If so, bag it. */
2225 for (r = 0; r < VG_MAX_REALREGS; r++) {
2226 if (real_to_temp[r] == VG_NOTHING)
2227 break;
2228 }
2229 if (r < VG_MAX_REALREGS) {
2230 real_to_temp[r] = tno;
2231 temp_info[tno].real_no = r;
2232 continue;
2233 }
2234
2235 /* Unfortunately, that didn't pan out either. So we'll have
2236 to eject some other unfortunate TempReg into a spill slot
2237 in order to free up a register. Of course, we need to be
2238 careful not to eject some other TempReg needed by this
2239 insn.
2240
2241 Select r in 0 .. VG_MAX_REALREGS-1 such that
2242 real_to_temp[r] is not mentioned in
njn810086f2002-11-14 12:42:47 +00002243 tempUse[0 .. k-1], since it would be just plain
sewardjde4a1d02002-03-22 01:27:54 +00002244 wrong to eject some other TempReg which we need to use in
2245 this insn.
2246
2247 It is here that it is important to make a good choice of
2248 register to spill. */
2249
2250 /* First, mark those regs which are not spill candidates. */
2251 for (r = 0; r < VG_MAX_REALREGS; r++) {
2252 is_spill_cand[r] = True;
2253 for (m = 0; m < k; m++) {
njn810086f2002-11-14 12:42:47 +00002254 if (real_to_temp[r] == tempUse[m]) {
sewardjde4a1d02002-03-22 01:27:54 +00002255 is_spill_cand[r] = False;
2256 break;
2257 }
2258 }
2259 }
2260
2261 /* We can choose any r satisfying is_spill_cand[r]. However,
2262 try to make a good choice. First, try and find r such
2263 that the associated TempReg is already dead. */
2264 for (r = 0; r < VG_MAX_REALREGS; r++) {
2265 if (is_spill_cand[r] &&
2266 temp_info[real_to_temp[r]].dead_before <= i)
2267 goto have_spill_cand;
2268 }
2269
2270 /* No spill cand is mapped to a dead TempReg. Now we really
2271 _do_ have to generate spill code. Choose r so that the
2272 next use of its associated TempReg is as far ahead as
2273 possible, in the hope that this will minimise the number of
2274 consequent reloads required. This is a bit expensive, but
2275 we don't have to do it very often. */
2276 {
2277 Int furthest_r = VG_MAX_REALREGS;
2278 Int furthest = 0;
2279 for (r = 0; r < VG_MAX_REALREGS; r++) {
2280 if (!is_spill_cand[r]) continue;
2281 for (m = i+1; m < c1->used; m++)
2282 if (uInstrMentionsTempReg(&c1->instrs[m],
2283 real_to_temp[r]))
2284 break;
2285 if (m > furthest) {
2286 furthest = m;
2287 furthest_r = r;
2288 }
2289 }
2290 r = furthest_r;
2291 goto have_spill_cand;
2292 }
2293
2294 have_spill_cand:
2295 if (r == VG_MAX_REALREGS)
njne427a662002-10-02 11:08:25 +00002296 VG_(core_panic)("new reg alloc: out of registers ?!");
sewardjde4a1d02002-03-22 01:27:54 +00002297
2298 /* Eject r. Important refinement: don't bother if the
2299 associated TempReg is now dead. */
2300 vg_assert(real_to_temp[r] != VG_NOTHING);
2301 vg_assert(real_to_temp[r] != tno);
2302 temp_info[real_to_temp[r]].real_no = VG_NOTHING;
2303 if (temp_info[real_to_temp[r]].dead_before > i) {
2304 uInstr2(c2, PUT, 4,
njn4ba5a792002-09-30 10:23:54 +00002305 RealReg, VG_(rank_to_realreg)(r),
sewardjde4a1d02002-03-22 01:27:54 +00002306 SpillNo, temp_info[real_to_temp[r]].spill_no);
nethercotebee3fd92004-08-02 15:17:43 +00002307 n_uinstrs_spill++;
sewardjde4a1d02002-03-22 01:27:54 +00002308 spill_reqd = True;
njn25e49d8e72002-09-23 09:36:25 +00002309 if (dis)
njn4ba5a792002-09-30 10:23:54 +00002310 VG_(pp_UInstr)(c2->used-1, &LAST_UINSTR(c2));
sewardjde4a1d02002-03-22 01:27:54 +00002311 }
2312
2313 /* Decide if tno is read. */
2314 isRead = False;
2315 for (m = 0; m < k; m++)
njn810086f2002-11-14 12:42:47 +00002316 if (tempUse[m] == tno && !isWrites[m])
sewardjde4a1d02002-03-22 01:27:54 +00002317 isRead = True;
2318
2319 /* If so, generate a spill load. */
2320 if (isRead) {
2321 uInstr2(c2, GET, 4,
2322 SpillNo, temp_info[tno].spill_no,
njn4ba5a792002-09-30 10:23:54 +00002323 RealReg, VG_(rank_to_realreg)(r) );
nethercotebee3fd92004-08-02 15:17:43 +00002324 n_uinstrs_spill++;
sewardjde4a1d02002-03-22 01:27:54 +00002325 spill_reqd = True;
njn25e49d8e72002-09-23 09:36:25 +00002326 if (dis)
njn4ba5a792002-09-30 10:23:54 +00002327 VG_(pp_UInstr)(c2->used-1, &LAST_UINSTR(c2));
sewardjde4a1d02002-03-22 01:27:54 +00002328 }
2329
2330 /* Update the forwards and backwards maps. */
2331 real_to_temp[r] = tno;
2332 temp_info[tno].real_no = r;
2333 }
2334
2335 /* By this point, all TempRegs mentioned by the insn have been
2336 bought into real regs. We now copy the insn to the output
2337 and use patchUInstr to convert its rTempRegs into
2338 realregs. */
2339 for (j = 0; j < k; j++)
njn810086f2002-11-14 12:42:47 +00002340 realUse[j] = VG_(rank_to_realreg)(temp_info[tempUse[j]].real_no);
njn4ba5a792002-09-30 10:23:54 +00002341 VG_(copy_UInstr)(c2, &c1->instrs[i]);
njn25e49d8e72002-09-23 09:36:25 +00002342 patchUInstr(&LAST_UINSTR(c2), &tempUse[0], &realUse[0], k);
sewardjde4a1d02002-03-22 01:27:54 +00002343
njn25e49d8e72002-09-23 09:36:25 +00002344 if (dis) {
njn4ba5a792002-09-30 10:23:54 +00002345 VG_(pp_UInstr)(c2->used-1, &LAST_UINSTR(c2));
sewardjde4a1d02002-03-22 01:27:54 +00002346 VG_(printf)("\n");
2347 }
2348 }
2349
2350 if (temp_info != NULL)
njn25e49d8e72002-09-23 09:36:25 +00002351 VG_(arena_free)(VG_AR_JITTER, temp_info);
sewardjde4a1d02002-03-22 01:27:54 +00002352
njn4ba5a792002-09-30 10:23:54 +00002353 VG_(free_UCodeBlock)(c1);
sewardjde4a1d02002-03-22 01:27:54 +00002354
2355 if (spill_reqd)
nethercotebee3fd92004-08-02 15:17:43 +00002356 n_translations_needing_spill++;
sewardjde4a1d02002-03-22 01:27:54 +00002357
2358 return c2;
2359
2360# undef VG_NOTHING
2361
2362}
sewardj7c4b6042003-06-14 15:47:15 +00002363
njn25e49d8e72002-09-23 09:36:25 +00002364/* Analysis records liveness of all general-use RealRegs in the UCode. */
2365static void vg_realreg_liveness_analysis ( UCodeBlock* cb )
2366{
2367 Int i, j, k;
2368 RRegSet rregs_live;
njnf4ce3d32003-02-10 10:17:26 +00002369 Int regUse[VG_MAX_REGS_USED];
2370 Bool isWrites[VG_MAX_REGS_USED];
njn25e49d8e72002-09-23 09:36:25 +00002371 UInstr* u;
sewardjde4a1d02002-03-22 01:27:54 +00002372
njn25e49d8e72002-09-23 09:36:25 +00002373 /* All regs are dead at the end of the block */
2374 rregs_live = ALL_RREGS_DEAD;
sewardjde4a1d02002-03-22 01:27:54 +00002375
sewardjde4a1d02002-03-22 01:27:54 +00002376 for (i = cb->used-1; i >= 0; i--) {
2377 u = &cb->instrs[i];
2378
njn25e49d8e72002-09-23 09:36:25 +00002379 u->regs_live_after = rregs_live;
sewardj97ced732002-03-25 00:07:36 +00002380
njn810086f2002-11-14 12:42:47 +00002381 k = VG_(get_reg_usage)(u, RealReg, &regUse[0], &isWrites[0]);
sewardj97ced732002-03-25 00:07:36 +00002382
njn25e49d8e72002-09-23 09:36:25 +00002383 /* For each reg usage ... bwds in program order. Variable is live
2384 before this UInstr if it is read by this UInstr.
njn810086f2002-11-14 12:42:47 +00002385 Note that regUse[j] holds the Intel reg number, so we must
njn25e49d8e72002-09-23 09:36:25 +00002386 convert it to our rank number. */
2387 for (j = k-1; j >= 0; j--) {
njn810086f2002-11-14 12:42:47 +00002388 SET_RREG_LIVENESS ( VG_(realreg_to_rank)(regUse[j]),
njn25e49d8e72002-09-23 09:36:25 +00002389 rregs_live,
njn810086f2002-11-14 12:42:47 +00002390 !isWrites[j] );
sewardjde4a1d02002-03-22 01:27:54 +00002391 }
2392 }
sewardjde4a1d02002-03-22 01:27:54 +00002393}
2394
sewardjde4a1d02002-03-22 01:27:54 +00002395/*------------------------------------------------------------*/
2396/*--- Main entry point for the JITter. ---*/
2397/*------------------------------------------------------------*/
2398
2399/* Translate the basic block beginning at orig_addr, placing the
2400 translation in a vg_malloc'd block, the address and size of which
2401 are returned in trans_addr and trans_size. Length of the original
2402 block is also returned in orig_size. If the latter three are NULL,
2403 this call is being done for debugging purposes, in which case (a)
2404 throw away the translation once it is made, and (b) produce a load
2405 of debugging output.
njn25e49d8e72002-09-23 09:36:25 +00002406
2407 'tst' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +00002408*/
njn72718642003-07-24 08:45:32 +00002409void VG_(translate) ( /*IN*/ ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +00002410 /*IN*/ Addr orig_addr,
2411 /*OUT*/ UInt* orig_size,
2412 /*OUT*/ Addr* trans_addr,
sewardj22854b92002-11-30 14:00:47 +00002413 /*OUT*/ UInt* trans_size,
2414 /*OUT*/ UShort jumps[VG_MAX_JUMPS])
sewardjde4a1d02002-03-22 01:27:54 +00002415{
fitzhardinge98abfc72003-12-16 02:05:15 +00002416 Int n_disassembled_bytes, final_code_size;
sewardjde4a1d02002-03-22 01:27:54 +00002417 Bool debugging_translation;
2418 UChar* final_code;
2419 UCodeBlock* cb;
sewardja60be0e2003-05-26 08:47:27 +00002420 Bool notrace_until_done;
sewardj1e86b8b2003-06-16 23:34:12 +00002421 UInt notrace_until_limit = 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00002422 Segment *seg;
2423 Addr redir;
sewardjde4a1d02002-03-22 01:27:54 +00002424
2425 VGP_PUSHCC(VgpTranslate);
2426 debugging_translation
2427 = orig_size == NULL || trans_addr == NULL || trans_size == NULL;
2428
sewardj25c7c3a2003-07-10 00:17:58 +00002429 /* Look in the code redirect table to see if we should
2430 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +00002431 redir = VG_(code_redirect)(orig_addr);
2432
2433 if (redir != orig_addr && VG_(clo_verbosity) >= 2)
2434 VG_(message)(Vg_UserMsg,
2435 "TRANSLATE: %p redirected to %p",
2436 orig_addr,
2437 redir );
2438 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +00002439
sewardja60be0e2003-05-26 08:47:27 +00002440 /* If codegen tracing, don't start tracing until
2441 notrace_until_limit blocks have gone by. This avoids printing
2442 huge amounts of useless junk when all we want to see is the last
2443 few blocks translated prior to a failure. Set
2444 notrace_until_limit to be the number of translations to be made
2445 before --trace-codegen= style printing takes effect. */
2446 notrace_until_done
fitzhardinge15117d22003-12-19 17:16:54 +00002447 = VG_(overall_in_count) >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +00002448
fitzhardinge98abfc72003-12-16 02:05:15 +00002449 seg = VG_(find_segment)(orig_addr);
2450
njn25e49d8e72002-09-23 09:36:25 +00002451 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +00002452 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +00002453
fitzhardinge98abfc72003-12-16 02:05:15 +00002454 if (seg == NULL ||
2455 !VG_(seg_contains)(seg, orig_addr, 1) ||
2456 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002457 /* Code address is bad - deliver a signal instead */
2458 vg_assert(!VG_(is_addressable)(orig_addr, 1));
2459
fitzhardinge98abfc72003-12-16 02:05:15 +00002460 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
2461 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
fitzhardingef1beb252004-03-16 09:49:08 +00002462 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00002463 } else
fitzhardingef1beb252004-03-16 09:49:08 +00002464 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +00002465
jsgf855d93d2003-10-13 22:26:55 +00002466 return;
fitzhardinge98abfc72003-12-16 02:05:15 +00002467 } else
2468 seg->flags |= SF_CODE; /* contains cached code */
jsgf855d93d2003-10-13 22:26:55 +00002469
njn4ba5a792002-09-30 10:23:54 +00002470 cb = VG_(alloc_UCodeBlock)();
sewardj22854b92002-11-30 14:00:47 +00002471 cb->orig_eip = orig_addr;
sewardjde4a1d02002-03-22 01:27:54 +00002472
njn25e49d8e72002-09-23 09:36:25 +00002473 /* If doing any code printing, print a basic block start marker */
sewardja60be0e2003-05-26 08:47:27 +00002474 if (VG_(clo_trace_codegen) && notrace_until_done) {
njn25e49d8e72002-09-23 09:36:25 +00002475 Char fnname[64] = "";
2476 VG_(get_fnname_if_entry)(orig_addr, fnname, 64);
2477 VG_(printf)(
njne0205ff2003-04-08 00:56:14 +00002478 "==== BB %d %s(%p) in %dB, out %dB, BBs exec'd %llu ====\n\n",
njn25e49d8e72002-09-23 09:36:25 +00002479 VG_(overall_in_count), fnname, orig_addr,
2480 VG_(overall_in_osize), VG_(overall_in_tsize),
2481 VG_(bbs_done));
2482 }
2483
2484 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardja60be0e2003-05-26 08:47:27 +00002485# define DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(n) \
2486 ( debugging_translation \
2487 || (notrace_until_done \
2488 && (VG_(clo_trace_codegen) & (1 << (n-1))) ))
njn25e49d8e72002-09-23 09:36:25 +00002489
sewardjde4a1d02002-03-22 01:27:54 +00002490 /* Disassemble this basic block into cb. */
njn25e49d8e72002-09-23 09:36:25 +00002491 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(1);
2492 VGP_PUSHCC(VgpToUCode);
sewardjde4a1d02002-03-22 01:27:54 +00002493 n_disassembled_bytes = VG_(disBB) ( cb, orig_addr );
njn25e49d8e72002-09-23 09:36:25 +00002494 VGP_POPCC(VgpToUCode);
2495
sewardjde4a1d02002-03-22 01:27:54 +00002496 /* Try and improve the code a bit. */
2497 if (VG_(clo_optimise)) {
njn25e49d8e72002-09-23 09:36:25 +00002498 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(2);
2499 VGP_PUSHCC(VgpImprove);
sewardjde4a1d02002-03-22 01:27:54 +00002500 vg_improve ( cb );
njn25e49d8e72002-09-23 09:36:25 +00002501 VGP_POPCC(VgpImprove);
sewardjde4a1d02002-03-22 01:27:54 +00002502 }
2503
njn25e49d8e72002-09-23 09:36:25 +00002504 /* Skin's instrumentation (Nb: must set VG_(print_codegen) in case
2505 SK_(instrument) looks at it. */
2506 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(3);
2507 VGP_PUSHCC(VgpInstrument);
2508 cb = SK_(instrument) ( cb, orig_addr );
2509 if (VG_(print_codegen))
njn4ba5a792002-09-30 10:23:54 +00002510 VG_(pp_UCodeBlock) ( cb, "Instrumented UCode:" );
njn25e49d8e72002-09-23 09:36:25 +00002511 VG_(saneUCodeBlock)( cb );
2512 VGP_POPCC(VgpInstrument);
njn4f9c9342002-04-29 16:03:24 +00002513
nethercote996901a2004-08-03 13:29:09 +00002514 /* Add %ESP-update hooks if the tool requires them */
njn9b007f62003-04-07 14:40:25 +00002515 /* Nb: We don't print out this phase, because it doesn't do much */
2516 if (VG_(need_to_handle_esp_assignment)()) {
2517 VGP_PUSHCC(VgpESPUpdate);
2518 cb = vg_ESP_update_pass ( cb );
2519 VGP_POPCC(VgpESPUpdate);
2520 }
2521
sewardjde4a1d02002-03-22 01:27:54 +00002522 /* Allocate registers. */
njn25e49d8e72002-09-23 09:36:25 +00002523 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(4);
2524 VGP_PUSHCC(VgpRegAlloc);
sewardjde4a1d02002-03-22 01:27:54 +00002525 cb = vg_do_register_allocation ( cb );
njn25e49d8e72002-09-23 09:36:25 +00002526 VGP_POPCC(VgpRegAlloc);
sewardjde4a1d02002-03-22 01:27:54 +00002527
njn25e49d8e72002-09-23 09:36:25 +00002528 /* Do post reg-alloc %e[acd]x liveness analysis (too boring to print
2529 * anything; results can be seen when emitting final code). */
2530 VGP_PUSHCC(VgpLiveness);
2531 vg_realreg_liveness_analysis ( cb );
2532 VGP_POPCC(VgpLiveness);
2533
2534 /* Emit final code */
2535 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(5);
2536
2537 VGP_PUSHCC(VgpFromUcode);
sewardj22854b92002-11-30 14:00:47 +00002538 final_code = VG_(emit_code)(cb, &final_code_size, jumps );
njn25e49d8e72002-09-23 09:36:25 +00002539 VGP_POPCC(VgpFromUcode);
njn4ba5a792002-09-30 10:23:54 +00002540 VG_(free_UCodeBlock)(cb);
sewardjde4a1d02002-03-22 01:27:54 +00002541
njn25e49d8e72002-09-23 09:36:25 +00002542#undef DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE
2543
sewardjde4a1d02002-03-22 01:27:54 +00002544 if (debugging_translation) {
2545 /* Only done for debugging -- throw away final result. */
njn25e49d8e72002-09-23 09:36:25 +00002546 VG_(arena_free)(VG_AR_JITTER, final_code);
sewardjde4a1d02002-03-22 01:27:54 +00002547 } else {
2548 /* Doing it for real -- return values to caller. */
sewardjde4a1d02002-03-22 01:27:54 +00002549 *orig_size = n_disassembled_bytes;
2550 *trans_addr = (Addr)final_code;
2551 *trans_size = final_code_size;
2552 }
njn25e49d8e72002-09-23 09:36:25 +00002553 VGP_POPCC(VgpTranslate);
sewardjde4a1d02002-03-22 01:27:54 +00002554}
2555
2556/*--------------------------------------------------------------------*/
2557/*--- end vg_translate.c ---*/
2558/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +00002559