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