mc_translate.c revision ac6c17667e489215a0795c24cc1b202254582a4f
1
2/*--------------------------------------------------------------------*/
3/*--- Instrument UCode to perform memory checking operations.      ---*/
4/*---                                               mc_translate.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of MemCheck, a heavyweight Valgrind skin for
9   detecting memory errors.
10
11   Copyright (C) 2000-2002 Julian Seward
12      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
32#include "mc_include.h"
33
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*/
42Bool SK_(sane_XUInstr)(Bool beforeRA, Bool beforeLiveness, UInstr* u)
43{
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);
97      VG_(skin_panic)("SK_(sane_XUInstr): unhandled opcode");
98   }
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";
159      default: VG_(skin_panic)("vg_nameOfTagOp");
160   }
161}
162
163
164Char* SK_(name_XUOpcode)(Opcode opc)
165{
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);
179         VG_(skin_panic)("SK_(name_XUOpcode): unhandled case");
180   }
181}
182
183/* ---------------------------------------------------------------------
184   Debugging stuff.
185   ------------------------------------------------------------------ */
186
187void SK_(pp_XUInstr)(UInstr* u)
188{
189   switch (u->opcode) {
190
191      case TAG1:
192         VG_(printf)("\t");
193         VG_(pp_UOperand)(u, 1, 4, False);
194         VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
195         VG_(pp_UOperand)(u, 1, 4, False);
196         VG_(printf)(" )");
197         break;
198
199      case TAG2:
200         VG_(printf)("\t");
201         VG_(pp_UOperand)(u, 2, 4, False);
202         VG_(printf)(" = %s ( ", nameOfTagOp( u->val3 ));
203         VG_(pp_UOperand)(u, 1, 4, False);
204         VG_(printf)(", ");
205         VG_(pp_UOperand)(u, 2, 4, False);
206         VG_(printf)(" )");
207         break;
208
209      case STOREV: case LOADV:
210         VG_(printf)("\t");
211         VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOADV);
212         VG_(printf)(", ");
213         VG_(pp_UOperand)(u, 2, u->size, u->opcode==STOREV);
214         break;
215
216      case PUTVF: case GETVF:
217         VG_(printf)("\t");
218         VG_(pp_UOperand)(u, 1, 0, False);
219         break;
220
221      case GETV: case PUTV:
222         VG_(printf)("\t");
223         VG_(pp_UOperand)(u, 1, u->opcode==PUTV ? 4 : u->size, False);
224         VG_(printf)(", ");
225         VG_(pp_UOperand)(u, 2, u->opcode==GETV ? 4 : u->size, False);
226         break;
227
228      case TESTV: case SETV:
229         VG_(printf)("\t");
230         VG_(pp_UOperand)(u, 1, u->size, False);
231         break;
232
233      default:
234         VG_(printf)("unhandled opcode: %u\n", u->opcode);
235         VG_(skin_panic)("SK_(pp_XUInstr): unhandled opcode");
236   }
237
238}
239
240Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, RegUse* arr)
241{
242#  define RD(ono)    VG_UINSTR_READS_REG(ono)
243#  define WR(ono)    VG_UINSTR_WRITES_REG(ono)
244
245   Int n = 0;
246   switch (u->opcode) {
247
248      case TAG1:    RD(1); WR(1);        break;
249      case TAG2:    RD(1); RD(2); WR(2); break;
250      case LOADV:   RD(1); WR(2);        break;
251      case STOREV:  RD(1); RD(2);        break;
252      case GETV:    WR(2);               break;
253      case PUTV:    RD(1);               break;
254      case TESTV:   RD(1);               break;
255      case SETV:    WR(1);               break;
256      case PUTVF:   RD(1);               break;
257      case GETVF:   WR(1);               break;
258
259      default:
260         VG_(printf)("unhandled opcode: %u\n", u->opcode);
261         VG_(skin_panic)("SK_(get_Xreg_usage): unhandled opcode");
262   }
263   return n;
264
265#  undef RD
266#  undef WR
267}
268
269/*------------------------------------------------------------*/
270/*--- New instrumentation machinery.                       ---*/
271/*------------------------------------------------------------*/
272
273static
274TagOp get_Tag_ImproveOR_TQ ( Int sz )
275{
276   switch (sz) {
277      case 4: return Tag_ImproveOR4_TQ;
278      case 2: return Tag_ImproveOR2_TQ;
279      case 1: return Tag_ImproveOR1_TQ;
280      default: VG_(skin_panic)("get_Tag_ImproveOR_TQ");
281   }
282}
283
284
285static
286TagOp get_Tag_ImproveAND_TQ ( Int sz )
287{
288   switch (sz) {
289      case 4: return Tag_ImproveAND4_TQ;
290      case 2: return Tag_ImproveAND2_TQ;
291      case 1: return Tag_ImproveAND1_TQ;
292      default: VG_(skin_panic)("get_Tag_ImproveAND_TQ");
293   }
294}
295
296
297static
298TagOp get_Tag_Left ( Int sz )
299{
300   switch (sz) {
301      case 4: return Tag_Left4;
302      case 2: return Tag_Left2;
303      case 1: return Tag_Left1;
304      default: VG_(skin_panic)("get_Tag_Left");
305   }
306}
307
308
309static
310TagOp get_Tag_UifU ( Int sz )
311{
312   switch (sz) {
313      case 4: return Tag_UifU4;
314      case 2: return Tag_UifU2;
315      case 1: return Tag_UifU1;
316      case 0: return Tag_UifU0;
317      default: VG_(skin_panic)("get_Tag_UifU");
318   }
319}
320
321
322static
323TagOp get_Tag_DifD ( Int sz )
324{
325   switch (sz) {
326      case 4: return Tag_DifD4;
327      case 2: return Tag_DifD2;
328      case 1: return Tag_DifD1;
329      default: VG_(skin_panic)("get_Tag_DifD");
330   }
331}
332
333
334static
335TagOp get_Tag_PCast ( Int szs, Int szd )
336{
337   if (szs == 4 && szd == 0) return Tag_PCast40;
338   if (szs == 2 && szd == 0) return Tag_PCast20;
339   if (szs == 1 && szd == 0) return Tag_PCast10;
340   if (szs == 0 && szd == 1) return Tag_PCast01;
341   if (szs == 0 && szd == 2) return Tag_PCast02;
342   if (szs == 0 && szd == 4) return Tag_PCast04;
343   if (szs == 1 && szd == 4) return Tag_PCast14;
344   if (szs == 1 && szd == 2) return Tag_PCast12;
345   if (szs == 1 && szd == 1) return Tag_PCast11;
346   VG_(printf)("get_Tag_PCast(%d,%d)\n", szs, szd);
347   VG_(skin_panic)("get_Tag_PCast");
348}
349
350
351static
352TagOp get_Tag_Widen ( Bool syned, Int szs, Int szd )
353{
354   if (szs == 1 && szd == 2 && syned)  return Tag_SWiden12;
355   if (szs == 1 && szd == 2 && !syned) return Tag_ZWiden12;
356
357   if (szs == 1 && szd == 4 && syned)  return Tag_SWiden14;
358   if (szs == 1 && szd == 4 && !syned) return Tag_ZWiden14;
359
360   if (szs == 2 && szd == 4 && syned)  return Tag_SWiden24;
361   if (szs == 2 && szd == 4 && !syned) return Tag_ZWiden24;
362
363   VG_(printf)("get_Tag_Widen(%d,%d,%d)\n", (Int)syned, szs, szd);
364   VG_(skin_panic)("get_Tag_Widen");
365}
366
367/* Pessimally cast the spec'd shadow from one size to another. */
368static
369void create_PCast ( UCodeBlock* cb, Int szs, Int szd, Int tempreg )
370{
371   if (szs == 0 && szd == 0)
372      return;
373   uInstr3(cb, TAG1, 0, TempReg, tempreg,
374                        NoValue, 0,
375                        Lit16,   get_Tag_PCast(szs,szd));
376}
377
378
379/* Create a signed or unsigned widen of the spec'd shadow from one
380   size to another.  The only allowed size transitions are 1->2, 1->4
381   and 2->4. */
382static
383void create_Widen ( UCodeBlock* cb, Bool signed_widen,
384                    Int szs, Int szd, Int tempreg )
385{
386   if (szs == szd) return;
387   uInstr3(cb, TAG1, 0, TempReg, tempreg,
388                        NoValue, 0,
389                        Lit16,   get_Tag_Widen(signed_widen,szs,szd));
390}
391
392
393/* Get the condition codes into a new shadow, at the given size. */
394static
395Int create_GETVF ( UCodeBlock* cb, Int sz )
396{
397   Int tt = newShadow(cb);
398   uInstr1(cb, GETVF, 0, TempReg, tt);
399   create_PCast(cb, 0, sz, tt);
400   return tt;
401}
402
403
404/* Save the condition codes from the spec'd shadow. */
405static
406void create_PUTVF ( UCodeBlock* cb, Int sz, Int tempreg )
407{
408   if (sz == 0) {
409      uInstr1(cb, PUTVF, 0, TempReg, tempreg);
410   } else {
411      Int tt = newShadow(cb);
412      uInstr2(cb, MOV, 4, TempReg, tempreg, TempReg, tt);
413      create_PCast(cb, sz, 0, tt);
414      uInstr1(cb, PUTVF, 0, TempReg, tt);
415   }
416}
417
418
419/* Do Left on the spec'd shadow. */
420static
421void create_Left ( UCodeBlock* cb, Int sz, Int tempreg )
422{
423   uInstr3(cb, TAG1, 0,
424               TempReg, tempreg,
425               NoValue, 0,
426               Lit16, get_Tag_Left(sz));
427}
428
429
430/* Do UifU on ts and td, putting the result in td. */
431static
432void create_UifU ( UCodeBlock* cb, Int sz, Int ts, Int td )
433{
434   uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
435               Lit16, get_Tag_UifU(sz));
436}
437
438
439/* Do DifD on ts and td, putting the result in td. */
440static
441void create_DifD ( UCodeBlock* cb, Int sz, Int ts, Int td )
442{
443   uInstr3(cb, TAG2, 0, TempReg, ts, TempReg, td,
444               Lit16, get_Tag_DifD(sz));
445}
446
447
448/* Do HelpAND on value tval and tag tqqq, putting the result in
449   tqqq. */
450static
451void create_ImproveAND_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
452{
453   uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
454               Lit16, get_Tag_ImproveAND_TQ(sz));
455}
456
457
458/* Do HelpOR on value tval and tag tqqq, putting the result in
459   tqqq. */
460static
461void create_ImproveOR_TQ ( UCodeBlock* cb, Int sz, Int tval, Int tqqq )
462{
463   uInstr3(cb, TAG2, 0, TempReg, tval, TempReg, tqqq,
464               Lit16, get_Tag_ImproveOR_TQ(sz));
465}
466
467
468/* Get the shadow for an operand described by (tag, val).  Emit code
469   to do this and return the identity of the shadow holding the
470   result.  The result tag is always copied into a new shadow, so it
471   can be modified without trashing the original.*/
472static
473Int /* TempReg */ getOperandShadow ( UCodeBlock* cb,
474                                     Int sz, Int tag, Int val )
475{
476   Int sh;
477   sh = newShadow(cb);
478   if (tag == TempReg) {
479      uInstr2(cb, MOV, 4, TempReg, SHADOW(val), TempReg, sh);
480      return sh;
481   }
482   if (tag == Literal) {
483      uInstr1(cb, SETV, sz, TempReg, sh);
484      return sh;
485   }
486   if (tag == ArchReg) {
487      uInstr2(cb, GETV, sz, ArchReg, val, TempReg, sh);
488      return sh;
489   }
490   VG_(skin_panic)("getOperandShadow");
491}
492
493/* Create and return an instrumented version of cb_in.  Free cb_in
494   before returning. */
495static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
496{
497   UCodeBlock* cb;
498   Int         i, j;
499   UInstr*     u_in;
500   Int         qs, qd, qt, qtt;
501   cb = VG_(alloc_UCodeBlock)();
502   cb->nextTemp = cb_in->nextTemp;
503
504   for (i = 0; i < cb_in->used; i++) {
505      qs = qd = qt = qtt = INVALID_TEMPREG;
506      u_in = &cb_in->instrs[i];
507
508      switch (u_in->opcode) {
509
510         case NOP:
511            break;
512
513         case INCEIP:
514            VG_(copy_UInstr)(cb, u_in);
515            break;
516
517         /* The segment registers do not have their definedness
518            tracked.  We therefore make fake shadows on GETSEG and
519            test them on PUTSEG.  This will catch writing garbage to a
520            segment register; therefore we can assume it to be defined
521            when read (GETSEGd).  Since the first arg of USESEG is
522            fetched by GETSEG, we can assume it to be defined, and so
523            the definedness of the result is simply the definedness of
524            the second (virtual_address) arg of USESEG.  The upshot of
525            all this is that instrumentation of USESEG is a no-op! */
526
527         case PUTSEG:
528            sk_assert(u_in->tag1 == TempReg);
529            uInstr1(cb, TESTV, 2, TempReg, SHADOW(u_in->val1));
530            uInstr1(cb, SETV,  2, TempReg, SHADOW(u_in->val1));
531            VG_(copy_UInstr)(cb, u_in);
532            break;
533
534         case GETSEG:
535            sk_assert(u_in->tag2 == TempReg);
536            uInstr1(cb, SETV,  2, TempReg, SHADOW(u_in->val2));
537            VG_(copy_UInstr)(cb, u_in);
538            break;
539
540         case USESEG:
541            VG_(copy_UInstr)(cb, u_in);
542            break;
543
544         /* Loads and stores.  Test the V bits for the address.  24
545            Mar 02: since the address is A-checked anyway, there's not
546            really much point in doing the V-check too, unless you
547            think that you might use addresses which are undefined but
548            still addressible.  Hence the optionalisation of the V
549            check.
550
551            The LOADV/STOREV does an addressibility check for the
552            address. */
553
554         case LOAD:
555            if (SK_(clo_check_addrVs)) {
556               uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
557               uInstr1(cb, SETV,  4, TempReg, SHADOW(u_in->val1));
558            }
559            uInstr2(cb, LOADV, u_in->size,
560                        TempReg, u_in->val1,
561                        TempReg, SHADOW(u_in->val2));
562            VG_(copy_UInstr)(cb, u_in);
563            break;
564
565         case STORE:
566            if (SK_(clo_check_addrVs)) {
567               uInstr1(cb, TESTV,  4, TempReg, SHADOW(u_in->val2));
568               uInstr1(cb, SETV,   4, TempReg, SHADOW(u_in->val2));
569            }
570            uInstr2(cb, STOREV, u_in->size,
571                        TempReg, SHADOW(u_in->val1),
572                        TempReg, u_in->val2);
573            VG_(copy_UInstr)(cb, u_in);
574            break;
575
576         /* Moving stuff around.  Make the V bits follow accordingly,
577            but don't do anything else.  */
578
579         case GET:
580            uInstr2(cb, GETV, u_in->size,
581                        ArchReg, u_in->val1,
582                        TempReg, SHADOW(u_in->val2));
583            VG_(copy_UInstr)(cb, u_in);
584            break;
585
586         case PUT:
587            uInstr2(cb, PUTV, u_in->size,
588                        TempReg, SHADOW(u_in->val1),
589                        ArchReg, u_in->val2);
590            VG_(copy_UInstr)(cb, u_in);
591            break;
592
593         case GETF:
594            /* This is not the smartest way to do it, but should work. */
595            qd = create_GETVF(cb, u_in->size);
596            uInstr2(cb, MOV, 4, TempReg, qd, TempReg, SHADOW(u_in->val1));
597            VG_(copy_UInstr)(cb, u_in);
598            break;
599
600         case PUTF:
601            create_PUTVF(cb, u_in->size, SHADOW(u_in->val1));
602            VG_(copy_UInstr)(cb, u_in);
603            break;
604
605         case MOV:
606            switch (u_in->tag1) {
607               case TempReg:
608                  uInstr2(cb, MOV, 4,
609                              TempReg, SHADOW(u_in->val1),
610                              TempReg, SHADOW(u_in->val2));
611                  break;
612               case Literal:
613                  uInstr1(cb, SETV, u_in->size,
614                              TempReg, SHADOW(u_in->val2));
615                  break;
616               default:
617                  VG_(skin_panic)("memcheck_instrument: MOV");
618            }
619            VG_(copy_UInstr)(cb, u_in);
620            break;
621
622         /* Special case of add, where one of the operands is a literal.
623            lea1(t) = t + some literal.
624            Therefore: lea1#(qa) = left(qa)
625         */
626         case LEA1:
627            sk_assert(u_in->size == 4 && !VG_(any_flag_use)(u_in));
628            qs = SHADOW(u_in->val1);
629            qd = SHADOW(u_in->val2);
630            uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qd);
631            create_Left(cb, u_in->size, qd);
632            VG_(copy_UInstr)(cb, u_in);
633            break;
634
635         /* Another form of add.
636            lea2(ts,tt,shift) = ts + (tt << shift); shift is a literal
637                                and is 0,1,2 or 3.
638            lea2#(qs,qt) = left(qs `UifU` (qt << shift)).
639            Note, subtly, that the shift puts zeroes at the bottom of qt,
640            meaning Valid, since the corresponding shift of tt puts
641            zeroes at the bottom of tb.
642         */
643         case LEA2: {
644            Int shift;
645            sk_assert(u_in->size == 4 && !VG_(any_flag_use)(u_in));
646            switch (u_in->extra4b) {
647               case 1: shift = 0; break;
648               case 2: shift = 1; break;
649               case 4: shift = 2; break;
650               case 8: shift = 3; break;
651               default: VG_(skin_panic)( "memcheck_instrument(LEA2)" );
652            }
653            qs = SHADOW(u_in->val1);
654            qt = SHADOW(u_in->val2);
655            qd = SHADOW(u_in->val3);
656            uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qd);
657            if (shift > 0) {
658               uInstr2(cb, SHL, 4, Literal, 0, TempReg, qd);
659               uLiteral(cb, shift);
660            }
661            create_UifU(cb, 4, qs, qd);
662            create_Left(cb, u_in->size, qd);
663            VG_(copy_UInstr)(cb, u_in);
664            break;
665         }
666
667         /* inc#/dec#(qd) = q `UifU` left(qd) = left(qd) */
668         case INC: case DEC:
669            qd = SHADOW(u_in->val1);
670            create_Left(cb, u_in->size, qd);
671            if (u_in->flags_w != FlagsEmpty)
672               create_PUTVF(cb, u_in->size, qd);
673            VG_(copy_UInstr)(cb, u_in);
674            break;
675
676         /* This is a HACK (approximation :-) */
677         /* rcl#/rcr#(qs,qd)
678               = let q0 = pcast-sz-0(qd) `UifU` pcast-sz-0(qs) `UifU` eflags#
679                 eflags# = q0
680                 qd =pcast-0-sz(q0)
681            Ie, cast everything down to a single bit, then back up.
682            This assumes that any bad bits infect the whole word and
683            the eflags.
684         */
685         case RCL: case RCR:
686	    sk_assert(u_in->flags_r != FlagsEmpty);
687            /* The following assertion looks like it makes sense, but is
688               actually wrong.  Consider this:
689                  rcll    %eax
690                  imull   %eax, %eax
691               The rcll writes O and C but so does the imull, so the O and C
692               write of the rcll is annulled by the prior improvement pass.
693               Noticed by Kevin Ryde <user42@zip.com.au>
694            */
695	    /* sk_assert(u_in->flags_w != FlagsEmpty); */
696            qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
697            /* We can safely modify qs; cast it to 0-size. */
698            create_PCast(cb, u_in->size, 0, qs);
699            qd = SHADOW(u_in->val2);
700            create_PCast(cb, u_in->size, 0, qd);
701            /* qs is cast-to-0(shift count#), and qd is cast-to-0(value#). */
702            create_UifU(cb, 0, qs, qd);
703            /* qs is now free; reuse it for the flag definedness. */
704            qs = create_GETVF(cb, 0);
705            create_UifU(cb, 0, qs, qd);
706            create_PUTVF(cb, 0, qd);
707            create_PCast(cb, 0, u_in->size, qd);
708            VG_(copy_UInstr)(cb, u_in);
709            break;
710
711         /* for OP in shl shr sar rol ror
712            (qs is shift count#, qd is value to be OP#d)
713            OP(ts,td)
714            OP#(qs,qd)
715               = pcast-1-sz(qs) `UifU` OP(ts,qd)
716            So we apply OP to the tag bits too, and then UifU with
717            the shift count# to take account of the possibility of it
718            being undefined.
719
720            A bit subtle:
721               ROL/ROR rearrange the tag bits as per the value bits.
722               SHL/SHR shifts zeroes into the value, and corresponding
723                  zeroes indicating Definedness into the tag.
724               SAR copies the top bit of the value downwards, and therefore
725                  SAR also copies the definedness of the top bit too.
726            So in all five cases, we just apply the same op to the tag
727            bits as is applied to the value bits.  Neat!
728         */
729         case SHL:
730         case SHR: case SAR:
731         case ROL: case ROR: {
732            Int t_amount = INVALID_TEMPREG;
733            sk_assert(u_in->tag1 == TempReg || u_in->tag1 == Literal);
734            sk_assert(u_in->tag2 == TempReg);
735            qd = SHADOW(u_in->val2);
736
737            /* Make qs hold shift-count# and make
738               t_amount be a TempReg holding the shift count. */
739            if (u_in->tag1 == Literal) {
740               t_amount = newTemp(cb);
741               uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_amount);
742               uLiteral(cb, u_in->lit32);
743               qs = SHADOW(t_amount);
744               uInstr1(cb, SETV, 1, TempReg, qs);
745            } else {
746               t_amount = u_in->val1;
747               qs = SHADOW(u_in->val1);
748            }
749
750            uInstr2(cb, u_in->opcode,
751                        u_in->size,
752                        TempReg, t_amount,
753                        TempReg, qd);
754            qt = newShadow(cb);
755            uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
756            create_PCast(cb, 1, u_in->size, qt);
757            create_UifU(cb, u_in->size, qt, qd);
758            VG_(copy_UInstr)(cb, u_in);
759            break;
760         }
761
762         /* One simple tag operation. */
763         case WIDEN:
764            sk_assert(u_in->tag1 == TempReg);
765            create_Widen(cb, u_in->signed_widen, u_in->extra4b, u_in->size,
766                             SHADOW(u_in->val1));
767            VG_(copy_UInstr)(cb, u_in);
768            break;
769
770         /* not#(x) = x (since bitwise independent) */
771         case NOT:
772            sk_assert(u_in->tag1 == TempReg);
773            VG_(copy_UInstr)(cb, u_in);
774            break;
775
776         /* neg#(x) = left(x) (derivable from case for SUB) */
777         case NEG:
778            sk_assert(u_in->tag1 == TempReg);
779            create_Left(cb, u_in->size, SHADOW(u_in->val1));
780            VG_(copy_UInstr)(cb, u_in);
781            break;
782
783         /* bswap#(x) = bswap(x) */
784         case BSWAP:
785            sk_assert(u_in->tag1 == TempReg);
786            sk_assert(u_in->size == 4);
787            qd = SHADOW(u_in->val1);
788            uInstr1(cb, BSWAP, 4, TempReg, qd);
789            VG_(copy_UInstr)(cb, u_in);
790            break;
791
792         /* cc2val#(qd) = pcast-0-to-size(eflags#) */
793         case CC2VAL:
794            sk_assert(u_in->tag1 == TempReg);
795            sk_assert(u_in->flags_r != FlagsEmpty);
796            qt = create_GETVF(cb, u_in->size);
797            uInstr2(cb, MOV, 4, TempReg, qt, TempReg, SHADOW(u_in->val1));
798            VG_(copy_UInstr)(cb, u_in);
799            break;
800
801         /* cmov#(qs,qd) = cmov(qs,qd)
802            That is, do the cmov of tags using the same flags as for
803            the data (obviously).  However, first do a test on the
804            validity of the flags.
805         */
806         case CMOV:
807            sk_assert(u_in->size == 4);
808            sk_assert(u_in->tag1 == TempReg);
809            sk_assert(u_in->tag2 == TempReg);
810            sk_assert(u_in->flags_r != FlagsEmpty);
811            sk_assert(u_in->flags_w == FlagsEmpty);
812            qs = SHADOW(u_in->val1);
813            qd = SHADOW(u_in->val2);
814            qt = create_GETVF(cb, 0);
815            uInstr1(cb, TESTV, 0, TempReg, qt);
816            /* qt should never be referred to again.  Nevertheless
817               ... */
818            uInstr1(cb, SETV, 0, TempReg, qt);
819
820            uInstr2(cb, CMOV, 4, TempReg, qs, TempReg, qd);
821            LAST_UINSTR(cb).cond    = u_in->cond;
822            LAST_UINSTR(cb).flags_r = u_in->flags_r;
823
824            VG_(copy_UInstr)(cb, u_in);
825            break;
826
827         /* add#/sub#(qs,qd)
828               = qs `UifU` qd `UifU` left(qs) `UifU` left(qd)
829               = left(qs) `UifU` left(qd)
830               = left(qs `UifU` qd)
831            adc#/sbb#(qs,qd)
832               = left(qs `UifU` qd) `UifU` pcast(eflags#)
833            Second arg (dest) is TempReg.
834            First arg (src) is Literal or TempReg or ArchReg.
835         */
836         case ADD: case SUB:
837         case ADC: case SBB:
838            qd = SHADOW(u_in->val2);
839            qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
840            create_UifU(cb, u_in->size, qs, qd);
841            create_Left(cb, u_in->size, qd);
842            if (u_in->opcode == ADC || u_in->opcode == SBB) {
843               sk_assert(u_in->flags_r != FlagsEmpty);
844               qt = create_GETVF(cb, u_in->size);
845               create_UifU(cb, u_in->size, qt, qd);
846            }
847            if (u_in->flags_w != FlagsEmpty) {
848               create_PUTVF(cb, u_in->size, qd);
849            }
850            VG_(copy_UInstr)(cb, u_in);
851            break;
852
853         /* xor#(qs,qd) = qs `UifU` qd */
854         case XOR:
855            qd = SHADOW(u_in->val2);
856            qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
857            create_UifU(cb, u_in->size, qs, qd);
858            if (u_in->flags_w != FlagsEmpty) {
859               create_PUTVF(cb, u_in->size, qd);
860            }
861            VG_(copy_UInstr)(cb, u_in);
862            break;
863
864         /* and#/or#(qs,qd)
865               = (qs `UifU` qd) `DifD` improve(vs,qs)
866                                `DifD` improve(vd,qd)
867            where improve is the relevant one of
868                Improve{AND,OR}_TQ
869            Use the following steps, with qt as a temp:
870               qt = improve(vd,qd)
871               qd = qs `UifU` qd
872               qd = qt `DifD` qd
873               qt = improve(vs,qs)
874               qd = qt `DifD` qd
875         */
876         case AND: case OR:
877            sk_assert(u_in->tag1 == TempReg);
878            sk_assert(u_in->tag2 == TempReg);
879            qd = SHADOW(u_in->val2);
880            qs = SHADOW(u_in->val1);
881            qt = newShadow(cb);
882
883            /* qt = improve(vd,qd) */
884            uInstr2(cb, MOV, 4, TempReg, qd, TempReg, qt);
885            if (u_in->opcode == AND)
886               create_ImproveAND_TQ(cb, u_in->size, u_in->val2, qt);
887            else
888               create_ImproveOR_TQ(cb, u_in->size, u_in->val2, qt);
889            /* qd = qs `UifU` qd */
890            create_UifU(cb, u_in->size, qs, qd);
891            /* qd = qt `DifD` qd */
892            create_DifD(cb, u_in->size, qt, qd);
893            /* qt = improve(vs,qs) */
894            uInstr2(cb, MOV, 4, TempReg, qs, TempReg, qt);
895            if (u_in->opcode == AND)
896               create_ImproveAND_TQ(cb, u_in->size, u_in->val1, qt);
897            else
898               create_ImproveOR_TQ(cb, u_in->size, u_in->val1, qt);
899            /* qd = qt `DifD` qd */
900               create_DifD(cb, u_in->size, qt, qd);
901            /* So, finally qd is the result tag. */
902            if (u_in->flags_w != FlagsEmpty) {
903               create_PUTVF(cb, u_in->size, qd);
904            }
905            VG_(copy_UInstr)(cb, u_in);
906            break;
907
908         /* Machinery to do with supporting CALLM.  Copy the start and
909            end markers only to make the result easier to read
910            (debug); they generate no code and have no effect.
911         */
912         case CALLM_S: case CALLM_E:
913            VG_(copy_UInstr)(cb, u_in);
914            break;
915
916         /* Copy PUSH and POP verbatim.  Arg/result absval
917            calculations are done when the associated CALL is
918            processed.  CLEAR has no effect on absval calculations but
919            needs to be copied.
920         */
921         case PUSH: case POP: case CLEAR:
922            VG_(copy_UInstr)(cb, u_in);
923            break;
924
925         /* In short:
926               callm#(a1# ... an#) = (a1# `UifU` ... `UifU` an#)
927            We have to decide on a size to do the computation at,
928            although the choice doesn't affect correctness.  We will
929            do a pcast to the final size anyway, so the only important
930            factor is to choose a size which minimises the total
931            number of casts needed.  Valgrind: just use size 0,
932            regardless.  It may not be very good for performance
933            but does simplify matters, mainly by reducing the number
934            of different pessimising casts which have to be implemented.
935         */
936         case CALLM: {
937            UInstr* uu;
938            Bool res_used;
939
940            /* Now generate the code.  Get the final result absval
941               into qt. */
942            qt  = newShadow(cb);
943            qtt = newShadow(cb);
944            uInstr1(cb, SETV, 0, TempReg, qt);
945            for (j = i-1; cb_in->instrs[j].opcode != CALLM_S; j--) {
946               uu = & cb_in->instrs[j];
947               if (uu->opcode != PUSH) continue;
948               /* cast via a temporary */
949               uInstr2(cb, MOV, 4, TempReg, SHADOW(uu->val1),
950                                   TempReg, qtt);
951               create_PCast(cb, uu->size, 0, qtt);
952               create_UifU(cb, 0, qtt, qt);
953            }
954            /* Remembering also that flags read count as inputs. */
955            if (u_in->flags_r != FlagsEmpty) {
956               qtt = create_GETVF(cb, 0);
957               create_UifU(cb, 0, qtt, qt);
958            }
959
960            /* qt now holds the result tag.  If any results from the
961               call are used, either by fetching with POP or
962               implicitly by writing the flags, we copy the result
963               absval to the relevant location.  If not used, the call
964               must have been for its side effects, so we test qt here
965               and now.  Note that this assumes that all values
966               removed by POP continue to be live.  So dead args
967               *must* be removed with CLEAR, not by POPping them into
968               a dummy tempreg.
969            */
970            res_used = False;
971            for (j = i+1; cb_in->instrs[j].opcode != CALLM_E; j++) {
972               uu = & cb_in->instrs[j];
973               if (uu->opcode != POP) continue;
974               /* Cast via a temp. */
975               uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qtt);
976               create_PCast(cb, 0, uu->size, qtt);
977               uInstr2(cb, MOV, 4, TempReg, qtt,
978                                   TempReg, SHADOW(uu->val1));
979               res_used = True;
980            }
981            if (u_in->flags_w != FlagsEmpty) {
982               create_PUTVF(cb, 0, qt);
983               res_used = True;
984            }
985            if (!res_used) {
986               uInstr1(cb, TESTV, 0, TempReg, qt);
987               /* qt should never be referred to again.  Nevertheless
988                  ... */
989               uInstr1(cb, SETV, 0, TempReg, qt);
990            }
991            VG_(copy_UInstr)(cb, u_in);
992            break;
993         }
994         /* Whew ... */
995
996         case JMP:
997            if (u_in->tag1 == TempReg) {
998               uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
999               uInstr1(cb, SETV,  4, TempReg, SHADOW(u_in->val1));
1000            } else {
1001               sk_assert(u_in->tag1 == Literal);
1002            }
1003            if (u_in->cond != CondAlways) {
1004               sk_assert(u_in->flags_r != FlagsEmpty);
1005               qt = create_GETVF(cb, 0);
1006               uInstr1(cb, TESTV, 0, TempReg, qt);
1007               /* qt should never be referred to again.  Nevertheless
1008                  ... */
1009               uInstr1(cb, SETV, 0, TempReg, qt);
1010            }
1011            VG_(copy_UInstr)(cb, u_in);
1012            break;
1013
1014         case JIFZ:
1015            uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val1));
1016            uInstr1(cb, SETV,  4, TempReg, SHADOW(u_in->val1));
1017            VG_(copy_UInstr)(cb, u_in);
1018            break;
1019
1020         /* Emit a check on the address used.  The value loaded into the
1021            FPU is checked by the call to fpu_{read/write}_check().  */
1022         case FPU_R: case FPU_W: {
1023            Int t_size = INVALID_TEMPREG;
1024
1025            sk_assert(u_in->tag2 == TempReg);
1026            uInstr1(cb, TESTV, 4, TempReg, SHADOW(u_in->val2));
1027            uInstr1(cb, SETV,  4, TempReg, SHADOW(u_in->val2));
1028
1029            t_size = newTemp(cb);
1030            uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_size);
1031            uLiteral(cb, u_in->size);
1032            uInstr2(cb, CCALL, 0, TempReg, u_in->val2, TempReg, t_size);
1033            uCCall(cb,
1034                   u_in->opcode==FPU_R ? (Addr) & SK_(fpu_read_check)
1035                                       : (Addr) & SK_(fpu_write_check),
1036                   2, 2, False);
1037
1038            VG_(copy_UInstr)(cb, u_in);
1039            break;
1040         }
1041
1042         /* For FPU insns not referencing memory, just copy thru. */
1043         case FPU:
1044            VG_(copy_UInstr)(cb, u_in);
1045            break;
1046
1047         default:
1048            VG_(pp_UInstr)(0, u_in);
1049            VG_(skin_panic)( "memcheck_instrument: unhandled case");
1050
1051      } /* end of switch (u_in->opcode) */
1052
1053   } /* end of for loop */
1054
1055   VG_(free_UCodeBlock)(cb_in);
1056   return cb;
1057}
1058
1059/*------------------------------------------------------------*/
1060/*--- Clean up mem check instrumentation.                  ---*/
1061/*------------------------------------------------------------*/
1062
1063Bool VG_(clo_memcheck_codegen) = False;
1064
1065#define dis    VG_(print_codegen)
1066
1067
1068#define VGC_IS_SHADOW(tempreg) ((tempreg % 2) == 1)
1069#define VGC_UNDEF ((UChar)100)
1070#define VGC_VALUE ((UChar)101)
1071
1072#define NOP_no_msg(uu)                                            \
1073   do { VG_(new_NOP)(uu); } while (False)
1074
1075#define NOP_tag1_op(uu)                                           \
1076   do { VG_(new_NOP)(uu);                                         \
1077        if (dis)                                                  \
1078           VG_(printf)("   at %2d: delete %s due to defd arg\n",  \
1079                       i, nameOfTagOp(u->val3));                  \
1080   } while (False)
1081
1082#define SETV_tag1_op(uu,newsz)                                    \
1083   do { uu->opcode = SETV;                                        \
1084        uu->size = newsz;                                         \
1085        uu->tag2 = uu->tag3 = NoValue;                            \
1086        if (dis)                                                  \
1087           VG_(printf)("   at %2d: convert %s to SETV%d "         \
1088                       "due to defd arg\n",                       \
1089                       i, nameOfTagOp(u->val3), newsz);           \
1090   } while (False)
1091
1092
1093
1094/* Run backwards and delete SETVs on shadow temps for which the next
1095   action is a write.  Needs an env saying whether or not the next
1096   action is a write.  The supplied UCodeBlock is destructively
1097   modified.
1098*/
1099static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
1100{
1101   Int     i, j, k;
1102   Int     n_temps = cb->nextTemp;
1103   Bool*   next_is_write;
1104   UInstr* u;
1105   RegUse  tempUse[3];
1106
1107   if (n_temps == 0) return;
1108
1109   next_is_write = VG_(malloc)(n_temps * sizeof(Bool));
1110
1111   for (i = 0; i < n_temps; i++) next_is_write[i] = True;
1112
1113   for (i = cb->used-1; i >= 0; i--) {
1114      u = &cb->instrs[i];
1115
1116      /* If we're not checking address V bits, there will be a lot of
1117         GETVs, TAG1s and TAG2s calculating values which are never
1118         used.  These first three cases get rid of them. */
1119
1120      if (u->opcode == GETV && VGC_IS_SHADOW(u->val2)
1121                            && next_is_write[u->val2]
1122                            && !SK_(clo_check_addrVs)) {
1123         VG_(new_NOP)(u);
1124         if (dis)
1125            VG_(printf)("   at %2d: delete GETV\n", i);
1126      } else
1127
1128      if (u->opcode == TAG1 && VGC_IS_SHADOW(u->val1)
1129                            && next_is_write[u->val1]
1130                            && !SK_(clo_check_addrVs)) {
1131         VG_(new_NOP)(u);
1132         if (dis)
1133            VG_(printf)("   at %2d: delete TAG1\n", i);
1134      } else
1135
1136      if (u->opcode == TAG2 && VGC_IS_SHADOW(u->val2)
1137                            && next_is_write[u->val2]
1138                            && !SK_(clo_check_addrVs)) {
1139         VG_(new_NOP)(u);
1140         if (dis)
1141            VG_(printf)("   at %2d: delete TAG2\n", i);
1142      } else
1143
1144      /* We do the rest of these regardless of whether or not
1145         addresses are V-checked. */
1146
1147      if (u->opcode == MOV && VGC_IS_SHADOW(u->val2)
1148                           && next_is_write[u->val2]) {
1149         /* This MOV is pointless because the target is dead at this
1150            point.  Delete it. */
1151         VG_(new_NOP)(u);
1152         if (dis)
1153            VG_(printf)("   at %2d: delete MOV\n", i);
1154      } else
1155
1156      if (u->opcode == SETV) {
1157         if (u->tag1 == TempReg) {
1158            sk_assert(VGC_IS_SHADOW(u->val1));
1159            if (next_is_write[u->val1]) {
1160               /* This write is pointless, so annul it. */
1161               VG_(new_NOP)(u);
1162               if (dis)
1163                  VG_(printf)("   at %2d: delete SETV\n", i);
1164            } else {
1165               /* This write has a purpose; don't annul it, but do
1166                  notice that we did it. */
1167               next_is_write[u->val1] = True;
1168            }
1169
1170         }
1171
1172      } else {
1173         /* Find out what this insn does to the temps. */
1174         k = VG_(get_reg_usage)(u, TempReg, &tempUse[0]);
1175         sk_assert(k <= 3);
1176         for (j = k-1; j >= 0; j--) {
1177            next_is_write[ tempUse[j].num ]
1178                         = tempUse[j].isWrite;
1179         }
1180      }
1181   }
1182}
1183
1184
1185/* Run forwards, propagating and using the is-completely-defined
1186   property.  This removes a lot of redundant tag-munging code.
1187   Unfortunately it requires intimate knowledge of how each uinstr and
1188   tagop modifies its arguments.  This duplicates knowledge of uinstr
1189   tempreg uses embodied in VG_(get_reg_usage)(), which is unfortunate.
1190   The supplied UCodeBlock* is modified in-place.
1191
1192   For each value temp, def[] should hold VGC_VALUE.
1193
1194   For each shadow temp, def[] may hold 4,2,1 or 0 iff that shadow is
1195   definitely known to be fully defined at that size.  In all other
1196   circumstances a shadow's def[] entry is VGC_UNDEF, meaning possibly
1197   undefined.  In cases of doubt, VGC_UNDEF is always safe.
1198*/
1199static void vg_propagate_definedness ( UCodeBlock* cb )
1200{
1201   Int     i, j, k, t;
1202   Int     n_temps = cb->nextTemp;
1203   UChar*  def;
1204   UInstr* u;
1205   RegUse  tempUse[3];
1206
1207   if (n_temps == 0) return;
1208
1209   def = VG_(malloc)(n_temps * sizeof(UChar));
1210
1211   for (i = 0; i < n_temps; i++)
1212      def[i] = VGC_IS_SHADOW(i) ? VGC_UNDEF : VGC_VALUE;
1213
1214   /* Run forwards, detecting and using the all-defined property. */
1215
1216   for (i = 0; i < cb->used; i++) {
1217      u = &cb->instrs[i];
1218      switch (u->opcode) {
1219
1220      /* Tag-handling uinstrs. */
1221
1222         /* Deal with these quickly. */
1223         case NOP:
1224         case INCEIP:
1225            break;
1226
1227         /* Make a tag defined. */
1228         case SETV:
1229            sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1230            def[u->val1] = u->size;
1231            break;
1232
1233         /* Check definedness of a tag. */
1234         case TESTV:
1235            sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1236            if (def[u->val1] <= 4) {
1237               sk_assert(def[u->val1] == u->size);
1238               NOP_no_msg(u);
1239               if (dis)
1240                  VG_(printf)("   at %2d: delete TESTV on defd arg\n", i);
1241            }
1242            break;
1243
1244         /* Applies to both values and tags.  Propagate Definedness
1245            property through copies.  Note that this isn't optional;
1246            we *have* to do this to keep def[] correct. */
1247         case MOV:
1248            sk_assert(u->tag2 == TempReg);
1249            if (u->tag1 == TempReg) {
1250               if (VGC_IS_SHADOW(u->val1)) {
1251                  sk_assert(VGC_IS_SHADOW(u->val2));
1252                  def[u->val2] = def[u->val1];
1253               }
1254            }
1255            break;
1256
1257         case PUTV:
1258            sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1259            if (def[u->val1] <= 4) {
1260               sk_assert(def[u->val1] == u->size);
1261               u->tag1 = Literal;
1262               u->val1 = 0;
1263               switch (u->size) {
1264                  case 4: u->lit32 = 0x00000000; break;
1265                  case 2: u->lit32 = 0xFFFF0000; break;
1266                  case 1: u->lit32 = 0xFFFFFF00; break;
1267                  default: VG_(skin_panic)("vg_cleanup(PUTV)");
1268               }
1269               if (dis)
1270                  VG_(printf)(
1271                     "   at %2d: propagate definedness into PUTV\n", i);
1272            }
1273            break;
1274
1275         case STOREV:
1276            sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1277            if (def[u->val1] <= 4) {
1278               sk_assert(def[u->val1] == u->size);
1279               u->tag1 = Literal;
1280               u->val1 = 0;
1281               switch (u->size) {
1282                  case 4: u->lit32 = 0x00000000; break;
1283                  case 2: u->lit32 = 0xFFFF0000; break;
1284                  case 1: u->lit32 = 0xFFFFFF00; break;
1285                  default: VG_(skin_panic)("vg_cleanup(STOREV)");
1286               }
1287               if (dis)
1288                  VG_(printf)(
1289                     "   at %2d: propagate definedness into STandV\n", i);
1290            }
1291            break;
1292
1293         /* Nothing interesting we can do with this, I think. */
1294         case PUTVF:
1295            break;
1296
1297         /* Tag handling operations. */
1298         case TAG2:
1299            sk_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
1300            sk_assert(u->tag3 == Lit16);
1301            /* Ultra-paranoid "type" checking. */
1302            switch (u->val3) {
1303               case Tag_ImproveAND4_TQ: case Tag_ImproveAND2_TQ:
1304               case Tag_ImproveAND1_TQ: case Tag_ImproveOR4_TQ:
1305               case Tag_ImproveOR2_TQ: case Tag_ImproveOR1_TQ:
1306                  sk_assert(u->tag1 == TempReg && !VGC_IS_SHADOW(u->val1));
1307                  break;
1308               default:
1309                  sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1310                  break;
1311            }
1312            switch (u->val3) {
1313               Int sz;
1314               case Tag_UifU4:
1315                  sz = 4; goto do_UifU;
1316               case Tag_UifU2:
1317                  sz = 2; goto do_UifU;
1318               case Tag_UifU1:
1319                  sz = 1; goto do_UifU;
1320               case Tag_UifU0:
1321                  sz = 0; goto do_UifU;
1322               do_UifU:
1323                  sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1324                  sk_assert(u->tag2 == TempReg && VGC_IS_SHADOW(u->val2));
1325                  if (def[u->val1] <= 4) {
1326                     /* UifU.  The first arg is defined, so result is
1327                        simply second arg.  Delete this operation. */
1328                     sk_assert(def[u->val1] == sz);
1329                     NOP_no_msg(u);
1330                     if (dis)
1331                        VG_(printf)(
1332                           "   at %2d: delete UifU%d due to defd arg1\n",
1333                           i, sz);
1334                  }
1335                  else
1336                  if (def[u->val2] <= 4) {
1337                     /* UifU.  The second arg is defined, so result is
1338                        simply first arg.  Copy to second. */
1339                     sk_assert(def[u->val2] == sz);
1340                     u->opcode = MOV;
1341                     u->size = 4;
1342                     u->tag3 = NoValue;
1343                     def[u->val2] = def[u->val1];
1344                     if (dis)
1345                        VG_(printf)(
1346                           "   at %2d: change UifU%d to MOV due to defd"
1347                           " arg2\n",
1348                           i, sz);
1349                  }
1350                  break;
1351               case Tag_ImproveAND4_TQ:
1352                  sz = 4; goto do_ImproveAND;
1353               case Tag_ImproveAND1_TQ:
1354                  sz = 1; goto do_ImproveAND;
1355               do_ImproveAND:
1356                  /* Implements Q = T OR Q.  So if Q is entirely defined,
1357                     ie all 0s, we get MOV T, Q. */
1358		  if (def[u->val2] <= 4) {
1359                     sk_assert(def[u->val2] == sz);
1360                     u->size = 4; /* Regardless of sz */
1361                     u->opcode = MOV;
1362                     u->tag3 = NoValue;
1363                     def[u->val2] = VGC_UNDEF;
1364                     if (dis)
1365                        VG_(printf)(
1366                            "   at %2d: change ImproveAND%d_TQ to MOV due "
1367                            "to defd arg2\n",
1368                            i, sz);
1369                  }
1370                  break;
1371               default:
1372                  goto unhandled;
1373            }
1374            break;
1375
1376         case TAG1:
1377            sk_assert(u->tag1 == TempReg && VGC_IS_SHADOW(u->val1));
1378            if (def[u->val1] > 4) break;
1379            /* We now know that the arg to the op is entirely defined.
1380               If the op changes the size of the arg, we must replace
1381               it with a SETV at the new size.  If it doesn't change
1382               the size, we can delete it completely. */
1383            switch (u->val3) {
1384               /* Maintain the same size ... */
1385               case Tag_Left4:
1386                  sk_assert(def[u->val1] == 4);
1387                  NOP_tag1_op(u);
1388                  break;
1389               case Tag_PCast11:
1390                  sk_assert(def[u->val1] == 1);
1391                  NOP_tag1_op(u);
1392                  break;
1393               /* Change size ... */
1394               case Tag_PCast40:
1395                  sk_assert(def[u->val1] == 4);
1396                  SETV_tag1_op(u,0);
1397                  def[u->val1] = 0;
1398                  break;
1399               case Tag_PCast14:
1400                  sk_assert(def[u->val1] == 1);
1401                  SETV_tag1_op(u,4);
1402                  def[u->val1] = 4;
1403                  break;
1404               case Tag_PCast12:
1405                  sk_assert(def[u->val1] == 1);
1406                  SETV_tag1_op(u,2);
1407                  def[u->val1] = 2;
1408                  break;
1409               case Tag_PCast10:
1410                  sk_assert(def[u->val1] == 1);
1411                  SETV_tag1_op(u,0);
1412                  def[u->val1] = 0;
1413                  break;
1414               case Tag_PCast02:
1415                  sk_assert(def[u->val1] == 0);
1416                  SETV_tag1_op(u,2);
1417                  def[u->val1] = 2;
1418                  break;
1419               default:
1420                  goto unhandled;
1421            }
1422            if (dis)
1423               VG_(printf)(
1424                  "   at %2d: delete TAG1 %s due to defd arg\n",
1425                  i, nameOfTagOp(u->val3));
1426            break;
1427
1428         default:
1429         unhandled:
1430            /* We don't know how to handle this uinstr.  Be safe, and
1431               set to VGC_VALUE or VGC_UNDEF all temps written by it. */
1432            k = VG_(get_reg_usage)(u, TempReg, &tempUse[0]);
1433            sk_assert(k <= 3);
1434            for (j = 0; j < k; j++) {
1435               t = tempUse[j].num;
1436               sk_assert(t >= 0 && t < n_temps);
1437               if (!tempUse[j].isWrite) {
1438                  /* t is read; ignore it. */
1439                  if (0&& VGC_IS_SHADOW(t) && def[t] <= 4)
1440                     VG_(printf)("ignoring def %d at %s %s\n",
1441                                 def[t],
1442                                 VG_(name_UOpcode)(True, u->opcode),
1443                                 (u->opcode == TAG1 || u->opcode == TAG2)
1444                                    ? nameOfTagOp(u->val3)
1445                                    : (Char*)"");
1446               } else {
1447                  /* t is written; better nullify it. */
1448                  def[t] = VGC_IS_SHADOW(t) ? VGC_UNDEF : VGC_VALUE;
1449               }
1450            }
1451      }
1452   }
1453}
1454
1455
1456/* Top level post-MemCheck-instrumentation cleanup function. */
1457static void vg_cleanup ( UCodeBlock* cb )
1458{
1459   vg_propagate_definedness ( cb );
1460   vg_delete_redundant_SETVs ( cb );
1461}
1462
1463
1464/* Caller will print out final instrumented code if necessary;  we
1465   print out intermediate instrumented code here if necessary. */
1466UCodeBlock* SK_(instrument) ( UCodeBlock* cb, Addr not_used )
1467{
1468   cb = memcheck_instrument ( cb );
1469   if (SK_(clo_cleanup)) {
1470      if (dis) {
1471         VG_(pp_UCodeBlock) ( cb, "Unimproved instrumented UCode:" );
1472         VG_(printf)("Instrumentation improvements:\n");
1473      }
1474      vg_cleanup(cb);
1475      if (dis) VG_(printf)("\n");
1476   }
1477   return cb;
1478}
1479
1480#undef dis
1481
1482/*--------------------------------------------------------------------*/
1483/*--- end                                           mc_translate.c ---*/
1484/*--------------------------------------------------------------------*/
1485