blob: d21bb86474d34cfba4203b8a60537c1d6710417a [file] [log] [blame]
nethercotebb1c9912004-01-04 16:43:23 +00001
njn25e49d8e72002-09-23 09:36:25 +00002/*--------------------------------------------------------------------*/
njnc9539842002-10-02 13:26:35 +00003/*--- Instrument UCode to perform memory checking operations. ---*/
njn25cac76cb2002-09-23 11:21:57 +00004/*--- mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00005/*--------------------------------------------------------------------*/
njnc9539842002-10-02 13:26:35 +00006
njn25e49d8e72002-09-23 09:36:25 +00007/*
nethercote137bc552003-11-14 17:47:54 +00008 This file is part of MemCheck, a heavyweight Valgrind tool for
njnc9539842002-10-02 13:26:35 +00009 detecting memory errors.
njn25e49d8e72002-09-23 09:36:25 +000010
nethercotebb1c9912004-01-04 16:43:23 +000011 Copyright (C) 2000-2004 Julian Seward
njn25e49d8e72002-09-23 09:36:25 +000012 jseward@acm.org
13
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
29 The GNU General Public License is contained in the file COPYING.
30*/
31
njn25cac76cb2002-09-23 11:21:57 +000032#include "mc_include.h"
njn25e49d8e72002-09-23 09:36:25 +000033
34/* ---------------------------------------------------------------------
35 Template functions for extending UCode
36 ------------------------------------------------------------------ */
37
38/* Compare this with the restrictions on core instructions in
39 vg_translate.c:VG_(saneUInstr)(). Everything general said there applies
40 here too.
41*/
njn4ba5a792002-09-30 10:23:54 +000042Bool SK_(sane_XUInstr)(Bool beforeRA, Bool beforeLiveness, UInstr* u)
njn25e49d8e72002-09-23 09:36:25 +000043{
44// SSS: duplicating these macros really sucks
45# define LIT0 (u->lit32 == 0)
46# define LIT1 (!(LIT0))
47# define LITm (u->tag1 == Literal ? True : LIT0 )
48# define SZ0 (u->size == 0)
49# define SZi (u->size == 4 || u->size == 2 || u->size == 1)
50# define SZj (u->size == 4 || u->size == 2 || u->size == 1 || u->size == 0)
51# define CC0 (u->flags_r == FlagsEmpty && u->flags_w == FlagsEmpty)
52# define TR1 (beforeRA ? (u->tag1 == TempReg) : (u->tag1 == RealReg))
53# define TR2 (beforeRA ? (u->tag2 == TempReg) : (u->tag2 == RealReg))
54# define A1 (u->tag1 == ArchReg)
55# define A2 (u->tag2 == ArchReg)
56# define L1 (u->tag1 == Literal && u->val1 == 0)
57# define Ls1 (u->tag1 == Lit16)
58# define Ls3 (u->tag3 == Lit16)
59# define TRL1 (TR1 || L1)
60# define TRA1 (TR1 || A1)
61# define N2 (u->tag2 == NoValue)
62# define N3 (u->tag3 == NoValue)
63# define COND0 (u->cond == 0)
64# define EXTRA4b0 (u->extra4b == 0)
65# define SG_WD0 (u->signed_widen == 0)
66# define JMPKIND0 (u->jmpkind == 0)
67# define CCALL0 (u->argc==0 && u->regparms_n==0 && u->has_ret_val==0 && \
68 ( beforeLiveness \
69 ? u->regs_live_after == ALL_RREGS_LIVE \
70 : True ))
71# define XOTHER (COND0 && EXTRA4b0 && SG_WD0 && JMPKIND0 && CCALL0)
72
73 Int n_lits = 0;
74 if (u->tag1 == Literal) n_lits++;
75 if (u->tag2 == Literal) n_lits++;
76 if (u->tag3 == Literal) n_lits++;
77 if (n_lits > 1)
78 return False;
79
80 /* Fields not checked: val1, val2, val3 */
81
82 switch (u->opcode) {
83
84 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
85 case LOADV: return LIT0 && SZi && CC0 && TR1 && TR2 && N3 && XOTHER;
86 case STOREV: return LITm && SZi && CC0 && TRL1 && TR2 && N3 && XOTHER;
87 case GETV: return LIT0 && SZi && CC0 && A1 && TR2 && N3 && XOTHER;
88 case PUTV: return LITm && SZi && CC0 && TRL1 && A2 && N3 && XOTHER;
89 case GETVF:
90 case PUTVF: return LIT0 && SZ0 && CC0 && TR1 && N2 && N3 && XOTHER;
91 case TESTV:
92 case SETV: return LIT0 && SZj && CC0 && TRA1 && N2 && N3 && XOTHER;
93 case TAG1: return LIT0 && SZ0 && CC0 && TR1 && N2 && Ls3 && XOTHER;
94 case TAG2: return LIT0 && SZ0 && CC0 && TR1 && TR2 && Ls3 && XOTHER;
95 default:
96 VG_(printf)("unhandled opcode: %u\n", u->opcode);
njne427a662002-10-02 11:08:25 +000097 VG_(skin_panic)("SK_(sane_XUInstr): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +000098 }
99# undef LIT0
100# undef LIT1
101# undef LITm
102# undef SZ0
103# undef SZi
104# undef SZj
105# undef CC0
106# undef TR1
107# undef TR2
108# undef A1
109# undef A2
110# undef L1
111# undef Ls1
112# undef Ls3
113# undef TRL1
114# undef TRA1
115# undef N2
116# undef N3
117# undef COND0
118# undef EXTRA4b0
119# undef JMPKIND0
120# undef CCALL0
121# undef XOTHER
122}
123
124static Char* nameOfTagOp ( TagOp h )
125{
126 switch (h) {
127 case Tag_PCast40: return "PCast40";
128 case Tag_PCast20: return "PCast20";
129 case Tag_PCast10: return "PCast10";
130 case Tag_PCast01: return "PCast01";
131 case Tag_PCast02: return "PCast02";
132 case Tag_PCast04: return "PCast04";
133 case Tag_PCast14: return "PCast14";
134 case Tag_PCast12: return "PCast12";
135 case Tag_PCast11: return "PCast11";
136 case Tag_Left4: return "Left4";
137 case Tag_Left2: return "Left2";
138 case Tag_Left1: return "Left1";
139 case Tag_SWiden14: return "SWiden14";
140 case Tag_SWiden24: return "SWiden24";
141 case Tag_SWiden12: return "SWiden12";
142 case Tag_ZWiden14: return "ZWiden14";
143 case Tag_ZWiden24: return "ZWiden24";
144 case Tag_ZWiden12: return "ZWiden12";
145 case Tag_UifU4: return "UifU4";
146 case Tag_UifU2: return "UifU2";
147 case Tag_UifU1: return "UifU1";
148 case Tag_UifU0: return "UifU0";
149 case Tag_DifD4: return "DifD4";
150 case Tag_DifD2: return "DifD2";
151 case Tag_DifD1: return "DifD1";
152 case Tag_ImproveAND4_TQ: return "ImproveAND4_TQ";
153 case Tag_ImproveAND2_TQ: return "ImproveAND2_TQ";
154 case Tag_ImproveAND1_TQ: return "ImproveAND1_TQ";
155 case Tag_ImproveOR4_TQ: return "ImproveOR4_TQ";
156 case Tag_ImproveOR2_TQ: return "ImproveOR2_TQ";
157 case Tag_ImproveOR1_TQ: return "ImproveOR1_TQ";
158 case Tag_DebugFn: return "DebugFn";
njne427a662002-10-02 11:08:25 +0000159 default: VG_(skin_panic)("vg_nameOfTagOp");
njn25e49d8e72002-09-23 09:36:25 +0000160 }
161}
162
163
njn4ba5a792002-09-30 10:23:54 +0000164Char* SK_(name_XUOpcode)(Opcode opc)
njn25e49d8e72002-09-23 09:36:25 +0000165{
166 switch (opc) {
167 case GETVF: return "GETVF";
168 case PUTVF: return "PUTVF";
169 case TAG1: return "TAG1";
170 case TAG2: return "TAG2";
171 case LOADV: return "LOADV";
172 case STOREV: return "STOREV";
173 case GETV: return "GETV";
174 case PUTV: return "PUTV";
175 case TESTV: return "TESTV";
176 case SETV: return "SETV";
177 default:
178 VG_(printf)("unhandled opcode: %u\n", opc);
njne427a662002-10-02 11:08:25 +0000179 VG_(skin_panic)("SK_(name_XUOpcode): unhandled case");
njn25e49d8e72002-09-23 09:36:25 +0000180 }
181}
182
183/* ---------------------------------------------------------------------
184 Debugging stuff.
185 ------------------------------------------------------------------ */
186
njn4ba5a792002-09-30 10:23:54 +0000187void SK_(pp_XUInstr)(UInstr* u)
njn25e49d8e72002-09-23 09:36:25 +0000188{
189 switch (u->opcode) {
njn25e49d8e72002-09-23 09:36:25 +0000190 case TAG1:
njn4ba5a792002-09-30 10:23:54 +0000191 VG_(pp_UOperand)(u, 1, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000192 VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
njn4ba5a792002-09-30 10:23:54 +0000193 VG_(pp_UOperand)(u, 1, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000194 VG_(printf)(" )");
195 break;
196
197 case TAG2:
njn4ba5a792002-09-30 10:23:54 +0000198 VG_(pp_UOperand)(u, 2, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000199 VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
njn4ba5a792002-09-30 10:23:54 +0000200 VG_(pp_UOperand)(u, 1, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000201 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +0000202 VG_(pp_UOperand)(u, 2, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000203 VG_(printf)(" )");
204 break;
205
206 case STOREV: case LOADV:
njn4ba5a792002-09-30 10:23:54 +0000207 VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOADV);
njn25e49d8e72002-09-23 09:36:25 +0000208 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +0000209 VG_(pp_UOperand)(u, 2, u->size, u->opcode==STOREV);
njn25e49d8e72002-09-23 09:36:25 +0000210 break;
211
212 case PUTVF: case GETVF:
njn4ba5a792002-09-30 10:23:54 +0000213 VG_(pp_UOperand)(u, 1, 0, False);
njn25e49d8e72002-09-23 09:36:25 +0000214 break;
215
216 case GETV: case PUTV:
njn4ba5a792002-09-30 10:23:54 +0000217 VG_(pp_UOperand)(u, 1, u->opcode==PUTV ? 4 : u->size, False);
njn25e49d8e72002-09-23 09:36:25 +0000218 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +0000219 VG_(pp_UOperand)(u, 2, u->opcode==GETV ? 4 : u->size, False);
njn25e49d8e72002-09-23 09:36:25 +0000220 break;
221
222 case TESTV: case SETV:
njn4ba5a792002-09-30 10:23:54 +0000223 VG_(pp_UOperand)(u, 1, u->size, False);
njn25e49d8e72002-09-23 09:36:25 +0000224 break;
225
226 default:
227 VG_(printf)("unhandled opcode: %u\n", u->opcode);
njne427a662002-10-02 11:08:25 +0000228 VG_(skin_panic)("SK_(pp_XUInstr): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000229 }
230
231}
232
njn810086f2002-11-14 12:42:47 +0000233Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, Int* regs, Bool* isWrites)
njn25e49d8e72002-09-23 09:36:25 +0000234{
njn810086f2002-11-14 12:42:47 +0000235# define RD(ono) VG_UINSTR_READS_REG(ono, regs, isWrites)
236# define WR(ono) VG_UINSTR_WRITES_REG(ono, regs, isWrites)
njn25e49d8e72002-09-23 09:36:25 +0000237
238 Int n = 0;
239 switch (u->opcode) {
njn25e49d8e72002-09-23 09:36:25 +0000240 case TAG1: RD(1); WR(1); break;
241 case TAG2: RD(1); RD(2); WR(2); break;
242 case LOADV: RD(1); WR(2); break;
243 case STOREV: RD(1); RD(2); break;
244 case GETV: WR(2); break;
245 case PUTV: RD(1); break;
246 case TESTV: RD(1); break;
247 case SETV: WR(1); break;
248 case PUTVF: RD(1); break;
249 case GETVF: WR(1); break;
250
251 default:
252 VG_(printf)("unhandled opcode: %u\n", u->opcode);
njne427a662002-10-02 11:08:25 +0000253 VG_(skin_panic)("SK_(get_Xreg_usage): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000254 }
255 return n;
256
257# undef RD
258# undef WR
259}
260
261/*------------------------------------------------------------*/
262/*--- New instrumentation machinery. ---*/
263/*------------------------------------------------------------*/
264
njn25e49d8e72002-09-23 09:36:25 +0000265static
266TagOp get_Tag_ImproveOR_TQ ( Int sz )
267{
268 switch (sz) {
269 case 4: return Tag_ImproveOR4_TQ;
270 case 2: return Tag_ImproveOR2_TQ;
271 case 1: return Tag_ImproveOR1_TQ;
njne427a662002-10-02 11:08:25 +0000272 default: VG_(skin_panic)("get_Tag_ImproveOR_TQ");
njn25e49d8e72002-09-23 09:36:25 +0000273 }
274}
275
276
277static
278TagOp get_Tag_ImproveAND_TQ ( Int sz )
279{
280 switch (sz) {
281 case 4: return Tag_ImproveAND4_TQ;
282 case 2: return Tag_ImproveAND2_TQ;
283 case 1: return Tag_ImproveAND1_TQ;
njne427a662002-10-02 11:08:25 +0000284 default: VG_(skin_panic)("get_Tag_ImproveAND_TQ");
njn25e49d8e72002-09-23 09:36:25 +0000285 }
286}
287
288
289static
290TagOp get_Tag_Left ( Int sz )
291{
292 switch (sz) {
293 case 4: return Tag_Left4;
294 case 2: return Tag_Left2;
295 case 1: return Tag_Left1;
njne427a662002-10-02 11:08:25 +0000296 default: VG_(skin_panic)("get_Tag_Left");
njn25e49d8e72002-09-23 09:36:25 +0000297 }
298}
299
300
301static
302TagOp get_Tag_UifU ( Int sz )
303{
304 switch (sz) {
305 case 4: return Tag_UifU4;
306 case 2: return Tag_UifU2;
307 case 1: return Tag_UifU1;
308 case 0: return Tag_UifU0;
njne427a662002-10-02 11:08:25 +0000309 default: VG_(skin_panic)("get_Tag_UifU");
njn25e49d8e72002-09-23 09:36:25 +0000310 }
311}
312
313
314static
315TagOp get_Tag_DifD ( Int sz )
316{
317 switch (sz) {
318 case 4: return Tag_DifD4;
319 case 2: return Tag_DifD2;
320 case 1: return Tag_DifD1;
njne427a662002-10-02 11:08:25 +0000321 default: VG_(skin_panic)("get_Tag_DifD");
njn25e49d8e72002-09-23 09:36:25 +0000322 }
323}
324
325
326static
327TagOp get_Tag_PCast ( Int szs, Int szd )
328{
329 if (szs == 4 && szd == 0) return Tag_PCast40;
330 if (szs == 2 && szd == 0) return Tag_PCast20;
331 if (szs == 1 && szd == 0) return Tag_PCast10;
332 if (szs == 0 && szd == 1) return Tag_PCast01;
333 if (szs == 0 && szd == 2) return Tag_PCast02;
334 if (szs == 0 && szd == 4) return Tag_PCast04;
335 if (szs == 1 && szd == 4) return Tag_PCast14;
336 if (szs == 1 && szd == 2) return Tag_PCast12;
337 if (szs == 1 && szd == 1) return Tag_PCast11;
338 VG_(printf)("get_Tag_PCast(%d,%d)\n", szs, szd);
njne427a662002-10-02 11:08:25 +0000339 VG_(skin_panic)("get_Tag_PCast");
njn25e49d8e72002-09-23 09:36:25 +0000340}
341
342
343static
344TagOp get_Tag_Widen ( Bool syned, Int szs, Int szd )
345{
346 if (szs == 1 && szd == 2 && syned) return Tag_SWiden12;
347 if (szs == 1 && szd == 2 && !syned) return Tag_ZWiden12;
348
349 if (szs == 1 && szd == 4 && syned) return Tag_SWiden14;
350 if (szs == 1 && szd == 4 && !syned) return Tag_ZWiden14;
351
352 if (szs == 2 && szd == 4 && syned) return Tag_SWiden24;
353 if (szs == 2 && szd == 4 && !syned) return Tag_ZWiden24;
354
355 VG_(printf)("get_Tag_Widen(%d,%d,%d)\n", (Int)syned, szs, szd);
njne427a662002-10-02 11:08:25 +0000356 VG_(skin_panic)("get_Tag_Widen");
njn25e49d8e72002-09-23 09:36:25 +0000357}
358
359/* Pessimally cast the spec'd shadow from one size to another. */
360static
361void create_PCast ( UCodeBlock* cb, Int szs, Int szd, Int tempreg )
362{
363 if (szs == 0 && szd == 0)
364 return;
365 uInstr3(cb, TAG1, 0, TempReg, tempreg,
366 NoValue, 0,
367 Lit16, get_Tag_PCast(szs,szd));
368}
369
370
371/* Create a signed or unsigned widen of the spec'd shadow from one
372 size to another. The only allowed size transitions are 1->2, 1->4
373 and 2->4. */
374static
375void create_Widen ( UCodeBlock* cb, Bool signed_widen,
376 Int szs, Int szd, Int tempreg )
377{
378 if (szs == szd) return;
379 uInstr3(cb, TAG1, 0, TempReg, tempreg,
380 NoValue, 0,
381 Lit16, get_Tag_Widen(signed_widen,szs,szd));
382}
383
384
385/* Get the condition codes into a new shadow, at the given size. */
386static
387Int create_GETVF ( UCodeBlock* cb, Int sz )
388{
389 Int tt = newShadow(cb);
390 uInstr1(cb, GETVF, 0, TempReg, tt);
391 create_PCast(cb, 0, sz, tt);
392 return tt;
393}
394
395
396/* Save the condition codes from the spec'd shadow. */
397static
398void create_PUTVF ( UCodeBlock* cb, Int sz, Int tempreg )
399{
400 if (sz == 0) {
401 uInstr1(cb, PUTVF, 0, TempReg, tempreg);
402 } else {
403 Int tt = newShadow(cb);
404 uInstr2(cb, MOV, 4, TempReg, tempreg, TempReg, tt);
405 create_PCast(cb, sz, 0, tt);
406 uInstr1(cb, PUTVF, 0, TempReg, tt);
407 }
408}
409
410
411/* Do Left on the spec'd shadow. */
412static
413void create_Left ( UCodeBlock* cb, Int sz, Int tempreg )
414{
415 uInstr3(cb, TAG1, 0,
416 TempReg, tempreg,
417 NoValue, 0,
418 Lit16, get_Tag_Left(sz));
419}
420
421
422/* Do UifU on ts and td, putting the result in td. */
423static
424void create_UifU ( UCodeBlock* cb, Int sz, Int ts, Int td )
425{
426 uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
427 Lit16, get_Tag_UifU(sz));
428}
429
430
431/* Do DifD on ts and td, putting the result in td. */
432static
433void create_DifD ( UCodeBlock* cb, Int sz, Int ts, Int td )
434{
435 uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
436 Lit16, get_Tag_DifD(sz));
437}
438
439
440/* Do HelpAND on value tval and tag tqqq, putting the result in
441 tqqq. */
442static
443void create_ImproveAND_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
444{
445 uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
446 Lit16, get_Tag_ImproveAND_TQ(sz));
447}
448
449
450/* Do HelpOR on value tval and tag tqqq, putting the result in
451 tqqq. */
452static
453void create_ImproveOR_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
454{
455 uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
456 Lit16, get_Tag_ImproveOR_TQ(sz));
457}
458
459
460/* Get the shadow for an operand described by (tag, val). Emit code
461 to do this and return the identity of the shadow holding the
462 result. The result tag is always copied into a new shadow, so it
463 can be modified without trashing the original.*/
464static
465Int /* TempReg */ getOperandShadow ( UCodeBlock* cb,
466 Int sz, Int tag, Int val )
467{
468 Int sh;
469 sh = newShadow(cb);
470 if (tag == TempReg) {
471 uInstr2(cb, MOV, 4, TempReg, SHADOW(val), TempReg, sh);
472 return sh;
473 }
474 if (tag == Literal) {
475 uInstr1(cb, SETV, sz, TempReg, sh);
476 return sh;
477 }
478 if (tag == ArchReg) {
479 uInstr2(cb, GETV, sz, ArchReg, val, TempReg, sh);
480 return sh;
481 }
njne427a662002-10-02 11:08:25 +0000482 VG_(skin_panic)("getOperandShadow");
njn25e49d8e72002-09-23 09:36:25 +0000483}
484
485/* Create and return an instrumented version of cb_in. Free cb_in
486 before returning. */
487static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
488{
489 UCodeBlock* cb;
490 Int i, j;
491 UInstr* u_in;
492 Int qs, qd, qt, qtt;
sewardj8ec2cfc2002-10-13 00:57:26 +0000493 Bool bogusLiterals;
njn810086f2002-11-14 12:42:47 +0000494
495 cb = VG_(setup_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +0000496
sewardj8ec2cfc2002-10-13 00:57:26 +0000497 /* Scan the block to look for bogus literals. These are magic
498 numbers which particularly appear in hand-optimised / inlined
499 implementations of strlen() et al which cause so much trouble
500 (spurious reports of uninit-var uses). Purpose of this horrible
501 hack is to disable some checks any such literals are present in
502 this basic block. */
503 bogusLiterals = False;
504
njn5c004e42002-11-18 11:04:50 +0000505 if (MC_(clo_avoid_strlen_errors)) {
njn810086f2002-11-14 12:42:47 +0000506 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
507 u_in = VG_(get_instr)(cb_in, i);
sewardj8ec2cfc2002-10-13 00:57:26 +0000508 switch (u_in->opcode) {
509 case ADD: case SUB: case MOV:
510 if (u_in->size == 4 && u_in->tag1 == Literal)
511 goto literal;
512 break;
513 case LEA1:
514 sk_assert(u_in->size == 4);
515 goto literal;
516 default:
517 break;
518 }
519 continue;
520 literal:
521 if (u_in->lit32 == 0xFEFEFEFF ||
522 u_in->lit32 == 0x80808080 ||
523 u_in->lit32 == 0x00008080) {
524 bogusLiterals = True;
525 break;
526 }
527 }
528 }
529
njn810086f2002-11-14 12:42:47 +0000530 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
531 u_in = VG_(get_instr)(cb_in, i);
njn25e49d8e72002-09-23 09:36:25 +0000532 qs = qd = qt = qtt = INVALID_TEMPREG;
njn25e49d8e72002-09-23 09:36:25 +0000533
534 switch (u_in->opcode) {
535
sewardj7a5ebcf2002-11-13 22:42:13 +0000536 case LOCK:
njn25e49d8e72002-09-23 09:36:25 +0000537 case NOP:
538 break;
539
540 case INCEIP:
njn4ba5a792002-09-30 10:23:54 +0000541 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000542 break;
543
sewardjd077f532002-09-30 21:52:50 +0000544 /* The segment registers do not have their definedness
545 tracked. We therefore make fake shadows on GETSEG and
546 test them on PUTSEG. This will catch writing garbage to a
547 segment register; therefore we can assume it to be defined
548 when read (GETSEGd). Since the first arg of USESEG is
549 fetched by GETSEG, we can assume it to be defined, and so
550 the definedness of the result is simply the definedness of
551 the second (virtual_address) arg of USESEG. The upshot of
552 all this is that instrumentation of USESEG is a no-op! */
553
554 case PUTSEG:
njne427a662002-10-02 11:08:25 +0000555 sk_assert(u_in->tag1 == TempReg);
sewardjd077f532002-09-30 21:52:50 +0000556 uInstr1(cb, TESTV, 2, TempReg, SHADOW(u_in->val1));
557 uInstr1(cb, SETV, 2, TempReg, SHADOW(u_in->val1));
558 VG_(copy_UInstr)(cb, u_in);
559 break;
560
561 case GETSEG:
njne427a662002-10-02 11:08:25 +0000562 sk_assert(u_in->tag2 == TempReg);
sewardjd077f532002-09-30 21:52:50 +0000563 uInstr1(cb, SETV, 2, TempReg, SHADOW(u_in->val2));
564 VG_(copy_UInstr)(cb, u_in);
565 break;
566
567 case USESEG:
568 VG_(copy_UInstr)(cb, u_in);
569 break;
570
njn25e49d8e72002-09-23 09:36:25 +0000571 /* Loads and stores. Test the V bits for the address. 24
572 Mar 02: since the address is A-checked anyway, there's not
573 really much point in doing the V-check too, unless you
574 think that you might use addresses which are undefined but
575 still addressible. Hence the optionalisation of the V
sewardj51647482002-12-15 01:42:22 +0000576 check. 15 Dec 02: optionalisation removed, since it no
577 longer makes much sense given we also have an addrcheck
578 skin.
njn25e49d8e72002-09-23 09:36:25 +0000579
580 The LOADV/STOREV does an addressibility check for the
581 address. */
582
583 case LOAD:
sewardj51647482002-12-15 01:42:22 +0000584 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
585 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
njn25e49d8e72002-09-23 09:36:25 +0000586 uInstr2(cb, LOADV, u_in->size,
587 TempReg, u_in->val1,
588 TempReg, SHADOW(u_in->val2));
njn4ba5a792002-09-30 10:23:54 +0000589 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000590 break;
591
592 case STORE:
sewardj51647482002-12-15 01:42:22 +0000593 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
594 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
njn25e49d8e72002-09-23 09:36:25 +0000595 uInstr2(cb, STOREV, u_in->size,
596 TempReg, SHADOW(u_in->val1),
597 TempReg, u_in->val2);
njn4ba5a792002-09-30 10:23:54 +0000598 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000599 break;
600
601 /* Moving stuff around. Make the V bits follow accordingly,
602 but don't do anything else. */
603
604 case GET:
605 uInstr2(cb, GETV, u_in->size,
606 ArchReg, u_in->val1,
607 TempReg, SHADOW(u_in->val2));
njn4ba5a792002-09-30 10:23:54 +0000608 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000609 break;
610
611 case PUT:
612 uInstr2(cb, PUTV, u_in->size,
613 TempReg, SHADOW(u_in->val1),
614 ArchReg, u_in->val2);
njn4ba5a792002-09-30 10:23:54 +0000615 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000616 break;
617
618 case GETF:
619 /* This is not the smartest way to do it, but should work. */
620 qd = create_GETVF(cb, u_in->size);
621 uInstr2(cb, MOV, 4, TempReg, qd, TempReg, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000622 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000623 break;
624
625 case PUTF:
626 create_PUTVF(cb, u_in->size, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000627 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000628 break;
629
630 case MOV:
631 switch (u_in->tag1) {
632 case TempReg:
633 uInstr2(cb, MOV, 4,
634 TempReg, SHADOW(u_in->val1),
635 TempReg, SHADOW(u_in->val2));
636 break;
637 case Literal:
638 uInstr1(cb, SETV, u_in->size,
639 TempReg, SHADOW(u_in->val2));
640 break;
641 default:
njne427a662002-10-02 11:08:25 +0000642 VG_(skin_panic)("memcheck_instrument: MOV");
njn25e49d8e72002-09-23 09:36:25 +0000643 }
njn4ba5a792002-09-30 10:23:54 +0000644 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000645 break;
646
647 /* Special case of add, where one of the operands is a literal.
648 lea1(t) = t + some literal.
649 Therefore: lea1#(qa) = left(qa)
650 */
651 case LEA1:
njne427a662002-10-02 11:08:25 +0000652 sk_assert(u_in->size == 4 && !VG_(any_flag_use)(u_in));
njn25e49d8e72002-09-23 09:36:25 +0000653 qs = SHADOW(u_in->val1);
654 qd = SHADOW(u_in->val2);
655 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qd);
656 create_Left(cb, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000657 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000658 break;
659
660 /* Another form of add.
661 lea2(ts,tt,shift) = ts + (tt << shift); shift is a literal
662 and is 0,1,2 or 3.
663 lea2#(qs,qt) = left(qs `UifU` (qt << shift)).
664 Note, subtly, that the shift puts zeroes at the bottom of qt,
665 meaning Valid, since the corresponding shift of tt puts
666 zeroes at the bottom of tb.
667 */
668 case LEA2: {
669 Int shift;
njne427a662002-10-02 11:08:25 +0000670 sk_assert(u_in->size == 4 && !VG_(any_flag_use)(u_in));
njn25e49d8e72002-09-23 09:36:25 +0000671 switch (u_in->extra4b) {
672 case 1: shift = 0; break;
673 case 2: shift = 1; break;
674 case 4: shift = 2; break;
675 case 8: shift = 3; break;
njne427a662002-10-02 11:08:25 +0000676 default: VG_(skin_panic)( "memcheck_instrument(LEA2)" );
njn25e49d8e72002-09-23 09:36:25 +0000677 }
678 qs = SHADOW(u_in->val1);
679 qt = SHADOW(u_in->val2);
680 qd = SHADOW(u_in->val3);
681 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qd);
682 if (shift > 0) {
683 uInstr2(cb, SHL, 4, Literal, 0, TempReg, qd);
684 uLiteral(cb, shift);
685 }
686 create_UifU(cb, 4, qs, qd);
687 create_Left(cb, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000688 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000689 break;
690 }
691
692 /* inc#/dec#(qd) = q `UifU` left(qd) = left(qd) */
693 case INC: case DEC:
694 qd = SHADOW(u_in->val1);
695 create_Left(cb, u_in->size, qd);
696 if (u_in->flags_w != FlagsEmpty)
697 create_PUTVF(cb, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000698 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000699 break;
700
701 /* This is a HACK (approximation :-) */
702 /* rcl#/rcr#(qs,qd)
703 = let q0 = pcast-sz-0(qd) `UifU` pcast-sz-0(qs) `UifU` eflags#
704 eflags# = q0
705 qd =pcast-0-sz(q0)
706 Ie, cast everything down to a single bit, then back up.
707 This assumes that any bad bits infect the whole word and
708 the eflags.
709 */
710 case RCL: case RCR:
njne427a662002-10-02 11:08:25 +0000711 sk_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000712 /* The following assertion looks like it makes sense, but is
713 actually wrong. Consider this:
714 rcll %eax
715 imull %eax, %eax
716 The rcll writes O and C but so does the imull, so the O and C
717 write of the rcll is annulled by the prior improvement pass.
718 Noticed by Kevin Ryde <user42@zip.com.au>
719 */
njne427a662002-10-02 11:08:25 +0000720 /* sk_assert(u_in->flags_w != FlagsEmpty); */
njn25e49d8e72002-09-23 09:36:25 +0000721 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
722 /* We can safely modify qs; cast it to 0-size. */
723 create_PCast(cb, u_in->size, 0, qs);
724 qd = SHADOW(u_in->val2);
725 create_PCast(cb, u_in->size, 0, qd);
726 /* qs is cast-to-0(shift count#), and qd is cast-to-0(value#). */
727 create_UifU(cb, 0, qs, qd);
728 /* qs is now free; reuse it for the flag definedness. */
729 qs = create_GETVF(cb, 0);
730 create_UifU(cb, 0, qs, qd);
731 create_PUTVF(cb, 0, qd);
732 create_PCast(cb, 0, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000733 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000734 break;
735
736 /* for OP in shl shr sar rol ror
737 (qs is shift count#, qd is value to be OP#d)
738 OP(ts,td)
739 OP#(qs,qd)
740 = pcast-1-sz(qs) `UifU` OP(ts,qd)
741 So we apply OP to the tag bits too, and then UifU with
742 the shift count# to take account of the possibility of it
743 being undefined.
744
745 A bit subtle:
746 ROL/ROR rearrange the tag bits as per the value bits.
747 SHL/SHR shifts zeroes into the value, and corresponding
748 zeroes indicating Definedness into the tag.
749 SAR copies the top bit of the value downwards, and therefore
750 SAR also copies the definedness of the top bit too.
751 So in all five cases, we just apply the same op to the tag
752 bits as is applied to the value bits. Neat!
753 */
754 case SHL:
755 case SHR: case SAR:
756 case ROL: case ROR: {
757 Int t_amount = INVALID_TEMPREG;
njne427a662002-10-02 11:08:25 +0000758 sk_assert(u_in->tag1 == TempReg || u_in->tag1 == Literal);
759 sk_assert(u_in->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000760 qd = SHADOW(u_in->val2);
761
762 /* Make qs hold shift-count# and make
763 t_amount be a TempReg holding the shift count. */
764 if (u_in->tag1 == Literal) {
765 t_amount = newTemp(cb);
766 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_amount);
767 uLiteral(cb, u_in->lit32);
768 qs = SHADOW(t_amount);
769 uInstr1(cb, SETV, 1, TempReg, qs);
770 } else {
771 t_amount = u_in->val1;
772 qs = SHADOW(u_in->val1);
773 }
774
775 uInstr2(cb, u_in->opcode,
776 u_in->size,
777 TempReg, t_amount,
778 TempReg, qd);
779 qt = newShadow(cb);
780 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
781 create_PCast(cb, 1, u_in->size, qt);
782 create_UifU(cb, u_in->size, qt, qd);
njn4ba5a792002-09-30 10:23:54 +0000783 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000784 break;
785 }
786
787 /* One simple tag operation. */
788 case WIDEN:
njne427a662002-10-02 11:08:25 +0000789 sk_assert(u_in->tag1 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000790 create_Widen(cb, u_in->signed_widen, u_in->extra4b, u_in->size,
791 SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000792 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000793 break;
794
795 /* not#(x) = x (since bitwise independent) */
796 case NOT:
njne427a662002-10-02 11:08:25 +0000797 sk_assert(u_in->tag1 == TempReg);
njn4ba5a792002-09-30 10:23:54 +0000798 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000799 break;
800
801 /* neg#(x) = left(x) (derivable from case for SUB) */
802 case NEG:
njne427a662002-10-02 11:08:25 +0000803 sk_assert(u_in->tag1 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000804 create_Left(cb, u_in->size, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000805 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000806 break;
807
808 /* bswap#(x) = bswap(x) */
809 case BSWAP:
njne427a662002-10-02 11:08:25 +0000810 sk_assert(u_in->tag1 == TempReg);
811 sk_assert(u_in->size == 4);
njn25e49d8e72002-09-23 09:36:25 +0000812 qd = SHADOW(u_in->val1);
813 uInstr1(cb, BSWAP, 4, TempReg, qd);
njn4ba5a792002-09-30 10:23:54 +0000814 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000815 break;
816
817 /* cc2val#(qd) = pcast-0-to-size(eflags#) */
818 case CC2VAL:
njne427a662002-10-02 11:08:25 +0000819 sk_assert(u_in->tag1 == TempReg);
820 sk_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000821 qt = create_GETVF(cb, u_in->size);
822 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000823 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000824 break;
825
826 /* cmov#(qs,qd) = cmov(qs,qd)
827 That is, do the cmov of tags using the same flags as for
828 the data (obviously). However, first do a test on the
829 validity of the flags.
830 */
831 case CMOV:
njne427a662002-10-02 11:08:25 +0000832 sk_assert(u_in->size == 4);
833 sk_assert(u_in->tag1 == TempReg);
834 sk_assert(u_in->tag2 == TempReg);
835 sk_assert(u_in->flags_r != FlagsEmpty);
836 sk_assert(u_in->flags_w == FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000837 qs = SHADOW(u_in->val1);
838 qd = SHADOW(u_in->val2);
839 qt = create_GETVF(cb, 0);
840 uInstr1(cb, TESTV, 0, TempReg, qt);
841 /* qt should never be referred to again. Nevertheless
842 ... */
843 uInstr1(cb, SETV, 0, TempReg, qt);
844
845 uInstr2(cb, CMOV, 4, TempReg, qs, TempReg, qd);
njn810086f2002-11-14 12:42:47 +0000846 uCond(cb, u_in->cond);
847 uFlagsRWU(cb, u_in->flags_r, u_in->flags_w, FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000848
njn4ba5a792002-09-30 10:23:54 +0000849 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000850 break;
851
852 /* add#/sub#(qs,qd)
853 = qs `UifU` qd `UifU` left(qs) `UifU` left(qd)
854 = left(qs) `UifU` left(qd)
855 = left(qs `UifU` qd)
856 adc#/sbb#(qs,qd)
857 = left(qs `UifU` qd) `UifU` pcast(eflags#)
858 Second arg (dest) is TempReg.
859 First arg (src) is Literal or TempReg or ArchReg.
860 */
861 case ADD: case SUB:
862 case ADC: case SBB:
jsgf5efa4fd2003-10-14 21:49:11 +0000863 case MUL:
njn25e49d8e72002-09-23 09:36:25 +0000864 qd = SHADOW(u_in->val2);
865 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
866 create_UifU(cb, u_in->size, qs, qd);
867 create_Left(cb, u_in->size, qd);
868 if (u_in->opcode == ADC || u_in->opcode == SBB) {
njne427a662002-10-02 11:08:25 +0000869 sk_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000870 qt = create_GETVF(cb, u_in->size);
871 create_UifU(cb, u_in->size, qt, qd);
872 }
873 if (u_in->flags_w != FlagsEmpty) {
874 create_PUTVF(cb, u_in->size, qd);
875 }
njn4ba5a792002-09-30 10:23:54 +0000876 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000877 break;
878
879 /* xor#(qs,qd) = qs `UifU` qd */
880 case XOR:
881 qd = SHADOW(u_in->val2);
882 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
883 create_UifU(cb, u_in->size, qs, qd);
884 if (u_in->flags_w != FlagsEmpty) {
885 create_PUTVF(cb, u_in->size, qd);
886 }
njn4ba5a792002-09-30 10:23:54 +0000887 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000888 break;
889
890 /* and#/or#(qs,qd)
891 = (qs `UifU` qd) `DifD` improve(vs,qs)
892 `DifD` improve(vd,qd)
893 where improve is the relevant one of
894 Improve{AND,OR}_TQ
895 Use the following steps, with qt as a temp:
896 qt = improve(vd,qd)
897 qd = qs `UifU` qd
898 qd = qt `DifD` qd
899 qt = improve(vs,qs)
900 qd = qt `DifD` qd
901 */
902 case AND: case OR:
njne427a662002-10-02 11:08:25 +0000903 sk_assert(u_in->tag1 == TempReg);
904 sk_assert(u_in->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000905 qd = SHADOW(u_in->val2);
906 qs = SHADOW(u_in->val1);
907 qt = newShadow(cb);
908
909 /* qt = improve(vd,qd) */
910 uInstr2(cb, MOV, 4, TempReg, qd, TempReg, qt);
911 if (u_in->opcode == AND)
912 create_ImproveAND_TQ(cb, u_in->size, u_in->val2, qt);
913 else
914 create_ImproveOR_TQ(cb, u_in->size, u_in->val2, qt);
915 /* qd = qs `UifU` qd */
916 create_UifU(cb, u_in->size, qs, qd);
917 /* qd = qt `DifD` qd */
918 create_DifD(cb, u_in->size, qt, qd);
919 /* qt = improve(vs,qs) */
920 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
921 if (u_in->opcode == AND)
922 create_ImproveAND_TQ(cb, u_in->size, u_in->val1, qt);
923 else
924 create_ImproveOR_TQ(cb, u_in->size, u_in->val1, qt);
925 /* qd = qt `DifD` qd */
926 create_DifD(cb, u_in->size, qt, qd);
927 /* So, finally qd is the result tag. */
928 if (u_in->flags_w != FlagsEmpty) {
929 create_PUTVF(cb, u_in->size, qd);
930 }
njn4ba5a792002-09-30 10:23:54 +0000931 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000932 break;
933
934 /* Machinery to do with supporting CALLM. Copy the start and
935 end markers only to make the result easier to read
936 (debug); they generate no code and have no effect.
937 */
938 case CALLM_S: case CALLM_E:
njn4ba5a792002-09-30 10:23:54 +0000939 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000940 break;
941
942 /* Copy PUSH and POP verbatim. Arg/result absval
943 calculations are done when the associated CALL is
944 processed. CLEAR has no effect on absval calculations but
945 needs to be copied.
946 */
947 case PUSH: case POP: case CLEAR:
njn4ba5a792002-09-30 10:23:54 +0000948 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000949 break;
950
951 /* In short:
952 callm#(a1# ... an#) = (a1# `UifU` ... `UifU` an#)
953 We have to decide on a size to do the computation at,
954 although the choice doesn't affect correctness. We will
955 do a pcast to the final size anyway, so the only important
956 factor is to choose a size which minimises the total
957 number of casts needed. Valgrind: just use size 0,
958 regardless. It may not be very good for performance
959 but does simplify matters, mainly by reducing the number
960 of different pessimising casts which have to be implemented.
961 */
962 case CALLM: {
963 UInstr* uu;
964 Bool res_used;
965
966 /* Now generate the code. Get the final result absval
967 into qt. */
968 qt = newShadow(cb);
969 qtt = newShadow(cb);
970 uInstr1(cb, SETV, 0, TempReg, qt);
njn810086f2002-11-14 12:42:47 +0000971 for (j = i-1; VG_(get_instr)(cb_in, j)->opcode != CALLM_S; j--) {
972 uu = VG_(get_instr)(cb_in, j);
njn25e49d8e72002-09-23 09:36:25 +0000973 if (uu->opcode != PUSH) continue;
974 /* cast via a temporary */
975 uInstr2(cb, MOV, 4, TempReg, SHADOW(uu->val1),
976 TempReg, qtt);
977 create_PCast(cb, uu->size, 0, qtt);
978 create_UifU(cb, 0, qtt, qt);
979 }
980 /* Remembering also that flags read count as inputs. */
981 if (u_in->flags_r != FlagsEmpty) {
982 qtt = create_GETVF(cb, 0);
983 create_UifU(cb, 0, qtt, qt);
984 }
985
986 /* qt now holds the result tag. If any results from the
987 call are used, either by fetching with POP or
988 implicitly by writing the flags, we copy the result
989 absval to the relevant location. If not used, the call
990 must have been for its side effects, so we test qt here
991 and now. Note that this assumes that all values
992 removed by POP continue to be live. So dead args
993 *must* be removed with CLEAR, not by POPping them into
994 a dummy tempreg.
995 */
996 res_used = False;
njn810086f2002-11-14 12:42:47 +0000997 for (j = i+1; VG_(get_instr)(cb_in, j)->opcode != CALLM_E; j++) {
998 uu = VG_(get_instr)(cb_in, j);
njn25e49d8e72002-09-23 09:36:25 +0000999 if (uu->opcode != POP) continue;
1000 /* Cast via a temp. */
1001 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qtt);
1002 create_PCast(cb, 0, uu->size, qtt);
1003 uInstr2(cb, MOV, 4, TempReg, qtt,
1004 TempReg, SHADOW(uu->val1));
1005 res_used = True;
1006 }
1007 if (u_in->flags_w != FlagsEmpty) {
1008 create_PUTVF(cb, 0, qt);
1009 res_used = True;
1010 }
1011 if (!res_used) {
1012 uInstr1(cb, TESTV, 0, TempReg, qt);
1013 /* qt should never be referred to again. Nevertheless
1014 ... */
1015 uInstr1(cb, SETV, 0, TempReg, qt);
1016 }
njn4ba5a792002-09-30 10:23:54 +00001017 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001018 break;
1019 }
1020 /* Whew ... */
1021
1022 case JMP:
1023 if (u_in->tag1 == TempReg) {
1024 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1025 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
1026 } else {
njne427a662002-10-02 11:08:25 +00001027 sk_assert(u_in->tag1 == Literal);
njn25e49d8e72002-09-23 09:36:25 +00001028 }
1029 if (u_in->cond != CondAlways) {
njne427a662002-10-02 11:08:25 +00001030 sk_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +00001031 qt = create_GETVF(cb, 0);
sewardj8ec2cfc2002-10-13 00:57:26 +00001032 if (/* HACK */ bogusLiterals) {
1033 if (0)
1034 VG_(printf)("ignore TESTV due to bogus literal\n");
1035 } else {
1036 uInstr1(cb, TESTV, 0, TempReg, qt);
1037 }
njn25e49d8e72002-09-23 09:36:25 +00001038 /* qt should never be referred to again. Nevertheless
1039 ... */
1040 uInstr1(cb, SETV, 0, TempReg, qt);
1041 }
njn4ba5a792002-09-30 10:23:54 +00001042 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001043 break;
1044
1045 case JIFZ:
1046 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1047 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +00001048 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001049 break;
1050
1051 /* Emit a check on the address used. The value loaded into the
1052 FPU is checked by the call to fpu_{read/write}_check(). */
sewardj901a4a92003-03-30 01:52:26 +00001053 case MMX2_MemRd: case MMX2_MemWr:
njn25e49d8e72002-09-23 09:36:25 +00001054 case FPU_R: case FPU_W: {
1055 Int t_size = INVALID_TEMPREG;
njnfa509e22003-08-28 17:46:16 +00001056 Bool is_load;
njn25e49d8e72002-09-23 09:36:25 +00001057
sewardjd7971012003-04-04 00:21:58 +00001058 if (u_in->opcode == MMX2_MemRd || u_in->opcode == MMX2_MemWr)
1059 sk_assert(u_in->size == 4 || u_in->size == 8);
1060
njnfa509e22003-08-28 17:46:16 +00001061 is_load = u_in->opcode==FPU_R || u_in->opcode==MMX2_MemRd;
njne427a662002-10-02 11:08:25 +00001062 sk_assert(u_in->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +00001063 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
1064 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1065
1066 t_size = newTemp(cb);
1067 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1068 uLiteral(cb, u_in->size);
1069 uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
njnfa509e22003-08-28 17:46:16 +00001070 uCCall(cb, is_load ? (Addr) & MC_(fpu_read_check)
1071 : (Addr) & MC_(fpu_write_check),
njn25e49d8e72002-09-23 09:36:25 +00001072 2, 2, False);
1073
njn4ba5a792002-09-30 10:23:54 +00001074 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001075 break;
1076 }
1077
sewardjb1116852003-10-17 21:51:28 +00001078 /* SSE ins referencing scalar integer registers */
daywalkerb6d9b542003-09-26 00:16:25 +00001079 case SSE3g_RegWr:
1080 case SSE3e_RegRd:
1081 case SSE3e_RegWr:
sewardjb1116852003-10-17 21:51:28 +00001082 case SSE3g1_RegWr:
1083 case SSE3e1_RegRd:
daywalkerb6d9b542003-09-26 00:16:25 +00001084 sk_assert(u_in->tag3 == TempReg);
1085
sewardjb1116852003-10-17 21:51:28 +00001086 if (u_in->opcode == SSE3e1_RegRd) {
1087 sk_assert(u_in->size == 2);
1088 } else {
1089 sk_assert(u_in->size == 4);
1090 }
daywalkerb6d9b542003-09-26 00:16:25 +00001091
sewardjb1116852003-10-17 21:51:28 +00001092 /* Is it a read ? Better check the V bits right now. */
1093 if ( u_in->opcode == SSE3e_RegRd
1094 || u_in->opcode == SSE3e1_RegRd )
1095 uInstr1(cb, TESTV, u_in->size,
1096 TempReg, SHADOW(u_in->val3));
1097
1098 /* And for both read and write, set the register to be
1099 defined. */
1100 uInstr1(cb, SETV, u_in->size,
1101 TempReg, SHADOW(u_in->val3));
daywalkerb6d9b542003-09-26 00:16:25 +00001102
1103 VG_(copy_UInstr)(cb, u_in);
1104 break;
1105
1106 /* ... and the same deal for SSE insns referencing memory */
sewardj93992e22003-05-26 09:17:41 +00001107 case SSE3a_MemRd:
1108 case SSE3a_MemWr:
1109 case SSE2a_MemWr:
sewardj77d30a22003-10-19 08:18:52 +00001110 case SSE2a_MemRd:
1111 case SSE3a1_MemRd: {
sewardj93992e22003-05-26 09:17:41 +00001112 Bool is_load;
1113 Int t_size;
1114
jsewardfca60182004-01-04 23:30:55 +00001115 sk_assert(u_in->size == 4 || u_in->size == 8
1116 || u_in->size == 16 || u_in->size == 512);
sewardj93992e22003-05-26 09:17:41 +00001117
1118 t_size = INVALID_TEMPREG;
sewardjb1116852003-10-17 21:51:28 +00001119 is_load = u_in->opcode==SSE2a_MemRd
sewardj77d30a22003-10-19 08:18:52 +00001120 || u_in->opcode==SSE3a_MemRd
1121 || u_in->opcode==SSE3a1_MemRd;
sewardj93992e22003-05-26 09:17:41 +00001122
daywalkerb6d9b542003-09-26 00:16:25 +00001123 sk_assert(u_in->tag3 == TempReg);
1124
1125 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val3));
1126 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val3));
1127 t_size = newTemp(cb);
1128 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1129 uLiteral(cb, u_in->size);
1130 uInstr2(cb, CCALL, 0, TempReg, u_in->val3, TempReg, t_size);
1131 uCCall(cb, is_load ? (Addr) & MC_(fpu_read_check)
1132 : (Addr) & MC_(fpu_write_check),
1133 2, 2, False);
1134
sewardj93992e22003-05-26 09:17:41 +00001135 VG_(copy_UInstr)(cb, u_in);
1136 break;
1137 }
sewardjb1116852003-10-17 21:51:28 +00001138
daywalkerb6d9b542003-09-26 00:16:25 +00001139 case SSE3ag_MemRd_RegWr:
1140 {
1141 Int t_size;
sewardj93992e22003-05-26 09:17:41 +00001142
daywalkerb6d9b542003-09-26 00:16:25 +00001143 sk_assert(u_in->size == 4 || u_in->size == 8);
1144 sk_assert(u_in->tag1 == TempReg);
1145 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1146 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
1147 t_size = newTemp(cb);
1148 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1149 uLiteral(cb, u_in->size);
1150 uInstr2(cb, CCALL, 0, TempReg, u_in->val1, TempReg, t_size);
1151 uCCall(cb, (Addr) MC_(fpu_read_check), 2, 2, False );
1152 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1153 VG_(copy_UInstr)(cb, u_in);
1154 break;
1155 }
sewardj247f32f2003-10-03 20:40:45 +00001156
1157 /* For FPU, MMX and SSE insns not referencing memory, just
1158 copy thru. */
1159 case SSE5: case SSE4: case SSE3:
sewardj901a4a92003-03-30 01:52:26 +00001160 case MMX1: case MMX2: case MMX3:
njn25e49d8e72002-09-23 09:36:25 +00001161 case FPU:
njn4ba5a792002-09-30 10:23:54 +00001162 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001163 break;
1164
sewardj901a4a92003-03-30 01:52:26 +00001165 /* Since we don't track definedness of values inside the
1166 MMX state, we'd better check that the (int) reg being
1167 read here is defined. */
sewardj4fbe6e92003-06-15 21:54:34 +00001168 case MMX2_ERegRd:
sewardj901a4a92003-03-30 01:52:26 +00001169 sk_assert(u_in->tag2 == TempReg);
1170 sk_assert(u_in->size == 4);
1171 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
1172 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1173 VG_(copy_UInstr)(cb, u_in);
1174 break;
1175
sewardjd1c9e432003-04-04 20:40:34 +00001176 /* The MMX register is assumed to be fully defined, so
1177 that's what this register becomes. */
sewardj4fbe6e92003-06-15 21:54:34 +00001178 case MMX2_ERegWr:
sewardjd1c9e432003-04-04 20:40:34 +00001179 sk_assert(u_in->tag2 == TempReg);
1180 sk_assert(u_in->size == 4);
1181 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1182 VG_(copy_UInstr)(cb, u_in);
sewardj3d7c9c82003-03-26 21:08:13 +00001183 break;
1184
njn25e49d8e72002-09-23 09:36:25 +00001185 default:
njn4ba5a792002-09-30 10:23:54 +00001186 VG_(pp_UInstr)(0, u_in);
njne427a662002-10-02 11:08:25 +00001187 VG_(skin_panic)( "memcheck_instrument: unhandled case");
njn25e49d8e72002-09-23 09:36:25 +00001188
1189 } /* end of switch (u_in->opcode) */
1190
1191 } /* end of for loop */
1192
njn4ba5a792002-09-30 10:23:54 +00001193 VG_(free_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +00001194 return cb;
1195}
1196
1197/*------------------------------------------------------------*/
1198/*--- Clean up mem check instrumentation. ---*/
1199/*------------------------------------------------------------*/
1200
njn25e49d8e72002-09-23 09:36:25 +00001201#define dis VG_(print_codegen)
1202
1203
1204#define VGC_IS_SHADOW(tempreg) ((tempreg % 2) == 1)
1205#define VGC_UNDEF ((UChar)100)
1206#define VGC_VALUE ((UChar)101)
1207
1208#define NOP_no_msg(uu) \
njn4ba5a792002-09-30 10:23:54 +00001209 do { VG_(new_NOP)(uu); } while (False)
njn25e49d8e72002-09-23 09:36:25 +00001210
1211#define NOP_tag1_op(uu) \
njn4ba5a792002-09-30 10:23:54 +00001212 do { VG_(new_NOP)(uu); \
njn25e49d8e72002-09-23 09:36:25 +00001213 if (dis) \
1214 VG_(printf)(" at %2d: delete %s due to defd arg\n", \
1215 i, nameOfTagOp(u->val3)); \
1216 } while (False)
1217
1218#define SETV_tag1_op(uu,newsz) \
1219 do { uu->opcode = SETV; \
1220 uu->size = newsz; \
1221 uu->tag2 = uu->tag3 = NoValue; \
1222 if (dis) \
1223 VG_(printf)(" at %2d: convert %s to SETV%d " \
1224 "due to defd arg\n", \
1225 i, nameOfTagOp(u->val3), newsz); \
1226 } while (False)
1227
1228
1229
1230/* Run backwards and delete SETVs on shadow temps for which the next
1231 action is a write. Needs an env saying whether or not the next
1232 action is a write. The supplied UCodeBlock is destructively
1233 modified.
1234*/
1235static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
1236{
1237 Int i, j, k;
njn810086f2002-11-14 12:42:47 +00001238 Int n_temps = VG_(get_num_temps)(cb);
njn25e49d8e72002-09-23 09:36:25 +00001239 Bool* next_is_write;
1240 UInstr* u;
njnf4ce3d32003-02-10 10:17:26 +00001241 Int tempUse[VG_MAX_REGS_USED];
1242 Bool isWrites[VG_MAX_REGS_USED];
njn25e49d8e72002-09-23 09:36:25 +00001243
1244 if (n_temps == 0) return;
1245
1246 next_is_write = VG_(malloc)(n_temps * sizeof(Bool));
1247
1248 for (i = 0; i < n_temps; i++) next_is_write[i] = True;
1249
njn810086f2002-11-14 12:42:47 +00001250 for (i = VG_(get_num_instrs)(cb) - 1; i >= 0; i--) {
1251 u = VG_(get_instr)(cb, i);
njn25e49d8e72002-09-23 09:36:25 +00001252
sewardj51647482002-12-15 01:42:22 +00001253 /* Occasionally there will be GETVs, TAG1s and TAG2s calculating
1254 values which are never used. These first three cases get rid
1255 of them. */
njn25e49d8e72002-09-23 09:36:25 +00001256
1257 if (u->opcode == GETV && VGC_IS_SHADOW(u->val2)
sewardj51647482002-12-15 01:42:22 +00001258 && next_is_write[u->val2]) {
1259 sk_assert(u->val2 < n_temps);
njn4ba5a792002-09-30 10:23:54 +00001260 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001261 if (dis)
1262 VG_(printf)(" at %2d: delete GETV\n", i);
1263 } else
1264
1265 if (u->opcode == TAG1 && VGC_IS_SHADOW(u->val1)
sewardj51647482002-12-15 01:42:22 +00001266 && next_is_write[u->val1]) {
1267 sk_assert(u->val1 < n_temps);
njn4ba5a792002-09-30 10:23:54 +00001268 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001269 if (dis)
1270 VG_(printf)(" at %2d: delete TAG1\n", i);
1271 } else
1272
1273 if (u->opcode == TAG2 && VGC_IS_SHADOW(u->val2)
sewardj51647482002-12-15 01:42:22 +00001274 && next_is_write[u->val2]) {
1275 sk_assert(u->val2 < n_temps);
njn4ba5a792002-09-30 10:23:54 +00001276 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001277 if (dis)
1278 VG_(printf)(" at %2d: delete TAG2\n", i);
1279 } else
1280
sewardj51647482002-12-15 01:42:22 +00001281 /* The bulk of the cleanup work of this function is done by
1282 the code from here downwards. */
njn25e49d8e72002-09-23 09:36:25 +00001283
1284 if (u->opcode == MOV && VGC_IS_SHADOW(u->val2)
1285 && next_is_write[u->val2]) {
1286 /* This MOV is pointless because the target is dead at this
1287 point. Delete it. */
njn4ba5a792002-09-30 10:23:54 +00001288 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001289 if (dis)
1290 VG_(printf)(" at %2d: delete MOV\n", i);
1291 } else
1292
1293 if (u->opcode == SETV) {
1294 if (u->tag1 == TempReg) {
njne427a662002-10-02 11:08:25 +00001295 sk_assert(VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001296 if (next_is_write[u->val1]) {
1297 /* This write is pointless, so annul it. */
njn4ba5a792002-09-30 10:23:54 +00001298 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001299 if (dis)
1300 VG_(printf)(" at %2d: delete SETV\n", i);
1301 } else {
1302 /* This write has a purpose; don't annul it, but do
1303 notice that we did it. */
1304 next_is_write[u->val1] = True;
1305 }
1306
1307 }
1308
1309 } else {
1310 /* Find out what this insn does to the temps. */
njn810086f2002-11-14 12:42:47 +00001311 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
njnf4ce3d32003-02-10 10:17:26 +00001312 sk_assert(0 <= k && k <= VG_MAX_REGS_USED);
njn25e49d8e72002-09-23 09:36:25 +00001313 for (j = k-1; j >= 0; j--) {
njn810086f2002-11-14 12:42:47 +00001314 next_is_write[ tempUse[j] ] = isWrites[j];
njn25e49d8e72002-09-23 09:36:25 +00001315 }
1316 }
1317 }
1318}
1319
1320
1321/* Run forwards, propagating and using the is-completely-defined
1322 property. This removes a lot of redundant tag-munging code.
1323 Unfortunately it requires intimate knowledge of how each uinstr and
1324 tagop modifies its arguments. This duplicates knowledge of uinstr
njn4ba5a792002-09-30 10:23:54 +00001325 tempreg uses embodied in VG_(get_reg_usage)(), which is unfortunate.
njn25e49d8e72002-09-23 09:36:25 +00001326 The supplied UCodeBlock* is modified in-place.
1327
1328 For each value temp, def[] should hold VGC_VALUE.
1329
1330 For each shadow temp, def[] may hold 4,2,1 or 0 iff that shadow is
1331 definitely known to be fully defined at that size. In all other
1332 circumstances a shadow's def[] entry is VGC_UNDEF, meaning possibly
1333 undefined. In cases of doubt, VGC_UNDEF is always safe.
1334*/
1335static void vg_propagate_definedness ( UCodeBlock* cb )
1336{
1337 Int i, j, k, t;
njn810086f2002-11-14 12:42:47 +00001338 Int n_temps = VG_(get_num_temps)(cb);
njn25e49d8e72002-09-23 09:36:25 +00001339 UChar* def;
1340 UInstr* u;
njnf4ce3d32003-02-10 10:17:26 +00001341 Int tempUse[VG_MAX_REGS_USED];
1342 Bool isWrites[VG_MAX_REGS_USED];
njn25e49d8e72002-09-23 09:36:25 +00001343
1344 if (n_temps == 0) return;
1345
1346 def = VG_(malloc)(n_temps * sizeof(UChar));
1347
1348 for (i = 0; i < n_temps; i++)
1349 def[i] = VGC_IS_SHADOW(i) ? VGC_UNDEF : VGC_VALUE;
1350
1351 /* Run forwards, detecting and using the all-defined property. */
1352
njn810086f2002-11-14 12:42:47 +00001353 for (i = 0; i < VG_(get_num_instrs)(cb); i++) {
1354 u = VG_(get_instr)(cb, i);
njn25e49d8e72002-09-23 09:36:25 +00001355 switch (u->opcode) {
1356
1357 /* Tag-handling uinstrs. */
1358
1359 /* Deal with these quickly. */
1360 case NOP:
sewardj7a5ebcf2002-11-13 22:42:13 +00001361 case LOCK:
njn25e49d8e72002-09-23 09:36:25 +00001362 case INCEIP:
1363 break;
1364
1365 /* Make a tag defined. */
1366 case SETV:
njne427a662002-10-02 11:08:25 +00001367 sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001368 def[u->val1] = u->size;
1369 break;
1370
1371 /* Check definedness of a tag. */
1372 case TESTV:
njne427a662002-10-02 11:08:25 +00001373 sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001374 if (def[u->val1] <= 4) {
njne427a662002-10-02 11:08:25 +00001375 sk_assert(def[u->val1] == u->size);
njn25e49d8e72002-09-23 09:36:25 +00001376 NOP_no_msg(u);
1377 if (dis)
1378 VG_(printf)(" at %2d: delete TESTV on defd arg\n", i);
1379 }
1380 break;
1381
1382 /* Applies to both values and tags. Propagate Definedness
1383 property through copies. Note that this isn't optional;
1384 we *have* to do this to keep def[] correct. */
1385 case MOV:
njne427a662002-10-02 11:08:25 +00001386 sk_assert(u->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +00001387 if (u->tag1 == TempReg) {
1388 if (VGC_IS_SHADOW(u->val1)) {
njne427a662002-10-02 11:08:25 +00001389 sk_assert(VGC_IS_SHADOW(u->val2));
njn25e49d8e72002-09-23 09:36:25 +00001390 def[u->val2] = def[u->val1];
1391 }
1392 }
1393 break;
1394
1395 case PUTV:
njne427a662002-10-02 11:08:25 +00001396 sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001397 if (def[u->val1] <= 4) {
njne427a662002-10-02 11:08:25 +00001398 sk_assert(def[u->val1] == u->size);
njn25e49d8e72002-09-23 09:36:25 +00001399 u->tag1 = Literal;
1400 u->val1 = 0;
1401 switch (u->size) {
1402 case 4: u->lit32 = 0x00000000; break;
1403 case 2: u->lit32 = 0xFFFF0000; break;
1404 case 1: u->lit32 = 0xFFFFFF00; break;
njne427a662002-10-02 11:08:25 +00001405 default: VG_(skin_panic)("vg_cleanup(PUTV)");
njn25e49d8e72002-09-23 09:36:25 +00001406 }
1407 if (dis)
1408 VG_(printf)(
1409 " at %2d: propagate definedness into PUTV\n", i);
1410 }
1411 break;
1412
1413 case STOREV:
njne427a662002-10-02 11:08:25 +00001414 sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001415 if (def[u->val1] <= 4) {
njne427a662002-10-02 11:08:25 +00001416 sk_assert(def[u->val1] == u->size);
njn25e49d8e72002-09-23 09:36:25 +00001417 u->tag1 = Literal;
1418 u->val1 = 0;
1419 switch (u->size) {
1420 case 4: u->lit32 = 0x00000000; break;
1421 case 2: u->lit32 = 0xFFFF0000; break;
1422 case 1: u->lit32 = 0xFFFFFF00; break;
njne427a662002-10-02 11:08:25 +00001423 default: VG_(skin_panic)("vg_cleanup(STOREV)");
njn25e49d8e72002-09-23 09:36:25 +00001424 }
1425 if (dis)
1426 VG_(printf)(
1427 " at %2d: propagate definedness into STandV\n", i);
1428 }
1429 break;
1430
1431 /* Nothing interesting we can do with this, I think. */
1432 case PUTVF:
1433 break;
1434
1435 /* Tag handling operations. */
1436 case TAG2:
njne427a662002-10-02 11:08:25 +00001437 sk_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
1438 sk_assert(u->tag3 == Lit16);
njn25e49d8e72002-09-23 09:36:25 +00001439 /* Ultra-paranoid "type" checking. */
1440 switch (u->val3) {
1441 case Tag_ImproveAND4_TQ: case Tag_ImproveAND2_TQ:
1442 case Tag_ImproveAND1_TQ: case Tag_ImproveOR4_TQ:
1443 case Tag_ImproveOR2_TQ: case Tag_ImproveOR1_TQ:
njne427a662002-10-02 11:08:25 +00001444 sk_assert(u->tag1 == TempReg && !VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001445 break;
1446 default:
njne427a662002-10-02 11:08:25 +00001447 sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001448 break;
1449 }
1450 switch (u->val3) {
1451 Int sz;
1452 case Tag_UifU4:
1453 sz = 4; goto do_UifU;
1454 case Tag_UifU2:
1455 sz = 2; goto do_UifU;
1456 case Tag_UifU1:
1457 sz = 1; goto do_UifU;
1458 case Tag_UifU0:
1459 sz = 0; goto do_UifU;
1460 do_UifU:
njne427a662002-10-02 11:08:25 +00001461 sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1462 sk_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
njn25e49d8e72002-09-23 09:36:25 +00001463 if (def[u->val1] <= 4) {
1464 /* UifU. The first arg is defined, so result is
1465 simply second arg. Delete this operation. */
njne427a662002-10-02 11:08:25 +00001466 sk_assert(def[u->val1] == sz);
njn25e49d8e72002-09-23 09:36:25 +00001467 NOP_no_msg(u);
1468 if (dis)
1469 VG_(printf)(
1470 " at %2d: delete UifU%d due to defd arg1\n",
1471 i, sz);
1472 }
1473 else
1474 if (def[u->val2] <= 4) {
1475 /* UifU. The second arg is defined, so result is
1476 simply first arg. Copy to second. */
njne427a662002-10-02 11:08:25 +00001477 sk_assert(def[u->val2] == sz);
njn25e49d8e72002-09-23 09:36:25 +00001478 u->opcode = MOV;
1479 u->size = 4;
1480 u->tag3 = NoValue;
1481 def[u->val2] = def[u->val1];
1482 if (dis)
1483 VG_(printf)(
1484 " at %2d: change UifU%d to MOV due to defd"
1485 " arg2\n",
1486 i, sz);
1487 }
1488 break;
1489 case Tag_ImproveAND4_TQ:
1490 sz = 4; goto do_ImproveAND;
1491 case Tag_ImproveAND1_TQ:
1492 sz = 1; goto do_ImproveAND;
1493 do_ImproveAND:
mueller00a8a6f2004-01-02 22:46:34 +00001494 /* Implements Q = T AND Q. So if Q is entirely defined,
njn25e49d8e72002-09-23 09:36:25 +00001495 ie all 0s, we get MOV T, Q. */
1496 if (def[u->val2] <= 4) {
njne427a662002-10-02 11:08:25 +00001497 sk_assert(def[u->val2] == sz);
njn25e49d8e72002-09-23 09:36:25 +00001498 u->size = 4; /* Regardless of sz */
1499 u->opcode = MOV;
1500 u->tag3 = NoValue;
1501 def[u->val2] = VGC_UNDEF;
1502 if (dis)
1503 VG_(printf)(
1504 " at %2d: change ImproveAND%d_TQ to MOV due "
1505 "to defd arg2\n",
1506 i, sz);
1507 }
1508 break;
1509 default:
1510 goto unhandled;
1511 }
1512 break;
1513
1514 case TAG1:
njne427a662002-10-02 11:08:25 +00001515 sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001516 if (def[u->val1] > 4) break;
1517 /* We now know that the arg to the op is entirely defined.
1518 If the op changes the size of the arg, we must replace
1519 it with a SETV at the new size. If it doesn't change
1520 the size, we can delete it completely. */
1521 switch (u->val3) {
1522 /* Maintain the same size ... */
1523 case Tag_Left4:
njne427a662002-10-02 11:08:25 +00001524 sk_assert(def[u->val1] == 4);
njn25e49d8e72002-09-23 09:36:25 +00001525 NOP_tag1_op(u);
1526 break;
1527 case Tag_PCast11:
njne427a662002-10-02 11:08:25 +00001528 sk_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001529 NOP_tag1_op(u);
1530 break;
1531 /* Change size ... */
1532 case Tag_PCast40:
njne427a662002-10-02 11:08:25 +00001533 sk_assert(def[u->val1] == 4);
njn25e49d8e72002-09-23 09:36:25 +00001534 SETV_tag1_op(u,0);
1535 def[u->val1] = 0;
1536 break;
1537 case Tag_PCast14:
njne427a662002-10-02 11:08:25 +00001538 sk_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001539 SETV_tag1_op(u,4);
1540 def[u->val1] = 4;
1541 break;
1542 case Tag_PCast12:
njne427a662002-10-02 11:08:25 +00001543 sk_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001544 SETV_tag1_op(u,2);
1545 def[u->val1] = 2;
1546 break;
1547 case Tag_PCast10:
njne427a662002-10-02 11:08:25 +00001548 sk_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001549 SETV_tag1_op(u,0);
1550 def[u->val1] = 0;
1551 break;
1552 case Tag_PCast02:
njne427a662002-10-02 11:08:25 +00001553 sk_assert(def[u->val1] == 0);
njn25e49d8e72002-09-23 09:36:25 +00001554 SETV_tag1_op(u,2);
1555 def[u->val1] = 2;
1556 break;
1557 default:
1558 goto unhandled;
1559 }
1560 if (dis)
1561 VG_(printf)(
1562 " at %2d: delete TAG1 %s due to defd arg\n",
1563 i, nameOfTagOp(u->val3));
1564 break;
1565
1566 default:
1567 unhandled:
1568 /* We don't know how to handle this uinstr. Be safe, and
1569 set to VGC_VALUE or VGC_UNDEF all temps written by it. */
njn810086f2002-11-14 12:42:47 +00001570 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
njnf4ce3d32003-02-10 10:17:26 +00001571 sk_assert(0 <= k && k <= VG_MAX_REGS_USED);
njn25e49d8e72002-09-23 09:36:25 +00001572 for (j = 0; j < k; j++) {
njn810086f2002-11-14 12:42:47 +00001573 t = tempUse[j];
njne427a662002-10-02 11:08:25 +00001574 sk_assert(t >= 0 && t < n_temps);
njn810086f2002-11-14 12:42:47 +00001575 if (!isWrites[j]) {
njn25e49d8e72002-09-23 09:36:25 +00001576 /* t is read; ignore it. */
1577 if (0&& VGC_IS_SHADOW(t) && def[t] <= 4)
1578 VG_(printf)("ignoring def %d at %s %s\n",
1579 def[t],
njn4ba5a792002-09-30 10:23:54 +00001580 VG_(name_UOpcode)(True, u->opcode),
njn25e49d8e72002-09-23 09:36:25 +00001581 (u->opcode == TAG1 || u->opcode == TAG2)
1582 ? nameOfTagOp(u->val3)
1583 : (Char*)"");
1584 } else {
1585 /* t is written; better nullify it. */
1586 def[t] = VGC_IS_SHADOW(t) ? VGC_UNDEF : VGC_VALUE;
1587 }
1588 }
1589 }
1590 }
1591}
1592
1593
1594/* Top level post-MemCheck-instrumentation cleanup function. */
1595static void vg_cleanup ( UCodeBlock* cb )
1596{
1597 vg_propagate_definedness ( cb );
1598 vg_delete_redundant_SETVs ( cb );
1599}
1600
1601
1602/* Caller will print out final instrumented code if necessary; we
1603 print out intermediate instrumented code here if necessary. */
1604UCodeBlock* SK_(instrument) ( UCodeBlock* cb, Addr not_used )
1605{
1606 cb = memcheck_instrument ( cb );
njn5c004e42002-11-18 11:04:50 +00001607 if (MC_(clo_cleanup)) {
njn25e49d8e72002-09-23 09:36:25 +00001608 if (dis) {
njn4ba5a792002-09-30 10:23:54 +00001609 VG_(pp_UCodeBlock) ( cb, "Unimproved instrumented UCode:" );
njn25e49d8e72002-09-23 09:36:25 +00001610 VG_(printf)("Instrumentation improvements:\n");
1611 }
1612 vg_cleanup(cb);
1613 if (dis) VG_(printf)("\n");
1614 }
1615 return cb;
1616}
1617
1618#undef dis
1619
1620/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001621/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001622/*--------------------------------------------------------------------*/