blob: 54918b3ca996769a0104c6a3e13cd4678cf80aaa [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
nethercotef1e5e152004-09-01 23:58:16 +000032#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000033
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,
nethercote3a42fb82004-08-03 18:08:50 +000052 "reg-alloc: %d t-req-spill, %d+%d orig+spill uis,",
nethercotebee3fd92004-08-02 15:17:43 +000053 n_translations_needing_spill,
nethercote3a42fb82004-08-03 18:08:50 +000054 n_uinstrs_prealloc, n_uinstrs_spill );
55 VG_(message)(Vg_DebugMsg,
56 " %d total-reg-rank",
57 n_total_reg_rank );
nethercotebee3fd92004-08-02 15:17:43 +000058}
sewardje1042472002-09-30 12:33:11 +000059
sewardjde4a1d02002-03-22 01:27:54 +000060/*------------------------------------------------------------*/
61/*--- Basics ---*/
62/*------------------------------------------------------------*/
63
nethercote85cdd342004-08-01 22:36:40 +000064#define VG_IS_FLAG_SUBSET(set1,set2) \
65 (( ((FlagSet)set1) & ((FlagSet)set2) ) == ((FlagSet)set1) )
66
67#define VG_UNION_FLAG_SETS(set1,set2) \
68 ( ((FlagSet)set1) | ((FlagSet)set2) )
69
nethercotecaee10d2004-08-03 17:39:06 +000070// This one is local.
71static UCodeBlock* alloc_UCodeBlock ( Addr orig_eip )
sewardjde4a1d02002-03-22 01:27:54 +000072{
njn25e49d8e72002-09-23 09:36:25 +000073 UCodeBlock* cb = VG_(arena_malloc)(VG_AR_CORE, sizeof(UCodeBlock));
nethercotecaee10d2004-08-03 17:39:06 +000074 cb->orig_eip = orig_eip;
75 cb->used = 0;
76 cb->size = 0;
77 cb->instrs = NULL;
78 cb->nextTemp = 0;
sewardjde4a1d02002-03-22 01:27:54 +000079 return cb;
80}
81
nethercotecaee10d2004-08-03 17:39:06 +000082// This one is called by tools.
njn810086f2002-11-14 12:42:47 +000083UCodeBlock* VG_(setup_UCodeBlock) ( UCodeBlock* cb_in )
84{
nethercotecaee10d2004-08-03 17:39:06 +000085 UCodeBlock* cb = alloc_UCodeBlock( cb_in->orig_eip );
njn810086f2002-11-14 12:42:47 +000086 cb->nextTemp = cb_in->nextTemp;
njn810086f2002-11-14 12:42:47 +000087 return cb;
88}
sewardjde4a1d02002-03-22 01:27:54 +000089
njn4ba5a792002-09-30 10:23:54 +000090void VG_(free_UCodeBlock) ( UCodeBlock* cb )
sewardjde4a1d02002-03-22 01:27:54 +000091{
njn25e49d8e72002-09-23 09:36:25 +000092 if (cb->instrs) VG_(arena_free)(VG_AR_CORE, cb->instrs);
93 VG_(arena_free)(VG_AR_CORE, cb);
sewardjde4a1d02002-03-22 01:27:54 +000094}
95
96
97/* Ensure there's enough space in a block to add one uinstr. */
daywalkerb18d2532003-09-27 20:15:01 +000098static
sewardjde4a1d02002-03-22 01:27:54 +000099void ensureUInstr ( UCodeBlock* cb )
100{
101 if (cb->used == cb->size) {
102 if (cb->instrs == NULL) {
103 vg_assert(cb->size == 0);
104 vg_assert(cb->used == 0);
105 cb->size = 8;
njn25e49d8e72002-09-23 09:36:25 +0000106 cb->instrs = VG_(arena_malloc)(VG_AR_CORE, 8 * sizeof(UInstr));
sewardjde4a1d02002-03-22 01:27:54 +0000107 } else {
108 Int i;
njn25e49d8e72002-09-23 09:36:25 +0000109 UInstr* instrs2 = VG_(arena_malloc)(VG_AR_CORE,
sewardjde4a1d02002-03-22 01:27:54 +0000110 2 * sizeof(UInstr) * cb->size);
111 for (i = 0; i < cb->used; i++)
112 instrs2[i] = cb->instrs[i];
113 cb->size *= 2;
njn25e49d8e72002-09-23 09:36:25 +0000114 VG_(arena_free)(VG_AR_CORE, cb->instrs);
sewardjde4a1d02002-03-22 01:27:54 +0000115 cb->instrs = instrs2;
116 }
117 }
118
119 vg_assert(cb->used < cb->size);
120}
121
122
123__inline__
njn4ba5a792002-09-30 10:23:54 +0000124void VG_(new_NOP) ( UInstr* u )
sewardjde4a1d02002-03-22 01:27:54 +0000125{
126 u->val1 = u->val2 = u->val3 = 0;
127 u->tag1 = u->tag2 = u->tag3 = NoValue;
128 u->flags_r = u->flags_w = FlagsEmpty;
sewardj2e93c502002-04-12 11:12:52 +0000129 u->jmpkind = JmpBoring;
njn25e49d8e72002-09-23 09:36:25 +0000130 u->signed_widen = u->has_ret_val = False;
131 u->regs_live_after = ALL_RREGS_LIVE;
sewardjde4a1d02002-03-22 01:27:54 +0000132 u->lit32 = 0;
njn25e49d8e72002-09-23 09:36:25 +0000133 u->opcode = NOP;
sewardjde4a1d02002-03-22 01:27:54 +0000134 u->size = 0;
135 u->cond = 0;
136 u->extra4b = 0;
njn25e49d8e72002-09-23 09:36:25 +0000137 u->argc = u->regparms_n = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000138}
139
140
141/* Add an instruction to a ucode block, and return the index of the
142 instruction. */
143__inline__
njn4ba5a792002-09-30 10:23:54 +0000144void VG_(new_UInstr3) ( UCodeBlock* cb, Opcode opcode, Int sz,
sewardjde4a1d02002-03-22 01:27:54 +0000145 Tag tag1, UInt val1,
146 Tag tag2, UInt val2,
147 Tag tag3, UInt val3 )
148{
149 UInstr* ui;
150 ensureUInstr(cb);
151 ui = & cb->instrs[cb->used];
152 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000153 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000154 ui->val1 = val1;
155 ui->val2 = val2;
156 ui->val3 = val3;
157 ui->opcode = opcode;
158 ui->tag1 = tag1;
159 ui->tag2 = tag2;
160 ui->tag3 = tag3;
161 ui->size = sz;
162 if (tag1 == TempReg) vg_assert(val1 != INVALID_TEMPREG);
163 if (tag2 == TempReg) vg_assert(val2 != INVALID_TEMPREG);
164 if (tag3 == TempReg) vg_assert(val3 != INVALID_TEMPREG);
165}
166
167
168__inline__
njn4ba5a792002-09-30 10:23:54 +0000169void VG_(new_UInstr2) ( UCodeBlock* cb, Opcode opcode, Int sz,
sewardjde4a1d02002-03-22 01:27:54 +0000170 Tag tag1, UInt val1,
171 Tag tag2, UInt val2 )
172{
173 UInstr* ui;
174 ensureUInstr(cb);
175 ui = & cb->instrs[cb->used];
176 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000177 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000178 ui->val1 = val1;
179 ui->val2 = val2;
180 ui->opcode = opcode;
181 ui->tag1 = tag1;
182 ui->tag2 = tag2;
183 ui->size = sz;
184 if (tag1 == TempReg) vg_assert(val1 != INVALID_TEMPREG);
185 if (tag2 == TempReg) vg_assert(val2 != INVALID_TEMPREG);
186}
187
188
189__inline__
njn4ba5a792002-09-30 10:23:54 +0000190void VG_(new_UInstr1) ( UCodeBlock* cb, Opcode opcode, Int sz,
sewardjde4a1d02002-03-22 01:27:54 +0000191 Tag tag1, UInt val1 )
192{
193 UInstr* ui;
194 ensureUInstr(cb);
195 ui = & cb->instrs[cb->used];
196 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000197 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000198 ui->val1 = val1;
199 ui->opcode = opcode;
200 ui->tag1 = tag1;
201 ui->size = sz;
202 if (tag1 == TempReg) vg_assert(val1 != INVALID_TEMPREG);
203}
204
205
206__inline__
njn4ba5a792002-09-30 10:23:54 +0000207void VG_(new_UInstr0) ( UCodeBlock* cb, Opcode opcode, Int sz )
sewardjde4a1d02002-03-22 01:27:54 +0000208{
209 UInstr* ui;
210 ensureUInstr(cb);
211 ui = & cb->instrs[cb->used];
212 cb->used++;
njn4ba5a792002-09-30 10:23:54 +0000213 VG_(new_NOP)(ui);
sewardjde4a1d02002-03-22 01:27:54 +0000214 ui->opcode = opcode;
215 ui->size = sz;
216}
217
sewardjde4a1d02002-03-22 01:27:54 +0000218/* Copy an instruction into the given codeblock. */
njn4f9c9342002-04-29 16:03:24 +0000219__inline__
njn4ba5a792002-09-30 10:23:54 +0000220void VG_(copy_UInstr) ( UCodeBlock* cb, UInstr* instr )
sewardjde4a1d02002-03-22 01:27:54 +0000221{
222 ensureUInstr(cb);
223 cb->instrs[cb->used] = *instr;
224 cb->used++;
225}
226
sewardjde4a1d02002-03-22 01:27:54 +0000227/* Set the lit32 field of the most recent uinsn. */
njn4ba5a792002-09-30 10:23:54 +0000228void VG_(set_lit_field) ( UCodeBlock* cb, UInt lit32 )
sewardjde4a1d02002-03-22 01:27:54 +0000229{
230 LAST_UINSTR(cb).lit32 = lit32;
231}
232
233
njn25e49d8e72002-09-23 09:36:25 +0000234/* Set the C call info fields of the most recent uinsn. */
njn4ba5a792002-09-30 10:23:54 +0000235void VG_(set_ccall_fields) ( UCodeBlock* cb, Addr fn, UChar argc, UChar
236 regparms_n, Bool has_ret_val )
njn25e49d8e72002-09-23 09:36:25 +0000237{
238 vg_assert(argc < 4);
239 vg_assert(regparms_n <= argc);
240 LAST_UINSTR(cb).lit32 = fn;
241 LAST_UINSTR(cb).argc = argc;
242 LAST_UINSTR(cb).regparms_n = regparms_n;
243 LAST_UINSTR(cb).has_ret_val = has_ret_val;
244}
245
njn810086f2002-11-14 12:42:47 +0000246/* For the last uinsn inserted into cb, set the read, written and
247 undefined flags. Undefined flags are counted as written, but it
248 seems worthwhile to distinguish them.
249*/
250__inline__
251void VG_(set_flag_fields) ( UCodeBlock* cb,
252 FlagSet rr, FlagSet ww, FlagSet uu )
253{
254 FlagSet uw = VG_UNION_FLAG_SETS(ww,uu);
255
256 vg_assert(rr == (rr & FlagsALL));
257 vg_assert(uw == (uw & FlagsALL));
258 LAST_UINSTR(cb).flags_r = rr;
259 LAST_UINSTR(cb).flags_w = uw;
260}
261
nethercote911cc372004-04-18 12:23:02 +0000262void VG_(set_cond_field) ( UCodeBlock* cb, Condcode cond )
263{
264 LAST_UINSTR(cb).cond = cond;
265}
266
267void VG_(set_widen_fields) ( UCodeBlock* cb, UInt szs, Bool is_signed )
268{
269 LAST_UINSTR(cb).extra4b = szs;
270 LAST_UINSTR(cb).signed_widen = is_signed;
271}
272
njn810086f2002-11-14 12:42:47 +0000273
njn4ba5a792002-09-30 10:23:54 +0000274Bool VG_(any_flag_use) ( UInstr* u )
sewardjde4a1d02002-03-22 01:27:54 +0000275{
276 return (u->flags_r != FlagsEmpty
277 || u->flags_w != FlagsEmpty);
278}
279
njn25e49d8e72002-09-23 09:36:25 +0000280#if 1
281# define BEST_ALLOC_ORDER
282#endif
sewardjde4a1d02002-03-22 01:27:54 +0000283
284/* Convert a rank in the range 0 .. VG_MAX_REALREGS-1 into an Intel
285 register number. This effectively defines the order in which real
286 registers are allocated. %ebp is excluded since it is permanently
njn25e49d8e72002-09-23 09:36:25 +0000287 reserved for pointing at VG_(baseBlock).
sewardjde4a1d02002-03-22 01:27:54 +0000288
njn25e49d8e72002-09-23 09:36:25 +0000289 Important! This function must correspond with the value of
290 VG_MAX_REALREGS (actually, VG_MAX_REALREGS can be reduced without
291 a problem, except the generated code will obviously be worse).
sewardjde4a1d02002-03-22 01:27:54 +0000292*/
njn25e49d8e72002-09-23 09:36:25 +0000293__inline__
njn4ba5a792002-09-30 10:23:54 +0000294Int VG_(rank_to_realreg) ( Int rank )
sewardjde4a1d02002-03-22 01:27:54 +0000295{
296 switch (rank) {
njn25e49d8e72002-09-23 09:36:25 +0000297# ifdef BEST_ALLOC_ORDER
sewardjde4a1d02002-03-22 01:27:54 +0000298 /* Probably the best allocation ordering. */
299 case 0: return R_EAX;
300 case 1: return R_EBX;
301 case 2: return R_ECX;
302 case 3: return R_EDX;
303 case 4: return R_ESI;
njn25e49d8e72002-09-23 09:36:25 +0000304 case 5: return R_EDI;
sewardjde4a1d02002-03-22 01:27:54 +0000305# else
306 /* Contrary; probably the worst. Helpful for debugging, tho. */
njn25e49d8e72002-09-23 09:36:25 +0000307 case 5: return R_EAX;
308 case 4: return R_EBX;
309 case 3: return R_ECX;
310 case 2: return R_EDX;
311 case 1: return R_ESI;
312 case 0: return R_EDI;
sewardjde4a1d02002-03-22 01:27:54 +0000313# endif
njne427a662002-10-02 11:08:25 +0000314 default: VG_(core_panic)("VG_(rank_to_realreg)");
njn25e49d8e72002-09-23 09:36:25 +0000315 }
316}
317
318/* Convert an Intel register number into a rank in the range 0 ..
njn4ba5a792002-09-30 10:23:54 +0000319 VG_MAX_REALREGS-1. See related comments for rank_to_realreg()
njn25e49d8e72002-09-23 09:36:25 +0000320 above. */
321__inline__
njn4ba5a792002-09-30 10:23:54 +0000322Int VG_(realreg_to_rank) ( Int realReg )
njn25e49d8e72002-09-23 09:36:25 +0000323{
324 switch (realReg) {
325# ifdef BEST_ALLOC_ORDER
326 case R_EAX: return 0;
327 case R_EBX: return 1;
328 case R_ECX: return 2;
329 case R_EDX: return 3;
330 case R_ESI: return 4;
331 case R_EDI: return 5;
332# else
333 case R_EAX: return 5;
334 case R_EBX: return 4;
335 case R_ECX: return 3;
336 case R_EDX: return 2;
337 case R_ESI: return 1;
338 case R_EDI: return 0;
339# endif
njne427a662002-10-02 11:08:25 +0000340 default: VG_(core_panic)("VG_(realreg_to_rank)");
sewardjde4a1d02002-03-22 01:27:54 +0000341 }
342}
343
nethercote0973f702004-08-03 15:49:50 +0000344Int VG_(get_num_instrs) ( UCodeBlock* cb )
345{
346 return cb->used;
347}
348
349Int VG_(get_num_temps) ( UCodeBlock* cb )
350{
351 return cb->nextTemp;
352}
353
354UInstr* VG_(get_instr) ( UCodeBlock* cb, Int i )
355{
356 return & cb->instrs[i];
357}
358
359UInstr* VG_(get_last_instr) ( UCodeBlock* cb )
360{
361 return & cb->instrs[cb->used-1];
362}
363
sewardjde4a1d02002-03-22 01:27:54 +0000364
365/*------------------------------------------------------------*/
366/*--- Sanity checking uinstrs. ---*/
367/*------------------------------------------------------------*/
368
nethercote885dd912004-08-03 23:14:00 +0000369// Global variables that indicate where we are in the translation of a basic
370// block, and affect exactly how UInstrs are sanity-checked.
371static Bool beforeRA = True;
372static Bool beforeLiveness = True;
373
sewardjde4a1d02002-03-22 01:27:54 +0000374/* This seems as good a place as any to record some important stuff
375 about ucode semantics.
376
377 * TempRegs are 32 bits wide. LOADs of 8/16 bit values into a
378 TempReg are defined to zero-extend the loaded value to 32 bits.
379 This is needed to make the translation of movzbl et al work
380 properly.
381
382 * Similarly, GETs of a 8/16 bit ArchRegs are zero-extended.
383
384 * Arithmetic on TempRegs is at the specified size. For example,
385 SUBW t1, t2 has to result in a real 16 bit x86 subtraction
386 being emitted -- not a 32 bit one.
387
388 * On some insns we allow the cc bit to be set. If so, the
389 intention is that the simulated machine's %eflags register
390 is copied into that of the real machine before the insn,
391 and copied back again afterwards. This means that the
392 code generated for that insn must be very careful only to
393 update %eflags in the intended way. This is particularly
394 important for the routines referenced by CALL insns.
395*/
396
397/* Meaning of operand kinds is as follows:
398
399 ArchReg is a register of the simulated CPU, stored in memory,
400 in vg_m_state.m_eax .. m_edi. These values are stored
401 using the Intel register encoding.
402
403 RealReg is a register of the real CPU. There are VG_MAX_REALREGS
404 available for allocation. As with ArchRegs, these values
405 are stored using the Intel register encoding.
406
407 TempReg is a temporary register used to express the results of
408 disassembly. There is an unlimited supply of them --
409 register allocation and spilling eventually assigns them
410 to RealRegs.
411
412 SpillNo is a spill slot number. The number of required spill
413 slots is VG_MAX_PSEUDOS, in general. Only allowed
414 as the ArchReg operand of GET and PUT.
415
416 Lit16 is a signed 16-bit literal value.
417
418 Literal is a 32-bit literal value. Each uinstr can only hold
419 one of these.
420
421 The disassembled code is expressed purely in terms of ArchReg,
422 TempReg and Literal operands. Eventually, register allocation
423 removes all the TempRegs, giving a result using ArchRegs, RealRegs,
424 and Literals. New x86 code can easily be synthesised from this.
425 There are carefully designed restrictions on which insns can have
426 which operands, intended to make it possible to generate x86 code
427 from the result of register allocation on the ucode efficiently and
428 without need of any further RealRegs.
429
njn25e49d8e72002-09-23 09:36:25 +0000430 Restrictions for the individual UInstrs are clear from the checks below.
431 Abbreviations: A=ArchReg S=SpillNo T=TempReg L=Literal
432 Ls=Lit16 R=RealReg N=NoValue
sewardje1042472002-09-30 12:33:11 +0000433 As=ArchRegS
sewardjde4a1d02002-03-22 01:27:54 +0000434
sewardjde4a1d02002-03-22 01:27:54 +0000435 Before register allocation, S operands should not appear anywhere.
436 After register allocation, all T operands should have been
437 converted into Rs, and S operands are allowed in GET and PUT --
438 denoting spill saves/restores.
439
njn25e49d8e72002-09-23 09:36:25 +0000440 Before liveness analysis, save_e[acd]x fields should all be True.
441 Afterwards, they may be False.
442
sewardjde4a1d02002-03-22 01:27:54 +0000443 The size field should be 0 for insns for which it is meaningless,
444 ie those which do not directly move/operate on data.
445*/
nethercote885dd912004-08-03 23:14:00 +0000446static Bool is_sane_UInstr ( UInstr* u )
sewardjde4a1d02002-03-22 01:27:54 +0000447{
njn25e49d8e72002-09-23 09:36:25 +0000448# define LIT0 (u->lit32 == 0)
sewardjb31b06d2003-06-13 00:26:02 +0000449# define LIT8 (((u->lit32) & 0xFFFFFF00) == 0)
njn25e49d8e72002-09-23 09:36:25 +0000450# define LIT1 (!(LIT0))
451# define LITm (u->tag1 == Literal ? True : LIT0 )
sewardj77d30a22003-10-19 08:18:52 +0000452# define SZ16 (u->size == 16)
sewardj3d7c9c82003-03-26 21:08:13 +0000453# define SZ8 (u->size == 8)
njn25e49d8e72002-09-23 09:36:25 +0000454# define SZ4 (u->size == 4)
455# define SZ2 (u->size == 2)
456# define SZ1 (u->size == 1)
457# define SZ0 (u->size == 0)
458# define SZ42 (u->size == 4 || u->size == 2)
sewardjd7971012003-04-04 00:21:58 +0000459# define SZ48 (u->size == 4 || u->size == 8)
sewardjfebaa3b2003-05-25 01:07:34 +0000460# define SZ416 (u->size == 4 || u->size == 16)
nethercoteb1affa82004-01-19 19:14:18 +0000461# define SZ816 (u->size == 8 || u->size == 16)
462# define SZsse2 (u->size == 4 || u->size == 8 || u->size == 16 || u->size == 512)
jsewardfca60182004-01-04 23:30:55 +0000463# define SZsse3 (u->size == 4 || u->size == 8 || u->size == 16)
njn25e49d8e72002-09-23 09:36:25 +0000464# define SZi (u->size == 4 || u->size == 2 || u->size == 1)
465# define SZf ( u->size == 4 || u->size == 8 || u->size == 2 \
466 || u->size == 10 || u->size == 28 || u->size == 108)
467# define SZ4m ((u->tag1 == TempReg || u->tag1 == RealReg) \
nethercoteafa17ef2004-04-26 09:21:25 +0000468 ? (u->size == 4) : SZi)
njn25e49d8e72002-09-23 09:36:25 +0000469
470/* For these ones, two cases:
471 *
472 * 1. They are transliterations of the corresponding x86 instruction, in
473 * which case they should have its flags (except that redundant write
474 * flags can be annulled by the optimisation pass).
475 *
476 * 2. They are being used generally for other purposes, eg. helping with a
477 * 'rep'-prefixed instruction, in which case should have empty flags .
478 */
479# define emptyR (u->flags_r == FlagsEmpty)
480# define emptyW (u->flags_w == FlagsEmpty)
481# define CC0 (emptyR && emptyW)
482# define CCr (u->flags_r == FlagsALL && emptyW)
483# define CCw (emptyR && u->flags_w == FlagsALL)
484# define CCa (emptyR && (u->flags_w == FlagsOSZACP || emptyW))
485# define CCc (emptyR && (u->flags_w == FlagsOC || emptyW))
486# define CCe (emptyR && (u->flags_w == FlagsOSZAP || emptyW))
487# define CCb ((u->flags_r==FlagC || emptyR) && \
488 (u->flags_w==FlagsOSZACP || emptyW))
489# define CCd ((u->flags_r==FlagC || emptyR) && \
490 (u->flags_w==FlagsOC || emptyW))
sewardjc232b212002-12-10 22:24:03 +0000491# define CCf (CC0 || (emptyR && u->flags_w==FlagsZCP) \
492 || (u->flags_r==FlagsZCP && emptyW))
njn25e49d8e72002-09-23 09:36:25 +0000493# define CCg ((u->flags_r==FlagsOSZACP || emptyR) && emptyW)
494# define CCj (u->cond==CondAlways ? CC0 : CCg)
495
sewardjde4a1d02002-03-22 01:27:54 +0000496# define TR1 (beforeRA ? (u->tag1 == TempReg) : (u->tag1 == RealReg))
497# define TR2 (beforeRA ? (u->tag2 == TempReg) : (u->tag2 == RealReg))
498# define TR3 (beforeRA ? (u->tag3 == TempReg) : (u->tag3 == RealReg))
499# define A1 (u->tag1 == ArchReg)
500# define A2 (u->tag2 == ArchReg)
501# define AS1 ((u->tag1 == ArchReg) || ((!beforeRA && (u->tag1 == SpillNo))))
502# define AS2 ((u->tag2 == ArchReg) || ((!beforeRA && (u->tag2 == SpillNo))))
503# define AS3 ((u->tag3 == ArchReg) || ((!beforeRA && (u->tag3 == SpillNo))))
504# define L1 (u->tag1 == Literal && u->val1 == 0)
505# define L2 (u->tag2 == Literal && u->val2 == 0)
506# define Ls1 (u->tag1 == Lit16)
sewardjfebaa3b2003-05-25 01:07:34 +0000507# define Ls2 (u->tag2 == Lit16)
sewardjde4a1d02002-03-22 01:27:54 +0000508# define Ls3 (u->tag3 == Lit16)
njn25e49d8e72002-09-23 09:36:25 +0000509# define TRL1 (TR1 || L1)
510# define TRAL1 (TR1 || A1 || L1)
jsgf5efa4fd2003-10-14 21:49:11 +0000511# define TRA1 (TR1 || A1)
512# define TRA2 (TR2 || A2)
sewardjde4a1d02002-03-22 01:27:54 +0000513# define N1 (u->tag1 == NoValue)
514# define N2 (u->tag2 == NoValue)
515# define N3 (u->tag3 == NoValue)
sewardje1042472002-09-30 12:33:11 +0000516# define Se1 (u->tag1 == ArchRegS)
517# define Se2 (u->tag2 == ArchRegS)
sewardjde4a1d02002-03-22 01:27:54 +0000518
njn25e49d8e72002-09-23 09:36:25 +0000519# define COND0 (u->cond == 0)
520# define EXTRA4b0 (u->extra4b == 0)
nethercote4a12dbd2004-04-16 16:16:34 +0000521# define EXTRA4b12 (u->extra4b == 1 || u->extra4b == 2)
njn25e49d8e72002-09-23 09:36:25 +0000522# define SG_WD0 (u->signed_widen == 0)
523# define JMPKIND0 (u->jmpkind == 0)
524# define CCALL0 (u->argc==0 && u->regparms_n==0 && u->has_ret_val==0 && \
525 ( beforeLiveness \
526 ? u->regs_live_after == ALL_RREGS_LIVE \
527 : True ))
528
529# define XCONDi ( EXTRA4b0 && SG_WD0 && JMPKIND0 && CCALL0)
nethercote4a12dbd2004-04-16 16:16:34 +0000530# define XLEA2 (COND0 && SG_WD0 && JMPKIND0 && CCALL0)
531# define XWIDEN (COND0 && EXTRA4b12 && JMPKIND0 && CCALL0)
njn25e49d8e72002-09-23 09:36:25 +0000532# define XJMP ( SG_WD0 && CCALL0)
533# define XCCALL (COND0 && EXTRA4b0 && SG_WD0 && JMPKIND0 )
534# define XOTHER (COND0 && EXTRA4b0 && SG_WD0 && JMPKIND0 && CCALL0)
535
536 /* 0 or 1 Literal args per UInstr */
sewardjde4a1d02002-03-22 01:27:54 +0000537 Int n_lits = 0;
538 if (u->tag1 == Literal) n_lits++;
539 if (u->tag2 == Literal) n_lits++;
540 if (u->tag3 == Literal) n_lits++;
541 if (n_lits > 1)
542 return False;
543
njn25e49d8e72002-09-23 09:36:25 +0000544 /* Fields not checked: val1, val2, val3 */
545
sewardjde4a1d02002-03-22 01:27:54 +0000546 switch (u->opcode) {
njn25e49d8e72002-09-23 09:36:25 +0000547
548 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
sewardje1042472002-09-30 12:33:11 +0000549 case PUTSEG: return LIT0 && SZ2 && CC0 && TR1 && Se2 && N3 && XOTHER;
550 case GETSEG: return LIT0 && SZ2 && CC0 && Se1 && TR2 && N3 && XOTHER;
551 case USESEG: return LIT0 && SZ0 && CC0 && TR1 && TR2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000552 case NOP: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
sewardj7a5ebcf2002-11-13 22:42:13 +0000553 case LOCK: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000554 case GETF: return LIT0 && SZ42 && CCr && TR1 && N2 && N3 && XOTHER;
555 case PUTF: return LIT0 && SZ42 && CCw && TR1 && N2 && N3 && XOTHER;
556 case GET: return LIT0 && SZi && CC0 && AS1 && TR2 && N3 && XOTHER;
557 case PUT: return LIT0 && SZi && CC0 && TR1 && AS2 && N3 && XOTHER;
558 case LOAD:
559 case STORE: return LIT0 && SZi && CC0 && TR1 && TR2 && N3 && XOTHER;
560 case MOV: return LITm && SZ4m && CC0 && TRL1 && TR2 && N3 && XOTHER;
561 case CMOV: return LIT0 && SZ4 && CCg && TR1 && TR2 && N3 && XCONDi;
njn95bc3862003-09-30 13:22:30 +0000562 case WIDEN: return LIT0 && SZ42 && CC0 && TR1 && N2 && N3 && XWIDEN;
njn25e49d8e72002-09-23 09:36:25 +0000563 case JMP: return LITm && SZ0 && CCj && TRL1 && N2 && N3 && XJMP;
564 case CALLM: return LIT0 && SZ0 /*any*/ && Ls1 && N2 && N3 && XOTHER;
565 case CALLM_S:
566 case CALLM_E:return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
567 case PUSH:
568 case POP: return LIT0 && SZi && CC0 && TR1 && N2 && N3 && XOTHER;
569 case CLEAR: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
570 case AND:
571 case OR: return LIT0 && SZi && CCa && TR1 && TR2 && N3 && XOTHER;
jsgf5efa4fd2003-10-14 21:49:11 +0000572 case MUL: return LIT0 && SZ42 && CCa && TRA1 &&TRA2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000573 case ADD:
574 case XOR:
575 case SUB: return LITm && SZi && CCa &&TRAL1 && TR2 && N3 && XOTHER;
576 case SBB:
577 case ADC: return LITm && SZi && CCb &&TRAL1 && TR2 && N3 && XOTHER;
578 case SHL:
579 case SHR:
580 case SAR: return LITm && SZi && CCa && TRL1 && TR2 && N3 && XOTHER;
581 case ROL:
582 case ROR: return LITm && SZi && CCc && TRL1 && TR2 && N3 && XOTHER;
583 case RCL:
584 case RCR: return LITm && SZi && CCd && TRL1 && TR2 && N3 && XOTHER;
585 case NOT: return LIT0 && SZi && CC0 && TR1 && N2 && N3 && XOTHER;
586 case NEG: return LIT0 && SZi && CCa && TR1 && N2 && N3 && XOTHER;
587 case INC:
588 case DEC: return LIT0 && SZi && CCe && TR1 && N2 && N3 && XOTHER;
589 case CC2VAL: return LIT0 && SZ1 && CCg && TR1 && N2 && N3 && XCONDi;
590 case BSWAP: return LIT0 && SZ4 && CC0 && TR1 && N2 && N3 && XOTHER;
591 case JIFZ: return LIT1 && SZ4 && CC0 && TR1 && L2 && N3 && XOTHER;
592 case FPU_R:
593 case FPU_W: return LIT0 && SZf && CC0 && Ls1 && TR2 && N3 && XOTHER;
594 case FPU: return LIT0 && SZ0 && CCf && Ls1 && N2 && N3 && XOTHER;
595 case LEA1: return /*any*/ SZ4 && CC0 && TR1 && TR2 && N3 && XOTHER;
nethercote4a12dbd2004-04-16 16:16:34 +0000596 case LEA2: return /*any*/ SZ4 && CC0 && TR1 && TR2 && TR3 && XLEA2;
njn25e49d8e72002-09-23 09:36:25 +0000597 case INCEIP: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
598 case CCALL: return LIT1 && SZ0 && CC0 &&
599 (u->argc > 0 ? TR1 : N1) &&
600 (u->argc > 1 ? TR2 : N2) &&
601 (u->argc > 2 || u->has_ret_val ? TR3 : N3) &&
602 u->regparms_n <= u->argc && XCCALL;
thughes96b466a2004-03-15 16:43:58 +0000603 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
sewardj3d7c9c82003-03-26 21:08:13 +0000604 case MMX1:
thughes96b466a2004-03-15 16:43:58 +0000605 case MMX2: return LIT0 && SZ0 && CC0 && Ls1 && N2 && N3 && XOTHER;
606 case MMX3: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && N3 && XOTHER;
607 case MMX2_MemRd: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER;
608 case MMX2_MemWr: return LIT0 && SZ48 && CC0 && Ls1 && TR2 && N3 && XOTHER;
609 case MMX2a1_MemRd: return LIT0 && SZ8 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
610 case MMX2_ERegRd: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER;
611 case MMX2_ERegWr: return LIT0 && SZ4 && CC0 && Ls1 && TR2 && N3 && XOTHER;
sewardjfebaa3b2003-05-25 01:07:34 +0000612
613 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
jsewardfca60182004-01-04 23:30:55 +0000614 case SSE2a_MemWr: return LIT0 && SZsse2 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
615 case SSE2a_MemRd: return LIT0 && SZsse2 && CCa && Ls1 && Ls2 && TR3 && XOTHER;
nethercote1018bdd2004-02-11 23:33:29 +0000616 case SSE2a1_MemRd: return LIT0 && SZsse3 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
nethercoteb1affa82004-01-19 19:14:18 +0000617 case SSE2g_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
618 case SSE2g1_RegWr: return LIT8 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
619 case SSE2e1_RegRd: return LIT8 && SZ2 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
jsewardfca60182004-01-04 23:30:55 +0000620 case SSE3a_MemWr: return LIT0 && SZsse3 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
621 case SSE3a_MemRd: return LIT0 && SZsse3 && CCa && Ls1 && Ls2 && TR3 && XOTHER;
622 case SSE3e_RegRd: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
623 case SSE3e_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
nethercoteb1affa82004-01-19 19:14:18 +0000624 case SSE3a1_MemRd: return LIT8 && SZ816 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
jsewardfca60182004-01-04 23:30:55 +0000625 case SSE3g_RegWr: return LIT0 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
626 case SSE3g1_RegWr: return LIT8 && SZ4 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
627 case SSE3e1_RegRd: return LIT8 && SZ2 && CC0 && Ls1 && Ls2 && TR3 && XOTHER;
628 case SSE3: return LIT0 && SZ0 && CCa && Ls1 && Ls2 && N3 && XOTHER;
629 case SSE4: return LIT0 && SZ0 && CCa && Ls1 && Ls2 && N3 && XOTHER;
630 case SSE5: return LIT0 && SZ0 && CC0 && Ls1 && Ls2 && Ls3 && XOTHER;
sewardje3891fa2003-06-15 03:13:48 +0000631 case SSE3ag_MemRd_RegWr:
jsewardfca60182004-01-04 23:30:55 +0000632 return SZ48 && CC0 && TR1 && TR2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +0000633 default:
634 if (VG_(needs).extended_UCode)
njn4ba5a792002-09-30 10:23:54 +0000635 return SK_(sane_XUInstr)(beforeRA, beforeLiveness, u);
njn25e49d8e72002-09-23 09:36:25 +0000636 else {
637 VG_(printf)("unhandled opcode: %u. Perhaps "
638 "VG_(needs).extended_UCode should be set?",
639 u->opcode);
njne427a662002-10-02 11:08:25 +0000640 VG_(core_panic)("VG_(saneUInstr): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000641 }
sewardjde4a1d02002-03-22 01:27:54 +0000642 }
njn25e49d8e72002-09-23 09:36:25 +0000643# undef LIT0
644# undef LIT1
sewardjb31b06d2003-06-13 00:26:02 +0000645# undef LIT8
njn25e49d8e72002-09-23 09:36:25 +0000646# undef LITm
sewardj77d30a22003-10-19 08:18:52 +0000647# undef SZ16
sewardj3d7c9c82003-03-26 21:08:13 +0000648# undef SZ8
sewardjde4a1d02002-03-22 01:27:54 +0000649# undef SZ4
650# undef SZ2
651# undef SZ1
652# undef SZ0
njn25e49d8e72002-09-23 09:36:25 +0000653# undef SZ42
sewardjd7971012003-04-04 00:21:58 +0000654# undef SZ48
sewardjfebaa3b2003-05-25 01:07:34 +0000655# undef SZ416
nethercote4a12dbd2004-04-16 16:16:34 +0000656# undef SZ816
jsewardfca60182004-01-04 23:30:55 +0000657# undef SZsse2
658# undef SZsse3
njn25e49d8e72002-09-23 09:36:25 +0000659# undef SZi
660# undef SZf
661# undef SZ4m
662# undef emptyR
663# undef emptyW
664# undef CC0
665# undef CCr
666# undef CCw
667# undef CCa
668# undef CCb
669# undef CCc
670# undef CCd
671# undef CCe
672# undef CCf
673# undef CCg
674# undef CCj
sewardjde4a1d02002-03-22 01:27:54 +0000675# undef TR1
676# undef TR2
677# undef TR3
678# undef A1
679# undef A2
680# undef AS1
681# undef AS2
682# undef AS3
683# undef L1
sewardjde4a1d02002-03-22 01:27:54 +0000684# undef L2
njn25e49d8e72002-09-23 09:36:25 +0000685# undef Ls1
sewardjfebaa3b2003-05-25 01:07:34 +0000686# undef Ls2
sewardjde4a1d02002-03-22 01:27:54 +0000687# undef Ls3
njn25e49d8e72002-09-23 09:36:25 +0000688# undef TRL1
689# undef TRAL1
nethercote4a12dbd2004-04-16 16:16:34 +0000690# undef TRA1
691# undef TRA2
sewardjde4a1d02002-03-22 01:27:54 +0000692# undef N1
693# undef N2
694# undef N3
sewardje1042472002-09-30 12:33:11 +0000695# undef Se2
696# undef Se1
njn25e49d8e72002-09-23 09:36:25 +0000697# undef COND0
698# undef EXTRA4b0
nethercote4a12dbd2004-04-16 16:16:34 +0000699# undef EXTRA4b12
njn25e49d8e72002-09-23 09:36:25 +0000700# undef SG_WD0
701# undef JMPKIND0
702# undef CCALL0
nethercote4a12dbd2004-04-16 16:16:34 +0000703# undef XCONDi
704# undef XLEA2
njn25e49d8e72002-09-23 09:36:25 +0000705# undef XWIDEN
706# undef XJMP
707# undef XCCALL
708# undef XOTHER
sewardjde4a1d02002-03-22 01:27:54 +0000709}
710
nethercote885dd912004-08-03 23:14:00 +0000711void VG_(sanity_check_UInstr)( UInt n, UInstr* u )
712{
713 Bool sane = is_sane_UInstr(u);
714 if (!sane) {
715 VG_(printf)("\nInsane instruction:\n");
716 VG_(pp_UInstr)(n, u);
717 VG_(up_UInstr)(n, u);
718 vg_assert(sane);
719 }
720}
721
722static void sanity_check_UCodeBlock ( UCodeBlock* cb )
njn25e49d8e72002-09-23 09:36:25 +0000723{
724 Int i;
725
726 for (i = 0; i < cb->used; i++) {
nethercote885dd912004-08-03 23:14:00 +0000727 Bool sane = is_sane_UInstr(&cb->instrs[i]);
njn25e49d8e72002-09-23 09:36:25 +0000728 if (!sane) {
729 VG_(printf)("Instruction failed sanity check:\n");
njn4ba5a792002-09-30 10:23:54 +0000730 VG_(up_UInstr)(i, &cb->instrs[i]);
njn25e49d8e72002-09-23 09:36:25 +0000731 }
732 vg_assert(sane);
733 }
734}
sewardjde4a1d02002-03-22 01:27:54 +0000735
736/* Sanity checks to do with CALLMs in UCodeBlocks. */
nethercote885dd912004-08-03 23:14:00 +0000737static Bool is_sane_UCodeBlockCalls ( UCodeBlock* cb )
sewardjde4a1d02002-03-22 01:27:54 +0000738{
739 Int callm = 0;
740 Int callm_s = 0;
741 Int callm_e = 0;
742 Int callm_ptr, calls_ptr;
743 Int i, j, t;
744 Bool incall = False;
745
746 /* Ensure the number of CALLM, CALLM_S and CALLM_E are the same. */
747
748 for (i = 0; i < cb->used; i++) {
749 switch (cb->instrs[i].opcode) {
750 case CALLM:
751 if (!incall) return False;
752 callm++;
753 break;
754 case CALLM_S:
755 if (incall) return False;
756 incall = True;
757 callm_s++;
758 break;
759 case CALLM_E:
760 if (!incall) return False;
761 incall = False;
762 callm_e++;
763 break;
764 case PUSH: case POP: case CLEAR:
765 if (!incall) return False;
766 break;
767 default:
768 break;
769 }
770 }
771 if (incall) return False;
772 if (callm != callm_s || callm != callm_e) return False;
773
774 /* Check the sections between CALLM_S and CALLM's. Ensure that no
775 PUSH uinsn pushes any TempReg that any other PUSH in the same
776 section pushes. Ie, check that the TempReg args to PUSHes in
777 the section are unique. If not, the instrumenter generates
778 incorrect code for CALLM insns. */
779
780 callm_ptr = 0;
781
782 find_next_CALLM:
783 /* Search for the next interval, making calls_ptr .. callm_ptr
784 bracket it. */
785 while (callm_ptr < cb->used
786 && cb->instrs[callm_ptr].opcode != CALLM)
787 callm_ptr++;
788 if (callm_ptr == cb->used)
789 return True;
790 vg_assert(cb->instrs[callm_ptr].opcode == CALLM);
791
792 calls_ptr = callm_ptr - 1;
793 while (cb->instrs[calls_ptr].opcode != CALLM_S)
794 calls_ptr--;
795 vg_assert(cb->instrs[calls_ptr].opcode == CALLM_S);
796 vg_assert(calls_ptr >= 0);
797
798 /* VG_(printf)("interval from %d to %d\n", calls_ptr, callm_ptr ); */
799
800 /* For each PUSH insn in the interval ... */
801 for (i = calls_ptr + 1; i < callm_ptr; i++) {
802 if (cb->instrs[i].opcode != PUSH) continue;
803 t = cb->instrs[i].val1;
804 /* Ensure no later PUSH insns up to callm_ptr push the same
805 TempReg. Return False if any such are found. */
806 for (j = i+1; j < callm_ptr; j++) {
807 if (cb->instrs[j].opcode == PUSH &&
808 cb->instrs[j].val1 == t)
809 return False;
810 }
811 }
812
813 /* This interval is clean. Keep going ... */
814 callm_ptr++;
815 goto find_next_CALLM;
816}
817
nethercote885dd912004-08-03 23:14:00 +0000818static void sanity_check_UCodeBlockCalls( UCodeBlock* cb )
819{
820 if ( ! is_sane_UCodeBlockCalls( cb ) ) {
821 VG_(pp_UCodeBlock)(cb, "block failing calls sanity check");
822 VG_(core_panic)("bad block");
823 }
824}
sewardjde4a1d02002-03-22 01:27:54 +0000825
826/*------------------------------------------------------------*/
827/*--- Printing uinstrs. ---*/
828/*------------------------------------------------------------*/
829
njn25e49d8e72002-09-23 09:36:25 +0000830/* Global that dictates whether to print generated code at all stages */
831Bool VG_(print_codegen);
832
njn563f96f2003-02-03 11:17:46 +0000833Char* VG_(name_UCondcode) ( Condcode cond )
sewardjde4a1d02002-03-22 01:27:54 +0000834{
835 switch (cond) {
836 case CondO: return "o";
837 case CondNO: return "no";
838 case CondB: return "b";
839 case CondNB: return "nb";
840 case CondZ: return "z";
841 case CondNZ: return "nz";
842 case CondBE: return "be";
843 case CondNBE: return "nbe";
844 case CondS: return "s";
sewardje1042472002-09-30 12:33:11 +0000845 case CondNS: return "ns";
sewardjde4a1d02002-03-22 01:27:54 +0000846 case CondP: return "p";
847 case CondNP: return "np";
848 case CondL: return "l";
849 case CondNL: return "nl";
850 case CondLE: return "le";
851 case CondNLE: return "nle";
852 case CondAlways: return "MP"; /* hack! */
njn563f96f2003-02-03 11:17:46 +0000853 default: VG_(core_panic)("name_UCondcode");
sewardjde4a1d02002-03-22 01:27:54 +0000854 }
855}
856
857
858static void vg_ppFlagSet ( Char* prefix, FlagSet set )
859{
860 VG_(printf)("%s", prefix);
861 if (set & FlagD) VG_(printf)("D");
862 if (set & FlagO) VG_(printf)("O");
863 if (set & FlagS) VG_(printf)("S");
864 if (set & FlagZ) VG_(printf)("Z");
865 if (set & FlagA) VG_(printf)("A");
866 if (set & FlagC) VG_(printf)("C");
867 if (set & FlagP) VG_(printf)("P");
868}
869
870
871static void ppTempReg ( Int tt )
872{
873 if ((tt & 1) == 0)
874 VG_(printf)("t%d", tt);
875 else
876 VG_(printf)("q%d", tt-1);
877}
878
879
njn4ba5a792002-09-30 10:23:54 +0000880void VG_(pp_UOperand) ( UInstr* u, Int operandNo, Int sz, Bool parens )
sewardjde4a1d02002-03-22 01:27:54 +0000881{
882 UInt tag, val;
883 switch (operandNo) {
884 case 1: tag = u->tag1; val = u->val1; break;
885 case 2: tag = u->tag2; val = u->val2; break;
886 case 3: tag = u->tag3; val = u->val3; break;
njne427a662002-10-02 11:08:25 +0000887 default: VG_(core_panic)("VG_(pp_UOperand)(1)");
sewardjde4a1d02002-03-22 01:27:54 +0000888 }
889 if (tag == Literal) val = u->lit32;
890
891 if (parens) VG_(printf)("(");
892 switch (tag) {
sewardje1042472002-09-30 12:33:11 +0000893 case TempReg: ppTempReg(val); break;
894 case RealReg: VG_(printf)("%s",nameIReg(sz==0 ? 4 : sz,val)); break;
895 case Literal: VG_(printf)("$0x%x", val); break;
896 case Lit16: VG_(printf)("$0x%x", val); break;
897 case NoValue: VG_(printf)("NoValue"); break;
898 case ArchReg: VG_(printf)("%S",nameIReg(sz,val)); break;
899 case ArchRegS: VG_(printf)("%S",nameSReg(val)); break;
900 case SpillNo: VG_(printf)("spill%d", val); break;
njne427a662002-10-02 11:08:25 +0000901 default: VG_(core_panic)("VG_(ppUOperand)(2)");
sewardjde4a1d02002-03-22 01:27:54 +0000902 }
903 if (parens) VG_(printf)(")");
904}
905
906
njn4ba5a792002-09-30 10:23:54 +0000907Char* VG_(name_UOpcode) ( Bool upper, Opcode opc )
sewardjde4a1d02002-03-22 01:27:54 +0000908{
909 switch (opc) {
910 case ADD: return (upper ? "ADD" : "add");
911 case ADC: return (upper ? "ADC" : "adc");
912 case AND: return (upper ? "AND" : "and");
913 case OR: return (upper ? "OR" : "or");
914 case XOR: return (upper ? "XOR" : "xor");
915 case SUB: return (upper ? "SUB" : "sub");
916 case SBB: return (upper ? "SBB" : "sbb");
917 case SHL: return (upper ? "SHL" : "shl");
918 case SHR: return (upper ? "SHR" : "shr");
919 case SAR: return (upper ? "SAR" : "sar");
920 case ROL: return (upper ? "ROL" : "rol");
921 case ROR: return (upper ? "ROR" : "ror");
922 case RCL: return (upper ? "RCL" : "rcl");
923 case RCR: return (upper ? "RCR" : "rcr");
jsgf5efa4fd2003-10-14 21:49:11 +0000924 case MUL: return (upper ? "MUL" : "mul");
sewardjde4a1d02002-03-22 01:27:54 +0000925 case NOT: return (upper ? "NOT" : "not");
926 case NEG: return (upper ? "NEG" : "neg");
927 case INC: return (upper ? "INC" : "inc");
928 case DEC: return (upper ? "DEC" : "dec");
929 case BSWAP: return (upper ? "BSWAP" : "bswap");
930 default: break;
931 }
njne427a662002-10-02 11:08:25 +0000932 if (!upper) VG_(core_panic)("vg_name_UOpcode: invalid !upper");
sewardjde4a1d02002-03-22 01:27:54 +0000933 switch (opc) {
sewardjde4a1d02002-03-22 01:27:54 +0000934 case CALLM_S: return "CALLM_S";
935 case CALLM_E: return "CALLM_E";
936 case INCEIP: return "INCEIP";
937 case LEA1: return "LEA1";
938 case LEA2: return "LEA2";
939 case NOP: return "NOP";
sewardj7a5ebcf2002-11-13 22:42:13 +0000940 case LOCK: return "LOCK";
sewardjde4a1d02002-03-22 01:27:54 +0000941 case GET: return "GET";
942 case PUT: return "PUT";
943 case GETF: return "GETF";
944 case PUTF: return "PUTF";
sewardje1042472002-09-30 12:33:11 +0000945 case GETSEG: return "GETSEG";
946 case PUTSEG: return "PUTSEG";
947 case USESEG: return "USESEG";
sewardjde4a1d02002-03-22 01:27:54 +0000948 case LOAD: return "LD" ;
949 case STORE: return "ST" ;
950 case MOV: return "MOV";
951 case CMOV: return "CMOV";
952 case WIDEN: return "WIDEN";
953 case JMP: return "J" ;
954 case JIFZ: return "JIFZ" ;
955 case CALLM: return "CALLM";
njn25e49d8e72002-09-23 09:36:25 +0000956 case CCALL: return "CCALL";
sewardjde4a1d02002-03-22 01:27:54 +0000957 case PUSH: return "PUSH" ;
958 case POP: return "POP" ;
959 case CLEAR: return "CLEAR";
960 case CC2VAL: return "CC2VAL";
961 case FPU_R: return "FPU_R";
962 case FPU_W: return "FPU_W";
963 case FPU: return "FPU" ;
sewardj3d7c9c82003-03-26 21:08:13 +0000964 case MMX1: return "MMX1" ;
965 case MMX2: return "MMX2" ;
sewardjca860012003-03-27 23:52:58 +0000966 case MMX3: return "MMX3" ;
sewardj3d7c9c82003-03-26 21:08:13 +0000967 case MMX2_MemRd: return "MMX2_MRd" ;
968 case MMX2_MemWr: return "MMX2_MWr" ;
thughes96b466a2004-03-15 16:43:58 +0000969 case MMX2a1_MemRd: return "MMX2a1_MRd" ;
sewardj4fbe6e92003-06-15 21:54:34 +0000970 case MMX2_ERegRd: return "MMX2_eRRd" ;
971 case MMX2_ERegWr: return "MMX2_eRWr" ;
sewardjfebaa3b2003-05-25 01:07:34 +0000972 case SSE2a_MemWr: return "SSE2a_MWr";
973 case SSE2a_MemRd: return "SSE2a_MRd";
nethercoteb1affa82004-01-19 19:14:18 +0000974 case SSE2g_RegWr: return "SSE2g_RWr";
sewardj9dd209f2003-06-18 23:30:52 +0000975 case SSE2a1_MemRd: return "SSE2a1_MRd";
nethercoteb1affa82004-01-19 19:14:18 +0000976 case SSE2g1_RegWr: return "SSE2g1_RWr";
977 case SSE2e1_RegRd: return "SSE2e1_RRd";
sewardj4fbe6e92003-06-15 21:54:34 +0000978 case SSE3e_RegRd: return "SSE3e_RRd";
sewardjabf8bf82003-06-15 22:28:05 +0000979 case SSE3e_RegWr: return "SSE3e_RWr";
sewardj02af6bc2003-06-12 00:56:06 +0000980 case SSE3g_RegWr: return "SSE3g_RWr";
sewardj77d30a22003-10-19 08:18:52 +0000981 case SSE3a1_MemRd: return "SSE3a1_MRd";
sewardjb31b06d2003-06-13 00:26:02 +0000982 case SSE3g1_RegWr: return "SSE3g1_RWr";
sewardj4fbe6e92003-06-15 21:54:34 +0000983 case SSE3e1_RegRd: return "SSE3e1_RRd";
sewardja60be0e2003-05-26 08:47:27 +0000984 case SSE3: return "SSE3";
sewardjfebaa3b2003-05-25 01:07:34 +0000985 case SSE4: return "SSE4";
sewardja453fb02003-06-14 13:22:36 +0000986 case SSE5: return "SSE5";
sewardjfebaa3b2003-05-25 01:07:34 +0000987 case SSE3a_MemWr: return "SSE3a_MWr";
988 case SSE3a_MemRd: return "SSE3a_MRd";
sewardje3891fa2003-06-15 03:13:48 +0000989 case SSE3ag_MemRd_RegWr: return "SSE3ag_MemRd_RegWr";
njn25e49d8e72002-09-23 09:36:25 +0000990 default:
991 if (VG_(needs).extended_UCode)
njn4ba5a792002-09-30 10:23:54 +0000992 return SK_(name_XUOpcode)(opc);
njn25e49d8e72002-09-23 09:36:25 +0000993 else {
994 VG_(printf)("unhandled opcode: %u. Perhaps "
995 "VG_(needs).extended_UCode should be set?",
996 opc);
njne427a662002-10-02 11:08:25 +0000997 VG_(core_panic)("name_UOpcode: unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000998 }
sewardjde4a1d02002-03-22 01:27:54 +0000999 }
1000}
1001
sewardja38e0922002-10-01 00:50:47 +00001002static
njn4ba5a792002-09-30 10:23:54 +00001003void pp_realregs_liveness ( UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +00001004{
1005# define PRINT_RREG_LIVENESS(realReg,s) \
njn4ba5a792002-09-30 10:23:54 +00001006 VG_(printf)( IS_RREG_LIVE(VG_(realreg_to_rank)(realReg), \
njn25e49d8e72002-09-23 09:36:25 +00001007 u->regs_live_after) \
1008 ? s : "-");
sewardjde4a1d02002-03-22 01:27:54 +00001009
njn25e49d8e72002-09-23 09:36:25 +00001010 VG_(printf)("[");
1011 PRINT_RREG_LIVENESS(R_EAX, "a");
1012 PRINT_RREG_LIVENESS(R_EBX, "b");
1013 PRINT_RREG_LIVENESS(R_ECX, "c");
1014 PRINT_RREG_LIVENESS(R_EDX, "d");
1015 PRINT_RREG_LIVENESS(R_ESI, "S");
1016 PRINT_RREG_LIVENESS(R_EDI, "D");
1017 VG_(printf)("]");
1018
1019# undef PRINT_RREG_LIVENESS
1020}
1021
1022/* Ugly-print UInstr :) */
njn4ba5a792002-09-30 10:23:54 +00001023void VG_(up_UInstr) ( Int i, UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +00001024{
njn4ba5a792002-09-30 10:23:54 +00001025 VG_(pp_UInstr_regs)(i, u);
njn25e49d8e72002-09-23 09:36:25 +00001026
1027 VG_(printf)("opcode: %d\n", u->opcode);
sewardjc1b86882002-10-06 21:43:50 +00001028 VG_(printf)("lit32: 0x%x\n", u->lit32);
njn25e49d8e72002-09-23 09:36:25 +00001029 VG_(printf)("size: %d\n", u->size);
1030 VG_(printf)("val1,val2,val3: %d, %d, %d\n", u->val1, u->val2, u->val3);
1031 VG_(printf)("tag1,tag2,tag3: %d, %d, %d\n", u->tag1, u->tag2, u->tag3);
sewardjc1b86882002-10-06 21:43:50 +00001032 VG_(printf)("flags_r: 0x%x\n", u->flags_r);
1033 VG_(printf)("flags_w: 0x%x\n", u->flags_w);
1034 VG_(printf)("extra4b: 0x%x\n", u->extra4b);
1035 VG_(printf)("cond: 0x%x\n", u->cond);
njn25e49d8e72002-09-23 09:36:25 +00001036 VG_(printf)("signed_widen: %d\n", u->signed_widen);
1037 VG_(printf)("jmpkind: %d\n", u->jmpkind);
1038 VG_(printf)("argc,regparms_n: %d, %d\n", u->argc, u->regparms_n);
1039 VG_(printf)("has_ret_val: %d\n", u->has_ret_val);
1040 VG_(printf)("regs_live_after: ");
njn4ba5a792002-09-30 10:23:54 +00001041 pp_realregs_liveness(u);
njn25e49d8e72002-09-23 09:36:25 +00001042 VG_(printf)("\n");
1043}
1044
sewardja38e0922002-10-01 00:50:47 +00001045static
njn4ba5a792002-09-30 10:23:54 +00001046void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
sewardjde4a1d02002-03-22 01:27:54 +00001047{
1048 VG_(printf)("\t%4d: %s", instrNo,
njn4ba5a792002-09-30 10:23:54 +00001049 VG_(name_UOpcode)(True, u->opcode));
nethercotee00f1ff2004-04-16 11:33:53 +00001050 // For JMP, the condition goes before the size
1051 if (u->opcode == JMP)
njn563f96f2003-02-03 11:17:46 +00001052 VG_(printf)("%s", VG_(name_UCondcode)(u->cond));
sewardjde4a1d02002-03-22 01:27:54 +00001053
1054 switch (u->size) {
1055 case 0: VG_(printf)("o"); break;
1056 case 1: VG_(printf)("B"); break;
1057 case 2: VG_(printf)("W"); break;
1058 case 4: VG_(printf)("L"); break;
1059 case 8: VG_(printf)("Q"); break;
sewardjfebaa3b2003-05-25 01:07:34 +00001060 case 16: VG_(printf)("QQ"); break;
sewardjde4a1d02002-03-22 01:27:54 +00001061 default: VG_(printf)("%d", (Int)u->size); break;
1062 }
1063
nethercotee00f1ff2004-04-16 11:33:53 +00001064 // For CC2VAL and CMOV, the condition goes after the size
1065 if (u->opcode == CC2VAL || u->opcode == CMOV)
1066 VG_(printf)("%s", VG_(name_UCondcode)(u->cond));
1067
nethercotebbcfb582004-04-16 15:39:22 +00001068 // Append extra bits
1069 switch (u->opcode) {
1070 case JMP:
nethercotee00f1ff2004-04-16 11:33:53 +00001071 switch (u->jmpkind) {
1072 case JmpCall: VG_(printf)("-c"); break;
1073 case JmpRet: VG_(printf)("-r"); break;
1074 case JmpSyscall: VG_(printf)("-sys"); break;
1075 case JmpClientReq: VG_(printf)("-cli"); break;
1076 case JmpYield: VG_(printf)("-yld"); break;
1077 default: break;
1078 }
nethercotebbcfb582004-04-16 15:39:22 +00001079 break;
1080
1081 case WIDEN:
1082 VG_(printf)("_%c%c", VG_(toupper)(nameISize(u->extra4b)),
1083 u->signed_widen?'s':'z');
1084 }
sewardjfebaa3b2003-05-25 01:07:34 +00001085 VG_(printf)(" \t");
1086
sewardjde4a1d02002-03-22 01:27:54 +00001087 switch (u->opcode) {
1088
sewardjde4a1d02002-03-22 01:27:54 +00001089 case CALLM_S: case CALLM_E:
1090 break;
1091
1092 case INCEIP:
sewardjfebaa3b2003-05-25 01:07:34 +00001093 VG_(printf)("$%d", u->val1);
sewardjde4a1d02002-03-22 01:27:54 +00001094 break;
1095
1096 case LEA2:
sewardjfebaa3b2003-05-25 01:07:34 +00001097 VG_(printf)("%d(" , u->lit32);
njn4ba5a792002-09-30 10:23:54 +00001098 VG_(pp_UOperand)(u, 1, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001099 VG_(printf)(",");
njn4ba5a792002-09-30 10:23:54 +00001100 VG_(pp_UOperand)(u, 2, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001101 VG_(printf)(",%d), ", (Int)u->extra4b);
njn4ba5a792002-09-30 10:23:54 +00001102 VG_(pp_UOperand)(u, 3, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001103 break;
1104
1105 case LEA1:
sewardjfebaa3b2003-05-25 01:07:34 +00001106 VG_(printf)("%d" , u->lit32);
njn4ba5a792002-09-30 10:23:54 +00001107 VG_(pp_UOperand)(u, 1, 4, True);
sewardjde4a1d02002-03-22 01:27:54 +00001108 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001109 VG_(pp_UOperand)(u, 2, 4, False);
sewardjde4a1d02002-03-22 01:27:54 +00001110 break;
1111
sewardj7a5ebcf2002-11-13 22:42:13 +00001112 case NOP: case LOCK:
sewardjde4a1d02002-03-22 01:27:54 +00001113 break;
1114
1115 case FPU_W:
sewardjfebaa3b2003-05-25 01:07:34 +00001116 VG_(printf)("0x%x:0x%x, ",
sewardjde4a1d02002-03-22 01:27:54 +00001117 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
njn4ba5a792002-09-30 10:23:54 +00001118 VG_(pp_UOperand)(u, 2, 4, True);
sewardjde4a1d02002-03-22 01:27:54 +00001119 break;
1120
1121 case FPU_R:
sewardjfebaa3b2003-05-25 01:07:34 +00001122 VG_(printf)("");
njn4ba5a792002-09-30 10:23:54 +00001123 VG_(pp_UOperand)(u, 2, 4, True);
sewardjde4a1d02002-03-22 01:27:54 +00001124 VG_(printf)(", 0x%x:0x%x",
1125 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1126 break;
1127
1128 case FPU:
sewardjfebaa3b2003-05-25 01:07:34 +00001129 VG_(printf)("0x%x:0x%x",
sewardjde4a1d02002-03-22 01:27:54 +00001130 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1131 break;
1132
sewardj3d7c9c82003-03-26 21:08:13 +00001133 case MMX1:
sewardjfebaa3b2003-05-25 01:07:34 +00001134 VG_(printf)("0x%x",
sewardj3d7c9c82003-03-26 21:08:13 +00001135 u->val1 & 0xFF );
1136 break;
1137
1138 case MMX2:
sewardjfebaa3b2003-05-25 01:07:34 +00001139 VG_(printf)("0x%x:0x%x",
sewardj3d7c9c82003-03-26 21:08:13 +00001140 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1141 break;
1142
sewardjca860012003-03-27 23:52:58 +00001143 case MMX3:
sewardjfebaa3b2003-05-25 01:07:34 +00001144 VG_(printf)("0x%x:0x%x:0x%x",
sewardjca860012003-03-27 23:52:58 +00001145 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
1146 break;
1147
sewardj4fbe6e92003-06-15 21:54:34 +00001148 case MMX2_ERegWr:
1149 case MMX2_ERegRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001150 VG_(printf)("0x%x:0x%x, ",
sewardjca860012003-03-27 23:52:58 +00001151 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1152 VG_(pp_UOperand)(u, 2, 4, False);
1153 break;
1154
sewardj3d7c9c82003-03-26 21:08:13 +00001155 case MMX2_MemWr:
1156 case MMX2_MemRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001157 VG_(printf)("0x%x:0x%x",
sewardj3d7c9c82003-03-26 21:08:13 +00001158 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
1159 VG_(pp_UOperand)(u, 2, 4, True);
1160 break;
1161
thughes96b466a2004-03-15 16:43:58 +00001162 case MMX2a1_MemRd:
1163 VG_(printf)("0x%x:0x%x:0x%x",
1164 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
1165 VG_(pp_UOperand)(u, 3, 4, True);
1166 break;
1167
sewardjfebaa3b2003-05-25 01:07:34 +00001168 case SSE2a_MemWr:
1169 case SSE2a_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001170 case SSE2g_RegWr:
1171 case SSE2g1_RegWr:
1172 case SSE2e1_RegRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001173 VG_(printf)("0x%x:0x%x:0x%x",
1174 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
1175 VG_(pp_UOperand)(u, 3, 4, True);
1176 break;
1177
sewardj9dd209f2003-06-18 23:30:52 +00001178 case SSE2a1_MemRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001179 case SSE3a_MemWr:
1180 case SSE3a_MemRd:
1181 VG_(printf)("0x%x:0x%x:0x%x:0x%x",
1182 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
sewardjde8aecf2003-05-27 00:46:28 +00001183 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
sewardjfebaa3b2003-05-25 01:07:34 +00001184 VG_(pp_UOperand)(u, 3, 4, True);
1185 break;
1186
sewardjabf8bf82003-06-15 22:28:05 +00001187 case SSE3e_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001188 case SSE3e_RegRd:
sewardj02af6bc2003-06-12 00:56:06 +00001189 case SSE3g_RegWr:
sewardjfebaa3b2003-05-25 01:07:34 +00001190 VG_(printf)("0x%x:0x%x:0x%x:0x%x",
1191 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1192 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
1193 VG_(pp_UOperand)(u, 3, 4, True);
1194 break;
1195
sewardjb31b06d2003-06-13 00:26:02 +00001196 case SSE3g1_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001197 case SSE3e1_RegRd:
sewardj77d30a22003-10-19 08:18:52 +00001198 case SSE3a1_MemRd:
sewardjb31b06d2003-06-13 00:26:02 +00001199 VG_(printf)("0x%x:0x%x:0x%x:0x%x:0x%x",
1200 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1201 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF,
1202 u->lit32 );
1203 VG_(pp_UOperand)(u, 3, 4, True);
1204 break;
1205
sewardja60be0e2003-05-26 08:47:27 +00001206 case SSE3:
1207 VG_(printf)("0x%x:0x%x:0x%x",
1208 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1209 u->val2 & 0xFF );
1210 break;
1211
sewardjfebaa3b2003-05-25 01:07:34 +00001212 case SSE4:
1213 VG_(printf)("0x%x:0x%x:0x%x:0x%x",
1214 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1215 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
1216 break;
1217
sewardja453fb02003-06-14 13:22:36 +00001218 case SSE5:
1219 VG_(printf)("0x%x:0x%x:0x%x:0x%x:0x%x",
1220 (u->val1 >> 8) & 0xFF, u->val1 & 0xFF,
1221 (u->val2 >> 8) & 0xFF, u->val2 & 0xFF,
1222 u->val3 & 0xFF );
1223 break;
1224
sewardje3891fa2003-06-15 03:13:48 +00001225 case SSE3ag_MemRd_RegWr:
1226 VG_(printf)("0x%x(addr=", u->lit32 );
1227 VG_(pp_UOperand)(u, 1, 4, False);
1228 VG_(printf)(", dst=");
1229 VG_(pp_UOperand)(u, 2, 4, False);
1230 VG_(printf)(")");
1231 break;
1232
sewardjde4a1d02002-03-22 01:27:54 +00001233 case GET: case PUT: case MOV: case LOAD: case STORE: case CMOV:
sewardje1042472002-09-30 12:33:11 +00001234 case GETSEG: case PUTSEG:
njn4ba5a792002-09-30 10:23:54 +00001235 VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOAD);
sewardjde4a1d02002-03-22 01:27:54 +00001236 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001237 VG_(pp_UOperand)(u, 2, u->size, u->opcode==STORE);
njn25e49d8e72002-09-23 09:36:25 +00001238 break;
1239
1240 case JMP:
njn4ba5a792002-09-30 10:23:54 +00001241 VG_(pp_UOperand)(u, 1, u->size, False);
njn25e49d8e72002-09-23 09:36:25 +00001242 if (CondAlways == u->cond) {
1243 /* Print x86 instruction size if filled in */
1244 if (0 != u->extra4b)
1245 VG_(printf)(" ($%u)", u->extra4b);
1246 }
sewardjde4a1d02002-03-22 01:27:54 +00001247 break;
1248
1249 case GETF: case PUTF:
njn25e49d8e72002-09-23 09:36:25 +00001250 case CC2VAL: case PUSH: case POP: case CLEAR: case CALLM:
1251 case NOT: case NEG: case INC: case DEC: case BSWAP:
njn4ba5a792002-09-30 10:23:54 +00001252 VG_(pp_UOperand)(u, 1, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001253 break;
1254
njn25e49d8e72002-09-23 09:36:25 +00001255 /* Print a "(s)" after args passed on stack */
1256 case CCALL:
njn25e49d8e72002-09-23 09:36:25 +00001257 if (u->has_ret_val) {
njn4ba5a792002-09-30 10:23:54 +00001258 VG_(pp_UOperand)(u, 3, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001259 VG_(printf)(" = ");
sewardj2e93c502002-04-12 11:12:52 +00001260 }
njn25e49d8e72002-09-23 09:36:25 +00001261 VG_(printf)("%p(", u->lit32);
1262 if (u->argc > 0) {
njn4ba5a792002-09-30 10:23:54 +00001263 VG_(pp_UOperand)(u, 1, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001264 if (u->regparms_n < 1)
1265 VG_(printf)("(s)");
1266 }
1267 if (u->argc > 1) {
1268 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001269 VG_(pp_UOperand)(u, 2, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001270 if (u->regparms_n < 2)
1271 VG_(printf)("(s)");
1272 }
1273 if (u->argc > 2) {
1274 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001275 VG_(pp_UOperand)(u, 3, 0, False);
njn25e49d8e72002-09-23 09:36:25 +00001276 if (u->regparms_n < 3)
1277 VG_(printf)("(s)");
1278 }
1279 VG_(printf)(") ");
njn6431be72002-07-28 09:53:34 +00001280 break;
1281
sewardje1042472002-09-30 12:33:11 +00001282 case USESEG:
sewardjde4a1d02002-03-22 01:27:54 +00001283 case JIFZ:
sewardjde4a1d02002-03-22 01:27:54 +00001284 case ADD: case ADC: case AND: case OR:
1285 case XOR: case SUB: case SBB:
1286 case SHL: case SHR: case SAR:
jsgf5efa4fd2003-10-14 21:49:11 +00001287 case ROL: case ROR: case RCL: case RCR:
1288 case MUL:
njn4ba5a792002-09-30 10:23:54 +00001289 VG_(pp_UOperand)(u, 1, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001290 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +00001291 VG_(pp_UOperand)(u, 2, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001292 break;
1293
1294 case WIDEN:
njn4ba5a792002-09-30 10:23:54 +00001295 VG_(pp_UOperand)(u, 1, u->size, False);
sewardjde4a1d02002-03-22 01:27:54 +00001296 break;
1297
njn25e49d8e72002-09-23 09:36:25 +00001298 default:
1299 if (VG_(needs).extended_UCode)
njn4ba5a792002-09-30 10:23:54 +00001300 SK_(pp_XUInstr)(u);
njn25e49d8e72002-09-23 09:36:25 +00001301 else {
1302 VG_(printf)("unhandled opcode: %u. Perhaps "
1303 "VG_(needs).extended_UCode should be set?",
1304 u->opcode);
njne427a662002-10-02 11:08:25 +00001305 VG_(core_panic)("pp_UInstr: unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +00001306 }
sewardjde4a1d02002-03-22 01:27:54 +00001307 }
sewardjde4a1d02002-03-22 01:27:54 +00001308 if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty) {
1309 VG_(printf)(" (");
1310 if (u->flags_r != FlagsEmpty)
1311 vg_ppFlagSet("-r", u->flags_r);
1312 if (u->flags_w != FlagsEmpty)
1313 vg_ppFlagSet("-w", u->flags_w);
1314 VG_(printf)(")");
1315 }
njn25e49d8e72002-09-23 09:36:25 +00001316
1317 if (ppRegsLiveness) {
1318 VG_(printf)("\t\t");
njn4ba5a792002-09-30 10:23:54 +00001319 pp_realregs_liveness ( u );
njn25e49d8e72002-09-23 09:36:25 +00001320 }
1321
sewardjde4a1d02002-03-22 01:27:54 +00001322 VG_(printf)("\n");
1323}
1324
njn4ba5a792002-09-30 10:23:54 +00001325void VG_(pp_UInstr) ( Int instrNo, UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +00001326{
njn4ba5a792002-09-30 10:23:54 +00001327 pp_UInstrWorker ( instrNo, u, /*ppRegsLiveness*/False );
njn25e49d8e72002-09-23 09:36:25 +00001328}
1329
njn4ba5a792002-09-30 10:23:54 +00001330void VG_(pp_UInstr_regs) ( Int instrNo, UInstr* u )
njn25e49d8e72002-09-23 09:36:25 +00001331{
njn4ba5a792002-09-30 10:23:54 +00001332 pp_UInstrWorker ( instrNo, u, /*ppRegsLiveness*/True );
njn25e49d8e72002-09-23 09:36:25 +00001333}
sewardjde4a1d02002-03-22 01:27:54 +00001334
njn4ba5a792002-09-30 10:23:54 +00001335void VG_(pp_UCodeBlock) ( UCodeBlock* cb, Char* title )
sewardjde4a1d02002-03-22 01:27:54 +00001336{
1337 Int i;
njn25e49d8e72002-09-23 09:36:25 +00001338 VG_(printf)("%s\n", title);
sewardjde4a1d02002-03-22 01:27:54 +00001339 for (i = 0; i < cb->used; i++)
njn25e49d8e72002-09-23 09:36:25 +00001340 if (cb->instrs[i].opcode != NOP)
njn4ba5a792002-09-30 10:23:54 +00001341 VG_(pp_UInstr) ( i, &cb->instrs[i] );
sewardjde4a1d02002-03-22 01:27:54 +00001342 VG_(printf)("\n");
1343}
1344
1345
1346/*------------------------------------------------------------*/
1347/*--- uinstr helpers for register allocation ---*/
1348/*--- and code improvement. ---*/
1349/*------------------------------------------------------------*/
1350
njn25e49d8e72002-09-23 09:36:25 +00001351/* Get the temp/reg use of a uinstr, parking them in an array supplied by
njn810086f2002-11-14 12:42:47 +00001352 the caller (regs), which is assumed to be big enough. Return the number
1353 of entries. Written regs are indicated in parallel array isWrites.
1354 Insns which read _and_ write a register wind up mentioning it twice.
1355 Entries are placed in the array in program order, so that if a reg is
1356 read-modified-written, it appears first as a read and then as a write.
1357 'tag' indicates whether we are looking at TempRegs or RealRegs.
sewardjde4a1d02002-03-22 01:27:54 +00001358*/
njn810086f2002-11-14 12:42:47 +00001359Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites )
sewardjde4a1d02002-03-22 01:27:54 +00001360{
njn810086f2002-11-14 12:42:47 +00001361# define RD(ono) VG_UINSTR_READS_REG(ono, regs, isWrites)
1362# define WR(ono) VG_UINSTR_WRITES_REG(ono, regs, isWrites)
sewardjde4a1d02002-03-22 01:27:54 +00001363
1364 Int n = 0;
1365 switch (u->opcode) {
1366 case LEA1: RD(1); WR(2); break;
1367 case LEA2: RD(1); RD(2); WR(3); break;
1368
sewardj77d30a22003-10-19 08:18:52 +00001369 case SSE3a1_MemRd:
sewardj9dd209f2003-06-18 23:30:52 +00001370 case SSE2a1_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001371 case SSE2e1_RegRd:
sewardj4fbe6e92003-06-15 21:54:34 +00001372 case SSE3e_RegRd:
sewardjfebaa3b2003-05-25 01:07:34 +00001373 case SSE3a_MemWr:
1374 case SSE3a_MemRd:
1375 case SSE2a_MemWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001376 case SSE3e1_RegRd:
sewardj02af6bc2003-06-12 00:56:06 +00001377 case SSE2a_MemRd: RD(3); break;
1378
nethercoteb1affa82004-01-19 19:14:18 +00001379 case SSE2g_RegWr:
1380 case SSE2g1_RegWr:
sewardjabf8bf82003-06-15 22:28:05 +00001381 case SSE3e_RegWr:
sewardjb31b06d2003-06-13 00:26:02 +00001382 case SSE3g1_RegWr:
sewardj02af6bc2003-06-12 00:56:06 +00001383 case SSE3g_RegWr: WR(3); break;
sewardjfebaa3b2003-05-25 01:07:34 +00001384
sewardje3891fa2003-06-15 03:13:48 +00001385 case SSE3ag_MemRd_RegWr: RD(1); WR(2); break;
1386
thughes96b466a2004-03-15 16:43:58 +00001387 case MMX2a1_MemRd: RD(3); break;
sewardj4fbe6e92003-06-15 21:54:34 +00001388 case MMX2_ERegRd: RD(2); break;
1389 case MMX2_ERegWr: WR(2); break;
sewardjca860012003-03-27 23:52:58 +00001390
sewardja453fb02003-06-14 13:22:36 +00001391 case SSE4: case SSE3: case SSE5:
sewardjca860012003-03-27 23:52:58 +00001392 case MMX1: case MMX2: case MMX3:
njn25e49d8e72002-09-23 09:36:25 +00001393 case NOP: case FPU: case INCEIP: case CALLM_S: case CALLM_E:
sewardj7a5ebcf2002-11-13 22:42:13 +00001394 case CLEAR: case CALLM: case LOCK: break;
njn25e49d8e72002-09-23 09:36:25 +00001395
1396 case CCALL:
1397 if (u->argc > 0) RD(1);
1398 if (u->argc > 1) RD(2);
1399 if (u->argc > 2) RD(3);
1400 if (u->has_ret_val) WR(3);
1401 break;
1402
sewardj3d7c9c82003-03-26 21:08:13 +00001403 case MMX2_MemRd: case MMX2_MemWr:
sewardjde4a1d02002-03-22 01:27:54 +00001404 case FPU_R: case FPU_W: RD(2); break;
1405
sewardje1042472002-09-30 12:33:11 +00001406 case GETSEG: WR(2); break;
1407 case PUTSEG: RD(1); break;
1408
sewardjde4a1d02002-03-22 01:27:54 +00001409 case GETF: WR(1); break;
1410 case PUTF: RD(1); break;
1411
1412 case GET: WR(2); break;
1413 case PUT: RD(1); break;
1414 case LOAD: RD(1); WR(2); break;
njn25e49d8e72002-09-23 09:36:25 +00001415 case STORE: RD(1); RD(2); break;
sewardjde4a1d02002-03-22 01:27:54 +00001416 case MOV: RD(1); WR(2); break;
1417
1418 case JMP: RD(1); break;
sewardjde4a1d02002-03-22 01:27:54 +00001419
njn25e49d8e72002-09-23 09:36:25 +00001420 case PUSH: RD(1); break;
sewardjde4a1d02002-03-22 01:27:54 +00001421 case POP: WR(1); break;
1422
sewardje1042472002-09-30 12:33:11 +00001423 case USESEG:
sewardjde4a1d02002-03-22 01:27:54 +00001424 case CMOV:
1425 case ADD: case ADC: case AND: case OR:
1426 case XOR: case SUB: case SBB:
jsgf5efa4fd2003-10-14 21:49:11 +00001427 case MUL:
sewardjde4a1d02002-03-22 01:27:54 +00001428 RD(1); RD(2); WR(2); break;
1429
1430 case SHL: case SHR: case SAR:
1431 case ROL: case ROR: case RCL: case RCR:
1432 RD(1); RD(2); WR(2); break;
1433
njn25e49d8e72002-09-23 09:36:25 +00001434 case NOT: case NEG: case INC: case DEC: case BSWAP:
sewardjde4a1d02002-03-22 01:27:54 +00001435 RD(1); WR(1); break;
1436
1437 case WIDEN: RD(1); WR(1); break;
1438
1439 case CC2VAL: WR(1); break;
1440 case JIFZ: RD(1); break;
1441
njn25e49d8e72002-09-23 09:36:25 +00001442 default:
1443 if (VG_(needs).extended_UCode)
njn810086f2002-11-14 12:42:47 +00001444 return SK_(get_Xreg_usage)(u, tag, regs, isWrites);
njn25e49d8e72002-09-23 09:36:25 +00001445 else {
1446 VG_(printf)("unhandled opcode: %u. Perhaps "
1447 "VG_(needs).extended_UCode should be set?",
1448 u->opcode);
njne427a662002-10-02 11:08:25 +00001449 VG_(core_panic)("VG_(get_reg_usage): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +00001450 }
sewardjde4a1d02002-03-22 01:27:54 +00001451 }
1452 return n;
1453
1454# undef RD
1455# undef WR
1456}
1457
1458
njn25e49d8e72002-09-23 09:36:25 +00001459/* Change temp regs in u into real regs, as directed by the
1460 * temps[i]-->reals[i] mapping. */
sewardj56867352003-10-12 10:27:06 +00001461static
njn810086f2002-11-14 12:42:47 +00001462void patchUInstr ( UInstr* u, Int temps[], UInt reals[], Int n_tmap )
sewardjde4a1d02002-03-22 01:27:54 +00001463{
1464 Int i;
1465 if (u->tag1 == TempReg) {
1466 for (i = 0; i < n_tmap; i++)
njn810086f2002-11-14 12:42:47 +00001467 if (temps[i] == u->val1) break;
njne427a662002-10-02 11:08:25 +00001468 if (i == n_tmap) VG_(core_panic)("patchUInstr(1)");
sewardjde4a1d02002-03-22 01:27:54 +00001469 u->tag1 = RealReg;
njn25e49d8e72002-09-23 09:36:25 +00001470 u->val1 = reals[i];
sewardjde4a1d02002-03-22 01:27:54 +00001471 }
1472 if (u->tag2 == TempReg) {
1473 for (i = 0; i < n_tmap; i++)
njn810086f2002-11-14 12:42:47 +00001474 if (temps[i] == u->val2) break;
njne427a662002-10-02 11:08:25 +00001475 if (i == n_tmap) VG_(core_panic)("patchUInstr(2)");
sewardjde4a1d02002-03-22 01:27:54 +00001476 u->tag2 = RealReg;
njn25e49d8e72002-09-23 09:36:25 +00001477 u->val2 = reals[i];
sewardjde4a1d02002-03-22 01:27:54 +00001478 }
1479 if (u->tag3 == TempReg) {
1480 for (i = 0; i < n_tmap; i++)
njn810086f2002-11-14 12:42:47 +00001481 if (temps[i] == u->val3) break;
njne427a662002-10-02 11:08:25 +00001482 if (i == n_tmap) VG_(core_panic)("patchUInstr(3)");
sewardjde4a1d02002-03-22 01:27:54 +00001483 u->tag3 = RealReg;
njn25e49d8e72002-09-23 09:36:25 +00001484 u->val3 = reals[i];
sewardjde4a1d02002-03-22 01:27:54 +00001485 }
1486}
1487
1488
1489/* Tedious x86-specific hack which compensates for the fact that the
1490 register numbers for %ah .. %dh do not correspond to those for %eax
1491 .. %edx. It maps a (reg size, reg no) pair to the number of the
1492 containing 32-bit reg. */
1493static __inline__
1494Int containingArchRegOf ( Int sz, Int aregno )
1495{
1496 switch (sz) {
1497 case 4: return aregno;
1498 case 2: return aregno;
1499 case 1: return aregno >= 4 ? aregno-4 : aregno;
njne427a662002-10-02 11:08:25 +00001500 default: VG_(core_panic)("containingArchRegOf");
sewardjde4a1d02002-03-22 01:27:54 +00001501 }
1502}
1503
1504
1505/* If u reads an ArchReg, return the number of the containing arch
njn25e49d8e72002-09-23 09:36:25 +00001506 reg. Otherwise return -1. Used in redundant-PUT elimination.
nethercote996901a2004-08-03 13:29:09 +00001507 Note that this is not required for tools extending UCode because
njn25e49d8e72002-09-23 09:36:25 +00001508 this happens before instrumentation. */
sewardj56867352003-10-12 10:27:06 +00001509static
sewardjde4a1d02002-03-22 01:27:54 +00001510Int maybe_uinstrReadsArchReg ( UInstr* u )
1511{
1512 switch (u->opcode) {
1513 case GET:
1514 case ADD: case ADC: case AND: case OR:
1515 case XOR: case SUB: case SBB:
1516 case SHL: case SHR: case SAR: case ROL:
1517 case ROR: case RCL: case RCR:
jsgf5efa4fd2003-10-14 21:49:11 +00001518 case MUL:
sewardjde4a1d02002-03-22 01:27:54 +00001519 if (u->tag1 == ArchReg)
1520 return containingArchRegOf ( u->size, u->val1 );
1521 else
1522 return -1;
1523
1524 case GETF: case PUTF:
1525 case CALLM_S: case CALLM_E:
1526 case INCEIP:
1527 case LEA1:
1528 case LEA2:
1529 case NOP:
sewardj7a5ebcf2002-11-13 22:42:13 +00001530 case LOCK:
sewardjde4a1d02002-03-22 01:27:54 +00001531 case PUT:
1532 case LOAD:
1533 case STORE:
1534 case MOV:
1535 case CMOV:
1536 case JMP:
1537 case CALLM: case CLEAR: case PUSH: case POP:
1538 case NOT: case NEG: case INC: case DEC: case BSWAP:
1539 case CC2VAL:
1540 case JIFZ:
1541 case FPU: case FPU_R: case FPU_W:
sewardjca860012003-03-27 23:52:58 +00001542 case MMX1: case MMX2: case MMX3:
thughes96b466a2004-03-15 16:43:58 +00001543 case MMX2_MemRd: case MMX2_MemWr: case MMX2a1_MemRd:
sewardj4fbe6e92003-06-15 21:54:34 +00001544 case MMX2_ERegRd: case MMX2_ERegWr:
sewardj9dd209f2003-06-18 23:30:52 +00001545 case SSE2a_MemWr: case SSE2a_MemRd: case SSE2a1_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001546 case SSE2g_RegWr: case SSE2g1_RegWr: case SSE2e1_RegRd:
sewardj77d30a22003-10-19 08:18:52 +00001547 case SSE3a_MemWr: case SSE3a_MemRd: case SSE3a1_MemRd:
sewardjabf8bf82003-06-15 22:28:05 +00001548 case SSE3e_RegRd: case SSE3g_RegWr: case SSE3e_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001549 case SSE3g1_RegWr: case SSE3e1_RegRd:
sewardje3891fa2003-06-15 03:13:48 +00001550 case SSE4: case SSE3: case SSE5: case SSE3ag_MemRd_RegWr:
sewardjde4a1d02002-03-22 01:27:54 +00001551 case WIDEN:
sewardje1042472002-09-30 12:33:11 +00001552 /* GETSEG and USESEG are to do with ArchRegS, not ArchReg */
1553 case GETSEG: case PUTSEG:
1554 case USESEG:
sewardjde4a1d02002-03-22 01:27:54 +00001555 return -1;
1556
1557 default:
njn4ba5a792002-09-30 10:23:54 +00001558 VG_(pp_UInstr)(0,u);
njne427a662002-10-02 11:08:25 +00001559 VG_(core_panic)("maybe_uinstrReadsArchReg: unhandled opcode");
sewardjde4a1d02002-03-22 01:27:54 +00001560 }
1561}
1562
1563static __inline__
1564Bool uInstrMentionsTempReg ( UInstr* u, Int tempreg )
1565{
1566 Int i, k;
njnf4ce3d32003-02-10 10:17:26 +00001567 Int tempUse[VG_MAX_REGS_USED];
1568 Bool notUsed[VG_MAX_REGS_USED];
njn810086f2002-11-14 12:42:47 +00001569
1570 k = VG_(get_reg_usage) ( u, TempReg, &tempUse[0], &notUsed[0] );
sewardjde4a1d02002-03-22 01:27:54 +00001571 for (i = 0; i < k; i++)
njn810086f2002-11-14 12:42:47 +00001572 if (tempUse[i] == tempreg)
sewardjde4a1d02002-03-22 01:27:54 +00001573 return True;
1574 return False;
1575}
1576
1577
1578/*------------------------------------------------------------*/
1579/*--- ucode improvement. ---*/
1580/*------------------------------------------------------------*/
1581
1582/* Improve the code in cb by doing
1583 -- Redundant ArchReg-fetch elimination
1584 -- Redundant PUT elimination
1585 -- Redundant cond-code restore/save elimination
1586 The overall effect of these is to allow target registers to be
1587 cached in host registers over multiple target insns.
1588*/
1589static void vg_improve ( UCodeBlock* cb )
1590{
1591 Int i, j, k, m, n, ar, tr, told, actual_areg;
nethercotec06e2132004-09-03 13:45:29 +00001592 Int areg_map[N_ARCH_REGS];
1593 Bool annul_put[N_ARCH_REGS];
njnf4ce3d32003-02-10 10:17:26 +00001594 Int tempUse[VG_MAX_REGS_USED];
1595 Bool isWrites[VG_MAX_REGS_USED];
sewardjde4a1d02002-03-22 01:27:54 +00001596 UInstr* u;
1597 Bool wr;
1598 Int* last_live_before;
1599 FlagSet future_dead_flags;
1600
njn25e49d8e72002-09-23 09:36:25 +00001601 if (dis)
1602 VG_(printf) ("Improvements:\n");
1603
sewardjde4a1d02002-03-22 01:27:54 +00001604 if (cb->nextTemp > 0)
njn25e49d8e72002-09-23 09:36:25 +00001605 last_live_before = VG_(arena_malloc) ( VG_AR_JITTER,
1606 cb->nextTemp * sizeof(Int) );
sewardjde4a1d02002-03-22 01:27:54 +00001607 else
1608 last_live_before = NULL;
1609
1610
1611 /* PASS 1: redundant GET elimination. (Actually, more general than
1612 that -- eliminates redundant fetches of ArchRegs). */
1613
1614 /* Find the live-range-ends for all temporaries. Duplicates code
1615 in the register allocator :-( */
1616
1617 for (i = 0; i < cb->nextTemp; i++) last_live_before[i] = -1;
1618
1619 for (i = cb->used-1; i >= 0; i--) {
1620 u = &cb->instrs[i];
1621
njn810086f2002-11-14 12:42:47 +00001622 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
sewardjde4a1d02002-03-22 01:27:54 +00001623
1624 /* For each temp usage ... bwds in program order. */
1625 for (j = k-1; j >= 0; j--) {
njn810086f2002-11-14 12:42:47 +00001626 tr = tempUse[j];
1627 wr = isWrites[j];
sewardjde4a1d02002-03-22 01:27:54 +00001628 if (last_live_before[tr] == -1) {
1629 vg_assert(tr >= 0 && tr < cb->nextTemp);
1630 last_live_before[tr] = wr ? (i+1) : i;
1631 }
1632 }
1633
1634 }
1635
1636# define BIND_ARCH_TO_TEMP(archreg,tempreg)\
1637 { Int q; \
1638 /* Invalidate any old binding(s) to tempreg. */ \
nethercotec06e2132004-09-03 13:45:29 +00001639 for (q = 0; q < N_ARCH_REGS; q++) \
sewardjde4a1d02002-03-22 01:27:54 +00001640 if (areg_map[q] == tempreg) areg_map[q] = -1; \
1641 /* Add the new binding. */ \
1642 areg_map[archreg] = (tempreg); \
1643 }
1644
1645 /* Set up the A-reg map. */
nethercotec06e2132004-09-03 13:45:29 +00001646 for (i = 0; i < N_ARCH_REGS; i++) areg_map[i] = -1;
sewardjde4a1d02002-03-22 01:27:54 +00001647
1648 /* Scan insns. */
1649 for (i = 0; i < cb->used; i++) {
1650 u = &cb->instrs[i];
1651 if (u->opcode == GET && u->size == 4) {
1652 /* GET; see if it can be annulled. */
1653 vg_assert(u->tag1 == ArchReg);
1654 vg_assert(u->tag2 == TempReg);
1655 ar = u->val1;
1656 tr = u->val2;
1657 told = areg_map[ar];
1658 if (told != -1 && last_live_before[told] <= i) {
1659 /* ar already has an old mapping to told, but that runs
1660 out here. Annul this GET, rename tr to told for the
1661 rest of the block, and extend told's live range to that
1662 of tr. */
njn4ba5a792002-09-30 10:23:54 +00001663 VG_(new_NOP)(u);
sewardjde4a1d02002-03-22 01:27:54 +00001664 n = last_live_before[tr] + 1;
1665 if (n > cb->used) n = cb->used;
1666 last_live_before[told] = last_live_before[tr];
1667 last_live_before[tr] = i-1;
njn25e49d8e72002-09-23 09:36:25 +00001668 if (dis)
sewardjde4a1d02002-03-22 01:27:54 +00001669 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00001670 " at %2d: delete GET, rename t%d to t%d in (%d .. %d)\n",
sewardjde4a1d02002-03-22 01:27:54 +00001671 i, tr, told,i+1, n-1);
1672 for (m = i+1; m < n; m++) {
1673 if (cb->instrs[m].tag1 == TempReg
1674 && cb->instrs[m].val1 == tr)
1675 cb->instrs[m].val1 = told;
1676 if (cb->instrs[m].tag2 == TempReg
1677 && cb->instrs[m].val2 == tr)
1678 cb->instrs[m].val2 = told;
sewardjfebaa3b2003-05-25 01:07:34 +00001679 if (cb->instrs[m].tag3 == TempReg
1680 && cb->instrs[m].val3 == tr)
1681 cb->instrs[m].val3 = told;
sewardjde4a1d02002-03-22 01:27:54 +00001682 }
1683 BIND_ARCH_TO_TEMP(ar,told);
1684 }
1685 else
1686 BIND_ARCH_TO_TEMP(ar,tr);
1687 }
1688 else if (u->opcode == GET && u->size != 4) {
1689 /* Invalidate any mapping for this archreg. */
1690 actual_areg = containingArchRegOf ( u->size, u->val1 );
1691 areg_map[actual_areg] = -1;
1692 }
1693 else if (u->opcode == PUT && u->size == 4) {
1694 /* PUT; re-establish t -> a binding */
1695 vg_assert(u->tag1 == TempReg);
1696 vg_assert(u->tag2 == ArchReg);
1697 BIND_ARCH_TO_TEMP(u->val2, u->val1);
1698 }
1699 else if (u->opcode == PUT && u->size != 4) {
1700 /* Invalidate any mapping for this archreg. */
1701 actual_areg = containingArchRegOf ( u->size, u->val2 );
1702 areg_map[actual_areg] = -1;
1703 } else {
1704
1705 /* see if insn has an archreg as a read operand; if so try to
1706 map it. */
1707 if (u->tag1 == ArchReg && u->size == 4
1708 && areg_map[u->val1] != -1) {
1709 switch (u->opcode) {
1710 case ADD: case SUB: case AND: case OR: case XOR:
1711 case ADC: case SBB:
1712 case SHL: case SHR: case SAR: case ROL: case ROR:
1713 case RCL: case RCR:
jsgf5efa4fd2003-10-14 21:49:11 +00001714 case MUL:
njn25e49d8e72002-09-23 09:36:25 +00001715 if (dis)
sewardjde4a1d02002-03-22 01:27:54 +00001716 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00001717 " at %2d: change ArchReg %S to TempReg t%d\n",
sewardjde4a1d02002-03-22 01:27:54 +00001718 i, nameIReg(4,u->val1), areg_map[u->val1]);
1719 u->tag1 = TempReg;
1720 u->val1 = areg_map[u->val1];
1721 /* Remember to extend the live range of the TempReg,
1722 if necessary. */
1723 if (last_live_before[u->val1] < i)
1724 last_live_before[u->val1] = i;
1725 break;
1726 default:
1727 break;
1728 }
1729 }
1730
1731 /* boring insn; invalidate any mappings to temps it writes */
njn810086f2002-11-14 12:42:47 +00001732 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
sewardjde4a1d02002-03-22 01:27:54 +00001733
1734 for (j = 0; j < k; j++) {
njn810086f2002-11-14 12:42:47 +00001735 wr = isWrites[j];
sewardjde4a1d02002-03-22 01:27:54 +00001736 if (!wr) continue;
njn810086f2002-11-14 12:42:47 +00001737 tr = tempUse[j];
nethercotec06e2132004-09-03 13:45:29 +00001738 for (m = 0; m < N_ARCH_REGS; m++)
sewardjde4a1d02002-03-22 01:27:54 +00001739 if (areg_map[m] == tr) areg_map[m] = -1;
1740 }
1741 }
1742
1743 }
1744
1745# undef BIND_ARCH_TO_TEMP
1746
sewardj05f1aa12002-04-30 00:29:36 +00001747 /* PASS 2: redundant PUT elimination. Don't annul (delay) puts of
1748 %ESP, since the memory check machinery always requires the
1749 in-memory value of %ESP to be up to date. Although this isn't
1750 actually required by other analyses (cache simulation), it's
1751 simplest to be consistent for all end-uses. */
nethercotec06e2132004-09-03 13:45:29 +00001752 for (j = 0; j < N_ARCH_REGS; j++)
sewardjde4a1d02002-03-22 01:27:54 +00001753 annul_put[j] = False;
1754
1755 for (i = cb->used-1; i >= 0; i--) {
1756 u = &cb->instrs[i];
1757 if (u->opcode == NOP) continue;
1758
1759 if (u->opcode == PUT && u->size == 4) {
1760 vg_assert(u->tag2 == ArchReg);
1761 actual_areg = containingArchRegOf ( 4, u->val2 );
1762 if (annul_put[actual_areg]) {
sewardj05f1aa12002-04-30 00:29:36 +00001763 vg_assert(actual_areg != R_ESP);
njn4ba5a792002-09-30 10:23:54 +00001764 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001765 if (dis)
1766 VG_(printf)(" at %2d: delete PUT\n", i );
sewardjde4a1d02002-03-22 01:27:54 +00001767 } else {
sewardj05f1aa12002-04-30 00:29:36 +00001768 if (actual_areg != R_ESP)
sewardjde4a1d02002-03-22 01:27:54 +00001769 annul_put[actual_areg] = True;
1770 }
1771 }
1772 else if (u->opcode == PUT && u->size != 4) {
1773 actual_areg = containingArchRegOf ( u->size, u->val2 );
1774 annul_put[actual_areg] = False;
1775 }
1776 else if (u->opcode == JMP || u->opcode == JIFZ
1777 || u->opcode == CALLM) {
nethercotec06e2132004-09-03 13:45:29 +00001778 for (j = 0; j < N_ARCH_REGS; j++)
sewardjde4a1d02002-03-22 01:27:54 +00001779 annul_put[j] = False;
1780 }
1781 else {
1782 /* If an instruction reads an ArchReg, the immediately
1783 preceding PUT cannot be annulled. */
1784 actual_areg = maybe_uinstrReadsArchReg ( u );
1785 if (actual_areg != -1)
1786 annul_put[actual_areg] = False;
1787 }
1788 }
1789
1790 /* PASS 2a: redundant-move elimination. Given MOV t1, t2 and t1 is
1791 dead after this point, annul the MOV insn and rename t2 to t1.
1792 Further modifies the last_live_before map. */
1793
1794# if 0
njn4ba5a792002-09-30 10:23:54 +00001795 VG_(pp_UCodeBlock)(cb, "Before MOV elimination" );
sewardjde4a1d02002-03-22 01:27:54 +00001796 for (i = 0; i < cb->nextTemp; i++)
1797 VG_(printf)("llb[t%d]=%d ", i, last_live_before[i]);
1798 VG_(printf)("\n");
1799# endif
1800
1801 for (i = 0; i < cb->used-1; i++) {
1802 u = &cb->instrs[i];
1803 if (u->opcode != MOV) continue;
1804 if (u->tag1 == Literal) continue;
1805 vg_assert(u->tag1 == TempReg);
1806 vg_assert(u->tag2 == TempReg);
1807 if (last_live_before[u->val1] == i) {
njn25e49d8e72002-09-23 09:36:25 +00001808 if (dis)
sewardjde4a1d02002-03-22 01:27:54 +00001809 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00001810 " at %2d: delete MOV, rename t%d to t%d in (%d .. %d)\n",
sewardjde4a1d02002-03-22 01:27:54 +00001811 i, u->val2, u->val1, i+1, last_live_before[u->val2] );
1812 for (j = i+1; j <= last_live_before[u->val2]; j++) {
1813 if (cb->instrs[j].tag1 == TempReg
1814 && cb->instrs[j].val1 == u->val2)
1815 cb->instrs[j].val1 = u->val1;
1816 if (cb->instrs[j].tag2 == TempReg
1817 && cb->instrs[j].val2 == u->val2)
1818 cb->instrs[j].val2 = u->val1;
sewardjfebaa3b2003-05-25 01:07:34 +00001819 if (cb->instrs[j].tag3 == TempReg
1820 && cb->instrs[j].val3 == u->val2)
1821 cb->instrs[j].val3 = u->val1;
sewardjde4a1d02002-03-22 01:27:54 +00001822 }
1823 last_live_before[u->val1] = last_live_before[u->val2];
1824 last_live_before[u->val2] = i-1;
njn4ba5a792002-09-30 10:23:54 +00001825 VG_(new_NOP)(u);
sewardjde4a1d02002-03-22 01:27:54 +00001826 }
1827 }
1828
1829 /* PASS 3: redundant condition-code restore/save elimination.
1830 Scan backwards from the end. future_dead_flags records the set
1831 of flags which are dead at this point, that is, will be written
1832 before they are next read. Earlier uinsns which write flags
1833 already in future_dead_flags can have their writes annulled.
1834 */
1835 future_dead_flags = FlagsEmpty;
1836
1837 for (i = cb->used-1; i >= 0; i--) {
1838 u = &cb->instrs[i];
1839
1840 /* We might never make it to insns beyond this one, so be
1841 conservative. */
1842 if (u->opcode == JIFZ || u->opcode == JMP) {
1843 future_dead_flags = FlagsEmpty;
1844 continue;
1845 }
1846
sewardjfbb6cda2002-07-24 09:33:52 +00001847 /* PUTF modifies the %EFLAGS in essentially unpredictable ways.
1848 For example people try to mess with bit 21 to see if CPUID
1849 works. The setting may or may not actually take hold. So we
1850 play safe here. */
1851 if (u->opcode == PUTF) {
1852 future_dead_flags = FlagsEmpty;
1853 continue;
1854 }
1855
sewardjde4a1d02002-03-22 01:27:54 +00001856 /* We can annul the flags written by this insn if it writes a
1857 subset (or eq) of the set of flags known to be dead after
1858 this insn. If not, just record the flags also written by
1859 this insn.*/
1860 if (u->flags_w != FlagsEmpty
1861 && VG_IS_FLAG_SUBSET(u->flags_w, future_dead_flags)) {
njn25e49d8e72002-09-23 09:36:25 +00001862 if (dis) {
1863 VG_(printf)(" at %2d: annul flag write ", i);
sewardjde4a1d02002-03-22 01:27:54 +00001864 vg_ppFlagSet("", u->flags_w);
1865 VG_(printf)(" due to later ");
1866 vg_ppFlagSet("", future_dead_flags);
1867 VG_(printf)("\n");
1868 }
1869 u->flags_w = FlagsEmpty;
1870 } else {
1871 future_dead_flags
1872 = VG_UNION_FLAG_SETS ( u->flags_w, future_dead_flags );
1873 }
1874
1875 /* If this insn also reads flags, empty out future_dead_flags so
1876 as to force preceding writes not to be annulled. */
1877 if (u->flags_r != FlagsEmpty)
1878 future_dead_flags = FlagsEmpty;
1879 }
1880
1881 if (last_live_before)
njn25e49d8e72002-09-23 09:36:25 +00001882 VG_(arena_free) ( VG_AR_JITTER, last_live_before );
1883
1884 if (dis) {
1885 VG_(printf)("\n");
njn4ba5a792002-09-30 10:23:54 +00001886 VG_(pp_UCodeBlock) ( cb, "Improved UCode:" );
njn25e49d8e72002-09-23 09:36:25 +00001887 }
sewardjde4a1d02002-03-22 01:27:54 +00001888}
1889
njn9b007f62003-04-07 14:40:25 +00001890/*------------------------------------------------------------*/
1891/*--- %ESP-update pass ---*/
1892/*------------------------------------------------------------*/
1893
nethercote996901a2004-08-03 13:29:09 +00001894/* For tools that want to know about %ESP changes, this pass adds
1895 in the appropriate hooks. We have to do it after the tool's
1896 instrumentation, so the tool doesn't have to worry about the CCALLs
njn9b007f62003-04-07 14:40:25 +00001897 it adds in, and we must do it before register allocation because
1898 spilled temps make it much harder to work out the %esp deltas.
njned619712003-10-01 16:45:04 +00001899 Thus we have it as an extra phase between the two.
1900
1901 We look for "GETL %ESP, t_ESP", then track ADDs and SUBs of
1902 literal values to t_ESP, and the total delta of the ADDs/SUBs. Then if
1903 "PUTL t_ESP, %ESP" happens, we call the helper with the known delta. We
1904 also cope with "MOVL t_ESP, tX", making tX the new t_ESP. If any other
1905 instruction clobbers t_ESP, we don't track it anymore, and fall back to
1906 the delta-is-unknown case. That case is also used when the delta is not
1907 a nice small amount, or an unknown amount.
1908*/
njn9b007f62003-04-07 14:40:25 +00001909static
1910UCodeBlock* vg_ESP_update_pass(UCodeBlock* cb_in)
1911{
1912 UCodeBlock* cb;
1913 UInstr* u;
1914 Int delta = 0;
1915 UInt t_ESP = INVALID_TEMPREG;
sewardj05bcdcb2003-05-18 10:05:38 +00001916 Int i;
njn9b007f62003-04-07 14:40:25 +00001917
1918 cb = VG_(setup_UCodeBlock)(cb_in);
1919
1920 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
1921 u = VG_(get_instr)(cb_in, i);
1922
1923 if (GET == u->opcode && R_ESP == u->val1) {
1924 t_ESP = u->val2;
1925 delta = 0;
1926
1927 } else if (PUT == u->opcode && R_ESP == u->val2 && 4 == u->size) {
1928
fitzhardinge98abfc72003-12-16 02:05:15 +00001929# define DO_GENERIC \
1930 if (VG_(defined_new_mem_stack)() || \
1931 VG_(defined_die_mem_stack)()) { \
1932 uInstr1(cb, CCALL, 0, TempReg, u->val1); \
1933 uCCall(cb, (Addr) VG_(unknown_esp_update), \
1934 1, 1, False); \
njn9b007f62003-04-07 14:40:25 +00001935 }
1936
fitzhardinge98abfc72003-12-16 02:05:15 +00001937# define DO(kind, size) \
1938 if (VG_(defined_##kind##_mem_stack_##size)()) { \
1939 uInstr1(cb, CCALL, 0, TempReg, u->val1); \
1940 uCCall(cb, (Addr) VG_(tool_interface).track_##kind##_mem_stack_##size, \
1941 1, 1, False); \
1942 \
1943 } else \
1944 DO_GENERIC \
njn9b007f62003-04-07 14:40:25 +00001945 break
1946
1947 if (u->val1 == t_ESP) {
1948 /* Known delta, common cases handled specially. */
1949 switch (delta) {
njned619712003-10-01 16:45:04 +00001950 case 0: break;
njn9b007f62003-04-07 14:40:25 +00001951 case 4: DO(die, 4);
1952 case -4: DO(new, 4);
1953 case 8: DO(die, 8);
1954 case -8: DO(new, 8);
1955 case 12: DO(die, 12);
1956 case -12: DO(new, 12);
1957 case 16: DO(die, 16);
1958 case -16: DO(new, 16);
1959 case 32: DO(die, 32);
1960 case -32: DO(new, 32);
1961 default: DO_GENERIC; break;
1962 }
1963 } else {
1964 /* Unknown delta */
1965 DO_GENERIC;
njned619712003-10-01 16:45:04 +00001966
daywalker972a7592003-10-01 10:19:08 +00001967 /* now we know the temp that points to %ESP */
njned619712003-10-01 16:45:04 +00001968 t_ESP = u->val1;
njn9b007f62003-04-07 14:40:25 +00001969 }
1970 delta = 0;
1971
1972# undef DO
1973# undef DO_GENERIC
1974
njned619712003-10-01 16:45:04 +00001975 } else if (ADD == u->opcode && Literal == u->tag1 && t_ESP == u->val2) {
1976 delta += u->lit32;
1977
1978 } else if (SUB == u->opcode && Literal == u->tag1 && t_ESP == u->val2) {
1979 delta -= u->lit32;
njn9b007f62003-04-07 14:40:25 +00001980
1981 } else if (MOV == u->opcode && TempReg == u->tag1 && t_ESP == u->val1 &&
1982 TempReg == u->tag2) {
njned619712003-10-01 16:45:04 +00001983 // t_ESP is transferred
njn9b007f62003-04-07 14:40:25 +00001984 t_ESP = u->val2;
njned619712003-10-01 16:45:04 +00001985
1986 } else {
1987 // Stop tracking t_ESP if it's clobbered by this instruction.
1988 Int tempUse [VG_MAX_REGS_USED];
1989 Bool isWrites[VG_MAX_REGS_USED];
1990 Int j, n = VG_(get_reg_usage)(u, TempReg, tempUse, isWrites);
1991
1992 for (j = 0; j < n; j++) {
1993 if (tempUse[j] == t_ESP && isWrites[j])
1994 t_ESP = INVALID_TEMPREG;
1995 }
njn9b007f62003-04-07 14:40:25 +00001996 }
1997 VG_(copy_UInstr) ( cb, u );
1998 }
1999
2000 VG_(free_UCodeBlock)(cb_in);
2001 return cb;
2002}
sewardjde4a1d02002-03-22 01:27:54 +00002003
2004/*------------------------------------------------------------*/
2005/*--- The new register allocator. ---*/
2006/*------------------------------------------------------------*/
2007
2008typedef
2009 struct {
2010 /* Becomes live for the first time after this insn ... */
2011 Int live_after;
jsewardfa70a8e2004-07-01 11:38:36 +00002012 /* Becomes dead for the last time before this insn ... */
sewardjde4a1d02002-03-22 01:27:54 +00002013 Int dead_before;
2014 /* The "home" spill slot, if needed. Never changes. */
2015 Int spill_no;
2016 /* Where is it? VG_NOVALUE==in a spill slot; else in reg. */
2017 Int real_no;
2018 }
2019 TempInfo;
2020
2021
2022/* Take a ucode block and allocate its TempRegs to RealRegs, or put
2023 them in spill locations, and add spill code, if there are not
2024 enough real regs. The usual register allocation deal, in short.
2025
2026 Important redundancy of representation:
2027
2028 real_to_temp maps real reg ranks (RRRs) to TempReg nos, or
2029 to VG_NOVALUE if the real reg has no currently assigned TempReg.
2030
2031 The .real_no field of a TempInfo gives the current RRR for
2032 this TempReg, or VG_NOVALUE if the TempReg is currently
2033 in memory, in which case it is in the SpillNo denoted by
2034 spillno.
2035
2036 These pieces of information (a fwds-bwds mapping, really) must
2037 be kept consistent!
2038
2039 This allocator uses the so-called Second Chance Bin Packing
2040 algorithm, as described in "Quality and Speed in Linear-scan
2041 Register Allocation" (Traub, Holloway and Smith, ACM PLDI98,
2042 pp142-151). It is simple and fast and remarkably good at
2043 minimising the amount of spill code introduced.
2044*/
2045
2046static
2047UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
2048{
2049 TempInfo* temp_info;
njned619712003-10-01 16:45:04 +00002050 Int real_to_temp [VG_MAX_REALREGS];
sewardjde4a1d02002-03-22 01:27:54 +00002051 Bool is_spill_cand[VG_MAX_REALREGS];
2052 Int ss_busy_until_before[VG_MAX_SPILLSLOTS];
2053 Int i, j, k, m, r, tno, max_ss_no;
2054 Bool wr, defer, isRead, spill_reqd;
njned619712003-10-01 16:45:04 +00002055 UInt realUse [VG_MAX_REGS_USED];
2056 Int tempUse [VG_MAX_REGS_USED];
njnf4ce3d32003-02-10 10:17:26 +00002057 Bool isWrites[VG_MAX_REGS_USED];
sewardjde4a1d02002-03-22 01:27:54 +00002058 UCodeBlock* c2;
2059
2060 /* Used to denote ... well, "no value" in this fn. */
2061# define VG_NOTHING (-2)
2062
2063 /* Initialise the TempReg info. */
2064 if (c1->nextTemp > 0)
njn25e49d8e72002-09-23 09:36:25 +00002065 temp_info = VG_(arena_malloc)(VG_AR_JITTER,
2066 c1->nextTemp * sizeof(TempInfo) );
sewardjde4a1d02002-03-22 01:27:54 +00002067 else
2068 temp_info = NULL;
2069
2070 for (i = 0; i < c1->nextTemp; i++) {
2071 temp_info[i].live_after = VG_NOTHING;
2072 temp_info[i].dead_before = VG_NOTHING;
2073 temp_info[i].spill_no = VG_NOTHING;
2074 /* temp_info[i].real_no is not yet relevant. */
2075 }
2076
2077 spill_reqd = False;
2078
2079 /* Scan fwds to establish live ranges. */
2080
2081 for (i = 0; i < c1->used; i++) {
njn810086f2002-11-14 12:42:47 +00002082 k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
2083 &isWrites[0]);
njnf4ce3d32003-02-10 10:17:26 +00002084 vg_assert(k >= 0 && k <= VG_MAX_REGS_USED);
sewardjde4a1d02002-03-22 01:27:54 +00002085
2086 /* For each temp usage ... fwds in program order */
2087 for (j = 0; j < k; j++) {
njn810086f2002-11-14 12:42:47 +00002088 tno = tempUse[j];
2089 wr = isWrites[j];
sewardjde4a1d02002-03-22 01:27:54 +00002090 if (wr) {
2091 /* Writes hold a reg live until after this insn. */
2092 if (temp_info[tno].live_after == VG_NOTHING)
2093 temp_info[tno].live_after = i;
2094 if (temp_info[tno].dead_before < i + 1)
2095 temp_info[tno].dead_before = i + 1;
2096 } else {
2097 /* First use of a tmp should be a write. */
njnfa0ad422003-02-03 11:07:03 +00002098 if (temp_info[tno].live_after == VG_NOTHING) {
2099 VG_(printf)("At instr %d...\n", i);
2100 VG_(core_panic)("First use of tmp not a write,"
nethercote996901a2004-08-03 13:29:09 +00002101 " probably a tool instrumentation error");
njnfa0ad422003-02-03 11:07:03 +00002102 }
sewardjde4a1d02002-03-22 01:27:54 +00002103 /* Reads only hold it live until before this insn. */
2104 if (temp_info[tno].dead_before < i)
2105 temp_info[tno].dead_before = i;
2106 }
2107 }
2108 }
2109
2110# if 0
2111 /* Sanity check on live ranges. Expensive but correct. */
2112 for (i = 0; i < c1->nextTemp; i++) {
2113 vg_assert( (temp_info[i].live_after == VG_NOTHING
2114 && temp_info[i].dead_before == VG_NOTHING)
2115 || (temp_info[i].live_after != VG_NOTHING
2116 && temp_info[i].dead_before != VG_NOTHING) );
2117 }
2118# endif
2119
2120 /* Do a rank-based allocation of TempRegs to spill slot numbers.
2121 We put as few as possible values in spill slots, but
2122 nevertheless need to have an assignment to them just in case. */
2123
2124 max_ss_no = -1;
2125
2126 for (i = 0; i < VG_MAX_SPILLSLOTS; i++)
2127 ss_busy_until_before[i] = 0;
2128
2129 for (i = 0; i < c1->nextTemp; i++) {
2130
2131 /* True iff this temp is unused. */
2132 if (temp_info[i].live_after == VG_NOTHING)
2133 continue;
2134
2135 /* Find the lowest-numbered spill slot which is available at the
2136 start point of this interval, and assign the interval to
2137 it. */
2138 for (j = 0; j < VG_MAX_SPILLSLOTS; j++)
2139 if (ss_busy_until_before[j] <= temp_info[i].live_after)
2140 break;
2141 if (j == VG_MAX_SPILLSLOTS) {
2142 VG_(printf)("VG_MAX_SPILLSLOTS is too low; increase and recompile.\n");
njne427a662002-10-02 11:08:25 +00002143 VG_(core_panic)("register allocation failed -- out of spill slots");
sewardjde4a1d02002-03-22 01:27:54 +00002144 }
2145 ss_busy_until_before[j] = temp_info[i].dead_before;
2146 temp_info[i].spill_no = j;
2147 if (j > max_ss_no)
2148 max_ss_no = j;
2149 }
2150
nethercotebee3fd92004-08-02 15:17:43 +00002151 n_total_reg_rank += (max_ss_no+1);
sewardjde4a1d02002-03-22 01:27:54 +00002152
2153 /* Show live ranges and assigned spill slot nos. */
2154
njn25e49d8e72002-09-23 09:36:25 +00002155 if (dis) {
2156 VG_(printf)("Live range assignments:\n");
sewardjde4a1d02002-03-22 01:27:54 +00002157
2158 for (i = 0; i < c1->nextTemp; i++) {
2159 if (temp_info[i].live_after == VG_NOTHING)
2160 continue;
2161 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +00002162 " LR %d is after %d to before %d\tspillno %d\n",
sewardjde4a1d02002-03-22 01:27:54 +00002163 i,
2164 temp_info[i].live_after,
2165 temp_info[i].dead_before,
2166 temp_info[i].spill_no
2167 );
2168 }
njn25e49d8e72002-09-23 09:36:25 +00002169 VG_(printf)("\n");
sewardjde4a1d02002-03-22 01:27:54 +00002170 }
2171
2172 /* Now that we've established a spill slot number for each used
2173 temporary, we can go ahead and do the core of the "Second-chance
2174 binpacking" allocation algorithm. */
2175
njn25e49d8e72002-09-23 09:36:25 +00002176 if (dis) VG_(printf)("Register allocated UCode:\n");
2177
2178
sewardjde4a1d02002-03-22 01:27:54 +00002179 /* Resulting code goes here. We generate it all in a forwards
2180 pass. */
nethercotecaee10d2004-08-03 17:39:06 +00002181 c2 = alloc_UCodeBlock( c1->orig_eip );
sewardjde4a1d02002-03-22 01:27:54 +00002182
2183 /* At the start, no TempRegs are assigned to any real register.
2184 Correspondingly, all temps claim to be currently resident in
2185 their spill slots, as computed by the previous two passes. */
2186 for (i = 0; i < VG_MAX_REALREGS; i++)
2187 real_to_temp[i] = VG_NOTHING;
2188 for (i = 0; i < c1->nextTemp; i++)
2189 temp_info[i].real_no = VG_NOTHING;
2190
sewardjde4a1d02002-03-22 01:27:54 +00002191 /* Process each insn in turn. */
2192 for (i = 0; i < c1->used; i++) {
2193
2194 if (c1->instrs[i].opcode == NOP) continue;
nethercotebee3fd92004-08-02 15:17:43 +00002195 n_uinstrs_prealloc++;
sewardjde4a1d02002-03-22 01:27:54 +00002196
2197# if 0
2198 /* Check map consistency. Expensive but correct. */
2199 for (r = 0; r < VG_MAX_REALREGS; r++) {
2200 if (real_to_temp[r] != VG_NOTHING) {
2201 tno = real_to_temp[r];
2202 vg_assert(tno >= 0 && tno < c1->nextTemp);
2203 vg_assert(temp_info[tno].real_no == r);
2204 }
2205 }
2206 for (tno = 0; tno < c1->nextTemp; tno++) {
2207 if (temp_info[tno].real_no != VG_NOTHING) {
2208 r = temp_info[tno].real_no;
2209 vg_assert(r >= 0 && r < VG_MAX_REALREGS);
2210 vg_assert(real_to_temp[r] == tno);
2211 }
2212 }
2213# endif
2214
njn25e49d8e72002-09-23 09:36:25 +00002215 if (dis)
njn4ba5a792002-09-30 10:23:54 +00002216 VG_(pp_UInstr)(i, &c1->instrs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002217
2218 /* First, free up enough real regs for this insn. This may
2219 generate spill stores since we may have to evict some TempRegs
2220 currently in real regs. Also generates spill loads. */
2221
njn810086f2002-11-14 12:42:47 +00002222 k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
2223 &isWrites[0]);
njnf4ce3d32003-02-10 10:17:26 +00002224 vg_assert(k >= 0 && k <= VG_MAX_REGS_USED);
sewardjde4a1d02002-03-22 01:27:54 +00002225
2226 /* For each ***different*** temp mentioned in the insn .... */
2227 for (j = 0; j < k; j++) {
2228
2229 /* First check if the temp is mentioned again later; if so,
2230 ignore this mention. We only want to process each temp
2231 used by the insn once, even if it is mentioned more than
2232 once. */
2233 defer = False;
njn810086f2002-11-14 12:42:47 +00002234 tno = tempUse[j];
sewardjde4a1d02002-03-22 01:27:54 +00002235 for (m = j+1; m < k; m++)
njn810086f2002-11-14 12:42:47 +00002236 if (tempUse[m] == tno)
sewardjde4a1d02002-03-22 01:27:54 +00002237 defer = True;
2238 if (defer)
2239 continue;
2240
njn810086f2002-11-14 12:42:47 +00002241 /* Now we're trying to find a register for tempUse[j].
sewardjde4a1d02002-03-22 01:27:54 +00002242 First of all, if it already has a register assigned, we
2243 don't need to do anything more. */
2244 if (temp_info[tno].real_no != VG_NOTHING)
2245 continue;
2246
2247 /* No luck. The next thing to do is see if there is a
2248 currently unassigned register available. If so, bag it. */
2249 for (r = 0; r < VG_MAX_REALREGS; r++) {
2250 if (real_to_temp[r] == VG_NOTHING)
2251 break;
2252 }
2253 if (r < VG_MAX_REALREGS) {
2254 real_to_temp[r] = tno;
2255 temp_info[tno].real_no = r;
2256 continue;
2257 }
2258
2259 /* Unfortunately, that didn't pan out either. So we'll have
2260 to eject some other unfortunate TempReg into a spill slot
2261 in order to free up a register. Of course, we need to be
2262 careful not to eject some other TempReg needed by this
2263 insn.
2264
2265 Select r in 0 .. VG_MAX_REALREGS-1 such that
2266 real_to_temp[r] is not mentioned in
njn810086f2002-11-14 12:42:47 +00002267 tempUse[0 .. k-1], since it would be just plain
sewardjde4a1d02002-03-22 01:27:54 +00002268 wrong to eject some other TempReg which we need to use in
2269 this insn.
2270
2271 It is here that it is important to make a good choice of
2272 register to spill. */
2273
2274 /* First, mark those regs which are not spill candidates. */
2275 for (r = 0; r < VG_MAX_REALREGS; r++) {
2276 is_spill_cand[r] = True;
2277 for (m = 0; m < k; m++) {
njn810086f2002-11-14 12:42:47 +00002278 if (real_to_temp[r] == tempUse[m]) {
sewardjde4a1d02002-03-22 01:27:54 +00002279 is_spill_cand[r] = False;
2280 break;
2281 }
2282 }
2283 }
2284
2285 /* We can choose any r satisfying is_spill_cand[r]. However,
2286 try to make a good choice. First, try and find r such
2287 that the associated TempReg is already dead. */
2288 for (r = 0; r < VG_MAX_REALREGS; r++) {
2289 if (is_spill_cand[r] &&
2290 temp_info[real_to_temp[r]].dead_before <= i)
2291 goto have_spill_cand;
2292 }
2293
2294 /* No spill cand is mapped to a dead TempReg. Now we really
2295 _do_ have to generate spill code. Choose r so that the
2296 next use of its associated TempReg is as far ahead as
2297 possible, in the hope that this will minimise the number of
2298 consequent reloads required. This is a bit expensive, but
2299 we don't have to do it very often. */
2300 {
2301 Int furthest_r = VG_MAX_REALREGS;
2302 Int furthest = 0;
2303 for (r = 0; r < VG_MAX_REALREGS; r++) {
2304 if (!is_spill_cand[r]) continue;
2305 for (m = i+1; m < c1->used; m++)
2306 if (uInstrMentionsTempReg(&c1->instrs[m],
2307 real_to_temp[r]))
2308 break;
2309 if (m > furthest) {
2310 furthest = m;
2311 furthest_r = r;
2312 }
2313 }
2314 r = furthest_r;
2315 goto have_spill_cand;
2316 }
2317
2318 have_spill_cand:
2319 if (r == VG_MAX_REALREGS)
njne427a662002-10-02 11:08:25 +00002320 VG_(core_panic)("new reg alloc: out of registers ?!");
sewardjde4a1d02002-03-22 01:27:54 +00002321
2322 /* Eject r. Important refinement: don't bother if the
2323 associated TempReg is now dead. */
2324 vg_assert(real_to_temp[r] != VG_NOTHING);
2325 vg_assert(real_to_temp[r] != tno);
2326 temp_info[real_to_temp[r]].real_no = VG_NOTHING;
2327 if (temp_info[real_to_temp[r]].dead_before > i) {
2328 uInstr2(c2, PUT, 4,
njn4ba5a792002-09-30 10:23:54 +00002329 RealReg, VG_(rank_to_realreg)(r),
sewardjde4a1d02002-03-22 01:27:54 +00002330 SpillNo, temp_info[real_to_temp[r]].spill_no);
nethercotebee3fd92004-08-02 15:17:43 +00002331 n_uinstrs_spill++;
sewardjde4a1d02002-03-22 01:27:54 +00002332 spill_reqd = True;
njn25e49d8e72002-09-23 09:36:25 +00002333 if (dis)
njn4ba5a792002-09-30 10:23:54 +00002334 VG_(pp_UInstr)(c2->used-1, &LAST_UINSTR(c2));
sewardjde4a1d02002-03-22 01:27:54 +00002335 }
2336
2337 /* Decide if tno is read. */
2338 isRead = False;
2339 for (m = 0; m < k; m++)
njn810086f2002-11-14 12:42:47 +00002340 if (tempUse[m] == tno && !isWrites[m])
sewardjde4a1d02002-03-22 01:27:54 +00002341 isRead = True;
2342
2343 /* If so, generate a spill load. */
2344 if (isRead) {
2345 uInstr2(c2, GET, 4,
2346 SpillNo, temp_info[tno].spill_no,
njn4ba5a792002-09-30 10:23:54 +00002347 RealReg, VG_(rank_to_realreg)(r) );
nethercotebee3fd92004-08-02 15:17:43 +00002348 n_uinstrs_spill++;
sewardjde4a1d02002-03-22 01:27:54 +00002349 spill_reqd = True;
njn25e49d8e72002-09-23 09:36:25 +00002350 if (dis)
njn4ba5a792002-09-30 10:23:54 +00002351 VG_(pp_UInstr)(c2->used-1, &LAST_UINSTR(c2));
sewardjde4a1d02002-03-22 01:27:54 +00002352 }
2353
2354 /* Update the forwards and backwards maps. */
2355 real_to_temp[r] = tno;
2356 temp_info[tno].real_no = r;
2357 }
2358
2359 /* By this point, all TempRegs mentioned by the insn have been
2360 bought into real regs. We now copy the insn to the output
2361 and use patchUInstr to convert its rTempRegs into
2362 realregs. */
2363 for (j = 0; j < k; j++)
njn810086f2002-11-14 12:42:47 +00002364 realUse[j] = VG_(rank_to_realreg)(temp_info[tempUse[j]].real_no);
njn4ba5a792002-09-30 10:23:54 +00002365 VG_(copy_UInstr)(c2, &c1->instrs[i]);
njn25e49d8e72002-09-23 09:36:25 +00002366 patchUInstr(&LAST_UINSTR(c2), &tempUse[0], &realUse[0], k);
sewardjde4a1d02002-03-22 01:27:54 +00002367
njn25e49d8e72002-09-23 09:36:25 +00002368 if (dis) {
njn4ba5a792002-09-30 10:23:54 +00002369 VG_(pp_UInstr)(c2->used-1, &LAST_UINSTR(c2));
sewardjde4a1d02002-03-22 01:27:54 +00002370 VG_(printf)("\n");
2371 }
2372 }
2373
2374 if (temp_info != NULL)
njn25e49d8e72002-09-23 09:36:25 +00002375 VG_(arena_free)(VG_AR_JITTER, temp_info);
sewardjde4a1d02002-03-22 01:27:54 +00002376
njn4ba5a792002-09-30 10:23:54 +00002377 VG_(free_UCodeBlock)(c1);
sewardjde4a1d02002-03-22 01:27:54 +00002378
2379 if (spill_reqd)
nethercotebee3fd92004-08-02 15:17:43 +00002380 n_translations_needing_spill++;
sewardjde4a1d02002-03-22 01:27:54 +00002381
2382 return c2;
2383
2384# undef VG_NOTHING
2385
2386}
sewardj7c4b6042003-06-14 15:47:15 +00002387
njn25e49d8e72002-09-23 09:36:25 +00002388/* Analysis records liveness of all general-use RealRegs in the UCode. */
2389static void vg_realreg_liveness_analysis ( UCodeBlock* cb )
2390{
2391 Int i, j, k;
2392 RRegSet rregs_live;
njnf4ce3d32003-02-10 10:17:26 +00002393 Int regUse[VG_MAX_REGS_USED];
2394 Bool isWrites[VG_MAX_REGS_USED];
njn25e49d8e72002-09-23 09:36:25 +00002395 UInstr* u;
sewardjde4a1d02002-03-22 01:27:54 +00002396
njn25e49d8e72002-09-23 09:36:25 +00002397 /* All regs are dead at the end of the block */
2398 rregs_live = ALL_RREGS_DEAD;
sewardjde4a1d02002-03-22 01:27:54 +00002399
sewardjde4a1d02002-03-22 01:27:54 +00002400 for (i = cb->used-1; i >= 0; i--) {
2401 u = &cb->instrs[i];
2402
njn25e49d8e72002-09-23 09:36:25 +00002403 u->regs_live_after = rregs_live;
sewardj97ced732002-03-25 00:07:36 +00002404
njn810086f2002-11-14 12:42:47 +00002405 k = VG_(get_reg_usage)(u, RealReg, &regUse[0], &isWrites[0]);
sewardj97ced732002-03-25 00:07:36 +00002406
njn25e49d8e72002-09-23 09:36:25 +00002407 /* For each reg usage ... bwds in program order. Variable is live
2408 before this UInstr if it is read by this UInstr.
njn810086f2002-11-14 12:42:47 +00002409 Note that regUse[j] holds the Intel reg number, so we must
njn25e49d8e72002-09-23 09:36:25 +00002410 convert it to our rank number. */
2411 for (j = k-1; j >= 0; j--) {
njn810086f2002-11-14 12:42:47 +00002412 SET_RREG_LIVENESS ( VG_(realreg_to_rank)(regUse[j]),
njn25e49d8e72002-09-23 09:36:25 +00002413 rregs_live,
njn810086f2002-11-14 12:42:47 +00002414 !isWrites[j] );
sewardjde4a1d02002-03-22 01:27:54 +00002415 }
2416 }
sewardjde4a1d02002-03-22 01:27:54 +00002417}
2418
sewardjde4a1d02002-03-22 01:27:54 +00002419/*------------------------------------------------------------*/
2420/*--- Main entry point for the JITter. ---*/
2421/*------------------------------------------------------------*/
2422
nethercote59a122d2004-08-03 17:16:51 +00002423/* Translate the basic block beginning at orig_addr, and add it to
2424 the translation cache & translation table. Unless 'debugging' is true,
2425 in which case the call is being done for debugging purposes, so
2426 (a) throw away the translation once it is made, and (b) produce a
2427 load of debugging output.
njn25e49d8e72002-09-23 09:36:25 +00002428
nethercote59a122d2004-08-03 17:16:51 +00002429 'tid' is the identity of the thread needing this block.
sewardjde4a1d02002-03-22 01:27:54 +00002430*/
nethercote4d714382004-10-13 09:47:24 +00002431Bool VG_(translate) ( ThreadId tid, Addr orig_addr,
nethercote59a122d2004-08-03 17:16:51 +00002432 Bool debugging_translation )
sewardjde4a1d02002-03-22 01:27:54 +00002433{
nethercote59a122d2004-08-03 17:16:51 +00002434 Addr trans_addr, redir, orig_addr0 = orig_addr;
2435 UShort jumps[VG_MAX_JUMPS];
2436 Int i, orig_size, trans_size;
sewardjde4a1d02002-03-22 01:27:54 +00002437 UCodeBlock* cb;
sewardja60be0e2003-05-26 08:47:27 +00002438 Bool notrace_until_done;
sewardj1e86b8b2003-06-16 23:34:12 +00002439 UInt notrace_until_limit = 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00002440 Segment *seg;
sewardjde4a1d02002-03-22 01:27:54 +00002441
2442 VGP_PUSHCC(VgpTranslate);
nethercote59a122d2004-08-03 17:16:51 +00002443
nethercote885dd912004-08-03 23:14:00 +00002444 beforeRA = True;
2445 beforeLiveness = True;
2446
nethercote59a122d2004-08-03 17:16:51 +00002447 for (i = 0; i < VG_MAX_JUMPS; i++)
2448 jumps[i] = (UShort)-1;
sewardjde4a1d02002-03-22 01:27:54 +00002449
sewardj25c7c3a2003-07-10 00:17:58 +00002450 /* Look in the code redirect table to see if we should
2451 translate an alternative address for orig_addr. */
fitzhardinge98abfc72003-12-16 02:05:15 +00002452 redir = VG_(code_redirect)(orig_addr);
2453
nethercote59a122d2004-08-03 17:16:51 +00002454 if (redir != orig_addr && VG_(clo_verbosity) >= 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002455 VG_(message)(Vg_UserMsg,
2456 "TRANSLATE: %p redirected to %p",
2457 orig_addr,
2458 redir );
nethercote59a122d2004-08-03 17:16:51 +00002459 }
fitzhardinge98abfc72003-12-16 02:05:15 +00002460 orig_addr = redir;
sewardj25c7c3a2003-07-10 00:17:58 +00002461
sewardja60be0e2003-05-26 08:47:27 +00002462 /* If codegen tracing, don't start tracing until
2463 notrace_until_limit blocks have gone by. This avoids printing
2464 huge amounts of useless junk when all we want to see is the last
2465 few blocks translated prior to a failure. Set
2466 notrace_until_limit to be the number of translations to be made
2467 before --trace-codegen= style printing takes effect. */
nethercote92e7b7f2004-08-07 17:52:25 +00002468 notrace_until_done = VG_(get_bbs_translated)() >= notrace_until_limit;
sewardja60be0e2003-05-26 08:47:27 +00002469
fitzhardinge98abfc72003-12-16 02:05:15 +00002470 seg = VG_(find_segment)(orig_addr);
2471
njn25e49d8e72002-09-23 09:36:25 +00002472 if (!debugging_translation)
njn72718642003-07-24 08:45:32 +00002473 VG_TRACK( pre_mem_read, Vg_CoreTranslate, tid, "", orig_addr, 1 );
sewardjde4a1d02002-03-22 01:27:54 +00002474
fitzhardinge98abfc72003-12-16 02:05:15 +00002475 if (seg == NULL ||
2476 !VG_(seg_contains)(seg, orig_addr, 1) ||
2477 (seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002478 /* Code address is bad - deliver a signal instead */
2479 vg_assert(!VG_(is_addressable)(orig_addr, 1));
2480
fitzhardinge98abfc72003-12-16 02:05:15 +00002481 if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
2482 vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
fitzhardingef1beb252004-03-16 09:49:08 +00002483 VG_(synth_fault_perms)(tid, orig_addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00002484 } else
fitzhardingef1beb252004-03-16 09:49:08 +00002485 VG_(synth_fault_mapping)(tid, orig_addr);
jsgf855d93d2003-10-13 22:26:55 +00002486
nethercote4d714382004-10-13 09:47:24 +00002487 return False;
fitzhardinge98abfc72003-12-16 02:05:15 +00002488 } else
2489 seg->flags |= SF_CODE; /* contains cached code */
jsgf855d93d2003-10-13 22:26:55 +00002490
nethercotecaee10d2004-08-03 17:39:06 +00002491 cb = alloc_UCodeBlock( orig_addr );
sewardjde4a1d02002-03-22 01:27:54 +00002492
njn25e49d8e72002-09-23 09:36:25 +00002493 /* If doing any code printing, print a basic block start marker */
sewardja60be0e2003-05-26 08:47:27 +00002494 if (VG_(clo_trace_codegen) && notrace_until_done) {
njn25e49d8e72002-09-23 09:36:25 +00002495 Char fnname[64] = "";
2496 VG_(get_fnname_if_entry)(orig_addr, fnname, 64);
2497 VG_(printf)(
nethercote92e7b7f2004-08-07 17:52:25 +00002498 "==== BB %d %s(%p) approx BBs exec'd %llu ====\n\n",
2499 VG_(get_bbs_translated)(), fnname, orig_addr,
njn25e49d8e72002-09-23 09:36:25 +00002500 VG_(bbs_done));
2501 }
2502
2503 /* True if a debug trans., or if bit N set in VG_(clo_trace_codegen). */
sewardja60be0e2003-05-26 08:47:27 +00002504# define DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(n) \
2505 ( debugging_translation \
2506 || (notrace_until_done \
2507 && (VG_(clo_trace_codegen) & (1 << (n-1))) ))
njn25e49d8e72002-09-23 09:36:25 +00002508
sewardjde4a1d02002-03-22 01:27:54 +00002509 /* Disassemble this basic block into cb. */
njn25e49d8e72002-09-23 09:36:25 +00002510 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(1);
2511 VGP_PUSHCC(VgpToUCode);
nethercote59a122d2004-08-03 17:16:51 +00002512 orig_size = VG_(disBB) ( cb, orig_addr );
nethercote885dd912004-08-03 23:14:00 +00002513 sanity_check_UCodeBlock ( cb );
2514 // Only sanity-check calls now because tools might remove the
2515 // CALLM_[ES] pairs.
2516 sanity_check_UCodeBlockCalls ( cb );
njn25e49d8e72002-09-23 09:36:25 +00002517 VGP_POPCC(VgpToUCode);
2518
sewardjde4a1d02002-03-22 01:27:54 +00002519 /* Try and improve the code a bit. */
2520 if (VG_(clo_optimise)) {
njn25e49d8e72002-09-23 09:36:25 +00002521 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(2);
2522 VGP_PUSHCC(VgpImprove);
sewardjde4a1d02002-03-22 01:27:54 +00002523 vg_improve ( cb );
njn25e49d8e72002-09-23 09:36:25 +00002524 VGP_POPCC(VgpImprove);
sewardjde4a1d02002-03-22 01:27:54 +00002525 }
2526
njn25e49d8e72002-09-23 09:36:25 +00002527 /* Skin's instrumentation (Nb: must set VG_(print_codegen) in case
2528 SK_(instrument) looks at it. */
2529 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(3);
2530 VGP_PUSHCC(VgpInstrument);
2531 cb = SK_(instrument) ( cb, orig_addr );
2532 if (VG_(print_codegen))
njn4ba5a792002-09-30 10:23:54 +00002533 VG_(pp_UCodeBlock) ( cb, "Instrumented UCode:" );
nethercote885dd912004-08-03 23:14:00 +00002534 sanity_check_UCodeBlock( cb );
njn25e49d8e72002-09-23 09:36:25 +00002535 VGP_POPCC(VgpInstrument);
njn4f9c9342002-04-29 16:03:24 +00002536
nethercote996901a2004-08-03 13:29:09 +00002537 /* Add %ESP-update hooks if the tool requires them */
njn9b007f62003-04-07 14:40:25 +00002538 /* Nb: We don't print out this phase, because it doesn't do much */
2539 if (VG_(need_to_handle_esp_assignment)()) {
2540 VGP_PUSHCC(VgpESPUpdate);
2541 cb = vg_ESP_update_pass ( cb );
2542 VGP_POPCC(VgpESPUpdate);
2543 }
2544
sewardjde4a1d02002-03-22 01:27:54 +00002545 /* Allocate registers. */
njn25e49d8e72002-09-23 09:36:25 +00002546 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(4);
2547 VGP_PUSHCC(VgpRegAlloc);
sewardjde4a1d02002-03-22 01:27:54 +00002548 cb = vg_do_register_allocation ( cb );
nethercote885dd912004-08-03 23:14:00 +00002549 beforeRA = False;
njn25e49d8e72002-09-23 09:36:25 +00002550 VGP_POPCC(VgpRegAlloc);
sewardjde4a1d02002-03-22 01:27:54 +00002551
njn25e49d8e72002-09-23 09:36:25 +00002552 /* Do post reg-alloc %e[acd]x liveness analysis (too boring to print
2553 * anything; results can be seen when emitting final code). */
2554 VGP_PUSHCC(VgpLiveness);
2555 vg_realreg_liveness_analysis ( cb );
nethercote885dd912004-08-03 23:14:00 +00002556 beforeLiveness = False;
njn25e49d8e72002-09-23 09:36:25 +00002557 VGP_POPCC(VgpLiveness);
2558
2559 /* Emit final code */
2560 VG_(print_codegen) = DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE(5);
njn25e49d8e72002-09-23 09:36:25 +00002561 VGP_PUSHCC(VgpFromUcode);
nethercote59a122d2004-08-03 17:16:51 +00002562 trans_addr = (Addr)VG_(emit_code)(cb, &trans_size, jumps );
njn25e49d8e72002-09-23 09:36:25 +00002563 VGP_POPCC(VgpFromUcode);
njn4ba5a792002-09-30 10:23:54 +00002564 VG_(free_UCodeBlock)(cb);
sewardjde4a1d02002-03-22 01:27:54 +00002565
njn25e49d8e72002-09-23 09:36:25 +00002566#undef DECIDE_IF_PRINTING_CODEGEN_FOR_PHASE
2567
nethercote59a122d2004-08-03 17:16:51 +00002568 /* Copy data at trans_addr into the translation cache. */
2569 /* Since the .orig_size and .trans_size fields are UShort, be paranoid. */
2570 vg_assert(orig_size > 0 && orig_size < 65536);
2571 vg_assert(trans_size > 0 && trans_size < 65536);
2572
2573 // If debugging, don't do anything with the translated block; we
2574 // only did this for the debugging output produced along the way.
2575 if (!debugging_translation) {
2576 // Note that we use orig_addr0, not orig_addr, which might have been
2577 // changed by the redirection
2578 VG_(add_to_trans_tab)( orig_addr0, orig_size, trans_addr, trans_size,
2579 jumps );
sewardjde4a1d02002-03-22 01:27:54 +00002580 }
nethercote59a122d2004-08-03 17:16:51 +00002581
2582 /* Free the intermediary -- was allocated by VG_(emit_code). */
2583 VG_(arena_free)( VG_AR_JITTER, (void*)trans_addr );
2584
njn25e49d8e72002-09-23 09:36:25 +00002585 VGP_POPCC(VgpTranslate);
nethercote4d714382004-10-13 09:47:24 +00002586
2587 return True;
sewardjde4a1d02002-03-22 01:27:54 +00002588}
2589
nethercote59a122d2004-08-03 17:16:51 +00002590
sewardjde4a1d02002-03-22 01:27:54 +00002591/*--------------------------------------------------------------------*/
2592/*--- end vg_translate.c ---*/
2593/*--------------------------------------------------------------------*/
njned619712003-10-01 16:45:04 +00002594