blob: 6a815c930d21bba417289fba8ee9bad4ebb0796b [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
nethercote885dd912004-08-03 23:14:00 +000039 vg_translate.c:is_sane_UInstr(). Everything general said there
40 applies here too.
njn25e49d8e72002-09-23 09:36:25 +000041*/
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)
njn25e49d8e72002-09-23 09:36:25 +000060# define N2 (u->tag2 == NoValue)
61# define N3 (u->tag3 == NoValue)
62# define COND0 (u->cond == 0)
63# define EXTRA4b0 (u->extra4b == 0)
64# define SG_WD0 (u->signed_widen == 0)
65# define JMPKIND0 (u->jmpkind == 0)
66# define CCALL0 (u->argc==0 && u->regparms_n==0 && u->has_ret_val==0 && \
67 ( beforeLiveness \
68 ? u->regs_live_after == ALL_RREGS_LIVE \
69 : True ))
70# define XOTHER (COND0 && EXTRA4b0 && SG_WD0 && JMPKIND0 && CCALL0)
71
72 Int n_lits = 0;
73 if (u->tag1 == Literal) n_lits++;
74 if (u->tag2 == Literal) n_lits++;
75 if (u->tag3 == Literal) n_lits++;
76 if (n_lits > 1)
77 return False;
78
79 /* Fields not checked: val1, val2, val3 */
80
81 switch (u->opcode) {
82
83 /* Fields checked: lit32 size flags_r/w tag1 tag2 tag3 (rest) */
84 case LOADV: return LIT0 && SZi && CC0 && TR1 && TR2 && N3 && XOTHER;
85 case STOREV: return LITm && SZi && CC0 && TRL1 && TR2 && N3 && XOTHER;
86 case GETV: return LIT0 && SZi && CC0 && A1 && TR2 && N3 && XOTHER;
87 case PUTV: return LITm && SZi && CC0 && TRL1 && A2 && N3 && XOTHER;
88 case GETVF:
89 case PUTVF: return LIT0 && SZ0 && CC0 && TR1 && N2 && N3 && XOTHER;
90 case TESTV:
nethercote0e5d2e32004-04-22 12:58:05 +000091 case SETV: return LIT0 && SZj && CC0 && TR1 && N2 && N3 && XOTHER;
njn25e49d8e72002-09-23 09:36:25 +000092 case TAG1: return LIT0 && SZ0 && CC0 && TR1 && N2 && Ls3 && XOTHER;
93 case TAG2: return LIT0 && SZ0 && CC0 && TR1 && TR2 && Ls3 && XOTHER;
94 default:
95 VG_(printf)("unhandled opcode: %u\n", u->opcode);
njn67993252004-11-22 18:02:32 +000096 VG_(tool_panic)("SK_(sane_XUInstr): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +000097 }
98# undef LIT0
99# undef LIT1
100# undef LITm
101# undef SZ0
102# undef SZi
103# undef SZj
104# undef CC0
105# undef TR1
106# undef TR2
107# undef A1
108# undef A2
109# undef L1
110# undef Ls1
111# undef Ls3
112# undef TRL1
njn25e49d8e72002-09-23 09:36:25 +0000113# undef N2
114# undef N3
115# undef COND0
116# undef EXTRA4b0
117# undef JMPKIND0
118# undef CCALL0
119# undef XOTHER
120}
121
122static Char* nameOfTagOp ( TagOp h )
123{
124 switch (h) {
125 case Tag_PCast40: return "PCast40";
126 case Tag_PCast20: return "PCast20";
127 case Tag_PCast10: return "PCast10";
128 case Tag_PCast01: return "PCast01";
129 case Tag_PCast02: return "PCast02";
130 case Tag_PCast04: return "PCast04";
131 case Tag_PCast14: return "PCast14";
132 case Tag_PCast12: return "PCast12";
133 case Tag_PCast11: return "PCast11";
134 case Tag_Left4: return "Left4";
135 case Tag_Left2: return "Left2";
136 case Tag_Left1: return "Left1";
137 case Tag_SWiden14: return "SWiden14";
138 case Tag_SWiden24: return "SWiden24";
139 case Tag_SWiden12: return "SWiden12";
140 case Tag_ZWiden14: return "ZWiden14";
141 case Tag_ZWiden24: return "ZWiden24";
142 case Tag_ZWiden12: return "ZWiden12";
143 case Tag_UifU4: return "UifU4";
144 case Tag_UifU2: return "UifU2";
145 case Tag_UifU1: return "UifU1";
146 case Tag_UifU0: return "UifU0";
147 case Tag_DifD4: return "DifD4";
148 case Tag_DifD2: return "DifD2";
149 case Tag_DifD1: return "DifD1";
150 case Tag_ImproveAND4_TQ: return "ImproveAND4_TQ";
151 case Tag_ImproveAND2_TQ: return "ImproveAND2_TQ";
152 case Tag_ImproveAND1_TQ: return "ImproveAND1_TQ";
153 case Tag_ImproveOR4_TQ: return "ImproveOR4_TQ";
154 case Tag_ImproveOR2_TQ: return "ImproveOR2_TQ";
155 case Tag_ImproveOR1_TQ: return "ImproveOR1_TQ";
156 case Tag_DebugFn: return "DebugFn";
njn67993252004-11-22 18:02:32 +0000157 default: VG_(tool_panic)("vg_nameOfTagOp");
njn25e49d8e72002-09-23 09:36:25 +0000158 }
159}
160
161
njn4ba5a792002-09-30 10:23:54 +0000162Char* SK_(name_XUOpcode)(Opcode opc)
njn25e49d8e72002-09-23 09:36:25 +0000163{
164 switch (opc) {
165 case GETVF: return "GETVF";
166 case PUTVF: return "PUTVF";
167 case TAG1: return "TAG1";
168 case TAG2: return "TAG2";
169 case LOADV: return "LOADV";
170 case STOREV: return "STOREV";
171 case GETV: return "GETV";
172 case PUTV: return "PUTV";
173 case TESTV: return "TESTV";
174 case SETV: return "SETV";
175 default:
176 VG_(printf)("unhandled opcode: %u\n", opc);
njn67993252004-11-22 18:02:32 +0000177 VG_(tool_panic)("SK_(name_XUOpcode): unhandled case");
njn25e49d8e72002-09-23 09:36:25 +0000178 }
179}
180
181/* ---------------------------------------------------------------------
182 Debugging stuff.
183 ------------------------------------------------------------------ */
184
njn4ba5a792002-09-30 10:23:54 +0000185void SK_(pp_XUInstr)(UInstr* u)
njn25e49d8e72002-09-23 09:36:25 +0000186{
187 switch (u->opcode) {
njn25e49d8e72002-09-23 09:36:25 +0000188 case TAG1:
njn4ba5a792002-09-30 10:23:54 +0000189 VG_(pp_UOperand)(u, 1, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000190 VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
njn4ba5a792002-09-30 10:23:54 +0000191 VG_(pp_UOperand)(u, 1, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000192 VG_(printf)(" )");
193 break;
194
195 case TAG2:
njn4ba5a792002-09-30 10:23:54 +0000196 VG_(pp_UOperand)(u, 2, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000197 VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
njn4ba5a792002-09-30 10:23:54 +0000198 VG_(pp_UOperand)(u, 1, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000199 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +0000200 VG_(pp_UOperand)(u, 2, 4, False);
njn25e49d8e72002-09-23 09:36:25 +0000201 VG_(printf)(" )");
202 break;
203
204 case STOREV: case LOADV:
njn4ba5a792002-09-30 10:23:54 +0000205 VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOADV);
njn25e49d8e72002-09-23 09:36:25 +0000206 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +0000207 VG_(pp_UOperand)(u, 2, u->size, u->opcode==STOREV);
njn25e49d8e72002-09-23 09:36:25 +0000208 break;
209
210 case PUTVF: case GETVF:
njn4ba5a792002-09-30 10:23:54 +0000211 VG_(pp_UOperand)(u, 1, 0, False);
njn25e49d8e72002-09-23 09:36:25 +0000212 break;
213
214 case GETV: case PUTV:
njn4ba5a792002-09-30 10:23:54 +0000215 VG_(pp_UOperand)(u, 1, u->opcode==PUTV ? 4 : u->size, False);
njn25e49d8e72002-09-23 09:36:25 +0000216 VG_(printf)(", ");
njn4ba5a792002-09-30 10:23:54 +0000217 VG_(pp_UOperand)(u, 2, u->opcode==GETV ? 4 : u->size, False);
njn25e49d8e72002-09-23 09:36:25 +0000218 break;
219
220 case TESTV: case SETV:
njn4ba5a792002-09-30 10:23:54 +0000221 VG_(pp_UOperand)(u, 1, u->size, False);
njn25e49d8e72002-09-23 09:36:25 +0000222 break;
223
224 default:
225 VG_(printf)("unhandled opcode: %u\n", u->opcode);
njn67993252004-11-22 18:02:32 +0000226 VG_(tool_panic)("SK_(pp_XUInstr): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000227 }
228
229}
230
njn810086f2002-11-14 12:42:47 +0000231Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, Int* regs, Bool* isWrites)
njn25e49d8e72002-09-23 09:36:25 +0000232{
njn810086f2002-11-14 12:42:47 +0000233# define RD(ono) VG_UINSTR_READS_REG(ono, regs, isWrites)
234# define WR(ono) VG_UINSTR_WRITES_REG(ono, regs, isWrites)
njn25e49d8e72002-09-23 09:36:25 +0000235
236 Int n = 0;
237 switch (u->opcode) {
njn25e49d8e72002-09-23 09:36:25 +0000238 case TAG1: RD(1); WR(1); break;
239 case TAG2: RD(1); RD(2); WR(2); break;
240 case LOADV: RD(1); WR(2); break;
241 case STOREV: RD(1); RD(2); break;
242 case GETV: WR(2); break;
243 case PUTV: RD(1); break;
244 case TESTV: RD(1); break;
245 case SETV: WR(1); break;
246 case PUTVF: RD(1); break;
247 case GETVF: WR(1); break;
248
249 default:
250 VG_(printf)("unhandled opcode: %u\n", u->opcode);
njn67993252004-11-22 18:02:32 +0000251 VG_(tool_panic)("SK_(get_Xreg_usage): unhandled opcode");
njn25e49d8e72002-09-23 09:36:25 +0000252 }
253 return n;
254
255# undef RD
256# undef WR
257}
258
259/*------------------------------------------------------------*/
260/*--- New instrumentation machinery. ---*/
261/*------------------------------------------------------------*/
262
njn25e49d8e72002-09-23 09:36:25 +0000263static
264TagOp get_Tag_ImproveOR_TQ ( Int sz )
265{
266 switch (sz) {
267 case 4: return Tag_ImproveOR4_TQ;
268 case 2: return Tag_ImproveOR2_TQ;
269 case 1: return Tag_ImproveOR1_TQ;
njn67993252004-11-22 18:02:32 +0000270 default: VG_(tool_panic)("get_Tag_ImproveOR_TQ");
njn25e49d8e72002-09-23 09:36:25 +0000271 }
272}
273
274
275static
276TagOp get_Tag_ImproveAND_TQ ( Int sz )
277{
278 switch (sz) {
279 case 4: return Tag_ImproveAND4_TQ;
280 case 2: return Tag_ImproveAND2_TQ;
281 case 1: return Tag_ImproveAND1_TQ;
njn67993252004-11-22 18:02:32 +0000282 default: VG_(tool_panic)("get_Tag_ImproveAND_TQ");
njn25e49d8e72002-09-23 09:36:25 +0000283 }
284}
285
286
287static
288TagOp get_Tag_Left ( Int sz )
289{
290 switch (sz) {
291 case 4: return Tag_Left4;
292 case 2: return Tag_Left2;
293 case 1: return Tag_Left1;
njn67993252004-11-22 18:02:32 +0000294 default: VG_(tool_panic)("get_Tag_Left");
njn25e49d8e72002-09-23 09:36:25 +0000295 }
296}
297
298
299static
300TagOp get_Tag_UifU ( Int sz )
301{
302 switch (sz) {
303 case 4: return Tag_UifU4;
304 case 2: return Tag_UifU2;
305 case 1: return Tag_UifU1;
306 case 0: return Tag_UifU0;
njn67993252004-11-22 18:02:32 +0000307 default: VG_(tool_panic)("get_Tag_UifU");
njn25e49d8e72002-09-23 09:36:25 +0000308 }
309}
310
311
312static
313TagOp get_Tag_DifD ( Int sz )
314{
315 switch (sz) {
316 case 4: return Tag_DifD4;
317 case 2: return Tag_DifD2;
318 case 1: return Tag_DifD1;
njn67993252004-11-22 18:02:32 +0000319 default: VG_(tool_panic)("get_Tag_DifD");
njn25e49d8e72002-09-23 09:36:25 +0000320 }
321}
322
323
324static
325TagOp get_Tag_PCast ( Int szs, Int szd )
326{
327 if (szs == 4 && szd == 0) return Tag_PCast40;
328 if (szs == 2 && szd == 0) return Tag_PCast20;
329 if (szs == 1 && szd == 0) return Tag_PCast10;
330 if (szs == 0 && szd == 1) return Tag_PCast01;
331 if (szs == 0 && szd == 2) return Tag_PCast02;
332 if (szs == 0 && szd == 4) return Tag_PCast04;
333 if (szs == 1 && szd == 4) return Tag_PCast14;
334 if (szs == 1 && szd == 2) return Tag_PCast12;
335 if (szs == 1 && szd == 1) return Tag_PCast11;
336 VG_(printf)("get_Tag_PCast(%d,%d)\n", szs, szd);
njn67993252004-11-22 18:02:32 +0000337 VG_(tool_panic)("get_Tag_PCast");
njn25e49d8e72002-09-23 09:36:25 +0000338}
339
340
341static
342TagOp get_Tag_Widen ( Bool syned, Int szs, Int szd )
343{
344 if (szs == 1 && szd == 2 && syned) return Tag_SWiden12;
345 if (szs == 1 && szd == 2 && !syned) return Tag_ZWiden12;
346
347 if (szs == 1 && szd == 4 && syned) return Tag_SWiden14;
348 if (szs == 1 && szd == 4 && !syned) return Tag_ZWiden14;
349
350 if (szs == 2 && szd == 4 && syned) return Tag_SWiden24;
351 if (szs == 2 && szd == 4 && !syned) return Tag_ZWiden24;
352
353 VG_(printf)("get_Tag_Widen(%d,%d,%d)\n", (Int)syned, szs, szd);
njn67993252004-11-22 18:02:32 +0000354 VG_(tool_panic)("get_Tag_Widen");
njn25e49d8e72002-09-23 09:36:25 +0000355}
356
357/* Pessimally cast the spec'd shadow from one size to another. */
358static
359void create_PCast ( UCodeBlock* cb, Int szs, Int szd, Int tempreg )
360{
361 if (szs == 0 && szd == 0)
362 return;
363 uInstr3(cb, TAG1, 0, TempReg, tempreg,
364 NoValue, 0,
365 Lit16, get_Tag_PCast(szs,szd));
366}
367
368
369/* Create a signed or unsigned widen of the spec'd shadow from one
370 size to another. The only allowed size transitions are 1->2, 1->4
371 and 2->4. */
372static
373void create_Widen ( UCodeBlock* cb, Bool signed_widen,
374 Int szs, Int szd, Int tempreg )
375{
376 if (szs == szd) return;
377 uInstr3(cb, TAG1, 0, TempReg, tempreg,
378 NoValue, 0,
379 Lit16, get_Tag_Widen(signed_widen,szs,szd));
380}
381
382
383/* Get the condition codes into a new shadow, at the given size. */
384static
385Int create_GETVF ( UCodeBlock* cb, Int sz )
386{
387 Int tt = newShadow(cb);
388 uInstr1(cb, GETVF, 0, TempReg, tt);
389 create_PCast(cb, 0, sz, tt);
390 return tt;
391}
392
393
394/* Save the condition codes from the spec'd shadow. */
395static
396void create_PUTVF ( UCodeBlock* cb, Int sz, Int tempreg )
397{
398 if (sz == 0) {
399 uInstr1(cb, PUTVF, 0, TempReg, tempreg);
400 } else {
401 Int tt = newShadow(cb);
402 uInstr2(cb, MOV, 4, TempReg, tempreg, TempReg, tt);
403 create_PCast(cb, sz, 0, tt);
404 uInstr1(cb, PUTVF, 0, TempReg, tt);
405 }
406}
407
408
409/* Do Left on the spec'd shadow. */
410static
411void create_Left ( UCodeBlock* cb, Int sz, Int tempreg )
412{
413 uInstr3(cb, TAG1, 0,
414 TempReg, tempreg,
415 NoValue, 0,
416 Lit16, get_Tag_Left(sz));
417}
418
419
420/* Do UifU on ts and td, putting the result in td. */
421static
422void create_UifU ( UCodeBlock* cb, Int sz, Int ts, Int td )
423{
424 uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
425 Lit16, get_Tag_UifU(sz));
426}
427
428
429/* Do DifD on ts and td, putting the result in td. */
430static
431void create_DifD ( UCodeBlock* cb, Int sz, Int ts, Int td )
432{
433 uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
434 Lit16, get_Tag_DifD(sz));
435}
436
437
438/* Do HelpAND on value tval and tag tqqq, putting the result in
439 tqqq. */
440static
441void create_ImproveAND_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
442{
443 uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
444 Lit16, get_Tag_ImproveAND_TQ(sz));
445}
446
447
448/* Do HelpOR on value tval and tag tqqq, putting the result in
449 tqqq. */
450static
451void create_ImproveOR_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
452{
453 uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
454 Lit16, get_Tag_ImproveOR_TQ(sz));
455}
456
457
458/* Get the shadow for an operand described by (tag, val). Emit code
459 to do this and return the identity of the shadow holding the
460 result. The result tag is always copied into a new shadow, so it
461 can be modified without trashing the original.*/
462static
463Int /* TempReg */ getOperandShadow ( UCodeBlock* cb,
464 Int sz, Int tag, Int val )
465{
466 Int sh;
467 sh = newShadow(cb);
468 if (tag == TempReg) {
469 uInstr2(cb, MOV, 4, TempReg, SHADOW(val), TempReg, sh);
470 return sh;
471 }
472 if (tag == Literal) {
473 uInstr1(cb, SETV, sz, TempReg, sh);
474 return sh;
475 }
476 if (tag == ArchReg) {
477 uInstr2(cb, GETV, sz, ArchReg, val, TempReg, sh);
478 return sh;
479 }
njn67993252004-11-22 18:02:32 +0000480 VG_(tool_panic)("getOperandShadow");
njn25e49d8e72002-09-23 09:36:25 +0000481}
482
483/* Create and return an instrumented version of cb_in. Free cb_in
484 before returning. */
485static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
486{
487 UCodeBlock* cb;
488 Int i, j;
489 UInstr* u_in;
490 Int qs, qd, qt, qtt;
sewardj8ec2cfc2002-10-13 00:57:26 +0000491 Bool bogusLiterals;
njn810086f2002-11-14 12:42:47 +0000492
493 cb = VG_(setup_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +0000494
sewardj8ec2cfc2002-10-13 00:57:26 +0000495 /* Scan the block to look for bogus literals. These are magic
496 numbers which particularly appear in hand-optimised / inlined
497 implementations of strlen() et al which cause so much trouble
498 (spurious reports of uninit-var uses). Purpose of this horrible
499 hack is to disable some checks any such literals are present in
500 this basic block. */
501 bogusLiterals = False;
502
njn5c004e42002-11-18 11:04:50 +0000503 if (MC_(clo_avoid_strlen_errors)) {
njn810086f2002-11-14 12:42:47 +0000504 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
505 u_in = VG_(get_instr)(cb_in, i);
sewardj8ec2cfc2002-10-13 00:57:26 +0000506 switch (u_in->opcode) {
507 case ADD: case SUB: case MOV:
508 if (u_in->size == 4 && u_in->tag1 == Literal)
509 goto literal;
510 break;
511 case LEA1:
njnca82cc02004-11-22 17:18:48 +0000512 tl_assert(u_in->size == 4);
sewardj8ec2cfc2002-10-13 00:57:26 +0000513 goto literal;
514 default:
515 break;
516 }
517 continue;
518 literal:
519 if (u_in->lit32 == 0xFEFEFEFF ||
520 u_in->lit32 == 0x80808080 ||
521 u_in->lit32 == 0x00008080) {
522 bogusLiterals = True;
523 break;
524 }
525 }
526 }
527
njn810086f2002-11-14 12:42:47 +0000528 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
529 u_in = VG_(get_instr)(cb_in, i);
njn25e49d8e72002-09-23 09:36:25 +0000530 qs = qd = qt = qtt = INVALID_TEMPREG;
njn25e49d8e72002-09-23 09:36:25 +0000531
532 switch (u_in->opcode) {
533
sewardj7a5ebcf2002-11-13 22:42:13 +0000534 case LOCK:
njn25e49d8e72002-09-23 09:36:25 +0000535 case NOP:
536 break;
537
538 case INCEIP:
njn4ba5a792002-09-30 10:23:54 +0000539 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000540 break;
541
sewardjd077f532002-09-30 21:52:50 +0000542 /* The segment registers do not have their definedness
543 tracked. We therefore make fake shadows on GETSEG and
544 test them on PUTSEG. This will catch writing garbage to a
545 segment register; therefore we can assume it to be defined
546 when read (GETSEGd). Since the first arg of USESEG is
547 fetched by GETSEG, we can assume it to be defined, and so
548 the definedness of the result is simply the definedness of
549 the second (virtual_address) arg of USESEG. The upshot of
550 all this is that instrumentation of USESEG is a no-op! */
551
552 case PUTSEG:
njnca82cc02004-11-22 17:18:48 +0000553 tl_assert(u_in->tag1 == TempReg);
sewardjd077f532002-09-30 21:52:50 +0000554 uInstr1(cb, TESTV, 2, TempReg, SHADOW(u_in->val1));
555 uInstr1(cb, SETV, 2, TempReg, SHADOW(u_in->val1));
556 VG_(copy_UInstr)(cb, u_in);
557 break;
558
559 case GETSEG:
njnca82cc02004-11-22 17:18:48 +0000560 tl_assert(u_in->tag2 == TempReg);
sewardjd077f532002-09-30 21:52:50 +0000561 uInstr1(cb, SETV, 2, TempReg, SHADOW(u_in->val2));
562 VG_(copy_UInstr)(cb, u_in);
563 break;
564
565 case USESEG:
566 VG_(copy_UInstr)(cb, u_in);
567 break;
568
njn25e49d8e72002-09-23 09:36:25 +0000569 /* Loads and stores. Test the V bits for the address. 24
570 Mar 02: since the address is A-checked anyway, there's not
571 really much point in doing the V-check too, unless you
572 think that you might use addresses which are undefined but
573 still addressible. Hence the optionalisation of the V
sewardj51647482002-12-15 01:42:22 +0000574 check. 15 Dec 02: optionalisation removed, since it no
575 longer makes much sense given we also have an addrcheck
nethercote996901a2004-08-03 13:29:09 +0000576 tool.
njn25e49d8e72002-09-23 09:36:25 +0000577
578 The LOADV/STOREV does an addressibility check for the
579 address. */
580
581 case LOAD:
sewardj51647482002-12-15 01:42:22 +0000582 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
583 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
njn25e49d8e72002-09-23 09:36:25 +0000584 uInstr2(cb, LOADV, u_in->size,
585 TempReg, u_in->val1,
586 TempReg, SHADOW(u_in->val2));
njn4ba5a792002-09-30 10:23:54 +0000587 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000588 break;
589
590 case STORE:
sewardj51647482002-12-15 01:42:22 +0000591 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
592 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
njn25e49d8e72002-09-23 09:36:25 +0000593 uInstr2(cb, STOREV, u_in->size,
594 TempReg, SHADOW(u_in->val1),
595 TempReg, u_in->val2);
njn4ba5a792002-09-30 10:23:54 +0000596 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000597 break;
598
599 /* Moving stuff around. Make the V bits follow accordingly,
600 but don't do anything else. */
601
602 case GET:
603 uInstr2(cb, GETV, u_in->size,
604 ArchReg, u_in->val1,
605 TempReg, SHADOW(u_in->val2));
njn4ba5a792002-09-30 10:23:54 +0000606 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000607 break;
608
609 case PUT:
610 uInstr2(cb, PUTV, u_in->size,
611 TempReg, SHADOW(u_in->val1),
612 ArchReg, u_in->val2);
njn4ba5a792002-09-30 10:23:54 +0000613 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000614 break;
615
616 case GETF:
617 /* This is not the smartest way to do it, but should work. */
618 qd = create_GETVF(cb, u_in->size);
619 uInstr2(cb, MOV, 4, TempReg, qd, TempReg, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000620 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000621 break;
622
623 case PUTF:
624 create_PUTVF(cb, u_in->size, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000625 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000626 break;
627
628 case MOV:
629 switch (u_in->tag1) {
630 case TempReg:
631 uInstr2(cb, MOV, 4,
632 TempReg, SHADOW(u_in->val1),
633 TempReg, SHADOW(u_in->val2));
634 break;
635 case Literal:
636 uInstr1(cb, SETV, u_in->size,
637 TempReg, SHADOW(u_in->val2));
638 break;
639 default:
njn67993252004-11-22 18:02:32 +0000640 VG_(tool_panic)("memcheck_instrument: MOV");
njn25e49d8e72002-09-23 09:36:25 +0000641 }
njn4ba5a792002-09-30 10:23:54 +0000642 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000643 break;
644
645 /* Special case of add, where one of the operands is a literal.
646 lea1(t) = t + some literal.
647 Therefore: lea1#(qa) = left(qa)
648 */
649 case LEA1:
njnca82cc02004-11-22 17:18:48 +0000650 tl_assert(u_in->size == 4 && !VG_(any_flag_use)(u_in));
njn25e49d8e72002-09-23 09:36:25 +0000651 qs = SHADOW(u_in->val1);
652 qd = SHADOW(u_in->val2);
653 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qd);
654 create_Left(cb, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000655 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000656 break;
657
658 /* Another form of add.
659 lea2(ts,tt,shift) = ts + (tt << shift); shift is a literal
660 and is 0,1,2 or 3.
661 lea2#(qs,qt) = left(qs `UifU` (qt << shift)).
662 Note, subtly, that the shift puts zeroes at the bottom of qt,
663 meaning Valid, since the corresponding shift of tt puts
664 zeroes at the bottom of tb.
665 */
666 case LEA2: {
667 Int shift;
njnca82cc02004-11-22 17:18:48 +0000668 tl_assert(u_in->size == 4 && !VG_(any_flag_use)(u_in));
njn25e49d8e72002-09-23 09:36:25 +0000669 switch (u_in->extra4b) {
670 case 1: shift = 0; break;
671 case 2: shift = 1; break;
672 case 4: shift = 2; break;
673 case 8: shift = 3; break;
njn67993252004-11-22 18:02:32 +0000674 default: VG_(tool_panic)( "memcheck_instrument(LEA2)" );
njn25e49d8e72002-09-23 09:36:25 +0000675 }
676 qs = SHADOW(u_in->val1);
677 qt = SHADOW(u_in->val2);
678 qd = SHADOW(u_in->val3);
679 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qd);
680 if (shift > 0) {
681 uInstr2(cb, SHL, 4, Literal, 0, TempReg, qd);
682 uLiteral(cb, shift);
683 }
684 create_UifU(cb, 4, qs, qd);
685 create_Left(cb, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000686 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000687 break;
688 }
689
690 /* inc#/dec#(qd) = q `UifU` left(qd) = left(qd) */
691 case INC: case DEC:
692 qd = SHADOW(u_in->val1);
693 create_Left(cb, u_in->size, qd);
694 if (u_in->flags_w != FlagsEmpty)
695 create_PUTVF(cb, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000696 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000697 break;
698
699 /* This is a HACK (approximation :-) */
700 /* rcl#/rcr#(qs,qd)
701 = let q0 = pcast-sz-0(qd) `UifU` pcast-sz-0(qs) `UifU` eflags#
702 eflags# = q0
703 qd =pcast-0-sz(q0)
704 Ie, cast everything down to a single bit, then back up.
705 This assumes that any bad bits infect the whole word and
706 the eflags.
707 */
708 case RCL: case RCR:
njnca82cc02004-11-22 17:18:48 +0000709 tl_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000710 /* The following assertion looks like it makes sense, but is
711 actually wrong. Consider this:
712 rcll %eax
713 imull %eax, %eax
714 The rcll writes O and C but so does the imull, so the O and C
715 write of the rcll is annulled by the prior improvement pass.
716 Noticed by Kevin Ryde <user42@zip.com.au>
717 */
njnca82cc02004-11-22 17:18:48 +0000718 /* tl_assert(u_in->flags_w != FlagsEmpty); */
nethercote1018bdd2004-02-11 23:33:29 +0000719 qs = getOperandShadow(cb, 1, u_in->tag1, u_in->val1);
njn25e49d8e72002-09-23 09:36:25 +0000720 /* We can safely modify qs; cast it to 0-size. */
nethercote1018bdd2004-02-11 23:33:29 +0000721 create_PCast(cb, 1, 0, qs);
njn25e49d8e72002-09-23 09:36:25 +0000722 qd = SHADOW(u_in->val2);
723 create_PCast(cb, u_in->size, 0, qd);
724 /* qs is cast-to-0(shift count#), and qd is cast-to-0(value#). */
725 create_UifU(cb, 0, qs, qd);
726 /* qs is now free; reuse it for the flag definedness. */
727 qs = create_GETVF(cb, 0);
728 create_UifU(cb, 0, qs, qd);
729 create_PUTVF(cb, 0, qd);
730 create_PCast(cb, 0, u_in->size, qd);
njn4ba5a792002-09-30 10:23:54 +0000731 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000732 break;
733
734 /* for OP in shl shr sar rol ror
735 (qs is shift count#, qd is value to be OP#d)
736 OP(ts,td)
737 OP#(qs,qd)
738 = pcast-1-sz(qs) `UifU` OP(ts,qd)
739 So we apply OP to the tag bits too, and then UifU with
740 the shift count# to take account of the possibility of it
741 being undefined.
742
743 A bit subtle:
744 ROL/ROR rearrange the tag bits as per the value bits.
745 SHL/SHR shifts zeroes into the value, and corresponding
746 zeroes indicating Definedness into the tag.
747 SAR copies the top bit of the value downwards, and therefore
748 SAR also copies the definedness of the top bit too.
749 So in all five cases, we just apply the same op to the tag
750 bits as is applied to the value bits. Neat!
751 */
752 case SHL:
753 case SHR: case SAR:
754 case ROL: case ROR: {
755 Int t_amount = INVALID_TEMPREG;
njnca82cc02004-11-22 17:18:48 +0000756 tl_assert(u_in->tag1 == TempReg || u_in->tag1 == Literal);
757 tl_assert(u_in->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000758 qd = SHADOW(u_in->val2);
759
760 /* Make qs hold shift-count# and make
761 t_amount be a TempReg holding the shift count. */
762 if (u_in->tag1 == Literal) {
763 t_amount = newTemp(cb);
764 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_amount);
765 uLiteral(cb, u_in->lit32);
766 qs = SHADOW(t_amount);
767 uInstr1(cb, SETV, 1, TempReg, qs);
768 } else {
769 t_amount = u_in->val1;
770 qs = SHADOW(u_in->val1);
771 }
772
773 uInstr2(cb, u_in->opcode,
774 u_in->size,
775 TempReg, t_amount,
776 TempReg, qd);
777 qt = newShadow(cb);
778 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
779 create_PCast(cb, 1, u_in->size, qt);
780 create_UifU(cb, u_in->size, qt, qd);
njn4ba5a792002-09-30 10:23:54 +0000781 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000782 break;
783 }
784
785 /* One simple tag operation. */
786 case WIDEN:
njnca82cc02004-11-22 17:18:48 +0000787 tl_assert(u_in->tag1 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000788 create_Widen(cb, u_in->signed_widen, u_in->extra4b, u_in->size,
789 SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000790 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000791 break;
792
793 /* not#(x) = x (since bitwise independent) */
794 case NOT:
njnca82cc02004-11-22 17:18:48 +0000795 tl_assert(u_in->tag1 == TempReg);
njn4ba5a792002-09-30 10:23:54 +0000796 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000797 break;
798
799 /* neg#(x) = left(x) (derivable from case for SUB) */
800 case NEG:
njnca82cc02004-11-22 17:18:48 +0000801 tl_assert(u_in->tag1 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000802 create_Left(cb, u_in->size, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000803 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000804 break;
805
806 /* bswap#(x) = bswap(x) */
807 case BSWAP:
njnca82cc02004-11-22 17:18:48 +0000808 tl_assert(u_in->tag1 == TempReg);
809 tl_assert(u_in->size == 4);
njn25e49d8e72002-09-23 09:36:25 +0000810 qd = SHADOW(u_in->val1);
811 uInstr1(cb, BSWAP, 4, TempReg, qd);
njn4ba5a792002-09-30 10:23:54 +0000812 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000813 break;
814
815 /* cc2val#(qd) = pcast-0-to-size(eflags#) */
816 case CC2VAL:
njnca82cc02004-11-22 17:18:48 +0000817 tl_assert(u_in->tag1 == TempReg);
818 tl_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000819 qt = create_GETVF(cb, u_in->size);
820 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +0000821 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000822 break;
823
824 /* cmov#(qs,qd) = cmov(qs,qd)
825 That is, do the cmov of tags using the same flags as for
826 the data (obviously). However, first do a test on the
827 validity of the flags.
828 */
829 case CMOV:
njnca82cc02004-11-22 17:18:48 +0000830 tl_assert(u_in->size == 4);
831 tl_assert(u_in->tag1 == TempReg);
832 tl_assert(u_in->tag2 == TempReg);
833 tl_assert(u_in->flags_r != FlagsEmpty);
834 tl_assert(u_in->flags_w == FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000835 qs = SHADOW(u_in->val1);
836 qd = SHADOW(u_in->val2);
837 qt = create_GETVF(cb, 0);
838 uInstr1(cb, TESTV, 0, TempReg, qt);
839 /* qt should never be referred to again. Nevertheless
840 ... */
841 uInstr1(cb, SETV, 0, TempReg, qt);
842
843 uInstr2(cb, CMOV, 4, TempReg, qs, TempReg, qd);
njn810086f2002-11-14 12:42:47 +0000844 uCond(cb, u_in->cond);
845 uFlagsRWU(cb, u_in->flags_r, u_in->flags_w, FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000846
njn4ba5a792002-09-30 10:23:54 +0000847 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000848 break;
849
850 /* add#/sub#(qs,qd)
851 = qs `UifU` qd `UifU` left(qs) `UifU` left(qd)
852 = left(qs) `UifU` left(qd)
853 = left(qs `UifU` qd)
854 adc#/sbb#(qs,qd)
855 = left(qs `UifU` qd) `UifU` pcast(eflags#)
856 Second arg (dest) is TempReg.
857 First arg (src) is Literal or TempReg or ArchReg.
858 */
859 case ADD: case SUB:
860 case ADC: case SBB:
jsgf5efa4fd2003-10-14 21:49:11 +0000861 case MUL:
njn25e49d8e72002-09-23 09:36:25 +0000862 qd = SHADOW(u_in->val2);
863 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
864 create_UifU(cb, u_in->size, qs, qd);
865 create_Left(cb, u_in->size, qd);
866 if (u_in->opcode == ADC || u_in->opcode == SBB) {
njnca82cc02004-11-22 17:18:48 +0000867 tl_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +0000868 qt = create_GETVF(cb, u_in->size);
869 create_UifU(cb, u_in->size, qt, qd);
870 }
871 if (u_in->flags_w != FlagsEmpty) {
872 create_PUTVF(cb, u_in->size, qd);
873 }
njn4ba5a792002-09-30 10:23:54 +0000874 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000875 break;
876
877 /* xor#(qs,qd) = qs `UifU` qd */
878 case XOR:
879 qd = SHADOW(u_in->val2);
880 qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
881 create_UifU(cb, u_in->size, qs, qd);
882 if (u_in->flags_w != FlagsEmpty) {
883 create_PUTVF(cb, u_in->size, qd);
884 }
njn4ba5a792002-09-30 10:23:54 +0000885 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000886 break;
887
888 /* and#/or#(qs,qd)
889 = (qs `UifU` qd) `DifD` improve(vs,qs)
890 `DifD` improve(vd,qd)
891 where improve is the relevant one of
892 Improve{AND,OR}_TQ
893 Use the following steps, with qt as a temp:
894 qt = improve(vd,qd)
895 qd = qs `UifU` qd
896 qd = qt `DifD` qd
897 qt = improve(vs,qs)
898 qd = qt `DifD` qd
899 */
900 case AND: case OR:
njnca82cc02004-11-22 17:18:48 +0000901 tl_assert(u_in->tag1 == TempReg);
902 tl_assert(u_in->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +0000903 qd = SHADOW(u_in->val2);
904 qs = SHADOW(u_in->val1);
905 qt = newShadow(cb);
906
907 /* qt = improve(vd,qd) */
908 uInstr2(cb, MOV, 4, TempReg, qd, TempReg, qt);
909 if (u_in->opcode == AND)
910 create_ImproveAND_TQ(cb, u_in->size, u_in->val2, qt);
911 else
912 create_ImproveOR_TQ(cb, u_in->size, u_in->val2, qt);
913 /* qd = qs `UifU` qd */
914 create_UifU(cb, u_in->size, qs, qd);
915 /* qd = qt `DifD` qd */
916 create_DifD(cb, u_in->size, qt, qd);
917 /* qt = improve(vs,qs) */
918 uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
919 if (u_in->opcode == AND)
920 create_ImproveAND_TQ(cb, u_in->size, u_in->val1, qt);
921 else
922 create_ImproveOR_TQ(cb, u_in->size, u_in->val1, qt);
923 /* qd = qt `DifD` qd */
924 create_DifD(cb, u_in->size, qt, qd);
925 /* So, finally qd is the result tag. */
926 if (u_in->flags_w != FlagsEmpty) {
927 create_PUTVF(cb, u_in->size, qd);
928 }
njn4ba5a792002-09-30 10:23:54 +0000929 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000930 break;
931
932 /* Machinery to do with supporting CALLM. Copy the start and
933 end markers only to make the result easier to read
934 (debug); they generate no code and have no effect.
935 */
936 case CALLM_S: case CALLM_E:
njn4ba5a792002-09-30 10:23:54 +0000937 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000938 break;
939
940 /* Copy PUSH and POP verbatim. Arg/result absval
941 calculations are done when the associated CALL is
942 processed. CLEAR has no effect on absval calculations but
943 needs to be copied.
944 */
945 case PUSH: case POP: case CLEAR:
njn4ba5a792002-09-30 10:23:54 +0000946 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +0000947 break;
948
949 /* In short:
950 callm#(a1# ... an#) = (a1# `UifU` ... `UifU` an#)
951 We have to decide on a size to do the computation at,
952 although the choice doesn't affect correctness. We will
953 do a pcast to the final size anyway, so the only important
954 factor is to choose a size which minimises the total
955 number of casts needed. Valgrind: just use size 0,
956 regardless. It may not be very good for performance
957 but does simplify matters, mainly by reducing the number
958 of different pessimising casts which have to be implemented.
959 */
960 case CALLM: {
961 UInstr* uu;
962 Bool res_used;
963
964 /* Now generate the code. Get the final result absval
965 into qt. */
966 qt = newShadow(cb);
967 qtt = newShadow(cb);
968 uInstr1(cb, SETV, 0, TempReg, qt);
njn810086f2002-11-14 12:42:47 +0000969 for (j = i-1; VG_(get_instr)(cb_in, j)->opcode != CALLM_S; j--) {
970 uu = VG_(get_instr)(cb_in, j);
njn25e49d8e72002-09-23 09:36:25 +0000971 if (uu->opcode != PUSH) continue;
972 /* cast via a temporary */
973 uInstr2(cb, MOV, 4, TempReg, SHADOW(uu->val1),
974 TempReg, qtt);
975 create_PCast(cb, uu->size, 0, qtt);
976 create_UifU(cb, 0, qtt, qt);
977 }
978 /* Remembering also that flags read count as inputs. */
979 if (u_in->flags_r != FlagsEmpty) {
980 qtt = create_GETVF(cb, 0);
981 create_UifU(cb, 0, qtt, qt);
982 }
983
984 /* qt now holds the result tag. If any results from the
985 call are used, either by fetching with POP or
986 implicitly by writing the flags, we copy the result
987 absval to the relevant location. If not used, the call
988 must have been for its side effects, so we test qt here
989 and now. Note that this assumes that all values
990 removed by POP continue to be live. So dead args
991 *must* be removed with CLEAR, not by POPping them into
992 a dummy tempreg.
993 */
994 res_used = False;
njn810086f2002-11-14 12:42:47 +0000995 for (j = i+1; VG_(get_instr)(cb_in, j)->opcode != CALLM_E; j++) {
996 uu = VG_(get_instr)(cb_in, j);
njn25e49d8e72002-09-23 09:36:25 +0000997 if (uu->opcode != POP) continue;
998 /* Cast via a temp. */
999 uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qtt);
1000 create_PCast(cb, 0, uu->size, qtt);
1001 uInstr2(cb, MOV, 4, TempReg, qtt,
1002 TempReg, SHADOW(uu->val1));
1003 res_used = True;
1004 }
1005 if (u_in->flags_w != FlagsEmpty) {
1006 create_PUTVF(cb, 0, qt);
1007 res_used = True;
1008 }
1009 if (!res_used) {
1010 uInstr1(cb, TESTV, 0, TempReg, qt);
1011 /* qt should never be referred to again. Nevertheless
1012 ... */
1013 uInstr1(cb, SETV, 0, TempReg, qt);
1014 }
njn4ba5a792002-09-30 10:23:54 +00001015 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001016 break;
1017 }
1018 /* Whew ... */
1019
1020 case JMP:
1021 if (u_in->tag1 == TempReg) {
1022 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1023 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
1024 } else {
njnca82cc02004-11-22 17:18:48 +00001025 tl_assert(u_in->tag1 == Literal);
njn25e49d8e72002-09-23 09:36:25 +00001026 }
1027 if (u_in->cond != CondAlways) {
njnca82cc02004-11-22 17:18:48 +00001028 tl_assert(u_in->flags_r != FlagsEmpty);
njn25e49d8e72002-09-23 09:36:25 +00001029 qt = create_GETVF(cb, 0);
sewardj8ec2cfc2002-10-13 00:57:26 +00001030 if (/* HACK */ bogusLiterals) {
1031 if (0)
1032 VG_(printf)("ignore TESTV due to bogus literal\n");
1033 } else {
1034 uInstr1(cb, TESTV, 0, TempReg, qt);
1035 }
njn25e49d8e72002-09-23 09:36:25 +00001036 /* qt should never be referred to again. Nevertheless
1037 ... */
1038 uInstr1(cb, SETV, 0, TempReg, qt);
1039 }
njn4ba5a792002-09-30 10:23:54 +00001040 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001041 break;
1042
1043 case JIFZ:
1044 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1045 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
njn4ba5a792002-09-30 10:23:54 +00001046 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001047 break;
1048
1049 /* Emit a check on the address used. The value loaded into the
1050 FPU is checked by the call to fpu_{read/write}_check(). */
sewardj901a4a92003-03-30 01:52:26 +00001051 case MMX2_MemRd: case MMX2_MemWr:
njn25e49d8e72002-09-23 09:36:25 +00001052 case FPU_R: case FPU_W: {
1053 Int t_size = INVALID_TEMPREG;
njnfa509e22003-08-28 17:46:16 +00001054 Bool is_load;
njn25e49d8e72002-09-23 09:36:25 +00001055
sewardjd7971012003-04-04 00:21:58 +00001056 if (u_in->opcode == MMX2_MemRd || u_in->opcode == MMX2_MemWr)
njnca82cc02004-11-22 17:18:48 +00001057 tl_assert(u_in->size == 4 || u_in->size == 8);
sewardjd7971012003-04-04 00:21:58 +00001058
njnfa509e22003-08-28 17:46:16 +00001059 is_load = u_in->opcode==FPU_R || u_in->opcode==MMX2_MemRd;
njnca82cc02004-11-22 17:18:48 +00001060 tl_assert(u_in->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +00001061 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
1062 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1063
1064 t_size = newTemp(cb);
1065 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1066 uLiteral(cb, u_in->size);
1067 uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
njnfa509e22003-08-28 17:46:16 +00001068 uCCall(cb, is_load ? (Addr) & MC_(fpu_read_check)
1069 : (Addr) & MC_(fpu_write_check),
njn25e49d8e72002-09-23 09:36:25 +00001070 2, 2, False);
1071
njn4ba5a792002-09-30 10:23:54 +00001072 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001073 break;
1074 }
1075
thughes96b466a2004-03-15 16:43:58 +00001076 case MMX2a1_MemRd: {
1077 Int t_size = INVALID_TEMPREG;
1078
njnca82cc02004-11-22 17:18:48 +00001079 tl_assert(u_in->size == 8);
thughes96b466a2004-03-15 16:43:58 +00001080
njnca82cc02004-11-22 17:18:48 +00001081 tl_assert(u_in->tag3 == TempReg);
thughes96b466a2004-03-15 16:43:58 +00001082 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val3));
1083 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val3));
1084
1085 t_size = newTemp(cb);
1086 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1087 uLiteral(cb, u_in->size);
1088 uInstr2(cb, CCALL, 0, TempReg, u_in->val3, TempReg, t_size);
1089 uCCall(cb, (Addr) & MC_(fpu_read_check), 2, 2, False);
1090
1091 VG_(copy_UInstr)(cb, u_in);
1092 break;
1093 }
1094
sewardjb1116852003-10-17 21:51:28 +00001095 /* SSE ins referencing scalar integer registers */
nethercoteb1affa82004-01-19 19:14:18 +00001096 case SSE2g_RegWr:
1097 case SSE2g1_RegWr:
1098 case SSE2e1_RegRd:
1099 case SSE3g_RegWr:
daywalkerb6d9b542003-09-26 00:16:25 +00001100 case SSE3e_RegRd:
1101 case SSE3e_RegWr:
sewardjb1116852003-10-17 21:51:28 +00001102 case SSE3g1_RegWr:
1103 case SSE3e1_RegRd:
njnca82cc02004-11-22 17:18:48 +00001104 tl_assert(u_in->tag3 == TempReg);
daywalkerb6d9b542003-09-26 00:16:25 +00001105
nethercote1018bdd2004-02-11 23:33:29 +00001106 if (u_in->opcode == SSE2e1_RegRd || u_in->opcode == SSE3e1_RegRd) {
njnca82cc02004-11-22 17:18:48 +00001107 tl_assert(u_in->size == 2);
sewardjb1116852003-10-17 21:51:28 +00001108 } else {
njnca82cc02004-11-22 17:18:48 +00001109 tl_assert(u_in->size == 4);
sewardjb1116852003-10-17 21:51:28 +00001110 }
daywalkerb6d9b542003-09-26 00:16:25 +00001111
sewardjb1116852003-10-17 21:51:28 +00001112 /* Is it a read ? Better check the V bits right now. */
nethercote09875282004-04-26 13:06:16 +00001113 if ( u_in->opcode == SSE2e1_RegRd
1114 || u_in->opcode == SSE3e_RegRd
sewardjb1116852003-10-17 21:51:28 +00001115 || u_in->opcode == SSE3e1_RegRd )
1116 uInstr1(cb, TESTV, u_in->size,
1117 TempReg, SHADOW(u_in->val3));
1118
1119 /* And for both read and write, set the register to be
1120 defined. */
1121 uInstr1(cb, SETV, u_in->size,
1122 TempReg, SHADOW(u_in->val3));
daywalkerb6d9b542003-09-26 00:16:25 +00001123
1124 VG_(copy_UInstr)(cb, u_in);
1125 break;
1126
1127 /* ... and the same deal for SSE insns referencing memory */
sewardj93992e22003-05-26 09:17:41 +00001128 case SSE3a_MemRd:
1129 case SSE3a_MemWr:
1130 case SSE2a_MemWr:
sewardj77d30a22003-10-19 08:18:52 +00001131 case SSE2a_MemRd:
nethercote1018bdd2004-02-11 23:33:29 +00001132 case SSE3a1_MemRd:
1133 case SSE2a1_MemRd: {
sewardj93992e22003-05-26 09:17:41 +00001134 Bool is_load;
1135 Int t_size;
1136
njnca82cc02004-11-22 17:18:48 +00001137 tl_assert(u_in->size == 4 || u_in->size == 8
jsewardfca60182004-01-04 23:30:55 +00001138 || u_in->size == 16 || u_in->size == 512);
sewardj93992e22003-05-26 09:17:41 +00001139
1140 t_size = INVALID_TEMPREG;
sewardjb1116852003-10-17 21:51:28 +00001141 is_load = u_in->opcode==SSE2a_MemRd
sewardj77d30a22003-10-19 08:18:52 +00001142 || u_in->opcode==SSE3a_MemRd
nethercote1018bdd2004-02-11 23:33:29 +00001143 || u_in->opcode==SSE2a1_MemRd
sewardj77d30a22003-10-19 08:18:52 +00001144 || u_in->opcode==SSE3a1_MemRd;
sewardj93992e22003-05-26 09:17:41 +00001145
njnca82cc02004-11-22 17:18:48 +00001146 tl_assert(u_in->tag3 == TempReg);
daywalkerb6d9b542003-09-26 00:16:25 +00001147
1148 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val3));
1149 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val3));
1150 t_size = newTemp(cb);
1151 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1152 uLiteral(cb, u_in->size);
1153 uInstr2(cb, CCALL, 0, TempReg, u_in->val3, TempReg, t_size);
1154 uCCall(cb, is_load ? (Addr) & MC_(fpu_read_check)
1155 : (Addr) & MC_(fpu_write_check),
1156 2, 2, False);
1157
sewardj93992e22003-05-26 09:17:41 +00001158 VG_(copy_UInstr)(cb, u_in);
1159 break;
1160 }
sewardjb1116852003-10-17 21:51:28 +00001161
daywalkerb6d9b542003-09-26 00:16:25 +00001162 case SSE3ag_MemRd_RegWr:
1163 {
1164 Int t_size;
sewardj93992e22003-05-26 09:17:41 +00001165
njnca82cc02004-11-22 17:18:48 +00001166 tl_assert(u_in->size == 4 || u_in->size == 8);
1167 tl_assert(u_in->tag1 == TempReg);
daywalkerb6d9b542003-09-26 00:16:25 +00001168 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1169 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val1));
1170 t_size = newTemp(cb);
1171 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1172 uLiteral(cb, u_in->size);
1173 uInstr2(cb, CCALL, 0, TempReg, u_in->val1, TempReg, t_size);
1174 uCCall(cb, (Addr) MC_(fpu_read_check), 2, 2, False );
1175 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1176 VG_(copy_UInstr)(cb, u_in);
1177 break;
1178 }
thughesd88f4152004-03-28 11:26:29 +00001179
1180 /* For MMX and SSE insns not referencing memory, just
1181 make sure the eflags are defined if the instruction
1182 read them, and make them defined it it writes them. */
sewardj247f32f2003-10-03 20:40:45 +00001183 case SSE5: case SSE4: case SSE3:
sewardj901a4a92003-03-30 01:52:26 +00001184 case MMX1: case MMX2: case MMX3:
thughesd88f4152004-03-28 11:26:29 +00001185 case FPU:
1186 if (u_in->flags_r != FlagsEmpty) {
1187 qt = create_GETVF(cb, 0);
1188 uInstr1(cb, TESTV, 0, TempReg, qt);
1189 /* qt should never be referred to again. Nevertheless
1190 ... */
1191 uInstr1(cb, SETV, 0, TempReg, qt);
1192 }
1193 if (u_in->flags_w != FlagsEmpty) {
1194 qd = newTemp(cb);
1195 uInstr2(cb, MOV, 4, Literal, 0, TempReg, qd);
thughes989df352004-03-28 11:36:23 +00001196 uLiteral(cb, 0);
thughesd88f4152004-03-28 11:26:29 +00001197 create_PUTVF(cb, 0, qd);
1198 }
njn4ba5a792002-09-30 10:23:54 +00001199 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001200 break;
1201
sewardj901a4a92003-03-30 01:52:26 +00001202 /* Since we don't track definedness of values inside the
1203 MMX state, we'd better check that the (int) reg being
1204 read here is defined. */
sewardj4fbe6e92003-06-15 21:54:34 +00001205 case MMX2_ERegRd:
njnca82cc02004-11-22 17:18:48 +00001206 tl_assert(u_in->tag2 == TempReg);
1207 tl_assert(u_in->size == 4);
sewardj901a4a92003-03-30 01:52:26 +00001208 uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
1209 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1210 VG_(copy_UInstr)(cb, u_in);
1211 break;
1212
sewardjd1c9e432003-04-04 20:40:34 +00001213 /* The MMX register is assumed to be fully defined, so
1214 that's what this register becomes. */
sewardj4fbe6e92003-06-15 21:54:34 +00001215 case MMX2_ERegWr:
njnca82cc02004-11-22 17:18:48 +00001216 tl_assert(u_in->tag2 == TempReg);
1217 tl_assert(u_in->size == 4);
sewardjd1c9e432003-04-04 20:40:34 +00001218 uInstr1(cb, SETV, 4, TempReg, SHADOW(u_in->val2));
1219 VG_(copy_UInstr)(cb, u_in);
sewardj3d7c9c82003-03-26 21:08:13 +00001220 break;
1221
njn25e49d8e72002-09-23 09:36:25 +00001222 default:
njn4ba5a792002-09-30 10:23:54 +00001223 VG_(pp_UInstr)(0, u_in);
njn67993252004-11-22 18:02:32 +00001224 VG_(tool_panic)( "memcheck_instrument: unhandled case");
njn25e49d8e72002-09-23 09:36:25 +00001225
1226 } /* end of switch (u_in->opcode) */
1227
1228 } /* end of for loop */
1229
njn4ba5a792002-09-30 10:23:54 +00001230 VG_(free_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +00001231 return cb;
1232}
1233
1234/*------------------------------------------------------------*/
1235/*--- Clean up mem check instrumentation. ---*/
1236/*------------------------------------------------------------*/
1237
njn25e49d8e72002-09-23 09:36:25 +00001238#define dis VG_(print_codegen)
1239
1240
1241#define VGC_IS_SHADOW(tempreg) ((tempreg % 2) == 1)
1242#define VGC_UNDEF ((UChar)100)
1243#define VGC_VALUE ((UChar)101)
1244
1245#define NOP_no_msg(uu) \
njn4ba5a792002-09-30 10:23:54 +00001246 do { VG_(new_NOP)(uu); } while (False)
njn25e49d8e72002-09-23 09:36:25 +00001247
1248#define NOP_tag1_op(uu) \
njn4ba5a792002-09-30 10:23:54 +00001249 do { VG_(new_NOP)(uu); \
njn25e49d8e72002-09-23 09:36:25 +00001250 if (dis) \
1251 VG_(printf)(" at %2d: delete %s due to defd arg\n", \
1252 i, nameOfTagOp(u->val3)); \
1253 } while (False)
1254
1255#define SETV_tag1_op(uu,newsz) \
1256 do { uu->opcode = SETV; \
1257 uu->size = newsz; \
1258 uu->tag2 = uu->tag3 = NoValue; \
1259 if (dis) \
1260 VG_(printf)(" at %2d: convert %s to SETV%d " \
1261 "due to defd arg\n", \
1262 i, nameOfTagOp(u->val3), newsz); \
1263 } while (False)
1264
1265
1266
1267/* Run backwards and delete SETVs on shadow temps for which the next
1268 action is a write. Needs an env saying whether or not the next
1269 action is a write. The supplied UCodeBlock is destructively
1270 modified.
1271*/
1272static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
1273{
1274 Int i, j, k;
njn810086f2002-11-14 12:42:47 +00001275 Int n_temps = VG_(get_num_temps)(cb);
njn25e49d8e72002-09-23 09:36:25 +00001276 Bool* next_is_write;
1277 UInstr* u;
njnf4ce3d32003-02-10 10:17:26 +00001278 Int tempUse[VG_MAX_REGS_USED];
1279 Bool isWrites[VG_MAX_REGS_USED];
njn25e49d8e72002-09-23 09:36:25 +00001280
1281 if (n_temps == 0) return;
1282
1283 next_is_write = VG_(malloc)(n_temps * sizeof(Bool));
1284
1285 for (i = 0; i < n_temps; i++) next_is_write[i] = True;
1286
njn810086f2002-11-14 12:42:47 +00001287 for (i = VG_(get_num_instrs)(cb) - 1; i >= 0; i--) {
1288 u = VG_(get_instr)(cb, i);
njn25e49d8e72002-09-23 09:36:25 +00001289
sewardj51647482002-12-15 01:42:22 +00001290 /* Occasionally there will be GETVs, TAG1s and TAG2s calculating
1291 values which are never used. These first three cases get rid
1292 of them. */
njn25e49d8e72002-09-23 09:36:25 +00001293
1294 if (u->opcode == GETV && VGC_IS_SHADOW(u->val2)
sewardj51647482002-12-15 01:42:22 +00001295 && next_is_write[u->val2]) {
njnca82cc02004-11-22 17:18:48 +00001296 tl_assert(u->val2 < n_temps);
njn4ba5a792002-09-30 10:23:54 +00001297 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001298 if (dis)
1299 VG_(printf)(" at %2d: delete GETV\n", i);
1300 } else
1301
1302 if (u->opcode == TAG1 && VGC_IS_SHADOW(u->val1)
sewardj51647482002-12-15 01:42:22 +00001303 && next_is_write[u->val1]) {
njnca82cc02004-11-22 17:18:48 +00001304 tl_assert(u->val1 < n_temps);
njn4ba5a792002-09-30 10:23:54 +00001305 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001306 if (dis)
1307 VG_(printf)(" at %2d: delete TAG1\n", i);
1308 } else
1309
1310 if (u->opcode == TAG2 && VGC_IS_SHADOW(u->val2)
sewardj51647482002-12-15 01:42:22 +00001311 && next_is_write[u->val2]) {
njnca82cc02004-11-22 17:18:48 +00001312 tl_assert(u->val2 < n_temps);
njn4ba5a792002-09-30 10:23:54 +00001313 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001314 if (dis)
1315 VG_(printf)(" at %2d: delete TAG2\n", i);
1316 } else
1317
sewardj51647482002-12-15 01:42:22 +00001318 /* The bulk of the cleanup work of this function is done by
1319 the code from here downwards. */
njn25e49d8e72002-09-23 09:36:25 +00001320
1321 if (u->opcode == MOV && VGC_IS_SHADOW(u->val2)
1322 && next_is_write[u->val2]) {
1323 /* This MOV is pointless because the target is dead at this
1324 point. Delete it. */
njn4ba5a792002-09-30 10:23:54 +00001325 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001326 if (dis)
1327 VG_(printf)(" at %2d: delete MOV\n", i);
1328 } else
1329
1330 if (u->opcode == SETV) {
1331 if (u->tag1 == TempReg) {
njnca82cc02004-11-22 17:18:48 +00001332 tl_assert(VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001333 if (next_is_write[u->val1]) {
1334 /* This write is pointless, so annul it. */
njn4ba5a792002-09-30 10:23:54 +00001335 VG_(new_NOP)(u);
njn25e49d8e72002-09-23 09:36:25 +00001336 if (dis)
1337 VG_(printf)(" at %2d: delete SETV\n", i);
1338 } else {
1339 /* This write has a purpose; don't annul it, but do
1340 notice that we did it. */
1341 next_is_write[u->val1] = True;
1342 }
1343
1344 }
1345
1346 } else {
1347 /* Find out what this insn does to the temps. */
njn810086f2002-11-14 12:42:47 +00001348 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
njnca82cc02004-11-22 17:18:48 +00001349 tl_assert(0 <= k && k <= VG_MAX_REGS_USED);
njn25e49d8e72002-09-23 09:36:25 +00001350 for (j = k-1; j >= 0; j--) {
njn810086f2002-11-14 12:42:47 +00001351 next_is_write[ tempUse[j] ] = isWrites[j];
njn25e49d8e72002-09-23 09:36:25 +00001352 }
1353 }
1354 }
1355}
1356
1357
1358/* Run forwards, propagating and using the is-completely-defined
1359 property. This removes a lot of redundant tag-munging code.
1360 Unfortunately it requires intimate knowledge of how each uinstr and
1361 tagop modifies its arguments. This duplicates knowledge of uinstr
njn4ba5a792002-09-30 10:23:54 +00001362 tempreg uses embodied in VG_(get_reg_usage)(), which is unfortunate.
njn25e49d8e72002-09-23 09:36:25 +00001363 The supplied UCodeBlock* is modified in-place.
1364
1365 For each value temp, def[] should hold VGC_VALUE.
1366
1367 For each shadow temp, def[] may hold 4,2,1 or 0 iff that shadow is
1368 definitely known to be fully defined at that size. In all other
1369 circumstances a shadow's def[] entry is VGC_UNDEF, meaning possibly
1370 undefined. In cases of doubt, VGC_UNDEF is always safe.
1371*/
1372static void vg_propagate_definedness ( UCodeBlock* cb )
1373{
1374 Int i, j, k, t;
njn810086f2002-11-14 12:42:47 +00001375 Int n_temps = VG_(get_num_temps)(cb);
njn25e49d8e72002-09-23 09:36:25 +00001376 UChar* def;
1377 UInstr* u;
njnf4ce3d32003-02-10 10:17:26 +00001378 Int tempUse[VG_MAX_REGS_USED];
1379 Bool isWrites[VG_MAX_REGS_USED];
njn25e49d8e72002-09-23 09:36:25 +00001380
1381 if (n_temps == 0) return;
1382
1383 def = VG_(malloc)(n_temps * sizeof(UChar));
1384
1385 for (i = 0; i < n_temps; i++)
1386 def[i] = VGC_IS_SHADOW(i) ? VGC_UNDEF : VGC_VALUE;
1387
1388 /* Run forwards, detecting and using the all-defined property. */
1389
njn810086f2002-11-14 12:42:47 +00001390 for (i = 0; i < VG_(get_num_instrs)(cb); i++) {
1391 u = VG_(get_instr)(cb, i);
njn25e49d8e72002-09-23 09:36:25 +00001392 switch (u->opcode) {
1393
1394 /* Tag-handling uinstrs. */
1395
1396 /* Deal with these quickly. */
1397 case NOP:
sewardj7a5ebcf2002-11-13 22:42:13 +00001398 case LOCK:
njn25e49d8e72002-09-23 09:36:25 +00001399 case INCEIP:
1400 break;
1401
1402 /* Make a tag defined. */
1403 case SETV:
njnca82cc02004-11-22 17:18:48 +00001404 tl_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001405 def[u->val1] = u->size;
1406 break;
1407
1408 /* Check definedness of a tag. */
1409 case TESTV:
njnca82cc02004-11-22 17:18:48 +00001410 tl_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001411 if (def[u->val1] <= 4) {
njnca82cc02004-11-22 17:18:48 +00001412 tl_assert(def[u->val1] == u->size);
njn25e49d8e72002-09-23 09:36:25 +00001413 NOP_no_msg(u);
1414 if (dis)
1415 VG_(printf)(" at %2d: delete TESTV on defd arg\n", i);
1416 }
1417 break;
1418
1419 /* Applies to both values and tags. Propagate Definedness
1420 property through copies. Note that this isn't optional;
1421 we *have* to do this to keep def[] correct. */
1422 case MOV:
njnca82cc02004-11-22 17:18:48 +00001423 tl_assert(u->tag2 == TempReg);
njn25e49d8e72002-09-23 09:36:25 +00001424 if (u->tag1 == TempReg) {
1425 if (VGC_IS_SHADOW(u->val1)) {
njnca82cc02004-11-22 17:18:48 +00001426 tl_assert(VGC_IS_SHADOW(u->val2));
njn25e49d8e72002-09-23 09:36:25 +00001427 def[u->val2] = def[u->val1];
1428 }
1429 }
1430 break;
1431
1432 case PUTV:
njnca82cc02004-11-22 17:18:48 +00001433 tl_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001434 if (def[u->val1] <= 4) {
njnca82cc02004-11-22 17:18:48 +00001435 tl_assert(def[u->val1] == u->size);
njn25e49d8e72002-09-23 09:36:25 +00001436 u->tag1 = Literal;
1437 u->val1 = 0;
1438 switch (u->size) {
1439 case 4: u->lit32 = 0x00000000; break;
1440 case 2: u->lit32 = 0xFFFF0000; break;
1441 case 1: u->lit32 = 0xFFFFFF00; break;
njn67993252004-11-22 18:02:32 +00001442 default: VG_(tool_panic)("vg_cleanup(PUTV)");
njn25e49d8e72002-09-23 09:36:25 +00001443 }
1444 if (dis)
1445 VG_(printf)(
1446 " at %2d: propagate definedness into PUTV\n", i);
1447 }
1448 break;
1449
1450 case STOREV:
njnca82cc02004-11-22 17:18:48 +00001451 tl_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001452 if (def[u->val1] <= 4) {
njnca82cc02004-11-22 17:18:48 +00001453 tl_assert(def[u->val1] == u->size);
njn25e49d8e72002-09-23 09:36:25 +00001454 u->tag1 = Literal;
1455 u->val1 = 0;
1456 switch (u->size) {
1457 case 4: u->lit32 = 0x00000000; break;
1458 case 2: u->lit32 = 0xFFFF0000; break;
1459 case 1: u->lit32 = 0xFFFFFF00; break;
njn67993252004-11-22 18:02:32 +00001460 default: VG_(tool_panic)("vg_cleanup(STOREV)");
njn25e49d8e72002-09-23 09:36:25 +00001461 }
1462 if (dis)
1463 VG_(printf)(
1464 " at %2d: propagate definedness into STandV\n", i);
1465 }
1466 break;
1467
1468 /* Nothing interesting we can do with this, I think. */
1469 case PUTVF:
1470 break;
1471
1472 /* Tag handling operations. */
1473 case TAG2:
njnca82cc02004-11-22 17:18:48 +00001474 tl_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
1475 tl_assert(u->tag3 == Lit16);
njn25e49d8e72002-09-23 09:36:25 +00001476 /* Ultra-paranoid "type" checking. */
1477 switch (u->val3) {
1478 case Tag_ImproveAND4_TQ: case Tag_ImproveAND2_TQ:
1479 case Tag_ImproveAND1_TQ: case Tag_ImproveOR4_TQ:
1480 case Tag_ImproveOR2_TQ: case Tag_ImproveOR1_TQ:
njnca82cc02004-11-22 17:18:48 +00001481 tl_assert(u->tag1 == TempReg && !VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001482 break;
1483 default:
njnca82cc02004-11-22 17:18:48 +00001484 tl_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001485 break;
1486 }
1487 switch (u->val3) {
1488 Int sz;
1489 case Tag_UifU4:
1490 sz = 4; goto do_UifU;
1491 case Tag_UifU2:
1492 sz = 2; goto do_UifU;
1493 case Tag_UifU1:
1494 sz = 1; goto do_UifU;
1495 case Tag_UifU0:
1496 sz = 0; goto do_UifU;
1497 do_UifU:
njnca82cc02004-11-22 17:18:48 +00001498 tl_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1499 tl_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
njn25e49d8e72002-09-23 09:36:25 +00001500 if (def[u->val1] <= 4) {
1501 /* UifU. The first arg is defined, so result is
1502 simply second arg. Delete this operation. */
njnca82cc02004-11-22 17:18:48 +00001503 tl_assert(def[u->val1] == sz);
njn25e49d8e72002-09-23 09:36:25 +00001504 NOP_no_msg(u);
1505 if (dis)
1506 VG_(printf)(
1507 " at %2d: delete UifU%d due to defd arg1\n",
1508 i, sz);
1509 }
1510 else
1511 if (def[u->val2] <= 4) {
1512 /* UifU. The second arg is defined, so result is
1513 simply first arg. Copy to second. */
njnca82cc02004-11-22 17:18:48 +00001514 tl_assert(def[u->val2] == sz);
njn25e49d8e72002-09-23 09:36:25 +00001515 u->opcode = MOV;
1516 u->size = 4;
1517 u->tag3 = NoValue;
1518 def[u->val2] = def[u->val1];
1519 if (dis)
1520 VG_(printf)(
1521 " at %2d: change UifU%d to MOV due to defd"
1522 " arg2\n",
1523 i, sz);
1524 }
1525 break;
1526 case Tag_ImproveAND4_TQ:
1527 sz = 4; goto do_ImproveAND;
1528 case Tag_ImproveAND1_TQ:
1529 sz = 1; goto do_ImproveAND;
1530 do_ImproveAND:
mueller00a8a6f2004-01-02 22:46:34 +00001531 /* Implements Q = T AND Q. So if Q is entirely defined,
njn25e49d8e72002-09-23 09:36:25 +00001532 ie all 0s, we get MOV T, Q. */
1533 if (def[u->val2] <= 4) {
njnca82cc02004-11-22 17:18:48 +00001534 tl_assert(def[u->val2] == sz);
njn25e49d8e72002-09-23 09:36:25 +00001535 u->size = 4; /* Regardless of sz */
1536 u->opcode = MOV;
1537 u->tag3 = NoValue;
1538 def[u->val2] = VGC_UNDEF;
1539 if (dis)
1540 VG_(printf)(
1541 " at %2d: change ImproveAND%d_TQ to MOV due "
1542 "to defd arg2\n",
1543 i, sz);
1544 }
1545 break;
1546 default:
1547 goto unhandled;
1548 }
1549 break;
1550
1551 case TAG1:
njnca82cc02004-11-22 17:18:48 +00001552 tl_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
njn25e49d8e72002-09-23 09:36:25 +00001553 if (def[u->val1] > 4) break;
1554 /* We now know that the arg to the op is entirely defined.
1555 If the op changes the size of the arg, we must replace
1556 it with a SETV at the new size. If it doesn't change
1557 the size, we can delete it completely. */
1558 switch (u->val3) {
1559 /* Maintain the same size ... */
1560 case Tag_Left4:
njnca82cc02004-11-22 17:18:48 +00001561 tl_assert(def[u->val1] == 4);
njn25e49d8e72002-09-23 09:36:25 +00001562 NOP_tag1_op(u);
1563 break;
1564 case Tag_PCast11:
njnca82cc02004-11-22 17:18:48 +00001565 tl_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001566 NOP_tag1_op(u);
1567 break;
1568 /* Change size ... */
1569 case Tag_PCast40:
njnca82cc02004-11-22 17:18:48 +00001570 tl_assert(def[u->val1] == 4);
njn25e49d8e72002-09-23 09:36:25 +00001571 SETV_tag1_op(u,0);
1572 def[u->val1] = 0;
1573 break;
1574 case Tag_PCast14:
njnca82cc02004-11-22 17:18:48 +00001575 tl_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001576 SETV_tag1_op(u,4);
1577 def[u->val1] = 4;
1578 break;
1579 case Tag_PCast12:
njnca82cc02004-11-22 17:18:48 +00001580 tl_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001581 SETV_tag1_op(u,2);
1582 def[u->val1] = 2;
1583 break;
1584 case Tag_PCast10:
njnca82cc02004-11-22 17:18:48 +00001585 tl_assert(def[u->val1] == 1);
njn25e49d8e72002-09-23 09:36:25 +00001586 SETV_tag1_op(u,0);
1587 def[u->val1] = 0;
1588 break;
1589 case Tag_PCast02:
njnca82cc02004-11-22 17:18:48 +00001590 tl_assert(def[u->val1] == 0);
njn25e49d8e72002-09-23 09:36:25 +00001591 SETV_tag1_op(u,2);
1592 def[u->val1] = 2;
1593 break;
1594 default:
1595 goto unhandled;
1596 }
1597 if (dis)
1598 VG_(printf)(
1599 " at %2d: delete TAG1 %s due to defd arg\n",
1600 i, nameOfTagOp(u->val3));
1601 break;
1602
1603 default:
1604 unhandled:
1605 /* We don't know how to handle this uinstr. Be safe, and
1606 set to VGC_VALUE or VGC_UNDEF all temps written by it. */
njn810086f2002-11-14 12:42:47 +00001607 k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
njnca82cc02004-11-22 17:18:48 +00001608 tl_assert(0 <= k && k <= VG_MAX_REGS_USED);
njn25e49d8e72002-09-23 09:36:25 +00001609 for (j = 0; j < k; j++) {
njn810086f2002-11-14 12:42:47 +00001610 t = tempUse[j];
njnca82cc02004-11-22 17:18:48 +00001611 tl_assert(t >= 0 && t < n_temps);
njn810086f2002-11-14 12:42:47 +00001612 if (!isWrites[j]) {
njn25e49d8e72002-09-23 09:36:25 +00001613 /* t is read; ignore it. */
1614 if (0&& VGC_IS_SHADOW(t) && def[t] <= 4)
1615 VG_(printf)("ignoring def %d at %s %s\n",
1616 def[t],
njn4ba5a792002-09-30 10:23:54 +00001617 VG_(name_UOpcode)(True, u->opcode),
njn25e49d8e72002-09-23 09:36:25 +00001618 (u->opcode == TAG1 || u->opcode == TAG2)
1619 ? nameOfTagOp(u->val3)
1620 : (Char*)"");
1621 } else {
1622 /* t is written; better nullify it. */
1623 def[t] = VGC_IS_SHADOW(t) ? VGC_UNDEF : VGC_VALUE;
1624 }
1625 }
1626 }
1627 }
1628}
1629
1630
1631/* Top level post-MemCheck-instrumentation cleanup function. */
1632static void vg_cleanup ( UCodeBlock* cb )
1633{
1634 vg_propagate_definedness ( cb );
1635 vg_delete_redundant_SETVs ( cb );
1636}
1637
1638
1639/* Caller will print out final instrumented code if necessary; we
1640 print out intermediate instrumented code here if necessary. */
1641UCodeBlock* SK_(instrument) ( UCodeBlock* cb, Addr not_used )
1642{
1643 cb = memcheck_instrument ( cb );
njn5c004e42002-11-18 11:04:50 +00001644 if (MC_(clo_cleanup)) {
njn25e49d8e72002-09-23 09:36:25 +00001645 if (dis) {
njn4ba5a792002-09-30 10:23:54 +00001646 VG_(pp_UCodeBlock) ( cb, "Unimproved instrumented UCode:" );
njn25e49d8e72002-09-23 09:36:25 +00001647 VG_(printf)("Instrumentation improvements:\n");
1648 }
1649 vg_cleanup(cb);
1650 if (dis) VG_(printf)("\n");
1651 }
1652 return cb;
1653}
1654
1655#undef dis
1656
1657/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001658/*--- end mc_translate.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001659/*--------------------------------------------------------------------*/