h_main.c revision 8b140dee891a850c09d27f316df913acc7d7bae7
1024598e40c84666cc311a42c256bbf880db3ac99sewardj
2024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Ptrcheck: a pointer-use checker.                             ---*/
4024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- This file checks heap accesses.                              ---*/
5024598e40c84666cc311a42c256bbf880db3ac99sewardj/*---                                                     h_main.c ---*/
6024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
7024598e40c84666cc311a42c256bbf880db3ac99sewardj
8024598e40c84666cc311a42c256bbf880db3ac99sewardj/*
9024598e40c84666cc311a42c256bbf880db3ac99sewardj   This file is part of Ptrcheck, a Valgrind tool for checking pointer
10024598e40c84666cc311a42c256bbf880db3ac99sewardj   use in programs.
11024598e40c84666cc311a42c256bbf880db3ac99sewardj
12024598e40c84666cc311a42c256bbf880db3ac99sewardj   Initial version (Annelid):
13024598e40c84666cc311a42c256bbf880db3ac99sewardj
14024598e40c84666cc311a42c256bbf880db3ac99sewardj   Copyright (C) 2003-2008 Nicholas Nethercote
15024598e40c84666cc311a42c256bbf880db3ac99sewardj      njn@valgrind.org
16024598e40c84666cc311a42c256bbf880db3ac99sewardj
17024598e40c84666cc311a42c256bbf880db3ac99sewardj   Valgrind-3.X port:
18024598e40c84666cc311a42c256bbf880db3ac99sewardj
19024598e40c84666cc311a42c256bbf880db3ac99sewardj   Copyright (C) 2008-2008 OpenWorks Ltd
20024598e40c84666cc311a42c256bbf880db3ac99sewardj      info@open-works.co.uk
21024598e40c84666cc311a42c256bbf880db3ac99sewardj
22024598e40c84666cc311a42c256bbf880db3ac99sewardj   This program is free software; you can redistribute it and/or
23024598e40c84666cc311a42c256bbf880db3ac99sewardj   modify it under the terms of the GNU General Public License as
24024598e40c84666cc311a42c256bbf880db3ac99sewardj   published by the Free Software Foundation; either version 2 of the
25024598e40c84666cc311a42c256bbf880db3ac99sewardj   License, or (at your option) any later version.
26024598e40c84666cc311a42c256bbf880db3ac99sewardj
27024598e40c84666cc311a42c256bbf880db3ac99sewardj   This program is distributed in the hope that it will be useful, but
28024598e40c84666cc311a42c256bbf880db3ac99sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
29024598e40c84666cc311a42c256bbf880db3ac99sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30024598e40c84666cc311a42c256bbf880db3ac99sewardj   General Public License for more details.
31024598e40c84666cc311a42c256bbf880db3ac99sewardj
32024598e40c84666cc311a42c256bbf880db3ac99sewardj   You should have received a copy of the GNU General Public License
33024598e40c84666cc311a42c256bbf880db3ac99sewardj   along with this program; if not, write to the Free Software
34024598e40c84666cc311a42c256bbf880db3ac99sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
35024598e40c84666cc311a42c256bbf880db3ac99sewardj   02111-1307, USA.
36024598e40c84666cc311a42c256bbf880db3ac99sewardj
37024598e40c84666cc311a42c256bbf880db3ac99sewardj   The GNU General Public License is contained in the file COPYING.
38024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
39024598e40c84666cc311a42c256bbf880db3ac99sewardj
40024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: 64-bit cleanness, check the following
41024598e40c84666cc311a42c256bbf880db3ac99sewardj// struct _ISNode.ownerCount is 32-bit
42024598e40c84666cc311a42c256bbf880db3ac99sewardj// struct _ISNode.topLevel is 32-bit
43024598e40c84666cc311a42c256bbf880db3ac99sewardj// or is that not really right now?  add assertion checks about
44024598e40c84666cc311a42c256bbf880db3ac99sewardj// the max size of a node
45024598e40c84666cc311a42c256bbf880db3ac99sewardj
46024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: should we shadow %RIP?  Maybe not.
47024598e40c84666cc311a42c256bbf880db3ac99sewardj
48024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: shadows of temporaries created in preamble, a la memcheck?
49024598e40c84666cc311a42c256bbf880db3ac99sewardj
50024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: result of add_new_segment is always ignored
51024598e40c84666cc311a42c256bbf880db3ac99sewardj
52024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: the mechanism involving last_seg_added is really ugly.
53024598e40c84666cc311a42c256bbf880db3ac99sewardj// Do something cleaner.
54024598e40c84666cc311a42c256bbf880db3ac99sewardj
55024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: post_reg_write_clientcall: check function pointer comparisons
56024598e40c84666cc311a42c256bbf880db3ac99sewardj// are safe on toc-afflicted platforms
57024598e40c84666cc311a42c256bbf880db3ac99sewardj
58024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: tidy up findShadowTmp
59024598e40c84666cc311a42c256bbf880db3ac99sewardj
60024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: post_reg_write_demux(Vg_CoreSysCall) is redundant w.r.t.
61024598e40c84666cc311a42c256bbf880db3ac99sewardj// the default 'NONPTR' behaviour of post_syscall.  post_reg_write_demux
62024598e40c84666cc311a42c256bbf880db3ac99sewardj// is called first, then post_syscall.
63024598e40c84666cc311a42c256bbf880db3ac99sewardj
64024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: check nothing is mapped in the lowest 1M of memory at
65024598e40c84666cc311a42c256bbf880db3ac99sewardj// startup, or quit (to do with nonptr_or_unknown, also sync 1M
66024598e40c84666cc311a42c256bbf880db3ac99sewardj// magic value with PIE default load address in m_ume.c.
67024598e40c84666cc311a42c256bbf880db3ac99sewardj
68024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: consider whether we could paint memory acquired from
69024598e40c84666cc311a42c256bbf880db3ac99sewardj// sys_read etc as NONPTR rather than UNKNOWN.
70024598e40c84666cc311a42c256bbf880db3ac99sewardj
71024598e40c84666cc311a42c256bbf880db3ac99sewardj// XXX: recycle freed segments
72024598e40c84666cc311a42c256bbf880db3ac99sewardj
73024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
74024598e40c84666cc311a42c256bbf880db3ac99sewardj// Metadata:
75024598e40c84666cc311a42c256bbf880db3ac99sewardj//   HeapBlock.id :: Seg (stored as heap shadowchunk; always non-zero)
76024598e40c84666cc311a42c256bbf880db3ac99sewardj//   MemLoc.aseg  :: Seg (implicitly stored)
77024598e40c84666cc311a42c256bbf880db3ac99sewardj//   MemLoc.vseg  :: Seg (explicitly stored as the shadow memory)
78024598e40c84666cc311a42c256bbf880db3ac99sewardj//   RegLoc.vseg  :: Seg (explicitly stored as shadow registers)
79024598e40c84666cc311a42c256bbf880db3ac99sewardj//
80024598e40c84666cc311a42c256bbf880db3ac99sewardj// A Seg is made when new memory is created, eg. with malloc() or mmap().
81024598e40c84666cc311a42c256bbf880db3ac99sewardj// There are two other Segs:
82024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - NONPTR:  for something that's definitely not a pointer
83024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - UNKNOWN: for something that could be a pointer
84024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - BOTTOM:  used with pointer differences (see below)
85024598e40c84666cc311a42c256bbf880db3ac99sewardj//
86024598e40c84666cc311a42c256bbf880db3ac99sewardj// MemLoc.vseg is done at word granularity.  If a pointer is written
87024598e40c84666cc311a42c256bbf880db3ac99sewardj// to memory misaligned, the information about it will be lost -- it's
88024598e40c84666cc311a42c256bbf880db3ac99sewardj// treated as two sub-word writes to two adjacent words.  This avoids
89024598e40c84666cc311a42c256bbf880db3ac99sewardj// certain nasty cases that could arise if we tried to track unaligned
90024598e40c84666cc311a42c256bbf880db3ac99sewardj// pointers.  Fortunately, misalignment is rare so we don't lose much
91024598e40c84666cc311a42c256bbf880db3ac99sewardj// information this way.
92024598e40c84666cc311a42c256bbf880db3ac99sewardj//
93024598e40c84666cc311a42c256bbf880db3ac99sewardj// MemLoc.aseg is done at byte granularity, and *implicitly* -- ie. not
94024598e40c84666cc311a42c256bbf880db3ac99sewardj// directly accessible like MemLoc.vseg, but only by searching through all
95024598e40c84666cc311a42c256bbf880db3ac99sewardj// the segments.  Fortunately, it's mostly checked at LOADs/STOREs;  at that
96024598e40c84666cc311a42c256bbf880db3ac99sewardj// point we have a pointer p to the MemLoc m as the other arg of the
97024598e40c84666cc311a42c256bbf880db3ac99sewardj// LOAD/STORE, so we can check to see if the p.vseg's range includes m.  If
98024598e40c84666cc311a42c256bbf880db3ac99sewardj// not, it's an error and we have to search through all segments to find out
99024598e40c84666cc311a42c256bbf880db3ac99sewardj// what m.aseg really is.  That's still pretty fast though, thanks to the
100024598e40c84666cc311a42c256bbf880db3ac99sewardj// interval skip-list used.  With syscalls we must also do the skip-list
101024598e40c84666cc311a42c256bbf880db3ac99sewardj// search, but only on the first and last bytes touched.
102024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
103024598e40c84666cc311a42c256bbf880db3ac99sewardj
104024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
105024598e40c84666cc311a42c256bbf880db3ac99sewardj// Assumptions, etc:
106024598e40c84666cc311a42c256bbf880db3ac99sewardj// - see comment at top of SK_(instrument)() for how sub-word ops are
107024598e40c84666cc311a42c256bbf880db3ac99sewardj//   handled.
108024598e40c84666cc311a42c256bbf880db3ac99sewardj//
109024598e40c84666cc311a42c256bbf880db3ac99sewardj// - ioctl(), socketcall() (and ipc() will be) assumed to return non-pointers
110024598e40c84666cc311a42c256bbf880db3ac99sewardj//
111024598e40c84666cc311a42c256bbf880db3ac99sewardj// - FPU_W is assumed to never write pointers.
112024598e40c84666cc311a42c256bbf880db3ac99sewardj//
113024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Assuming none of the post_mem_writes create segments worth tracking.
114024598e40c84666cc311a42c256bbf880db3ac99sewardj//
115024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Treating mmap'd segments (all! including code) like heap segments.  But
116024598e40c84666cc311a42c256bbf880db3ac99sewardj//   their ranges can change, new ones can be created by unmapping parts of
117024598e40c84666cc311a42c256bbf880db3ac99sewardj//   old segments, etc.  But this nasty behaviour seems to never happen --
118024598e40c84666cc311a42c256bbf880db3ac99sewardj//   there are assertions checking it.
119024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
120024598e40c84666cc311a42c256bbf880db3ac99sewardj
121024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
122024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am checking:
123024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Type errors:
124024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ADD, OR, LEA2: error if two pointer inputs.
125024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ADC, SBB: error if one or two pointer inputs.
126024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * AND, OR: error if two unequal pointer inputs.
127024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * NEG: error if pointer input.
128024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * {,i}mul_32_64 if either input is a pointer.
129024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * shldl/shrdl, bsf/bsr if any inputs are pointers.
130024598e40c84666cc311a42c256bbf880db3ac99sewardj//
131024598e40c84666cc311a42c256bbf880db3ac99sewardj// - LOAD, STORE:
132024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ptr.vseg must match ptee.aseg.
133024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ptee.aseg must not be a freed segment.
134024598e40c84666cc311a42c256bbf880db3ac99sewardj//
135024598e40c84666cc311a42c256bbf880db3ac99sewardj// - syscalls: for those accessing memory, look at first and last bytes:
136024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * check first.aseg == last.aseg
137024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * check first.aseg and last.aseg are not freed segments.
138024598e40c84666cc311a42c256bbf880db3ac99sewardj//
139024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking, that I expected to when I started:
140024598e40c84666cc311a42c256bbf880db3ac99sewardj// - AND, XOR: allowing two pointers to be used if both from the same segment,
141024598e40c84666cc311a42c256bbf880db3ac99sewardj//   because "xor %r,%r" is commonly used to zero %r, and "test %r,%r"
142024598e40c84666cc311a42c256bbf880db3ac99sewardj//   (which is translated with an AND) is common too.
143024598e40c84666cc311a42c256bbf880db3ac99sewardj//
144024598e40c84666cc311a42c256bbf880db3ac99sewardj// - div_64_32/idiv_64_32 can take pointer inputs for the dividend;
145024598e40c84666cc311a42c256bbf880db3ac99sewardj//   division doesn't make sense, but modulo does, and they're done with the
146024598e40c84666cc311a42c256bbf880db3ac99sewardj//   same instruction.  (Could try to be super-clever and watch the outputs
147024598e40c84666cc311a42c256bbf880db3ac99sewardj//   to see if the quotient is used, but not worth it.)
148024598e40c84666cc311a42c256bbf880db3ac99sewardj//
149024598e40c84666cc311a42c256bbf880db3ac99sewardj// - mul_64_32/imul_64_32 can take pointers inputs for one arg or the
150024598e40c84666cc311a42c256bbf880db3ac99sewardj//   other, but not both.  This is because some programs (eg. Mozilla
151024598e40c84666cc311a42c256bbf880db3ac99sewardj//   Firebird) multiply pointers in hash routines.
152024598e40c84666cc311a42c256bbf880db3ac99sewardj//
153024598e40c84666cc311a42c256bbf880db3ac99sewardj// - NEG: can take a pointer.  It happens in glibc in a few places.  I've
154024598e40c84666cc311a42c256bbf880db3ac99sewardj//   seen the code, didn't understand it, but it's done deliberately.
155024598e40c84666cc311a42c256bbf880db3ac99sewardj//
156024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking/doing, but could, but it would require more
157024598e40c84666cc311a42c256bbf880db3ac99sewardj// instrumentation and/or slow things down a bit:
158024598e40c84666cc311a42c256bbf880db3ac99sewardj// - SUB: when differencing two pointers, result is BOTTOM, ie. "don't
159024598e40c84666cc311a42c256bbf880db3ac99sewardj//   check".  Could link segments instead, slower but a bit more accurate.
160024598e40c84666cc311a42c256bbf880db3ac99sewardj//   Also use BOTTOM when doing (ptr - unknown), which could be a pointer
161024598e40c84666cc311a42c256bbf880db3ac99sewardj//   difference with a stack/static pointer.
162024598e40c84666cc311a42c256bbf880db3ac99sewardj//
163024598e40c84666cc311a42c256bbf880db3ac99sewardj// - PUTF: input should be non-pointer
164024598e40c84666cc311a42c256bbf880db3ac99sewardj//
165024598e40c84666cc311a42c256bbf880db3ac99sewardj// - arithmetic error messages: eg. for adding two pointers, just giving the
166024598e40c84666cc311a42c256bbf880db3ac99sewardj//   segments, not the actual pointers.
167024598e40c84666cc311a42c256bbf880db3ac99sewardj//
168024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking, and would be difficult:
169024598e40c84666cc311a42c256bbf880db3ac99sewardj// - mmap(...MAP_FIXED...) is not handled specially.  It might be used in
170024598e40c84666cc311a42c256bbf880db3ac99sewardj//   ways that fool Ptrcheck into giving false positives.
171024598e40c84666cc311a42c256bbf880db3ac99sewardj//
172024598e40c84666cc311a42c256bbf880db3ac99sewardj// - syscalls: for those accessing memory, not checking that the asegs of the
173024598e40c84666cc311a42c256bbf880db3ac99sewardj//   accessed words match the vseg of the accessing pointer, because the
174024598e40c84666cc311a42c256bbf880db3ac99sewardj//   vseg is not easily accessible at the required time (would required
175024598e40c84666cc311a42c256bbf880db3ac99sewardj//   knowing for every syscall which register each arg came in, and looking
176024598e40c84666cc311a42c256bbf880db3ac99sewardj//   there).
177024598e40c84666cc311a42c256bbf880db3ac99sewardj//
178024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking, and would be difficult, but doesn't matter:
179024598e40c84666cc311a42c256bbf880db3ac99sewardj// - free(p): similar to syscalls, not checking that the p.vseg matches the
180024598e40c84666cc311a42c256bbf880db3ac99sewardj//   aseg of the first byte in the block.  However, Memcheck does an
181024598e40c84666cc311a42c256bbf880db3ac99sewardj//   equivalent "bad free" check using shadow_chunks;  indeed, Ptrcheck could
182024598e40c84666cc311a42c256bbf880db3ac99sewardj//   do the same check, but there's no point duplicating functionality.  So
183024598e40c84666cc311a42c256bbf880db3ac99sewardj//   no loss, really.
184024598e40c84666cc311a42c256bbf880db3ac99sewardj//
185024598e40c84666cc311a42c256bbf880db3ac99sewardj// Other:
186024598e40c84666cc311a42c256bbf880db3ac99sewardj// - not doing anything with mprotect();  probably not worth the effort.
187024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
188024598e40c84666cc311a42c256bbf880db3ac99sewardj
189024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
190024598e40c84666cc311a42c256bbf880db3ac99sewardj// Todo:
191024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Segments for stack frames.  Would detect (some, large) stack
192024598e40c84666cc311a42c256bbf880db3ac99sewardj//   over/under-runs, dangling pointers.
193024598e40c84666cc311a42c256bbf880db3ac99sewardj//
194024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Segments for static data.  Would detect over/under-runs.  Requires
195024598e40c84666cc311a42c256bbf880db3ac99sewardj//   reading debug info.
196024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
197024598e40c84666cc311a42c256bbf880db3ac99sewardj
198024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
199024598e40c84666cc311a42c256bbf880db3ac99sewardj// Some profiling results:
200024598e40c84666cc311a42c256bbf880db3ac99sewardj//                                                 twolf   konq    date sz
201024598e40c84666cc311a42c256bbf880db3ac99sewardj// 1. started                                              35.0s   14.7
202024598e40c84666cc311a42c256bbf880db3ac99sewardj// 2. introduced GETV/PUTV                                 30.2s   10.1
203024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3. inlined check_load_or_store                  5.6s    27.5s   10.1
204024598e40c84666cc311a42c256bbf880db3ac99sewardj// 4. (made check_load, check_store4 regparm(0))          (27.9s) (11.0)
205024598e40c84666cc311a42c256bbf880db3ac99sewardj// 5. um, not sure                                 5.3s    27.3s   10.6
206024598e40c84666cc311a42c256bbf880db3ac99sewardj//    ...
207024598e40c84666cc311a42c256bbf880db3ac99sewardj// 6. after big changes, corrections              11.2s    32.8s   14.0
208024598e40c84666cc311a42c256bbf880db3ac99sewardj// 7. removed link-segment chasing in check/L/S    8.9s    30.8s   14.0
209024598e40c84666cc311a42c256bbf880db3ac99sewardj// 8. avoiding do_lea1 if k is a nonptr            8.0s    28.0s   12.9
210024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
211024598e40c84666cc311a42c256bbf880db3ac99sewardj
212024598e40c84666cc311a42c256bbf880db3ac99sewardj//#include "vg_skin.h"
213024598e40c84666cc311a42c256bbf880db3ac99sewardj
214024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_basics.h"
215024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_libcbase.h"
216024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_libcprint.h"
217024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_libcassert.h"
218024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_mallocfree.h"
219024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_execontext.h"
220024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_hashtable.h"
221024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_tooliface.h"
222024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_replacemalloc.h"
223024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_options.h"
224024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_execontext.h"
225024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_aspacemgr.h"    // VG_(am_shadow_malloc)
226024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_vki.h"          // VKI_MAX_PAGE_SIZE
227024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_machine.h"      // VG_({get,set}_shadow_regs_area) et al
228024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_debuginfo.h"    // VG_(get_fnname)
229024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_threadstate.h"  // VG_(get_running_tid)
230024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_oset.h"
231024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_vkiscnums.h"
232024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_machine.h"
233024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_wordfm.h"
234024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_xarray.h"
235024598e40c84666cc311a42c256bbf880db3ac99sewardj
236024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pc_common.h"
237024598e40c84666cc311a42c256bbf880db3ac99sewardj
238024598e40c84666cc311a42c256bbf880db3ac99sewardj//#include "h_list.h"
239024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "h_main.h"
240024598e40c84666cc311a42c256bbf880db3ac99sewardj
241024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "sg_main.h"   // sg_instrument_*, and struct _SGEnv
242024598e40c84666cc311a42c256bbf880db3ac99sewardj
243024598e40c84666cc311a42c256bbf880db3ac99sewardj
244024598e40c84666cc311a42c256bbf880db3ac99sewardj
245024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
246024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Debug/trace options                                  ---*/
247024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
248024598e40c84666cc311a42c256bbf880db3ac99sewardj
249024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Set to 1 to do sanity checks on Seg values in many places, which
250024598e40c84666cc311a42c256bbf880db3ac99sewardj   checks if bogus Segs are in circulation.  Quite expensive from a
251024598e40c84666cc311a42c256bbf880db3ac99sewardj   performance point of view. */
252024598e40c84666cc311a42c256bbf880db3ac99sewardj#define SC_SEGS 0
253024598e40c84666cc311a42c256bbf880db3ac99sewardj
254024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__client_mallocs = 0;
255024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__client_frees   = 0;
256024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__segs_allocd    = 0;
257024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__segs_recycled  = 0;
258024598e40c84666cc311a42c256bbf880db3ac99sewardj
259024598e40c84666cc311a42c256bbf880db3ac99sewardj
260024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
261024598e40c84666cc311a42c256bbf880db3ac99sewardj//                                                          //
262024598e40c84666cc311a42c256bbf880db3ac99sewardj// Segments low level storage                               //
263024598e40c84666cc311a42c256bbf880db3ac99sewardj//                                                          //
264024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
265024598e40c84666cc311a42c256bbf880db3ac99sewardj
266024598e40c84666cc311a42c256bbf880db3ac99sewardj// NONPTR, UNKNOWN, BOTTOM defined in h_main.h since
267024598e40c84666cc311a42c256bbf880db3ac99sewardj// pc_common.c needs to see them, for error processing
268024598e40c84666cc311a42c256bbf880db3ac99sewardj
269024598e40c84666cc311a42c256bbf880db3ac99sewardj// we only start recycling segs when this many exist
270024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_FREED_SEGS (1 * 1000 * 1000)
271024598e40c84666cc311a42c256bbf880db3ac99sewardj
272024598e40c84666cc311a42c256bbf880db3ac99sewardjstruct _Seg {
273024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr  addr;
274024598e40c84666cc311a42c256bbf880db3ac99sewardj   SizeT szB; /* may be zero */
275024598e40c84666cc311a42c256bbf880db3ac99sewardj   ExeContext* ec;  /* where malloc'd or freed */
276024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* When 1, indicates block is in use.  Otherwise, used to form a
277024598e40c84666cc311a42c256bbf880db3ac99sewardj      linked list of freed blocks, running from oldest freed block to
278024598e40c84666cc311a42c256bbf880db3ac99sewardj      the most recently freed block. */
279024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct _Seg* nextfree;
280024598e40c84666cc311a42c256bbf880db3ac99sewardj};
281024598e40c84666cc311a42c256bbf880db3ac99sewardj
282024598e40c84666cc311a42c256bbf880db3ac99sewardj// Determines if 'a' is before, within, or after seg's range.  Sets 'cmp' to
283024598e40c84666cc311a42c256bbf880db3ac99sewardj// -1/0/1 accordingly.  Sets 'n' to the number of bytes before/within/after.
284024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n)
285024598e40c84666cc311a42c256bbf880db3ac99sewardj{
286024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (a < seg->addr) {
287024598e40c84666cc311a42c256bbf880db3ac99sewardj      *cmp = -1;
288024598e40c84666cc311a42c256bbf880db3ac99sewardj      *n   = seg->addr - a;
289024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (a < seg->addr + seg->szB && seg->szB > 0) {
290024598e40c84666cc311a42c256bbf880db3ac99sewardj      *cmp = 0;
291024598e40c84666cc311a42c256bbf880db3ac99sewardj      *n = a - seg->addr;
292024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
293024598e40c84666cc311a42c256bbf880db3ac99sewardj      *cmp = 1;
294024598e40c84666cc311a42c256bbf880db3ac99sewardj      *n = a - (seg->addr + seg->szB);
295024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
296024598e40c84666cc311a42c256bbf880db3ac99sewardj}
297024598e40c84666cc311a42c256bbf880db3ac99sewardj
298024598e40c84666cc311a42c256bbf880db3ac99sewardjinline Bool Seg__is_freed(Seg* seg)
299024598e40c84666cc311a42c256bbf880db3ac99sewardj{
300024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!is_known_segment(seg))
301024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
302024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
303024598e40c84666cc311a42c256bbf880db3ac99sewardj      return seg->nextfree != (Seg*)1;
304024598e40c84666cc311a42c256bbf880db3ac99sewardj}
305024598e40c84666cc311a42c256bbf880db3ac99sewardj
306024598e40c84666cc311a42c256bbf880db3ac99sewardjExeContext* Seg__where(Seg* seg)
307024598e40c84666cc311a42c256bbf880db3ac99sewardj{
308024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(is_known_segment(seg));
309024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg->ec;
310024598e40c84666cc311a42c256bbf880db3ac99sewardj}
311024598e40c84666cc311a42c256bbf880db3ac99sewardj
312024598e40c84666cc311a42c256bbf880db3ac99sewardjSizeT Seg__size(Seg* seg)
313024598e40c84666cc311a42c256bbf880db3ac99sewardj{
314024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(is_known_segment(seg));
315024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg->szB;
316024598e40c84666cc311a42c256bbf880db3ac99sewardj}
317024598e40c84666cc311a42c256bbf880db3ac99sewardj
318024598e40c84666cc311a42c256bbf880db3ac99sewardjAddr Seg__addr(Seg* seg)
319024598e40c84666cc311a42c256bbf880db3ac99sewardj{
320024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(is_known_segment(seg));
321024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg->addr;
322024598e40c84666cc311a42c256bbf880db3ac99sewardj}
323024598e40c84666cc311a42c256bbf880db3ac99sewardj
324024598e40c84666cc311a42c256bbf880db3ac99sewardj
325024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_SEGS_PER_GROUP 10000
326024598e40c84666cc311a42c256bbf880db3ac99sewardj
327024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
328024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct _SegGroup {
329024598e40c84666cc311a42c256bbf880db3ac99sewardj      struct _SegGroup* admin;
330024598e40c84666cc311a42c256bbf880db3ac99sewardj      UWord nextfree; /* 0 .. N_SEGS_PER_GROUP */
331024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg segs[N_SEGS_PER_GROUP];
332024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
333024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup;
334024598e40c84666cc311a42c256bbf880db3ac99sewardj
335024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SegGroup* group_list = NULL;
336024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UWord     nFreeSegs = 0;
337024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg*      freesegs_youngest = NULL;
338024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg*      freesegs_oldest = NULL;
339024598e40c84666cc311a42c256bbf880db3ac99sewardj
340024598e40c84666cc311a42c256bbf880db3ac99sewardj
341024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SegGroup* new_SegGroup ( void ) {
342024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup* g = VG_(malloc)("pc.h_main.nTG.1", sizeof(SegGroup));
343024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)(g, 0, sizeof(*g));
344024598e40c84666cc311a42c256bbf880db3ac99sewardj   return g;
345024598e40c84666cc311a42c256bbf880db3ac99sewardj}
346024598e40c84666cc311a42c256bbf880db3ac99sewardj
347024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Get a completely new Seg */
348024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* new_Seg ( void )
349024598e40c84666cc311a42c256bbf880db3ac99sewardj{
350024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg*      teg;
351024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup* g;
352024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (group_list == NULL) {
353024598e40c84666cc311a42c256bbf880db3ac99sewardj      g = new_SegGroup();
354024598e40c84666cc311a42c256bbf880db3ac99sewardj      g->admin = NULL;
355024598e40c84666cc311a42c256bbf880db3ac99sewardj      group_list = g;
356024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
357024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(group_list->nextfree <= N_SEGS_PER_GROUP);
358024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (group_list->nextfree == N_SEGS_PER_GROUP) {
359024598e40c84666cc311a42c256bbf880db3ac99sewardj      g = new_SegGroup();
360024598e40c84666cc311a42c256bbf880db3ac99sewardj      g->admin = group_list;
361024598e40c84666cc311a42c256bbf880db3ac99sewardj      group_list = g;
362024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
363024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(group_list->nextfree < N_SEGS_PER_GROUP);
364024598e40c84666cc311a42c256bbf880db3ac99sewardj   teg = &group_list->segs[ group_list->nextfree ];
365024598e40c84666cc311a42c256bbf880db3ac99sewardj   group_list->nextfree++;
366024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__segs_allocd++;
367024598e40c84666cc311a42c256bbf880db3ac99sewardj   return teg;
368024598e40c84666cc311a42c256bbf880db3ac99sewardj}
369024598e40c84666cc311a42c256bbf880db3ac99sewardj
370024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* get_Seg_for_malloc ( void )
371024598e40c84666cc311a42c256bbf880db3ac99sewardj{
372024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg;
373024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (nFreeSegs < N_FREED_SEGS) {
374024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg = new_Seg();
375024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg->nextfree = (Seg*)1;
376024598e40c84666cc311a42c256bbf880db3ac99sewardj      return seg;
377024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
378024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* else recycle the oldest Seg in the free list */
379024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(freesegs_youngest);
380024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(freesegs_oldest);
381024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(freesegs_youngest != freesegs_oldest);
382024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg = freesegs_oldest;
383024598e40c84666cc311a42c256bbf880db3ac99sewardj   freesegs_oldest = seg->nextfree;
384024598e40c84666cc311a42c256bbf880db3ac99sewardj   nFreeSegs--;
385024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->nextfree = (Seg*)1;
386024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__segs_recycled++;
387024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg;
388024598e40c84666cc311a42c256bbf880db3ac99sewardj}
389024598e40c84666cc311a42c256bbf880db3ac99sewardj
390024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void set_Seg_freed ( Seg* seg )
391024598e40c84666cc311a42c256bbf880db3ac99sewardj{
392024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(seg);
393024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!Seg__is_freed(seg));
394024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (nFreeSegs == 0) {
395024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_oldest == NULL);
396024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_youngest == NULL);
397024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg->nextfree = NULL;
398024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_youngest = seg;
399024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_oldest = seg;
400024598e40c84666cc311a42c256bbf880db3ac99sewardj      nFreeSegs++;
401024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
402024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_youngest);
403024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_oldest);
404024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (nFreeSegs == 1) {
405024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(freesegs_youngest == freesegs_oldest);
406024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
407024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(freesegs_youngest != freesegs_oldest);
408024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
409024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_youngest->nextfree == NULL);
410024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(seg != freesegs_youngest && seg != freesegs_oldest);
411024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg->nextfree = NULL;
412024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_youngest->nextfree = seg;
413024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_youngest = seg;
414024598e40c84666cc311a42c256bbf880db3ac99sewardj      nFreeSegs++;
415024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
416024598e40c84666cc311a42c256bbf880db3ac99sewardj}
417024598e40c84666cc311a42c256bbf880db3ac99sewardj
4189520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardjstatic WordFM* addr_to_seg_map = NULL; /* GuestAddr -> Seg* */
419024598e40c84666cc311a42c256bbf880db3ac99sewardj
420024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void addr_to_seg_map_ENSURE_INIT ( void )
421024598e40c84666cc311a42c256bbf880db3ac99sewardj{
422024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (UNLIKELY(addr_to_seg_map == NULL)) {
423024598e40c84666cc311a42c256bbf880db3ac99sewardj      addr_to_seg_map = VG_(newFM)( VG_(malloc), "pc.h_main.attmEI.1",
4249520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj                                    VG_(free), NULL/*unboxedcmp*/ );
425024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
426024598e40c84666cc311a42c256bbf880db3ac99sewardj}
427024598e40c84666cc311a42c256bbf880db3ac99sewardj
428024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* find_Seg_by_addr ( Addr ga )
429024598e40c84666cc311a42c256bbf880db3ac99sewardj{
430024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord keyW, valW;
431024598e40c84666cc311a42c256bbf880db3ac99sewardj   addr_to_seg_map_ENSURE_INIT();
432024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga )) {
433024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(keyW == ga);
434024598e40c84666cc311a42c256bbf880db3ac99sewardj      return (Seg*)valW;
435024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
436024598e40c84666cc311a42c256bbf880db3ac99sewardj      return NULL;
437024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
438024598e40c84666cc311a42c256bbf880db3ac99sewardj}
439024598e40c84666cc311a42c256bbf880db3ac99sewardj
440024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void bind_addr_to_Seg ( Addr ga, Seg* seg )
441024598e40c84666cc311a42c256bbf880db3ac99sewardj{
442024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool b;
443024598e40c84666cc311a42c256bbf880db3ac99sewardj   addr_to_seg_map_ENSURE_INIT();
444024598e40c84666cc311a42c256bbf880db3ac99sewardj   b = VG_(addToFM)( addr_to_seg_map, (UWord)ga, (UWord)seg );
445024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!b); /* else ga is already bound */
446024598e40c84666cc311a42c256bbf880db3ac99sewardj}
447024598e40c84666cc311a42c256bbf880db3ac99sewardj
448024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void unbind_addr_from_Seg ( Addr ga )
449024598e40c84666cc311a42c256bbf880db3ac99sewardj{
450024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool b;
451024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord keyW, valW;
452024598e40c84666cc311a42c256bbf880db3ac99sewardj   addr_to_seg_map_ENSURE_INIT();
453024598e40c84666cc311a42c256bbf880db3ac99sewardj   b = VG_(delFromFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga );
454024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(b); /* else ga was not already bound */
455024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(keyW == ga);
456024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(valW != 0);
457024598e40c84666cc311a42c256bbf880db3ac99sewardj}
458024598e40c84666cc311a42c256bbf880db3ac99sewardj
459024598e40c84666cc311a42c256bbf880db3ac99sewardj
460024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
461024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
462024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
463024598e40c84666cc311a42c256bbf880db3ac99sewardj
464024598e40c84666cc311a42c256bbf880db3ac99sewardj// So that post_reg_write_clientcall knows the segment just allocated.
465024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* last_seg_added = NULL;
466024598e40c84666cc311a42c256bbf880db3ac99sewardj
467024598e40c84666cc311a42c256bbf880db3ac99sewardj// Returns the added heap segment
468024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* add_new_segment ( ThreadId tid, Addr p, SizeT size )
469024598e40c84666cc311a42c256bbf880db3ac99sewardj{
470024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg = get_Seg_for_malloc();
471024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(seg != (Seg*)1); /* since we're using 1 as a special value */
472024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->addr = p;
473024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->szB  = size;
474024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->ec   = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
475024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!Seg__is_freed(seg));
476024598e40c84666cc311a42c256bbf880db3ac99sewardj
477024598e40c84666cc311a42c256bbf880db3ac99sewardj   bind_addr_to_Seg(p, seg);
478024598e40c84666cc311a42c256bbf880db3ac99sewardj
479024598e40c84666cc311a42c256bbf880db3ac99sewardj   last_seg_added = seg;
480024598e40c84666cc311a42c256bbf880db3ac99sewardj
481024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg;
482024598e40c84666cc311a42c256bbf880db3ac99sewardj}
483024598e40c84666cc311a42c256bbf880db3ac99sewardj
484024598e40c84666cc311a42c256bbf880db3ac99sewardj// Forward declarations
485024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void copy_mem( Addr from, Addr to, SizeT len );
486024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void set_mem_unknown ( Addr a, SizeT len );
487024598e40c84666cc311a42c256bbf880db3ac99sewardj
488024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline VG_REGPARM(1) Seg* nonptr_or_unknown(UWord x); /*fwds*/
489024598e40c84666cc311a42c256bbf880db3ac99sewardj
490024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
491024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* alloc_and_new_mem_heap ( ThreadId tid,
492024598e40c84666cc311a42c256bbf880db3ac99sewardj                               SizeT size, SizeT alignment, Bool is_zeroed )
493024598e40c84666cc311a42c256bbf880db3ac99sewardj{
494024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr p;
495024598e40c84666cc311a42c256bbf880db3ac99sewardj
496024598e40c84666cc311a42c256bbf880db3ac99sewardj   if ( ((SSizeT)size) < 0) return NULL;
497024598e40c84666cc311a42c256bbf880db3ac99sewardj
498024598e40c84666cc311a42c256bbf880db3ac99sewardj   p = (Addr)VG_(cli_malloc)(alignment, size);
499024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_zeroed) VG_(memset)((void*)p, 0, size);
500024598e40c84666cc311a42c256bbf880db3ac99sewardj
501024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( p, size );
502024598e40c84666cc311a42c256bbf880db3ac99sewardj   add_new_segment( tid, p, size );
503024598e40c84666cc311a42c256bbf880db3ac99sewardj
504024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__client_mallocs++;
505024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (void*)p;
506024598e40c84666cc311a42c256bbf880db3ac99sewardj}
507024598e40c84666cc311a42c256bbf880db3ac99sewardj
508024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void die_and_free_mem_heap ( ThreadId tid, Seg* seg )
509024598e40c84666cc311a42c256bbf880db3ac99sewardj{
510024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Empty and free the actual block
511024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!Seg__is_freed(seg));
512024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( seg->addr, seg->szB );
513024598e40c84666cc311a42c256bbf880db3ac99sewardj
514024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(cli_free)( (void*)seg->addr );
515024598e40c84666cc311a42c256bbf880db3ac99sewardj
516024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Remember where freed
517024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
518024598e40c84666cc311a42c256bbf880db3ac99sewardj
519024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_Seg_freed(seg);
520024598e40c84666cc311a42c256bbf880db3ac99sewardj   unbind_addr_from_Seg( seg->addr );
521024598e40c84666cc311a42c256bbf880db3ac99sewardj
522024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__client_frees++;
523024598e40c84666cc311a42c256bbf880db3ac99sewardj}
524024598e40c84666cc311a42c256bbf880db3ac99sewardj
525024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void handle_free_heap( ThreadId tid, void* p )
526024598e40c84666cc311a42c256bbf880db3ac99sewardj{
527024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg = find_Seg_by_addr( (Addr)p );
528024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!seg) {
529024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* freeing a block that wasn't malloc'd.  Ignore. */
530024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
531024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
532024598e40c84666cc311a42c256bbf880db3ac99sewardj   die_and_free_mem_heap( tid, seg );
533024598e40c84666cc311a42c256bbf880db3ac99sewardj}
534024598e40c84666cc311a42c256bbf880db3ac99sewardj
535024598e40c84666cc311a42c256bbf880db3ac99sewardj
536024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
537024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Shadow memory                                        ---*/
538024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
539024598e40c84666cc311a42c256bbf880db3ac99sewardj
540024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Shadow memory holds one Seg for each naturally aligned (guest)
541024598e40c84666cc311a42c256bbf880db3ac99sewardj   word.  For a 32 bit target (assuming host word size == guest word
542024598e40c84666cc311a42c256bbf880db3ac99sewardj   size) that means one Seg per 4 bytes, and each Seg occupies 4
543024598e40c84666cc311a42c256bbf880db3ac99sewardj   bytes.  For a 64 bit target that means one Seg per 8 bytes, and
544024598e40c84666cc311a42c256bbf880db3ac99sewardj   each Seg occupies 8 bytes.  Hence in each case the overall space
545024598e40c84666cc311a42c256bbf880db3ac99sewardj   overhead for shadow memory is 1:1.
546024598e40c84666cc311a42c256bbf880db3ac99sewardj
547024598e40c84666cc311a42c256bbf880db3ac99sewardj   This does however make it a bit tricky to size SecMap.vseg[], simce
548024598e40c84666cc311a42c256bbf880db3ac99sewardj   it needs to hold 16384 entries for 32 bit targets but only 8192
549024598e40c84666cc311a42c256bbf880db3ac99sewardj   entries for 64 bit targets. */
550024598e40c84666cc311a42c256bbf880db3ac99sewardj
551024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
552024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((unused))
553024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void pp_curr_ExeContext(void)
554024598e40c84666cc311a42c256bbf880db3ac99sewardj{
555024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(pp_ExeContext)(
556024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(get_ExeContext)(
557024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(get_current_or_recent_tid)() ) );
558024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(message)(Vg_UserMsg, "");
559024598e40c84666cc311a42c256bbf880db3ac99sewardj}
560024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
561024598e40c84666cc311a42c256bbf880db3ac99sewardj
562024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_x86) || defined(VGA_ppc32)
563024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_MASK         0xFFFC
564024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_SHIFT        2
565024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_4_ALIGNED(_a)
566024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SEC_MAP_WORDS             (0x10000UL / 4UL) /* 16k */
567024598e40c84666cc311a42c256bbf880db3ac99sewardj#elif defined(VGA_amd64) || defined(VGA_ppc64)
568024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_MASK         0xFFF8
569024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_SHIFT        3
570024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_8_ALIGNED(_a)
571024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SEC_MAP_WORDS             (0x10000UL / 8UL) /* 8k */
572024598e40c84666cc311a42c256bbf880db3ac99sewardj#else
573024598e40c84666cc311a42c256bbf880db3ac99sewardj#  error "Unknown arch"
574024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
575024598e40c84666cc311a42c256bbf880db3ac99sewardj
576024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
577024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
578024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* vseg[SEC_MAP_WORDS];
579024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
580024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap;
581024598e40c84666cc311a42c256bbf880db3ac99sewardj
582024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SecMap  distinguished_secondary_map;
583024598e40c84666cc311a42c256bbf880db3ac99sewardj
584024598e40c84666cc311a42c256bbf880db3ac99sewardj/* An entry in the primary map.  base must be a 64k-aligned value, and
585024598e40c84666cc311a42c256bbf880db3ac99sewardj   sm points at the relevant secondary map.  The secondary may be
586024598e40c84666cc311a42c256bbf880db3ac99sewardj   either a real secondary, or the distinguished secondary.  DO NOT
587024598e40c84666cc311a42c256bbf880db3ac99sewardj   CHANGE THIS LAYOUT: the first word has to be the key for OSet fast
588024598e40c84666cc311a42c256bbf880db3ac99sewardj   lookups.
589024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
590024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
591024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
592024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr    base;
593024598e40c84666cc311a42c256bbf880db3ac99sewardj      SecMap* sm;
594024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
595024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt;
596024598e40c84666cc311a42c256bbf880db3ac99sewardj
597024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Primary map is an OSet of PriMapEnt (primap_L2), "fronted" by a
598024598e40c84666cc311a42c256bbf880db3ac99sewardj   cache (primap_L1). */
599024598e40c84666cc311a42c256bbf880db3ac99sewardj
600024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Tunable parameter: How big is the L1 queue? */
601024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_PRIMAP_L1 24
602024598e40c84666cc311a42c256bbf880db3ac99sewardj
603024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Tunable parameter: How far along the L1 queue to insert
604024598e40c84666cc311a42c256bbf880db3ac99sewardj   entries resulting from L2 lookups? */
605024598e40c84666cc311a42c256bbf880db3ac99sewardj#define PRIMAP_L1_INSERT_IX 12
606024598e40c84666cc311a42c256bbf880db3ac99sewardj
607024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic struct {
608024598e40c84666cc311a42c256bbf880db3ac99sewardj          Addr       base; // must be 64k aligned
609024598e40c84666cc311a42c256bbf880db3ac99sewardj          PriMapEnt* ent; // pointer to the matching primap_L2 node
610024598e40c84666cc311a42c256bbf880db3ac99sewardj       }
611024598e40c84666cc311a42c256bbf880db3ac99sewardj       primap_L1[N_PRIMAP_L1];
612024598e40c84666cc311a42c256bbf880db3ac99sewardj
613024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic OSet* primap_L2 = NULL;
614024598e40c84666cc311a42c256bbf880db3ac99sewardj
615024598e40c84666cc311a42c256bbf880db3ac99sewardj
616024598e40c84666cc311a42c256bbf880db3ac99sewardj/* # searches initiated in auxmap_L1, and # base cmps required */
617024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L1_searches  = 0;
618024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L1_cmps      = 0;
619024598e40c84666cc311a42c256bbf880db3ac99sewardj/* # of searches that missed in auxmap_L1 and therefore had to
620024598e40c84666cc311a42c256bbf880db3ac99sewardj   be handed to auxmap_L2. And the number of nodes inserted. */
621024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L2_searches  = 0;
622024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L2_nodes     = 0;
623024598e40c84666cc311a42c256bbf880db3ac99sewardj
624024598e40c84666cc311a42c256bbf880db3ac99sewardj
625024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_shadow_memory ( void )
626024598e40c84666cc311a42c256bbf880db3ac99sewardj{
627024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i;
628024598e40c84666cc311a42c256bbf880db3ac99sewardj
629024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < SEC_MAP_WORDS; i++)
630024598e40c84666cc311a42c256bbf880db3ac99sewardj      distinguished_secondary_map.vseg[i] = NONPTR;
631024598e40c84666cc311a42c256bbf880db3ac99sewardj
632024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < N_PRIMAP_L1; i++) {
633024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[i].base = 1; /* not 64k aligned, so doesn't match any
634024598e40c84666cc311a42c256bbf880db3ac99sewardj                                request ==> slot is empty */
635024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[i].ent  = NULL;
636024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
637024598e40c84666cc311a42c256bbf880db3ac99sewardj
638024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == offsetof(PriMapEnt,base));
639024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr) == sizeof(void*));
640024598e40c84666cc311a42c256bbf880db3ac99sewardj   primap_L2 = VG_(OSetGen_Create)( /*keyOff*/  offsetof(PriMapEnt,base),
641024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    /*fastCmp*/ NULL,
642024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(malloc), "pc.h_main.ism.1",
643024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(free) );
644024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(primap_L2);
645024598e40c84666cc311a42c256bbf880db3ac99sewardj}
646024598e40c84666cc311a42c256bbf880db3ac99sewardj
647024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void insert_into_primap_L1_at ( Word rank, PriMapEnt* ent )
648024598e40c84666cc311a42c256bbf880db3ac99sewardj{
649024598e40c84666cc311a42c256bbf880db3ac99sewardj   Word i;
650024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(ent);
651024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(rank >= 0 && rank < N_PRIMAP_L1);
652024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = N_PRIMAP_L1-1; i > rank; i--)
653024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[i] = primap_L1[i-1];
654024598e40c84666cc311a42c256bbf880db3ac99sewardj   primap_L1[rank].base = ent->base;
655024598e40c84666cc311a42c256bbf880db3ac99sewardj   primap_L1[rank].ent  = ent;
656024598e40c84666cc311a42c256bbf880db3ac99sewardj}
657024598e40c84666cc311a42c256bbf880db3ac99sewardj
658024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline PriMapEnt* maybe_find_in_primap ( Addr a )
659024598e40c84666cc311a42c256bbf880db3ac99sewardj{
660024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt  key;
661024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt* res;
662024598e40c84666cc311a42c256bbf880db3ac99sewardj   Word       i;
663024598e40c84666cc311a42c256bbf880db3ac99sewardj
664024598e40c84666cc311a42c256bbf880db3ac99sewardj   a &= ~(Addr)0xFFFF;
665024598e40c84666cc311a42c256bbf880db3ac99sewardj
666024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First search the front-cache, which is a self-organising
667024598e40c84666cc311a42c256bbf880db3ac99sewardj      list containing the most popular entries. */
668024598e40c84666cc311a42c256bbf880db3ac99sewardj
669024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (LIKELY(primap_L1[0].base == a))
670024598e40c84666cc311a42c256bbf880db3ac99sewardj      return primap_L1[0].ent;
671024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (LIKELY(primap_L1[1].base == a)) {
672024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr       t_base = primap_L1[0].base;
673024598e40c84666cc311a42c256bbf880db3ac99sewardj      PriMapEnt* t_ent  = primap_L1[0].ent;
674024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[0].base = primap_L1[1].base;
675024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[0].ent  = primap_L1[1].ent;
676024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[1].base = t_base;
677024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[1].ent  = t_ent;
678024598e40c84666cc311a42c256bbf880db3ac99sewardj      return primap_L1[0].ent;
679024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
680024598e40c84666cc311a42c256bbf880db3ac99sewardj
681024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L1_searches++;
682024598e40c84666cc311a42c256bbf880db3ac99sewardj
683024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < N_PRIMAP_L1; i++) {
684024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (primap_L1[i].base == a) {
685024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
686024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
687024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
688024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0 && i <= N_PRIMAP_L1);
689024598e40c84666cc311a42c256bbf880db3ac99sewardj
690024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L1_cmps += (ULong)(i+1);
691024598e40c84666cc311a42c256bbf880db3ac99sewardj
692024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i < N_PRIMAP_L1) {
693024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (i > 0) {
694024598e40c84666cc311a42c256bbf880db3ac99sewardj         Addr       t_base = primap_L1[i-1].base;
695024598e40c84666cc311a42c256bbf880db3ac99sewardj         PriMapEnt* t_ent  = primap_L1[i-1].ent;
696024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-1].base = primap_L1[i-0].base;
697024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-1].ent  = primap_L1[i-0].ent;
698024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-0].base = t_base;
699024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-0].ent  = t_ent;
700024598e40c84666cc311a42c256bbf880db3ac99sewardj         i--;
701024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
702024598e40c84666cc311a42c256bbf880db3ac99sewardj      return primap_L1[i].ent;
703024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
704024598e40c84666cc311a42c256bbf880db3ac99sewardj
705024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L2_searches++;
706024598e40c84666cc311a42c256bbf880db3ac99sewardj
707024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First see if we already have it. */
708024598e40c84666cc311a42c256bbf880db3ac99sewardj   key.base = a;
709024598e40c84666cc311a42c256bbf880db3ac99sewardj   key.sm   = 0;
710024598e40c84666cc311a42c256bbf880db3ac99sewardj
711024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = VG_(OSetGen_Lookup)(primap_L2, &key);
712024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (res)
713024598e40c84666cc311a42c256bbf880db3ac99sewardj      insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, res );
714024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
715024598e40c84666cc311a42c256bbf880db3ac99sewardj}
716024598e40c84666cc311a42c256bbf880db3ac99sewardj
717024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SecMap* alloc_secondary_map ( void )
718024598e40c84666cc311a42c256bbf880db3ac99sewardj{
719024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap* map;
720024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt  i;
721024598e40c84666cc311a42c256bbf880db3ac99sewardj
722024598e40c84666cc311a42c256bbf880db3ac99sewardj   // JRS 2008-June-25: what's the following assertion for?
723024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (sizeof(SecMap) % VKI_MAX_PAGE_SIZE));
724024598e40c84666cc311a42c256bbf880db3ac99sewardj
725024598e40c84666cc311a42c256bbf880db3ac99sewardj   map = VG_(am_shadow_alloc)( sizeof(SecMap) );
726024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (map == NULL)
727024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(out_of_memory_NORETURN)( "annelid:allocate new SecMap",
728024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   sizeof(SecMap) );
729024598e40c84666cc311a42c256bbf880db3ac99sewardj
730024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < SEC_MAP_WORDS; i++)
731024598e40c84666cc311a42c256bbf880db3ac99sewardj      map->vseg[i] = NONPTR;
732024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("XXX new secmap %p\n", map);
733024598e40c84666cc311a42c256bbf880db3ac99sewardj   return map;
734024598e40c84666cc311a42c256bbf880db3ac99sewardj}
735024598e40c84666cc311a42c256bbf880db3ac99sewardj
736024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic PriMapEnt* find_or_alloc_in_primap ( Addr a )
737024598e40c84666cc311a42c256bbf880db3ac99sewardj{
738024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt *nyu, *res;
739024598e40c84666cc311a42c256bbf880db3ac99sewardj
740024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First see if we already have it. */
741024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = maybe_find_in_primap( a );
742024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (LIKELY(res))
743024598e40c84666cc311a42c256bbf880db3ac99sewardj      return res;
744024598e40c84666cc311a42c256bbf880db3ac99sewardj
745024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Ok, there's no entry in the secondary map, so we'll have
746024598e40c84666cc311a42c256bbf880db3ac99sewardj      to allocate one. */
747024598e40c84666cc311a42c256bbf880db3ac99sewardj   a &= ~(Addr)0xFFFF;
748024598e40c84666cc311a42c256bbf880db3ac99sewardj
749024598e40c84666cc311a42c256bbf880db3ac99sewardj   nyu = (PriMapEnt*) VG_(OSetGen_AllocNode)(
750024598e40c84666cc311a42c256bbf880db3ac99sewardj                         primap_L2, sizeof(PriMapEnt) );
751024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(nyu);
752024598e40c84666cc311a42c256bbf880db3ac99sewardj   nyu->base = a;
753024598e40c84666cc311a42c256bbf880db3ac99sewardj   nyu->sm   = alloc_secondary_map();
754024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(nyu->sm);
755024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(OSetGen_Insert)( primap_L2, nyu );
756024598e40c84666cc311a42c256bbf880db3ac99sewardj   insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, nyu );
757024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L2_nodes++;
758024598e40c84666cc311a42c256bbf880db3ac99sewardj   return nyu;
759024598e40c84666cc311a42c256bbf880db3ac99sewardj}
760024598e40c84666cc311a42c256bbf880db3ac99sewardj
761024598e40c84666cc311a42c256bbf880db3ac99sewardj/////////////////////////////////////////////////
762024598e40c84666cc311a42c256bbf880db3ac99sewardj
763024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: 'a' must be naturally word aligned for the host.
764024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Seg* get_mem_vseg ( Addr a )
765024598e40c84666cc311a42c256bbf880db3ac99sewardj{
766024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap* sm     = find_or_alloc_in_primap(a)->sm;
767024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord   sm_off = (a & SHMEM_SECMAP_MASK) >> SHMEM_SECMAP_SHIFT;
768024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(SHMEM_IS_WORD_ALIGNED(a));
769024598e40c84666cc311a42c256bbf880db3ac99sewardj   return sm->vseg[sm_off];
770024598e40c84666cc311a42c256bbf880db3ac99sewardj}
771024598e40c84666cc311a42c256bbf880db3ac99sewardj
772024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: 'a' must be naturally word aligned for the host.
773024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline void set_mem_vseg ( Addr a, Seg* vseg )
774024598e40c84666cc311a42c256bbf880db3ac99sewardj{
775024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap* sm     = find_or_alloc_in_primap(a)->sm;
776024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord   sm_off = (a & SHMEM_SECMAP_MASK) >> SHMEM_SECMAP_SHIFT;
777024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(SHMEM_IS_WORD_ALIGNED(a));
778024598e40c84666cc311a42c256bbf880db3ac99sewardj   sm->vseg[sm_off] = vseg;
779024598e40c84666cc311a42c256bbf880db3ac99sewardj}
780024598e40c84666cc311a42c256bbf880db3ac99sewardj
7819520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj// Find the Seg which contains the given address.
782024598e40c84666cc311a42c256bbf880db3ac99sewardj// Returns UNKNOWN if no matches.  Never returns BOTTOM or NONPTR.
783024598e40c84666cc311a42c256bbf880db3ac99sewardj// Also, only returns in-use segments, not freed ones.
7849520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj/* Doing this fast is distinctly difficult when there are more than a
7859520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   few heap allocated blocks live.  Basically it is done by searching
7869520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   addr_to_seg_map for 'a'.
7879520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj
7889520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   First, if 'a' is the start address of a segment, then we can detect
7899520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   that by simply doing a VG_(lookupFM) of 'a', and we are done (nice
7909520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   and easy).
7919520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj
7929520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   If 'a' is within some segment, but does not point to the start, it
7939520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   is much more complex.  We use VG_(findBoundsFM) to find the segment
7949520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   with the largest .addr field which is <= a, and we then inspect the
7959520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   segment to see if 'a' really falls inside it or not.  This is all a
7969520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   bit complex and fragile, and so there's a lot of assertery in the
7979520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   code below.  It has been crosschecked however against the trivial
7989520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   _SLOW implementation shown after the end of this fn.
7999520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj*/
8009520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardjstatic Seg* get_Seg_containing_addr( Addr a )
8019520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj{
8029520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   UWord keyW, valW;
8039520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   Seg*  s2;
8049520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj
8059520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   /* Since we are going to poke around in it */
8069520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   addr_to_seg_map_ENSURE_INIT();
8079520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj
8089520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   /* first, see if 'a' is at the start of a block.  We do this both
8099520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      because it's easy and more imporantly because VG_(findBoundsFM)
8109520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      will fail in this case, so we need to exclude it first. */
8119520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, a )) {
8129520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      tl_assert(keyW == a);
8139520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      s2 = (Seg*)valW;
8149520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      tl_assert(s2->addr == a);
8159520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   } else {
8169520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      Bool  ok;
8179520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      UWord kMin, vMin, kMax, vMax;
8189520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      Seg   minSeg;
8199520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      Seg   maxSeg;
8209520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      UWord minAddr = 0;
8219520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      UWord maxAddr = ~minAddr;
8229520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      VG_(memset)(&minSeg, 0, sizeof(minSeg));
8239520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      VG_(memset)(&maxSeg, 0, sizeof(maxSeg));
8249520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      minSeg.addr = minAddr;
8259520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      maxSeg.addr = maxAddr;
8269520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      ok = VG_(findBoundsFM)( addr_to_seg_map,
8279520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj                              &kMin, &vMin, &kMax, &vMax,
8289520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj                              minAddr, (UWord)&minSeg,
8299520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj                              maxAddr, (UWord)&maxSeg, a );
8309520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      tl_assert(ok); /* must be so, since False is only returned when
8319520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj                        'a' is directly present in the map, and we
8329520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj                        just established that it isn't. */
8339520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      /* At this point, either vMin points at minSeg, or it points at a
8349520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         real Seg.  In the former case, there is no live heap-allocated
8359520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         Seg which has a start address <= a, so a is not in any block.
8369520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         In the latter case, the Seg vMin points at may or may not
8379520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         actually contain 'a'; we can only tell that by inspecting the
8389520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         Seg itself. */
8399520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      s2 = (Seg*)vMin;
8409520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      tl_assert(kMin == s2->addr);
8419520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      if (s2 == &minSeg) {
8429520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         /* the former */
8439520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         s2 = UNKNOWN;
8449520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      } else {
8459520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         /* the latter */
8469520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         tl_assert(s2->addr <= a);
8479520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         /* if s2 doesn't actually contain 'a', we must forget about it. */
8489520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         if (s2->szB == 0 /* a zero sized block can't contain anything */
8499520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj             || s2->addr + s2->szB < a /* the usual range check */)
8509520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj            s2 = UNKNOWN;
8519520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      }
8529520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      /* while we're at it, do as much assertery as we can, since this
8539520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         is all rather complex.  Either vMax points at maxSeg, or it
8549520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         points to a real block, which must have a start address
8559520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         greater than a. */
8569520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      tl_assert(kMax == ((Seg*)vMax)->addr);
857ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      if (vMax == (UWord)&maxSeg) {
8589520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         /* nothing we can check */
8599520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      } else {
8609520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj         tl_assert(a < kMax); /* hence also a < ((Seg*)vMax)->addr */
8619520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj      }
8629520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   }
8639520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj
8649520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   return s2;
8659520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj}
8669520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj
8679520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj/* XXXX very slow reference implementation.  Do not use.
868024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* get_Seg_containing_addr_SLOW( Addr a )
869024598e40c84666cc311a42c256bbf880db3ac99sewardj{
870024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup* group;
871024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord i;
872024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__slow_searches++;
873024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (group = group_list; group; group = group->admin) {
874024598e40c84666cc311a42c256bbf880db3ac99sewardj      for (i = 0; i < group->nextfree; i++) {
875024598e40c84666cc311a42c256bbf880db3ac99sewardj         stats__slow_totcmps++;
876024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (Seg__is_freed(&group->segs[i]))
877024598e40c84666cc311a42c256bbf880db3ac99sewardj            continue;
878024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (group->segs[i].addr <= a
879024598e40c84666cc311a42c256bbf880db3ac99sewardj             && a < group->segs[i].addr + group->segs[i].szB)
880024598e40c84666cc311a42c256bbf880db3ac99sewardj            return &group->segs[i];
881024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
882024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
883024598e40c84666cc311a42c256bbf880db3ac99sewardj   return UNKNOWN;
884024598e40c84666cc311a42c256bbf880db3ac99sewardj}
8859520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj*/
8869520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj
887024598e40c84666cc311a42c256bbf880db3ac99sewardj
888024598e40c84666cc311a42c256bbf880db3ac99sewardj
889024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
890024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- malloc() et al replacements                          ---*/
891024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
892024598e40c84666cc311a42c256bbf880db3ac99sewardj
893024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_malloc ( ThreadId tid, SizeT n )
894024598e40c84666cc311a42c256bbf880db3ac99sewardj{
895024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
896024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        /*is_zeroed*/False );
897024598e40c84666cc311a42c256bbf880db3ac99sewardj}
898024598e40c84666cc311a42c256bbf880db3ac99sewardj
899024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace___builtin_new ( ThreadId tid, SizeT n )
900024598e40c84666cc311a42c256bbf880db3ac99sewardj{
901024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
902024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           /*is_zeroed*/False );
903024598e40c84666cc311a42c256bbf880db3ac99sewardj}
904024598e40c84666cc311a42c256bbf880db3ac99sewardj
905024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace___builtin_vec_new ( ThreadId tid, SizeT n )
906024598e40c84666cc311a42c256bbf880db3ac99sewardj{
907024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
908024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           /*is_zeroed*/False );
909024598e40c84666cc311a42c256bbf880db3ac99sewardj}
910024598e40c84666cc311a42c256bbf880db3ac99sewardj
911024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
912024598e40c84666cc311a42c256bbf880db3ac99sewardj{
913024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, align,
914024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        /*is_zeroed*/False );
915024598e40c84666cc311a42c256bbf880db3ac99sewardj}
916024598e40c84666cc311a42c256bbf880db3ac99sewardj
917024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
918024598e40c84666cc311a42c256bbf880db3ac99sewardj{
919024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment),
920024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        /*is_zeroed*/True );
921024598e40c84666cc311a42c256bbf880db3ac99sewardj}
922024598e40c84666cc311a42c256bbf880db3ac99sewardj
923024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_replace_free ( ThreadId tid, void* p )
924024598e40c84666cc311a42c256bbf880db3ac99sewardj{
925024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Should arguably check here if p.vseg matches the segID of the
926024598e40c84666cc311a42c256bbf880db3ac99sewardj   // pointed-to block... unfortunately, by this stage, we don't know what
927024598e40c84666cc311a42c256bbf880db3ac99sewardj   // p.vseg is, because we don't know the address of p (the p here is a
928024598e40c84666cc311a42c256bbf880db3ac99sewardj   // copy, and we've lost the address of its source).  To do so would
929024598e40c84666cc311a42c256bbf880db3ac99sewardj   // require passing &p in, which would require rewriting part of
930024598e40c84666cc311a42c256bbf880db3ac99sewardj   // vg_replace_malloc.c... argh.
931024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
932024598e40c84666cc311a42c256bbf880db3ac99sewardj   // However, Memcheck does free checking, and will catch almost all
933024598e40c84666cc311a42c256bbf880db3ac99sewardj   // violations this checking would have caught.  (Would only miss if we
934024598e40c84666cc311a42c256bbf880db3ac99sewardj   // unluckily passed an unrelated pointer to the very start of a heap
935024598e40c84666cc311a42c256bbf880db3ac99sewardj   // block that was unrelated to that block.  This is very unlikely!)    So
936024598e40c84666cc311a42c256bbf880db3ac99sewardj   // we haven't lost much.
937024598e40c84666cc311a42c256bbf880db3ac99sewardj
938024598e40c84666cc311a42c256bbf880db3ac99sewardj   handle_free_heap(tid, p);
939024598e40c84666cc311a42c256bbf880db3ac99sewardj}
940024598e40c84666cc311a42c256bbf880db3ac99sewardj
941024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_replace___builtin_delete ( ThreadId tid, void* p )
942024598e40c84666cc311a42c256bbf880db3ac99sewardj{
943024598e40c84666cc311a42c256bbf880db3ac99sewardj   handle_free_heap(tid, p);
944024598e40c84666cc311a42c256bbf880db3ac99sewardj}
945024598e40c84666cc311a42c256bbf880db3ac99sewardj
946024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_replace___builtin_vec_delete ( ThreadId tid, void* p )
947024598e40c84666cc311a42c256bbf880db3ac99sewardj{
948024598e40c84666cc311a42c256bbf880db3ac99sewardj   handle_free_heap(tid, p);
949024598e40c84666cc311a42c256bbf880db3ac99sewardj}
950024598e40c84666cc311a42c256bbf880db3ac99sewardj
951024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
952024598e40c84666cc311a42c256bbf880db3ac99sewardj{
953024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg;
954024598e40c84666cc311a42c256bbf880db3ac99sewardj
955024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First try and find the block. */
956024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg = find_Seg_by_addr( (Addr)p_old );
957024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!seg)
958024598e40c84666cc311a42c256bbf880db3ac99sewardj      return NULL;
959024598e40c84666cc311a42c256bbf880db3ac99sewardj
960024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(seg->addr == (Addr)p_old);
961024598e40c84666cc311a42c256bbf880db3ac99sewardj
962024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (new_size <= seg->szB) {
963024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* new size is smaller: allocate, copy from old to new */
964024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
965024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(memcpy)((void*)p_new, p_old, new_size);
966024598e40c84666cc311a42c256bbf880db3ac99sewardj
967024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Notification: copy retained part */
968024598e40c84666cc311a42c256bbf880db3ac99sewardj      copy_mem       ( (Addr)p_old, p_new, new_size );
969024598e40c84666cc311a42c256bbf880db3ac99sewardj
970024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Free old memory */
971024598e40c84666cc311a42c256bbf880db3ac99sewardj      die_and_free_mem_heap( tid, seg );
972024598e40c84666cc311a42c256bbf880db3ac99sewardj
973024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* This has to be after die_and_free_mem_heap, otherwise the
974024598e40c84666cc311a42c256bbf880db3ac99sewardj         former succeeds in shorting out the new block, not the
975024598e40c84666cc311a42c256bbf880db3ac99sewardj         old, in the case when both are on the same list.  */
976024598e40c84666cc311a42c256bbf880db3ac99sewardj      add_new_segment ( tid, p_new, new_size );
977024598e40c84666cc311a42c256bbf880db3ac99sewardj
978024598e40c84666cc311a42c256bbf880db3ac99sewardj      return (void*)p_new;
979024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
980024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* new size is bigger: allocate, copy from old to new */
981024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
982024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(memcpy)((void*)p_new, p_old, seg->szB);
983024598e40c84666cc311a42c256bbf880db3ac99sewardj
984024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Notification: first half kept and copied, second half new */
985024598e40c84666cc311a42c256bbf880db3ac99sewardj      copy_mem       ( (Addr)p_old, p_new, seg->szB );
986024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_unknown( p_new + seg->szB, new_size - seg->szB );
987024598e40c84666cc311a42c256bbf880db3ac99sewardj
988024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Free old memory */
989024598e40c84666cc311a42c256bbf880db3ac99sewardj      die_and_free_mem_heap( tid, seg );
990024598e40c84666cc311a42c256bbf880db3ac99sewardj
991024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* This has to be after die_and_free_mem_heap, otherwise the
992024598e40c84666cc311a42c256bbf880db3ac99sewardj         former succeeds in shorting out the new block, not the old,
993024598e40c84666cc311a42c256bbf880db3ac99sewardj         in the case when both are on the same list.  NB jrs
994024598e40c84666cc311a42c256bbf880db3ac99sewardj         2008-Sept-11: not sure if this comment is valid/correct any
995024598e40c84666cc311a42c256bbf880db3ac99sewardj         more -- I suspect not. */
996024598e40c84666cc311a42c256bbf880db3ac99sewardj      add_new_segment ( tid, p_new, new_size );
997024598e40c84666cc311a42c256bbf880db3ac99sewardj
998024598e40c84666cc311a42c256bbf880db3ac99sewardj      return (void*)p_new;
999024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1000024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1001024598e40c84666cc311a42c256bbf880db3ac99sewardj
10028b140dee891a850c09d27f316df913acc7d7bae7njnSizeT h_replace_malloc_usable_size ( ThreadId tid, void* p )
10038b140dee891a850c09d27f316df913acc7d7bae7njn{
10048b140dee891a850c09d27f316df913acc7d7bae7njn   Seg* seg = find_Seg_by_addr( (Addr)p );
10058b140dee891a850c09d27f316df913acc7d7bae7njn
10068b140dee891a850c09d27f316df913acc7d7bae7njn   // There may be slop, but pretend there isn't because only the asked-for
10078b140dee891a850c09d27f316df913acc7d7bae7njn   // area will have been shadowed properly.
10088b140dee891a850c09d27f316df913acc7d7bae7njn   return ( seg ? seg->szB : 0 );
10098b140dee891a850c09d27f316df913acc7d7bae7njn}
10108b140dee891a850c09d27f316df913acc7d7bae7njn
1011024598e40c84666cc311a42c256bbf880db3ac99sewardj
1012024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1013024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Memory events                                        ---*/
1014024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1015024598e40c84666cc311a42c256bbf880db3ac99sewardj
1016024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
1017024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid set_mem ( Addr a, SizeT len, Seg* seg )
1018024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1019024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr end;
1020024598e40c84666cc311a42c256bbf880db3ac99sewardj
1021024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0 == len)
1022024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
1023024598e40c84666cc311a42c256bbf880db3ac99sewardj
1024024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (len > 100 * 1000 * 1000)
1025024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg,
1026024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "Warning: set address range state: large range %lu", len);
1027024598e40c84666cc311a42c256bbf880db3ac99sewardj
1028024598e40c84666cc311a42c256bbf880db3ac99sewardj   a   = VG_ROUNDDN(a,       sizeof(UWord));
1029024598e40c84666cc311a42c256bbf880db3ac99sewardj   end = VG_ROUNDUP(a + len, sizeof(UWord));
1030024598e40c84666cc311a42c256bbf880db3ac99sewardj   for ( ; a < end; a += sizeof(UWord))
1031024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg(a, seg);
1032024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1033024598e40c84666cc311a42c256bbf880db3ac99sewardj
1034024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void set_mem_unknown( Addr a, SizeT len )
1035024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1036024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem( a, len, UNKNOWN );
1037024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1038024598e40c84666cc311a42c256bbf880db3ac99sewardj
1039024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void set_mem_nonptr( Addr a, UInt len )
1040024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1041024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem( a, len, NONPTR );
1042024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1043024598e40c84666cc311a42c256bbf880db3ac99sewardj
1044024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_new_mem_startup( Addr a, SizeT len,
1045024598e40c84666cc311a42c256bbf880db3ac99sewardj                        Bool rr, Bool ww, Bool xx, ULong di_handle )
1046024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1047024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("new_mem_startup(%#lx,%lu)\n", a, len);
1048024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( a, len );
1049024598e40c84666cc311a42c256bbf880db3ac99sewardj   //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1050024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1051024598e40c84666cc311a42c256bbf880db3ac99sewardj
1052024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // XXX: Currently not doing anything with brk() -- new segments, or not?
1053024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // Proper way to do it would be to grow/shrink a single, special brk segment.
1054024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
1055024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // brk is difficult: it defines a single segment, of changeable size.
1056024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // It starts off with size zero, at the address given by brk(0).  There are
1057024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // no pointers within the program to it.  Any subsequent calls by the
1058024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // program to brk() (possibly growing or shrinking it) return pointers to
1059024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // the *end* of the segment (nb: this is the kernel brk(), which is
1060024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // different to the libc brk()).
1061024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
1062024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // If fixing this, don't forget to update the brk case in SK_(post_syscall).
1063024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
1064024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // Nb: not sure if the return value is the last byte addressible, or one
1065024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // past the end of the segment.
1066024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
1067024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void new_mem_brk( Addr a, UInt len )
1068024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1069024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem_unknown(a, len);
1070024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    //VG_(skin_panic)("can't handle new_mem_brk");
1071024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1072024598e40c84666cc311a42c256bbf880db3ac99sewardj
1073024598e40c84666cc311a42c256bbf880db3ac99sewardj// Not quite right:  if you mmap a segment into a specified place, it could
1074024598e40c84666cc311a42c256bbf880db3ac99sewardj// be legitimate to do certain arithmetic with the pointer that it wouldn't
1075024598e40c84666cc311a42c256bbf880db3ac99sewardj// otherwise.  Hopefully this is rare, though.
1076024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_new_mem_mmap( Addr a, SizeT len,
1077024598e40c84666cc311a42c256bbf880db3ac99sewardj                     Bool rr, Bool ww, Bool xx, ULong di_handle )
1078024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1079024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("new_mem_mmap(%#lx,%lu)\n", a, len);
1080024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #if 0
1081024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    Seg seg = NULL;
1082024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1083024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    // Check for overlapping segments
1084024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #if 0
1085024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___a   = a;    // 'free' variable
1086024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___len = len;  // 'free' variable
1087024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    seg = (Seg)VG_(HT_first_match) ( mlist, is_overlapping_seg );
1088024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___a   = 0;    // paranoia, reset
1089024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___len = 0;    // paranoia, reset
1090024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #endif
1091024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1092024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    // XXX: do this check properly with ISLists
1093024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1094024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if ( ISList__findI( seglist, a, &seg )) {
1095024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       sk_assert(SegMmap == seg->status || SegMmapFree == seg->status);
1096024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (SegMmap == seg->status)
1097024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1098024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    }
1099024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1100024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (NULL != seg) {
1101024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       // Right, we found an overlap
1102024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (VG_(clo_verbosity) > 1)
1103024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          VG_(message)(Vg_UserMsg, "mmap overlap:  old: %#lx, %d;  new: %#lx, %d",
1104024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz                                   seg->left, Seg__size(seg), a, len);
1105024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (seg->left <= a && a <= seg->right) {
1106024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // New one truncates end of the old one.  Nb: we don't adjust its
1107024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // size, because the first segment's pointer can be (and for
1108024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // Konqueror, is) legitimately used to access parts of the second
1109024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // segment.  At least, I assume Konqueror is doing something legal.
1110024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // so that a size mismatch upon munmap isn't a problem.
1111024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //         seg->size = a - seg->data;
1112024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //         seg->is_truncated_map = True;
1113024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //         if (VG_(clo_verbosity) > 1)
1114024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //            VG_(message)(Vg_UserMsg, "old seg truncated to length %d",
1115024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //                                     seg->size);
1116024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       } else {
1117024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          VG_(skin_panic)("Can't handle this mmap() overlap case");
1118024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       }
1119024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    }
1120024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( a, len );
1121024598e40c84666cc311a42c256bbf880db3ac99sewardj   //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1122024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #endif
1123024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1124024598e40c84666cc311a42c256bbf880db3ac99sewardj
1125024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void copy_mem( Addr from, Addr to, SizeT len )
1126024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1127024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr fromend = from + len;
1128024598e40c84666cc311a42c256bbf880db3ac99sewardj
1129024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Must be aligned due to malloc always returning aligned objects.
1130024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(VG_IS_8_ALIGNED(from) && VG_IS_8_ALIGNED(to));
1131024598e40c84666cc311a42c256bbf880db3ac99sewardj
1132024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Must only be called with positive len.
1133024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0 == len)
1134024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
1135024598e40c84666cc311a42c256bbf880db3ac99sewardj
1136024598e40c84666cc311a42c256bbf880db3ac99sewardj   for ( ; from < fromend; from += sizeof(UWord), to += sizeof(UWord))
1137024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( to, get_mem_vseg(from) );
1138024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1139024598e40c84666cc311a42c256bbf880db3ac99sewardj
1140024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // Similar to SK_(realloc)()
1141024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void copy_mem_remap( Addr from, Addr to, UInt len )
1142024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1143024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    VG_(skin_panic)("argh: copy_mem_remap");
1144024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1145024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1146024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void die_mem_brk( Addr a, UInt len )
1147024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1148024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem_unknown(a, len);
1149024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //   VG_(skin_panic)("can't handle die_mem_brk()");
1150024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1151024598e40c84666cc311a42c256bbf880db3ac99sewardj
1152024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_die_mem_munmap( Addr a, SizeT len )
1153024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1154024598e40c84666cc311a42c256bbf880db3ac99sewardj//   handle_free_munmap( (void*)a, len );
1155024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1156024598e40c84666cc311a42c256bbf880db3ac99sewardj
1157024598e40c84666cc311a42c256bbf880db3ac99sewardj// Don't need to check all addresses within the block; in the absence of
1158024598e40c84666cc311a42c256bbf880db3ac99sewardj// discontiguous segments, the segments for the first and last bytes should
1159024598e40c84666cc311a42c256bbf880db3ac99sewardj// be the same.  Can't easily check the pointer segment matches the block
1160024598e40c84666cc311a42c256bbf880db3ac99sewardj// segment, unfortunately, but the first/last check should catch most
1161024598e40c84666cc311a42c256bbf880db3ac99sewardj// errors.
1162024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void pre_mem_access2 ( CorePart part, ThreadId tid, Char* str,
1163024598e40c84666cc311a42c256bbf880db3ac99sewardj                              Addr s/*tart*/, Addr e/*nd*/ )
1164024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1165024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg  *seglo, *seghi;
1166024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool s_in_seglo, s_in_seghi, e_in_seglo, e_in_seghi;
1167024598e40c84666cc311a42c256bbf880db3ac99sewardj
1168024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Don't check code being translated -- very slow, and not much point
1169024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (Vg_CoreTranslate == part) return;
1170024598e40c84666cc311a42c256bbf880db3ac99sewardj
1171024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Don't check the signal case -- only happens in core, no need to check
1172024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (Vg_CoreSignal == part) return;
1173024598e40c84666cc311a42c256bbf880db3ac99sewardj
1174024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Only expect syscalls after this point
1175024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (part != Vg_CoreSysCall) {
1176024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("part = %d\n", part);
1177024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("unknown corepart in pre_mem_access2");
1178024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1179024598e40c84666cc311a42c256bbf880db3ac99sewardj
1180024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Check first and last bytes match
11819520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   seglo = get_Seg_containing_addr( s );
11829520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   seghi = get_Seg_containing_addr( e );
1183024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert( BOTTOM != seglo && NONPTR != seglo );
1184024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert( BOTTOM != seghi && NONPTR != seghi );
1185024598e40c84666cc311a42c256bbf880db3ac99sewardj
1186024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* so seglo and seghi are either UNKNOWN or P(..) */
1187024598e40c84666cc311a42c256bbf880db3ac99sewardj   s_in_seglo
1188024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seglo)
1189024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seglo->addr <= s && s < seglo->addr + seglo->szB;
1190024598e40c84666cc311a42c256bbf880db3ac99sewardj   s_in_seghi
1191024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seghi)
1192024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seghi->addr <= s && s < seghi->addr + seghi->szB;
1193024598e40c84666cc311a42c256bbf880db3ac99sewardj   e_in_seglo
1194024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seglo)
1195024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seglo->addr <= e && e < seglo->addr + seglo->szB;
1196024598e40c84666cc311a42c256bbf880db3ac99sewardj   e_in_seghi
1197024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seghi)
1198024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seghi->addr <= e && e < seghi->addr + seghi->szB;
1199024598e40c84666cc311a42c256bbf880db3ac99sewardj
1200024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if start and end are in different, but known
1201024598e40c84666cc311a42c256bbf880db3ac99sewardj      segments */
1202024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seglo) && is_known_segment(seghi)
1203024598e40c84666cc311a42c256bbf880db3ac99sewardj       && seglo != seghi) {
1204024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, seglo, seghi);
1205024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1206024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
1207024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if start is in a known segment but end isn't */
1208024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seglo) && !is_known_segment(seghi)) {
1209024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
1210024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1211024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
1212024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if end is in a known segment but start isn't */
1213024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!is_known_segment(seglo) && is_known_segment(seghi)) {
1214024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, UNKNOWN, seghi);
1215024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1216024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1217024598e40c84666cc311a42c256bbf880db3ac99sewardj
1218024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
1219024598e40c84666cc311a42c256bbf880db3ac99sewardj                        Addr base, SizeT size )
1220024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1221024598e40c84666cc311a42c256bbf880db3ac99sewardj   pre_mem_access2( part, tid, s, base, base + size - 1 );
1222024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1223024598e40c84666cc311a42c256bbf880db3ac99sewardj
1224024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
1225024598e40c84666cc311a42c256bbf880db3ac99sewardj                             Char* s, Addr lo )
1226024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1227024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr hi = lo;
1228024598e40c84666cc311a42c256bbf880db3ac99sewardj
1229024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Nb: the '\0' must be included in the lo...hi range
1230024598e40c84666cc311a42c256bbf880db3ac99sewardj   while ('\0' != *(Char*)hi) hi++;
1231024598e40c84666cc311a42c256bbf880db3ac99sewardj   pre_mem_access2( part, tid, s, lo, hi );
1232024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1233024598e40c84666cc311a42c256bbf880db3ac99sewardj
1234024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_mem_write(Addr a, UInt len)
1235024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1236024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem_unknown(a, len);
1237024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1238024598e40c84666cc311a42c256bbf880db3ac99sewardj
1239024598e40c84666cc311a42c256bbf880db3ac99sewardj
1240024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1241024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Register event handlers                              ---*/
1242024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1243024598e40c84666cc311a42c256bbf880db3ac99sewardj
1244024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_regs_write_init ( void )
1245024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1246024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    UInt i;
1247024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    for (i = R_EAX; i <= R_EDI; i++)
1248024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       VG_(set_shadow_archreg)( i, (UInt)UNKNOWN );
1249024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1250024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    // Don't bother about eflags
1251024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1252024598e40c84666cc311a42c256bbf880db3ac99sewardj
1253024598e40c84666cc311a42c256bbf880db3ac99sewardj// BEGIN move this uglyness to pc_machine.c
1254024598e40c84666cc311a42c256bbf880db3ac99sewardj
1255024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_big_endian ( void ) {
1256024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt x = 0x11223344;
1257024598e40c84666cc311a42c256bbf880db3ac99sewardj   return 0x1122 == *(UShort*)(&x);
1258024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1259024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_little_endian ( void ) {
1260024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt x = 0x11223344;
1261024598e40c84666cc311a42c256bbf880db3ac99sewardj   return 0x3344 == *(UShort*)(&x);
1262024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1263024598e40c84666cc311a42c256bbf880db3ac99sewardj
1264024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_INTREGINFO_OFFSETS 4
1265024598e40c84666cc311a42c256bbf880db3ac99sewardj
1266024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Holds the result of a query to 'get_IntRegInfo'.  Valid values for
1267024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_offsets are:
1268024598e40c84666cc311a42c256bbf880db3ac99sewardj
1269024598e40c84666cc311a42c256bbf880db3ac99sewardj   -1: means the queried guest state slice exactly matches
1270024598e40c84666cc311a42c256bbf880db3ac99sewardj       one integer register
1271024598e40c84666cc311a42c256bbf880db3ac99sewardj
1272024598e40c84666cc311a42c256bbf880db3ac99sewardj   0: means the queried guest state slice does not overlap any
1273024598e40c84666cc311a42c256bbf880db3ac99sewardj      integer registers
1274024598e40c84666cc311a42c256bbf880db3ac99sewardj
1275024598e40c84666cc311a42c256bbf880db3ac99sewardj   1 .. N_INTREGINFO_OFFSETS: means the queried guest state offset
1276024598e40c84666cc311a42c256bbf880db3ac99sewardj      overlaps n_offsets different integer registers, and their base
1277024598e40c84666cc311a42c256bbf880db3ac99sewardj      offsets are placed in the offsets array.
1278024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
1279024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
1280024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
1281024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int offsets[N_INTREGINFO_OFFSETS];
1282024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int n_offsets;
1283024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1284024598e40c84666cc311a42c256bbf880db3ac99sewardj   IntRegInfo;
1285024598e40c84666cc311a42c256bbf880db3ac99sewardj
1286024598e40c84666cc311a42c256bbf880db3ac99sewardj
1287024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_x86)
1288024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_x86.h"
1289024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestX86State)
1290024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1291024598e40c84666cc311a42c256bbf880db3ac99sewardj
1292024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_amd64)
1293024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_amd64.h"
1294024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestAMD64State)
1295024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_OFF_FS_ZERO offsetof(VexGuestAMD64State,guest_FS_ZERO)
1296024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_SZB_FS_ZERO sizeof( ((VexGuestAMD64State*)0)->guest_FS_ZERO)
1297024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1298024598e40c84666cc311a42c256bbf880db3ac99sewardj
1299024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc32)
1300024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc32.h"
1301024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC32State)
1302024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1303024598e40c84666cc311a42c256bbf880db3ac99sewardj
1304024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc64)
1305024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc64.h"
1306024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State)
1307024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1308024598e40c84666cc311a42c256bbf880db3ac99sewardj
1309024598e40c84666cc311a42c256bbf880db3ac99sewardj
1310024598e40c84666cc311a42c256bbf880db3ac99sewardj/* See description on definition of type IntRegInfo. */
1311024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB )
1312024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1313024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------------- x86 --------------------- */
1314024598e40c84666cc311a42c256bbf880db3ac99sewardj
1315024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86)
1316024598e40c84666cc311a42c256bbf880db3ac99sewardj
1317024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1318024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestX86State,guest_##_fieldname))
1319024598e40c84666cc311a42c256bbf880db3ac99sewardj
1320024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1321024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1322024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1323024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is21 = sz == 2 || sz == 1;
1324024598e40c84666cc311a42c256bbf880db3ac99sewardj
1325024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1326024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_little_endian());
1327024598e40c84666cc311a42c256bbf880db3ac99sewardj
1328024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1329024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1330024598e40c84666cc311a42c256bbf880db3ac99sewardj
1331024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1332024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)     && is4) goto exactly1;
1333024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)     && is4) goto exactly1;
1334024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)     && is4) goto exactly1;
1335024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBX)     && is4) goto exactly1;
1336024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESP)     && is4) goto exactly1;
1337024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBP)     && is4) goto exactly1;
1338024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESI)     && is4) goto exactly1;
1339024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDI)     && is4) goto exactly1;
1340024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EIP)     && is4) goto none;
1341024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_OP)   && is4) goto none;
1342024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP1) && is4) goto none;
1343024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP2) && is4) goto none;
1344024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_NDEP) && is4) goto none;
1345024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(DFLAG)   && is4) goto none;
1346024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(IDFLAG)  && is4) goto none;
1347024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ACFLAG)  && is4) goto none;
1348024598e40c84666cc311a42c256bbf880db3ac99sewardj
1349024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Partial accesses to integer registers */
1350024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)     && is21) {         o -= 0; goto contains_o; }
1351024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1352024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)     && is21) {         o -= 0; goto contains_o; }
1353024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1354024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBX)     && is21) {         o -= 0; goto contains_o; }
1355db44098732d646126c8f9168e4f05e08a4040cafsewardj   if (o == GOF(EBX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1356024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)     && is21) {         o -= 0; goto contains_o; }
1357024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1358024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESI)     && is21) {         o -= 0; goto contains_o; }
1359024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDI)     && is21) {         o -= 0; goto contains_o; }
1360024598e40c84666cc311a42c256bbf880db3ac99sewardj
1361024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Segment related guff */
1362024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GS)  && sz == 2) goto none;
1363024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LDT) && is4) goto none;
1364024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GDT) && is4) goto none;
1365024598e40c84666cc311a42c256bbf880db3ac99sewardj
1366024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1367024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(SSEROUND) && is4) goto none;
1368024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND)  && is4) goto none;
1369024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)   && is4) goto none;
1370024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FTOP)     && is4) goto none;
1371024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPTAG)    && sz == 8) goto none;
1372024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FC3210)   && is4) goto none;
1373024598e40c84666cc311a42c256bbf880db3ac99sewardj
1374024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* xmm registers, including arbitrary sub-parts */
1375024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1376024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1377024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1378024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1379024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1380024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1381024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1382024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1383024598e40c84666cc311a42c256bbf880db3ac99sewardj
1384024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1385024598e40c84666cc311a42c256bbf880db3ac99sewardj      to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1386024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1387024598e40c84666cc311a42c256bbf880db3ac99sewardj
1388024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* the entire mmx/x87 register bank in one big piece */
1389024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPREG) && sz == 64) goto none;
1390024598e40c84666cc311a42c256bbf880db3ac99sewardj
1391024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(x86):failing on (%d,%d)\n", o, sz);
1392024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1393024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1394024598e40c84666cc311a42c256bbf880db3ac99sewardj
1395024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- amd64 -------------------- */
1396024598e40c84666cc311a42c256bbf880db3ac99sewardj
1397024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64)
1398024598e40c84666cc311a42c256bbf880db3ac99sewardj
1399024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1400024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestAMD64State,guest_##_fieldname))
1401024598e40c84666cc311a42c256bbf880db3ac99sewardj
1402024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o     = offset;
1403024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz    = szB;
1404024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is421 = sz == 4 || sz == 2 || sz == 1;
1405024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8   = sz == 8;
1406024598e40c84666cc311a42c256bbf880db3ac99sewardj
1407024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1408024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_little_endian());
1409024598e40c84666cc311a42c256bbf880db3ac99sewardj
1410024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1411024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1412024598e40c84666cc311a42c256bbf880db3ac99sewardj
1413024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1414024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)     && is8) goto exactly1;
1415024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)     && is8) goto exactly1;
1416024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)     && is8) goto exactly1;
1417024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)     && is8) goto exactly1;
1418024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSP)     && is8) goto exactly1;
1419024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBP)     && is8) goto exactly1;
1420024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSI)     && is8) goto exactly1;
1421024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDI)     && is8) goto exactly1;
1422024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R8)      && is8) goto exactly1;
1423024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R9)      && is8) goto exactly1;
1424024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R10)     && is8) goto exactly1;
1425024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R11)     && is8) goto exactly1;
1426024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R12)     && is8) goto exactly1;
1427024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R13)     && is8) goto exactly1;
1428024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R14)     && is8) goto exactly1;
1429024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R15)     && is8) goto exactly1;
1430024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RIP)     && is8) goto exactly1;
1431024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_OP)   && is8) goto none;
1432024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP1) && is8) goto none;
1433024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP2) && is8) goto none;
1434024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_NDEP) && is8) goto none;
1435024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(DFLAG)   && is8) goto none;
1436024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(IDFLAG)  && is8) goto none;
1437024598e40c84666cc311a42c256bbf880db3ac99sewardj
1438024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Partial accesses to integer registers */
1439024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)     && is421) {         o -= 0; goto contains_o; }
1440024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1441024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)     && is421) {         o -= 0; goto contains_o; }
1442024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1443024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)     && is421) {         o -= 0; goto contains_o; }
1444024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1445024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)     && is421) {         o -= 0; goto contains_o; }
1446024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1447024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBP)     && is421) {         o -= 0; goto contains_o; }
1448024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSI)     && is421) {         o -= 0; goto contains_o; }
1449024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDI)     && is421) {         o -= 0; goto contains_o; }
1450024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R8)      && is421) {         o -= 0; goto contains_o; }
1451024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R9)      && is421) {         o -= 0; goto contains_o; }
1452024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R10)     && is421) {         o -= 0; goto contains_o; }
1453024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R11)     && is421) {         o -= 0; goto contains_o; }
1454024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R12)     && is421) {         o -= 0; goto contains_o; }
1455024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R13)     && is421) {         o -= 0; goto contains_o; }
1456024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R14)     && is421) {         o -= 0; goto contains_o; }
1457024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R15)     && is421) {         o -= 0; goto contains_o; }
1458024598e40c84666cc311a42c256bbf880db3ac99sewardj
1459024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Segment related guff */
1460024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FS_ZERO) && is8) goto exactly1;
1461024598e40c84666cc311a42c256bbf880db3ac99sewardj
1462024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1463024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(SSEROUND) && is8) goto none;
1464024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND)  && is8) goto none;
1465024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)   && sz == 4) goto none;
1466024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FTOP)     && sz == 4) goto none;
1467024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPTAG)    && is8) goto none;
1468024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FC3210)   && is8) goto none;
1469024598e40c84666cc311a42c256bbf880db3ac99sewardj
1470024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* xmm registers, including arbitrary sub-parts */
1471024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM0)  && o+sz <= GOF(XMM0)+16)  goto none;
1472024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM1)  && o+sz <= GOF(XMM1)+16)  goto none;
1473024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM2)  && o+sz <= GOF(XMM2)+16)  goto none;
1474024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM3)  && o+sz <= GOF(XMM3)+16)  goto none;
1475024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM4)  && o+sz <= GOF(XMM4)+16)  goto none;
1476024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM5)  && o+sz <= GOF(XMM5)+16)  goto none;
1477024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM6)  && o+sz <= GOF(XMM6)+16)  goto none;
1478024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM7)  && o+sz <= GOF(XMM7)+16)  goto none;
1479024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM8)  && o+sz <= GOF(XMM8)+16)  goto none;
1480024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM9)  && o+sz <= GOF(XMM9)+16)  goto none;
1481024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+16) goto none;
1482024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+16) goto none;
1483024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+16) goto none;
1484024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+16) goto none;
1485024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+16) goto none;
1486024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+16) goto none;
1487024598e40c84666cc311a42c256bbf880db3ac99sewardj
1488024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1489024598e40c84666cc311a42c256bbf880db3ac99sewardj      to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1490024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1491024598e40c84666cc311a42c256bbf880db3ac99sewardj
1492024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(amd64):failing on (%d,%d)\n", o, sz);
1493024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1494024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1495024598e40c84666cc311a42c256bbf880db3ac99sewardj
1496024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc32 -------------------- */
1497024598e40c84666cc311a42c256bbf880db3ac99sewardj
1498024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc32)
1499024598e40c84666cc311a42c256bbf880db3ac99sewardj
1500024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1501024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestPPC32State,guest_##_fieldname))
1502024598e40c84666cc311a42c256bbf880db3ac99sewardj
1503024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1504024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1505024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1506024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8  = sz == 8;
1507024598e40c84666cc311a42c256bbf880db3ac99sewardj
1508024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1509024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_big_endian());
1510024598e40c84666cc311a42c256bbf880db3ac99sewardj
1511024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1512024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1513024598e40c84666cc311a42c256bbf880db3ac99sewardj
1514024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1515024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR0)  && is4) goto exactly1;
1516024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR1)  && is4) goto exactly1;
1517024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR2)  && is4) goto exactly1;
1518024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR3)  && is4) goto exactly1;
1519024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR4)  && is4) goto exactly1;
1520024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR5)  && is4) goto exactly1;
1521024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR6)  && is4) goto exactly1;
1522024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR7)  && is4) goto exactly1;
1523024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR8)  && is4) goto exactly1;
1524024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR9)  && is4) goto exactly1;
1525024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR10) && is4) goto exactly1;
1526024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR11) && is4) goto exactly1;
1527024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR12) && is4) goto exactly1;
1528024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR13) && is4) goto exactly1;
1529024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR14) && is4) goto exactly1;
1530024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR15) && is4) goto exactly1;
1531024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR16) && is4) goto exactly1;
1532024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR17) && is4) goto exactly1;
1533024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR18) && is4) goto exactly1;
1534024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR19) && is4) goto exactly1;
1535024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR20) && is4) goto exactly1;
1536024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR21) && is4) goto exactly1;
1537024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR22) && is4) goto exactly1;
1538024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR23) && is4) goto exactly1;
1539024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR24) && is4) goto exactly1;
1540024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR25) && is4) goto exactly1;
1541024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR26) && is4) goto exactly1;
1542024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR27) && is4) goto exactly1;
1543024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR28) && is4) goto exactly1;
1544024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR29) && is4) goto exactly1;
1545024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR30) && is4) goto exactly1;
1546024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR31) && is4) goto exactly1;
1547024598e40c84666cc311a42c256bbf880db3ac99sewardj
1548024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Misc integer reg and condition code accesses */
1549024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LR)        && is4) goto exactly1;
1550024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CTR)       && is4) goto exactly1;
1551024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA)       && is4) goto none;
1552024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA_AT_SC) && is4) goto none;
1553024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RESVN)     && is4) goto none;
1554024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TISTART)   && is4) goto none;
1555024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TILEN)     && is4) goto none;
1556024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(REDIR_SP)  && is4) goto none;
1557024598e40c84666cc311a42c256bbf880db3ac99sewardj
1558024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sz == 1) {
1559024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_SO))  goto none;
1560024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_OV))  goto none;
1561024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_CA))  goto none;
1562024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_BC))  goto none;
1563024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_321)) goto none;
1564024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_0))   goto none;
1565024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_321)) goto none;
1566024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_0))   goto none;
1567024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_321)) goto none;
1568024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_0))   goto none;
1569024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_321)) goto none;
1570024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_0))   goto none;
1571024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_321)) goto none;
1572024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_0))   goto none;
1573024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_321)) goto none;
1574024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_0))   goto none;
1575024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_321)) goto none;
1576024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_0))   goto none;
1577024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_321)) goto none;
1578024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_0))   goto none;
1579024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1580024598e40c84666cc311a42c256bbf880db3ac99sewardj
1581024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to FP registers */
1582024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR0)  && is8) goto none;
1583024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR1)  && is8) goto none;
1584024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR2)  && is8) goto none;
1585024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR3)  && is8) goto none;
1586024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR4)  && is8) goto none;
1587024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR5)  && is8) goto none;
1588024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR6)  && is8) goto none;
1589024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR7)  && is8) goto none;
1590024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR8)  && is8) goto none;
1591024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR9)  && is8) goto none;
1592024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR10) && is8) goto none;
1593024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR11) && is8) goto none;
1594024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR12) && is8) goto none;
1595024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR13) && is8) goto none;
1596024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR14) && is8) goto none;
1597024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR15) && is8) goto none;
1598024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR16) && is8) goto none;
1599024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR17) && is8) goto none;
1600024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR18) && is8) goto none;
1601024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR19) && is8) goto none;
1602024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR20) && is8) goto none;
1603024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR21) && is8) goto none;
1604024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR22) && is8) goto none;
1605024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR23) && is8) goto none;
1606024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR24) && is8) goto none;
1607024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR25) && is8) goto none;
1608024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR26) && is8) goto none;
1609024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR27) && is8) goto none;
1610024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR28) && is8) goto none;
1611024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR29) && is8) goto none;
1612024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR30) && is8) goto none;
1613024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR31) && is8) goto none;
1614024598e40c84666cc311a42c256bbf880db3ac99sewardj
1615024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1616024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND) && is4) goto none;
1617024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)  && is4) goto none;
1618024598e40c84666cc311a42c256bbf880db3ac99sewardj
1619024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Altivec registers */
1620024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR0)  && sz == 16) goto none;
1621024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR1)  && sz == 16) goto none;
1622024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR2)  && sz == 16) goto none;
1623024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR3)  && sz == 16) goto none;
1624024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR4)  && sz == 16) goto none;
1625024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR5)  && sz == 16) goto none;
1626024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR6)  && sz == 16) goto none;
1627024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR7)  && sz == 16) goto none;
1628024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR8)  && sz == 16) goto none;
1629024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR9)  && sz == 16) goto none;
1630024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR10) && sz == 16) goto none;
1631024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR11) && sz == 16) goto none;
1632024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR12) && sz == 16) goto none;
1633024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR13) && sz == 16) goto none;
1634024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR14) && sz == 16) goto none;
1635024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR15) && sz == 16) goto none;
1636024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR16) && sz == 16) goto none;
1637024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR17) && sz == 16) goto none;
1638024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR18) && sz == 16) goto none;
1639024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR19) && sz == 16) goto none;
1640024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR20) && sz == 16) goto none;
1641024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR21) && sz == 16) goto none;
1642024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR22) && sz == 16) goto none;
1643024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR23) && sz == 16) goto none;
1644024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR24) && sz == 16) goto none;
1645024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR25) && sz == 16) goto none;
1646024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR26) && sz == 16) goto none;
1647024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR27) && sz == 16) goto none;
1648024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR28) && sz == 16) goto none;
1649024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR29) && sz == 16) goto none;
1650024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR30) && sz == 16) goto none;
1651024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR31) && sz == 16) goto none;
1652024598e40c84666cc311a42c256bbf880db3ac99sewardj
1653aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   /* Altivec admin related */
1654aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   if (o == GOF(VRSAVE) && is4) goto none;
1655aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj
1656024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(ppc32):failing on (%d,%d)\n", o, sz);
1657024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1658024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1659024598e40c84666cc311a42c256bbf880db3ac99sewardj
1660024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc64 -------------------- */
1661024598e40c84666cc311a42c256bbf880db3ac99sewardj
1662024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc64)
1663024598e40c84666cc311a42c256bbf880db3ac99sewardj
1664024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1665024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestPPC64State,guest_##_fieldname))
1666024598e40c84666cc311a42c256bbf880db3ac99sewardj
1667024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1668024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1669024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1670024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8  = sz == 8;
1671024598e40c84666cc311a42c256bbf880db3ac99sewardj
1672024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1673024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_big_endian());
1674024598e40c84666cc311a42c256bbf880db3ac99sewardj
1675024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1676024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1677024598e40c84666cc311a42c256bbf880db3ac99sewardj
1678024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1679024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR0)  && is8) goto exactly1;
1680024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR1)  && is8) goto exactly1;
1681024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR2)  && is8) goto exactly1;
1682024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR3)  && is8) goto exactly1;
1683024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR4)  && is8) goto exactly1;
1684024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR5)  && is8) goto exactly1;
1685024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR6)  && is8) goto exactly1;
1686024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR7)  && is8) goto exactly1;
1687024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR8)  && is8) goto exactly1;
1688024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR9)  && is8) goto exactly1;
1689024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR10) && is8) goto exactly1;
1690024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR11) && is8) goto exactly1;
1691024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR12) && is8) goto exactly1;
1692024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR13) && is8) goto exactly1;
1693024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR14) && is8) goto exactly1;
1694024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR15) && is8) goto exactly1;
1695024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR16) && is8) goto exactly1;
1696024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR17) && is8) goto exactly1;
1697024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR18) && is8) goto exactly1;
1698024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR19) && is8) goto exactly1;
1699024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR20) && is8) goto exactly1;
1700024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR21) && is8) goto exactly1;
1701024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR22) && is8) goto exactly1;
1702024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR23) && is8) goto exactly1;
1703024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR24) && is8) goto exactly1;
1704024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR25) && is8) goto exactly1;
1705024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR26) && is8) goto exactly1;
1706024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR27) && is8) goto exactly1;
1707024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR28) && is8) goto exactly1;
1708024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR29) && is8) goto exactly1;
1709024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR30) && is8) goto exactly1;
1710024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR31) && is8) goto exactly1;
1711024598e40c84666cc311a42c256bbf880db3ac99sewardj
1712024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Misc integer reg and condition code accesses */
1713024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LR)        && is8) goto exactly1;
1714024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CTR)       && is8) goto exactly1;
1715024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA)       && is8) goto none;
1716024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA_AT_SC) && is8) goto none;
1717024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RESVN)     && is8) goto none;
1718024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TISTART)   && is8) goto none;
1719024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TILEN)     && is8) goto none;
1720024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(REDIR_SP)  && is8) goto none;
1721024598e40c84666cc311a42c256bbf880db3ac99sewardj
1722024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sz == 1) {
1723024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_SO))  goto none;
1724024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_OV))  goto none;
1725024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_CA))  goto none;
1726024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_BC))  goto none;
1727024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_321)) goto none;
1728024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_0))   goto none;
1729024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_321)) goto none;
1730024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_0))   goto none;
1731024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_321)) goto none;
1732024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_0))   goto none;
1733024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_321)) goto none;
1734024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_0))   goto none;
1735024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_321)) goto none;
1736024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_0))   goto none;
1737024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_321)) goto none;
1738024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_0))   goto none;
1739024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_321)) goto none;
1740024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_0))   goto none;
1741024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_321)) goto none;
1742024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_0))   goto none;
1743024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1744024598e40c84666cc311a42c256bbf880db3ac99sewardj
1745024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to FP registers */
1746024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR0)  && is8) goto none;
1747024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR1)  && is8) goto none;
1748024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR2)  && is8) goto none;
1749024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR3)  && is8) goto none;
1750024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR4)  && is8) goto none;
1751024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR5)  && is8) goto none;
1752024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR6)  && is8) goto none;
1753024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR7)  && is8) goto none;
1754024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR8)  && is8) goto none;
1755024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR9)  && is8) goto none;
1756024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR10) && is8) goto none;
1757024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR11) && is8) goto none;
1758024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR12) && is8) goto none;
1759024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR13) && is8) goto none;
1760024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR14) && is8) goto none;
1761024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR15) && is8) goto none;
1762024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR16) && is8) goto none;
1763024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR17) && is8) goto none;
1764024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR18) && is8) goto none;
1765024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR19) && is8) goto none;
1766024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR20) && is8) goto none;
1767024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR21) && is8) goto none;
1768024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR22) && is8) goto none;
1769024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR23) && is8) goto none;
1770024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR24) && is8) goto none;
1771024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR25) && is8) goto none;
1772024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR26) && is8) goto none;
1773024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR27) && is8) goto none;
1774024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR28) && is8) goto none;
1775024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR29) && is8) goto none;
1776024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR30) && is8) goto none;
1777024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR31) && is8) goto none;
1778024598e40c84666cc311a42c256bbf880db3ac99sewardj
1779024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1780024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND) && is4) goto none;
1781024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)  && is4) goto none;
1782024598e40c84666cc311a42c256bbf880db3ac99sewardj
1783024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Altivec registers */
1784024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR0)  && sz == 16) goto none;
1785024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR1)  && sz == 16) goto none;
1786024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR2)  && sz == 16) goto none;
1787024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR3)  && sz == 16) goto none;
1788024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR4)  && sz == 16) goto none;
1789024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR5)  && sz == 16) goto none;
1790024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR6)  && sz == 16) goto none;
1791024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR7)  && sz == 16) goto none;
1792024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR8)  && sz == 16) goto none;
1793024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR9)  && sz == 16) goto none;
1794024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR10) && sz == 16) goto none;
1795024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR11) && sz == 16) goto none;
1796024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR12) && sz == 16) goto none;
1797024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR13) && sz == 16) goto none;
1798024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR14) && sz == 16) goto none;
1799024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR15) && sz == 16) goto none;
1800024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR16) && sz == 16) goto none;
1801024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR17) && sz == 16) goto none;
1802024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR18) && sz == 16) goto none;
1803024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR19) && sz == 16) goto none;
1804024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR20) && sz == 16) goto none;
1805024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR21) && sz == 16) goto none;
1806024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR22) && sz == 16) goto none;
1807024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR23) && sz == 16) goto none;
1808024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR24) && sz == 16) goto none;
1809024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR25) && sz == 16) goto none;
1810024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR26) && sz == 16) goto none;
1811024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR27) && sz == 16) goto none;
1812024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR28) && sz == 16) goto none;
1813024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR29) && sz == 16) goto none;
1814024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR30) && sz == 16) goto none;
1815024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR31) && sz == 16) goto none;
1816024598e40c84666cc311a42c256bbf880db3ac99sewardj
1817aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   /* Altivec admin related */
1818aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   if (o == GOF(VRSAVE) && is4) goto none;
1819aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj
1820024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(ppc64):failing on (%d,%d)\n", o, sz);
1821024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1822024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1823024598e40c84666cc311a42c256bbf880db3ac99sewardj
1824024598e40c84666cc311a42c256bbf880db3ac99sewardj
1825024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
1826024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "FIXME: not implemented for this architecture"
1827024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
1828024598e40c84666cc311a42c256bbf880db3ac99sewardj
1829024598e40c84666cc311a42c256bbf880db3ac99sewardj  exactly1:
1830024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = -1;
1831024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1832024598e40c84666cc311a42c256bbf880db3ac99sewardj  none:
1833024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = 0;
1834024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1835024598e40c84666cc311a42c256bbf880db3ac99sewardj  contains_o:
1836024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(o >= 0 && 0 == (o % sizeof(UWord)));
1837024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = 1;
1838024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->offsets[0] = o;
1839024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1840024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1841024598e40c84666cc311a42c256bbf880db3ac99sewardj
1842024598e40c84666cc311a42c256bbf880db3ac99sewardj
1843024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Does 'arr' describe an indexed guest state section containing host
1844024598e40c84666cc311a42c256bbf880db3ac99sewardj   words, that we want to shadow? */
1845024598e40c84666cc311a42c256bbf880db3ac99sewardj
1846024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg_array ( IRRegArray* arr )
1847024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1848024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------------- x86 --------------------- */
1849024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86)
1850024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 tag array. */
1851024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestX86State,guest_FPTAG[0])
1852024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I8 && arr->nElems == 8)
1853024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1854024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 register array. */
1855024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestX86State,guest_FPREG[0])
1856024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_F64 && arr->nElems == 8)
1857024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1858024598e40c84666cc311a42c256bbf880db3ac99sewardj
1859024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(x86): unhandled: ");
1860024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1861024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1862024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1863024598e40c84666cc311a42c256bbf880db3ac99sewardj
1864024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- amd64 -------------------- */
1865024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64)
1866024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 tag array. */
1867024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestAMD64State,guest_FPTAG[0])
1868024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I8 && arr->nElems == 8)
1869024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1870024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 register array. */
1871024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestAMD64State,guest_FPREG[0])
1872024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_F64 && arr->nElems == 8)
1873024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1874024598e40c84666cc311a42c256bbf880db3ac99sewardj
1875024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(amd64): unhandled: ");
1876024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1877024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1878024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1879024598e40c84666cc311a42c256bbf880db3ac99sewardj
1880024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc32 -------------------- */
1881024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc32)
1882024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The redir stack. */
1883024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestPPC32State,guest_REDIR_STACK[0])
1884024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I32
1885024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->nElems == VEX_GUEST_PPC32_REDIR_STACK_SIZE)
1886024598e40c84666cc311a42c256bbf880db3ac99sewardj      return True;
1887024598e40c84666cc311a42c256bbf880db3ac99sewardj
1888024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(ppc32): unhandled: ");
1889024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1890024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1891024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1892024598e40c84666cc311a42c256bbf880db3ac99sewardj
1893024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc64 -------------------- */
1894024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc64)
1895024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The redir stack. */
1896024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestPPC64State,guest_REDIR_STACK[0])
1897024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I64
1898024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->nElems == VEX_GUEST_PPC64_REDIR_STACK_SIZE)
1899024598e40c84666cc311a42c256bbf880db3ac99sewardj      return True;
1900024598e40c84666cc311a42c256bbf880db3ac99sewardj
1901024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(ppc64): unhandled: ");
1902024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1903024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1904024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1905024598e40c84666cc311a42c256bbf880db3ac99sewardj
1906024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
1907024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "FIXME: not implemented for this architecture"
1908024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
1909024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1910024598e40c84666cc311a42c256bbf880db3ac99sewardj
1911024598e40c84666cc311a42c256bbf880db3ac99sewardj
1912024598e40c84666cc311a42c256bbf880db3ac99sewardj// END move this uglyness to pc_machine.c
1913024598e40c84666cc311a42c256bbf880db3ac99sewardj
1914024598e40c84666cc311a42c256bbf880db3ac99sewardj/* returns True iff given slice exactly matches an int reg.  Merely
1915024598e40c84666cc311a42c256bbf880db3ac99sewardj   a convenience wrapper around get_IntRegInfo. */
1916024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg ( Int offset, Int szB )
1917024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1918024598e40c84666cc311a42c256bbf880db3ac99sewardj   IntRegInfo iii;
1919024598e40c84666cc311a42c256bbf880db3ac99sewardj   get_IntRegInfo( &iii, offset, szB );
1920024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(iii.n_offsets >= -1 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
1921024598e40c84666cc311a42c256bbf880db3ac99sewardj   return iii.n_offsets == -1;
1922024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1923024598e40c84666cc311a42c256bbf880db3ac99sewardj
1924024598e40c84666cc311a42c256bbf880db3ac99sewardj/* these assume guest and host have the same endianness and
1925024598e40c84666cc311a42c256bbf880db3ac99sewardj   word size (probably). */
1926024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UWord get_guest_intreg ( ThreadId tid, Int shadowNo,
1927c4431bfe04c7490ea2d74939d222d87f13f30960njn                                PtrdiffT offset, SizeT size )
1928024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1929024598e40c84666cc311a42c256bbf880db3ac99sewardj   UChar tmp[ 2 + sizeof(UWord) ];
1930024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(size == sizeof(UWord));
1931024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (offset % sizeof(UWord)));
1932024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)(tmp, 0, sizeof(tmp));
1933024598e40c84666cc311a42c256bbf880db3ac99sewardj   tmp[0] = 0x31;
1934024598e40c84666cc311a42c256bbf880db3ac99sewardj   tmp[ sizeof(tmp)-1 ] = 0x27;
1935024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(get_shadow_regs_area)(tid, &tmp[1], shadowNo, offset, size);
1936024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tmp[0] == 0x31);
1937024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tmp[ sizeof(tmp)-1 ] == 0x27);
1938024598e40c84666cc311a42c256bbf880db3ac99sewardj   return * ((UWord*) &tmp[1] ); /* MISALIGNED LOAD */
1939024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1940024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void put_guest_intreg ( ThreadId tid, Int shadowNo,
1941c4431bfe04c7490ea2d74939d222d87f13f30960njn                               PtrdiffT offset, SizeT size, UWord w )
1942024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1943024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(size == sizeof(UWord));
1944024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (offset % sizeof(UWord)));
1945024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(set_shadow_regs_area)(tid, shadowNo, offset, size,
1946024598e40c84666cc311a42c256bbf880db3ac99sewardj                             (const UChar*)&w);
1947024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1948024598e40c84666cc311a42c256bbf880db3ac99sewardj
1949024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Initialise the integer shadow registers to UNKNOWN.  This is a bit
1950024598e40c84666cc311a42c256bbf880db3ac99sewardj   of a nasty kludge, but it does mean we don't need to know which
1951024598e40c84666cc311a42c256bbf880db3ac99sewardj   registers we really need to initialise -- simply assume that all
1952024598e40c84666cc311a42c256bbf880db3ac99sewardj   integer registers will be naturally aligned w.r.t. the start of the
1953024598e40c84666cc311a42c256bbf880db3ac99sewardj   guest state, and fill in all possible entries. */
1954024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_shadow_registers ( ThreadId tid )
1955024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1956024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i, wordSzB = sizeof(UWord);
1957024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < MC_SIZEOF_GUEST_STATE-wordSzB; i += wordSzB) {
1958024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg( tid, 1, i, wordSzB, (UWord)UNKNOWN );
1959024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1960024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1961024598e40c84666cc311a42c256bbf880db3ac99sewardj
1962c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic void post_reg_write_nonptr ( ThreadId tid, PtrdiffT offset, SizeT size )
1963024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1964024598e40c84666cc311a42c256bbf880db3ac99sewardj   // syscall_return: Default is non-pointer.  If it really is a pointer
1965024598e40c84666cc311a42c256bbf880db3ac99sewardj   // (eg. for mmap()), SK_(post_syscall) sets it again afterwards.
1966024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1967024598e40c84666cc311a42c256bbf880db3ac99sewardj   // clientreq_return: All the global client requests return non-pointers
1968024598e40c84666cc311a42c256bbf880db3ac99sewardj   // (except possibly CLIENT_CALL[0123], but they're handled by
1969024598e40c84666cc311a42c256bbf880db3ac99sewardj   // post_reg_write_clientcall, not here).
1970024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1971024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1972024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg( tid, 1, offset, size, (UWord)NONPTR );
1973024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
1974024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
1975024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1976024598e40c84666cc311a42c256bbf880db3ac99sewardj   //   VG_(set_thread_shadow_archreg)( tid, reg, (UInt)NONPTR );
1977024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1978024598e40c84666cc311a42c256bbf880db3ac99sewardj
1979024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void post_reg_write_nonptr_or_unknown ( ThreadId tid,
1980c4431bfe04c7490ea2d74939d222d87f13f30960njn                                               PtrdiffT offset, SizeT size )
1981024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1982024598e40c84666cc311a42c256bbf880db3ac99sewardj   // deliver_signal: called from two places; one sets the reg to zero, the
1983024598e40c84666cc311a42c256bbf880db3ac99sewardj   // other sets the stack pointer.
1984024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1985024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1986024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg(
1987024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, 1/*shadowno*/, offset, size,
1988024598e40c84666cc311a42c256bbf880db3ac99sewardj         (UWord)nonptr_or_unknown(
1989024598e40c84666cc311a42c256bbf880db3ac99sewardj                   get_guest_intreg( tid, 0/*shadowno*/,
1990024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     offset, size )));
1991024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
1992024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
1993024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1994024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1995024598e40c84666cc311a42c256bbf880db3ac99sewardj
1996024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_reg_write_demux ( CorePart part, ThreadId tid,
1997c4431bfe04c7490ea2d74939d222d87f13f30960njn                              PtrdiffT guest_state_offset, SizeT size)
1998024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1999024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0)
2000024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n",
2001024598e40c84666cc311a42c256bbf880db3ac99sewardj               (Int)tid, (Int)part,
2002024598e40c84666cc311a42c256bbf880db3ac99sewardj              guest_state_offset, size);
2003024598e40c84666cc311a42c256bbf880db3ac99sewardj   switch (part) {
2004024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreStartup:
2005024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* This is a bit of a kludge since for any Vg_CoreStartup
2006024598e40c84666cc311a42c256bbf880db3ac99sewardj            event we overwrite the entire shadow register set.  But
2007024598e40c84666cc311a42c256bbf880db3ac99sewardj            that's ok - we're only called once with
2008024598e40c84666cc311a42c256bbf880db3ac99sewardj            part==Vg_CoreStartup event, and in that case the supplied
2009024598e40c84666cc311a42c256bbf880db3ac99sewardj            offset & size cover the entire guest state anyway. */
2010024598e40c84666cc311a42c256bbf880db3ac99sewardj         init_shadow_registers(tid);
2011024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2012024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreSysCall:
2013024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ p_r_w    -> NONPTR\n");
2014024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr( tid, guest_state_offset, size );
2015024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2016024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreClientReq:
2017024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr( tid, guest_state_offset, size );
2018024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2019024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreSignal:
2020024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr_or_unknown( tid, guest_state_offset, size );
2021024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2022024598e40c84666cc311a42c256bbf880db3ac99sewardj      default:
2023024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(0);
2024024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2025024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2026024598e40c84666cc311a42c256bbf880db3ac99sewardj
2027c4431bfe04c7490ea2d74939d222d87f13f30960njnvoid h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset,
2028024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 SizeT size, Addr f )
2029024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2030024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord p;
2031024598e40c84666cc311a42c256bbf880db3ac99sewardj
2032024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Having to do this is a bit nasty...
2033024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (f == (Addr)h_replace_malloc
2034024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace___builtin_new
2035024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace___builtin_vec_new
2036024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_calloc
2037024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_memalign
2038024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_realloc)
2039024598e40c84666cc311a42c256bbf880db3ac99sewardj   {
2040024598e40c84666cc311a42c256bbf880db3ac99sewardj      // We remembered the last added segment;  make sure it's the right one.
2041024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* What's going on: at this point, the scheduler has just called
2042024598e40c84666cc311a42c256bbf880db3ac99sewardj         'f' -- one of our malloc replacement functions -- and it has
2043024598e40c84666cc311a42c256bbf880db3ac99sewardj         returned.  The return value has been written to the guest
2044024598e40c84666cc311a42c256bbf880db3ac99sewardj         state of thread 'tid', offset 'guest_state_offset' length
2045024598e40c84666cc311a42c256bbf880db3ac99sewardj         'size'.  We need to look at that return value and set the
2046024598e40c84666cc311a42c256bbf880db3ac99sewardj         shadow return value accordingly.  The shadow return value
2047024598e40c84666cc311a42c256bbf880db3ac99sewardj         required is handed to us "under the counter" through the
2048024598e40c84666cc311a42c256bbf880db3ac99sewardj         global variable 'last_seg_added'.  This is all very ugly, not
2049024598e40c84666cc311a42c256bbf880db3ac99sewardj         to mention, non-thread-safe should V ever become
2050024598e40c84666cc311a42c256bbf880db3ac99sewardj         multithreaded. */
2051024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* assert the place where the return value is is a legit int reg */
2052024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(is_integer_guest_reg(guest_state_offset, size));
2053024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Now we need to look at the returned value, to see whether the
2054024598e40c84666cc311a42c256bbf880db3ac99sewardj         malloc succeeded or not. */
2055024598e40c84666cc311a42c256bbf880db3ac99sewardj      p = get_guest_intreg(tid, 0/*non-shadow*/, guest_state_offset, size);
2056024598e40c84666cc311a42c256bbf880db3ac99sewardj      if ((UWord)NULL == p) {
2057024598e40c84666cc311a42c256bbf880db3ac99sewardj         // if alloc failed, eg. realloc on bogus pointer
2058024598e40c84666cc311a42c256bbf880db3ac99sewardj         put_guest_intreg(tid, 1/*first-shadow*/,
2059024598e40c84666cc311a42c256bbf880db3ac99sewardj                          guest_state_offset, size, (UWord)NONPTR );
2060024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2061024598e40c84666cc311a42c256bbf880db3ac99sewardj         // alloc didn't fail.  Check we have the correct segment.
2062024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(p == last_seg_added->addr);
2063024598e40c84666cc311a42c256bbf880db3ac99sewardj         put_guest_intreg(tid, 1/*first-shadow*/,
2064024598e40c84666cc311a42c256bbf880db3ac99sewardj                          guest_state_offset, size, (UWord)last_seg_added );
2065024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2066024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2067024598e40c84666cc311a42c256bbf880db3ac99sewardj   else if (f == (Addr)h_replace_free
2068024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)h_replace___builtin_delete
2069024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)h_replace___builtin_vec_delete
2070024598e40c84666cc311a42c256bbf880db3ac99sewardj   //            || f == (Addr)VG_(cli_block_size)
2071024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)VG_(message))
2072024598e40c84666cc311a42c256bbf880db3ac99sewardj   {
2073024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Probably best to set the (non-existent!) return value to
2074024598e40c84666cc311a42c256bbf880db3ac99sewardj      // non-pointer.
2075024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(is_integer_guest_reg(guest_state_offset, size));
2076024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg(tid, 1/*first-shadow*/,
2077024598e40c84666cc311a42c256bbf880db3ac99sewardj                       guest_state_offset, size, (UWord)NONPTR );
2078024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2079024598e40c84666cc311a42c256bbf880db3ac99sewardj   else {
2080024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Anything else, probably best to set return value to non-pointer.
2081024598e40c84666cc311a42c256bbf880db3ac99sewardj      //VG_(set_thread_shadow_archreg)(tid, reg, (UInt)UNKNOWN);
2082024598e40c84666cc311a42c256bbf880db3ac99sewardj      Char fbuf[100];
2083024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("f = %#lx\n", f);
2084024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(get_fnname)(f, fbuf, 100);
2085024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("name = %s\n", fbuf);
2086024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("argh: clientcall");
2087024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2088024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2089024598e40c84666cc311a42c256bbf880db3ac99sewardj
2090024598e40c84666cc311a42c256bbf880db3ac99sewardj
2091024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/
2092024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--- Sanity checking                                              ---*/
2093024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/
2094024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2095024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* Check that nobody has spuriously claimed that the first or last 16
2096024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    pages (64 KB) of address space have become accessible.  Failure of
2097024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    the following do not per se indicate an internal consistency
2098024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    problem, but they are so likely to that we really want to know
2099024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    about it if so. */
2100024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool pc_replace_cheap_sanity_check) ( void )
2101024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2102024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (IS_DISTINGUISHED_SM(primary_map[0])
2103024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz        /* kludge: kernel drops a page up at top of address range for
2104024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz           magic "optimized syscalls", so we can no longer check the
2105024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz           highest page */
2106024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz        /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
2107024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       )
2108024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
2109024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    else
2110024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return False;
2111024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2112024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2113024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool SK_(expensive_sanity_check) ( void )
2114024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2115024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    Int i;
2116024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2117024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    /* Make sure nobody changed the distinguished secondary. */
2118024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    for (i = 0; i < SEC_MAP_WORDS; i++)
2119024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (distinguished_secondary_map.vseg[i] != UNKNOWN)
2120024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          return False;
2121024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2122024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return True;
2123024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2124024598e40c84666cc311a42c256bbf880db3ac99sewardj
2125024598e40c84666cc311a42c256bbf880db3ac99sewardj
2126024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2127024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- System calls                                                 ---*/
2128024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2129024598e40c84666cc311a42c256bbf880db3ac99sewardj
2130024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_syscall ( ThreadId tid, UInt sysno )
2131024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2132024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* we don't do anything at the pre-syscall point */
2133024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2134024598e40c84666cc311a42c256bbf880db3ac99sewardj
2135024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The post-syscall table is a table of pairs (number, flag).
2136024598e40c84666cc311a42c256bbf880db3ac99sewardj
2137024598e40c84666cc311a42c256bbf880db3ac99sewardj   'flag' is only ever zero or one.  If it is zero, it indicates that
2138024598e40c84666cc311a42c256bbf880db3ac99sewardj   default handling for that syscall is required -- namely that the
2139024598e40c84666cc311a42c256bbf880db3ac99sewardj   syscall is deemed to return NONPTR.  This is the case for the vast
2140024598e40c84666cc311a42c256bbf880db3ac99sewardj   majority of syscalls.  If it is one then some special
2141024598e40c84666cc311a42c256bbf880db3ac99sewardj   syscall-specific handling is is required.  No further details of it
2142024598e40c84666cc311a42c256bbf880db3ac99sewardj   are stored in the table.
2143024598e40c84666cc311a42c256bbf880db3ac99sewardj
2144024598e40c84666cc311a42c256bbf880db3ac99sewardj   On Linux, 'number' is a __NR_xxx constant.
2145024598e40c84666cc311a42c256bbf880db3ac99sewardj
2146024598e40c84666cc311a42c256bbf880db3ac99sewardj   On AIX5, 'number' is an Int*, which points to the Int variable
2147024598e40c84666cc311a42c256bbf880db3ac99sewardj   holding the currently assigned number for this syscall.
2148024598e40c84666cc311a42c256bbf880db3ac99sewardj
2149024598e40c84666cc311a42c256bbf880db3ac99sewardj   When querying the table, we compare the supplied syscall number
2150024598e40c84666cc311a42c256bbf880db3ac99sewardj   with the 'number' field (directly on Linux, after dereferencing on
2151024598e40c84666cc311a42c256bbf880db3ac99sewardj   AIX5), to find the relevant entry.  This requires a linear search
2152024598e40c84666cc311a42c256bbf880db3ac99sewardj   of the table.  To stop the costs getting too high, the table is
2153024598e40c84666cc311a42c256bbf880db3ac99sewardj   incrementally rearranged after each search, to move commonly
2154024598e40c84666cc311a42c256bbf880db3ac99sewardj   requested items a bit closer to the front.
2155024598e40c84666cc311a42c256bbf880db3ac99sewardj
2156024598e40c84666cc311a42c256bbf880db3ac99sewardj   The table is built once, the first time it is used.  After that we
2157024598e40c84666cc311a42c256bbf880db3ac99sewardj   merely query it (and reorder the entries as a result). */
2158024598e40c84666cc311a42c256bbf880db3ac99sewardj
2159024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic XArray* /* of UWordPair */ post_syscall_table = NULL;
2160024598e40c84666cc311a42c256bbf880db3ac99sewardj
2161024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void setup_post_syscall_table ( void )
2162024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2163024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!post_syscall_table);
2164024598e40c84666cc311a42c256bbf880db3ac99sewardj   post_syscall_table = VG_(newXA)( VG_(malloc), "pc.h_main.spst.1",
2165024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(free), sizeof(UWordPair) );
2166024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(post_syscall_table);
2167024598e40c84666cc311a42c256bbf880db3ac99sewardj
2168024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------- LINUX --------------- */
2169024598e40c84666cc311a42c256bbf880db3ac99sewardj
2170024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGO_linux)
2171024598e40c84666cc311a42c256bbf880db3ac99sewardj
2172024598e40c84666cc311a42c256bbf880db3ac99sewardj#     define ADD(_flag, _syscallname) \
2173024598e40c84666cc311a42c256bbf880db3ac99sewardj         do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2174024598e40c84666cc311a42c256bbf880db3ac99sewardj              VG_(addToXA)( post_syscall_table, &p ); \
2175024598e40c84666cc311a42c256bbf880db3ac99sewardj         } while (0)
2176024598e40c84666cc311a42c256bbf880db3ac99sewardj
2177024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* These ones definitely don't return pointers.  They're not
2178024598e40c84666cc311a42c256bbf880db3ac99sewardj         particularly grammatical, either. */
2179024598e40c84666cc311a42c256bbf880db3ac99sewardj
2180024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR__llseek)
2181024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__llseek);
2182024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2183024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__sysctl);
2184024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR__newselect)
2185024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__newselect);
2186024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2187024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_accept)
2188024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_accept);
2189024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2190024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_access);
2191332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_alarm);
2192024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_bind)
2193024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_bind);
2194024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2195024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_chdir)
2196024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chdir);
2197024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2198024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chmod);
2199024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chown);
220041d5dea0b6d0672bd3986b5886e89b66941eef8asewardj#     if defined(__NR_chown32)
220141d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_chown32);
220241d5dea0b6d0672bd3986b5886e89b66941eef8asewardj#     endif
2203024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clock_getres);
2204024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clock_gettime);
2205024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clone);
2206024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_close);
2207024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_connect)
2208024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_connect);
2209024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2210332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_creat);
2211024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_dup);
2212024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_dup2);
2213024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_execve); /* presumably we see this because the call failed? */
2214024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_exit); /* hmm, why are we still alive? */
2215024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_exit_group);
2216024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fadvise64);
2217024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchmod);
2218024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchown);
2219024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fchown32)
2220024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchown32);
2221024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2222024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fcntl);
2223024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fcntl64)
2224024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fcntl64);
2225024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2226024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fdatasync);
222733c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_flock);
2228024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstat);
2229024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fstat64)
2230024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstat64);
2231024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2232024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstatfs);
2233024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fsync);
2234024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ftruncate);
2235024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_ftruncate64)
2236024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ftruncate64);
2237024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2238024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_futex);
2239024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getcwd);
2240024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getdents); // something to do with teeth
2241024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getdents64);
2242024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getegid);
2243024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getegid32)
2244024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getegid32);
2245024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2246024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_geteuid);
2247024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_geteuid32)
2248024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_geteuid32);
2249024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2250024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getgid);
2251024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getgid32)
2252024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getgid32);
2253024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2254ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_getgroups);
2255024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getitimer);
2256024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getpeername)
2257024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getpeername);
2258024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2259024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getpid);
22607d7691194ba0f1011b341ccc517f8a474169f403sewardj      ADD(0, __NR_getpgrp);
2261024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getppid);
2262024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getresgid);
2263024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getresuid);
2264024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getrlimit);
2265332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_getrusage);
2266024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getsockname)
2267024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getsockname);
2268024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2269024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getsockopt)
2270024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getsockopt);
2271024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
227241d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_gettid);
2273024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_gettimeofday);
2274024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getuid);
2275024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getuid32)
2276024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getuid32);
2277024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2278024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getxattr);
2279738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_inotify_add_watch);
2280024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_inotify_init);
2281738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_inotify_rm_watch);
2282024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ioctl); // ioctl -- assuming no pointers returned
228333c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_ioprio_get);
2284024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_kill);
2285024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_link);
2286024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_listen)
2287024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_listen);
2288024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2289024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lseek);
2290024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lstat);
2291024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_lstat64)
2292024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lstat64);
2293024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2294024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_madvise);
2295024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_mkdir);
229633c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_mlock);
2297024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_mprotect);
2298024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_munmap); // die_mem_munmap already called, segment remove);
2299738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_nanosleep);
2300024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_open);
2301024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pipe);
2302024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_poll);
2303024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pread64);
2304024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pwrite64);
2305024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_read);
2306024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_readlink);
2307024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_readv);
2308024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_recvfrom)
2309024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_recvfrom);
2310024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2311024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_recvmsg)
2312024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_recvmsg);
2313024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2314024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rename);
2315024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rmdir);
2316024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigaction);
2317024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigprocmask);
2318024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigreturn); /* not sure if we should see this or not */
2319024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_get_priority_max);
2320024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_get_priority_min);
2321738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_sched_getaffinity);
2322024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_getparam);
2323024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_getscheduler);
232441d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_sched_setaffinity);
2325024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_setscheduler);
2326024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_yield);
2327024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_select);
232833c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     if defined(__NR_semctl)
232933c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_semctl);
233033c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     endif
233133c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     if defined(__NR_semget)
233233c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_semget);
233333c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     endif
233433c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     if defined(__NR_semop)
233533c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_semop);
233633c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     endif
2337024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_sendto)
2338024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sendto);
2339024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2340332ffecd96becfaea1a67ddfab3e70372922393btom#     if defined(__NR_sendmsg)
2341332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_sendmsg);
2342332ffecd96becfaea1a67ddfab3e70372922393btom#     endif
2343024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_robust_list);
2344024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_set_thread_area)
2345024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_thread_area);
2346024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2347024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_tid_address);
2348ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setfsgid);
2349ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setfsuid);
2350ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setgid);
2351024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setitimer);
23527d7691194ba0f1011b341ccc517f8a474169f403sewardj      ADD(0, __NR_setpgid);
2353ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setresgid);
2354024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setrlimit);
2355024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setsid);
2356024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_setsockopt)
2357024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setsockopt);
2358024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2359ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setuid);
2360024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmctl)
2361024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shmctl);
2362024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shmdt);
2363024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2364024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shutdown)
2365024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shutdown);
2366024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
236741d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_sigaltstack);
2368024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_socket)
2369024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_socket);
2370024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2371024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_socketcall)
2372024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_socketcall); /* the nasty x86-linux socket multiplexor */
2373024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
237423e8a29882812f4b1d33d6fb9719f779becfba6esewardj#     if defined(__NR_socketpair)
237523e8a29882812f4b1d33d6fb9719f779becfba6esewardj      ADD(0, __NR_socketpair);
237623e8a29882812f4b1d33d6fb9719f779becfba6esewardj#     endif
2377024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_statfs64)
2378024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_statfs64);
2379024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2380024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_sigreturn)
2381024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sigreturn); /* not sure if we should see this or not */
2382024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2383024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_stat64)
2384024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_stat64);
2385024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2386024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_stat);
2387024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_statfs);
2388024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_symlink);
2389024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sysinfo);
2390024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_tgkill);
2391024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_time);
2392024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_times);
2393024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_truncate);
2394024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_truncate64)
2395024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_truncate64);
2396024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2397024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_ugetrlimit)
2398024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ugetrlimit);
2399024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2400024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_umask);
2401024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_uname);
2402024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_unlink);
2403024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_utime);
2404024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_waitpid)
2405024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_waitpid);
2406024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2407024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_wait4);
2408024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_write);
2409024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_writev);
2410024598e40c84666cc311a42c256bbf880db3ac99sewardj
2411024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Whereas the following need special treatment */
2412024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_arch_prctl)
2413024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_arch_prctl);
2414024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2415024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_brk);
2416024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_mmap);
2417024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_mmap2)
2418024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_mmap2);
2419024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2420024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmat)
2421024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_shmat);
2422024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2423024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmget)
2424024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_shmget);
2425024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2426024598e40c84666cc311a42c256bbf880db3ac99sewardj
2427024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------- AIX5 --------------- */
2428024598e40c84666cc311a42c256bbf880db3ac99sewardj
2429024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGO_aix5)
2430024598e40c84666cc311a42c256bbf880db3ac99sewardj
2431024598e40c84666cc311a42c256bbf880db3ac99sewardj#     define ADD(_flag, _syscallname) \
2432024598e40c84666cc311a42c256bbf880db3ac99sewardj         do { \
2433024598e40c84666cc311a42c256bbf880db3ac99sewardj            UWordPair p; \
2434024598e40c84666cc311a42c256bbf880db3ac99sewardj            if ((_syscallname) != __NR_AIX5_UNKNOWN) { \
2435024598e40c84666cc311a42c256bbf880db3ac99sewardj               p.uw1 = (UWord)&(_syscallname); p.uw2 = (_flag); \
2436024598e40c84666cc311a42c256bbf880db3ac99sewardj               VG_(addToXA)( post_syscall_table, &p ); \
2437024598e40c84666cc311a42c256bbf880db3ac99sewardj            } \
2438024598e40c84666cc311a42c256bbf880db3ac99sewardj         } while (0)
2439024598e40c84666cc311a42c256bbf880db3ac99sewardj
2440024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Just a minimal set of handlers, enough to make
2441024598e40c84666cc311a42c256bbf880db3ac99sewardj         a 32- and 64-bit hello-world program run. */
2442024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_AIX5___loadx); /* not sure what to do here */
2443024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5__exit);
2444024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_access);
2445024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_getgidx);
2446024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_getuidx);
2447024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kfcntl);
2448024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kioctl);
2449024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_AIX5_kload); /* not sure what to do here */
2450024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kwrite);
2451024598e40c84666cc311a42c256bbf880db3ac99sewardj
2452024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
2453024598e40c84666cc311a42c256bbf880db3ac99sewardj#     error "Unsupported OS"
2454024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2455024598e40c84666cc311a42c256bbf880db3ac99sewardj
2456024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef ADD
2457024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2458024598e40c84666cc311a42c256bbf880db3ac99sewardj
2459024598e40c84666cc311a42c256bbf880db3ac99sewardj
2460024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_syscall ( ThreadId tid, UInt sysno, SysRes res )
2461024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2462024598e40c84666cc311a42c256bbf880db3ac99sewardj   Word i, n;
2463024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWordPair* pair;
2464024598e40c84666cc311a42c256bbf880db3ac99sewardj
2465024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!post_syscall_table)
2466024598e40c84666cc311a42c256bbf880db3ac99sewardj      setup_post_syscall_table();
2467024598e40c84666cc311a42c256bbf880db3ac99sewardj
2468024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* search for 'sysno' in the post_syscall_table */
2469024598e40c84666cc311a42c256bbf880db3ac99sewardj   n = VG_(sizeXA)( post_syscall_table );
2470024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < n; i++) {
2471024598e40c84666cc311a42c256bbf880db3ac99sewardj      pair = VG_(indexXA)( post_syscall_table, i );
2472024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(VGO_linux)
2473024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (pair->uw1 == (UWord)sysno)
2474024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2475024598e40c84666cc311a42c256bbf880db3ac99sewardj#     elif defined(VGO_aix5)
2476024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (*(Int*)(pair->uw1) == (Int)sysno)
2477024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2478024598e40c84666cc311a42c256bbf880db3ac99sewardj#     else
2479024598e40c84666cc311a42c256bbf880db3ac99sewardj#        error "Unsupported OS"
2480024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2481024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2482024598e40c84666cc311a42c256bbf880db3ac99sewardj
2483024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0 && i <= n);
2484024598e40c84666cc311a42c256bbf880db3ac99sewardj
2485024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i == n) {
2486024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("sysno == %u\n", sysno);
2487024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(VGO_aix5)
2488024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("syscallnm == %s\n",
2489024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(aix5_sysno_to_sysname)(sysno));
2490024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2491024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("unhandled syscall");
2492024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2493024598e40c84666cc311a42c256bbf880db3ac99sewardj
2494024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* So we found the relevant entry.  Move it one step
2495024598e40c84666cc311a42c256bbf880db3ac99sewardj      forward so as to speed future accesses to it. */
2496024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i > 0) {
2497024598e40c84666cc311a42c256bbf880db3ac99sewardj      UWordPair tmp, *p, *q;
2498024598e40c84666cc311a42c256bbf880db3ac99sewardj      p = VG_(indexXA)( post_syscall_table, i-1 );
2499024598e40c84666cc311a42c256bbf880db3ac99sewardj      q = VG_(indexXA)( post_syscall_table, i-0 );
2500024598e40c84666cc311a42c256bbf880db3ac99sewardj      tmp = *p;
2501024598e40c84666cc311a42c256bbf880db3ac99sewardj      *p = *q;
2502024598e40c84666cc311a42c256bbf880db3ac99sewardj      *q = tmp;
2503024598e40c84666cc311a42c256bbf880db3ac99sewardj      i--;
2504024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2505024598e40c84666cc311a42c256bbf880db3ac99sewardj
2506024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Deal with the common case */
2507024598e40c84666cc311a42c256bbf880db3ac99sewardj   pair = VG_(indexXA)( post_syscall_table, i );
2508024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pair->uw2 == 0) {
2509024598e40c84666cc311a42c256bbf880db3ac99sewardj     /* the common case */
2510024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)(
2511024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, /* retval */ (UWord)NONPTR, 0,
2512024598e40c84666cc311a42c256bbf880db3ac99sewardj              /* error */  (UWord)NONPTR, 0
2513024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
2514024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2515024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2516024598e40c84666cc311a42c256bbf880db3ac99sewardj
2517024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Special handling for all remaining cases */
2518024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(pair->uw2 == 1);
2519024598e40c84666cc311a42c256bbf880db3ac99sewardj
2520024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_arch_prctl)
2521024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_arch_prctl) {
2522024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* This is nasty.  On amd64-linux, arch_prctl may write a
2523024598e40c84666cc311a42c256bbf880db3ac99sewardj         value to guest_FS_ZERO, and we need to shadow that value.
2524024598e40c84666cc311a42c256bbf880db3ac99sewardj         Hence apply nonptr_or_unknown to it here, after the
2525024598e40c84666cc311a42c256bbf880db3ac99sewardj         syscall completes. */
2526024598e40c84666cc311a42c256bbf880db3ac99sewardj      post_reg_write_nonptr_or_unknown( tid, PC_OFF_FS_ZERO,
2527024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             PC_SZB_FS_ZERO );
2528024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)(
2529024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, /* retval */ (UWord)NONPTR, 0,
2530024598e40c84666cc311a42c256bbf880db3ac99sewardj              /* error */  (UWord)NONPTR, 0
2531024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
2532024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2533024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2534024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2535024598e40c84666cc311a42c256bbf880db3ac99sewardj
2536024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_brk)
2537024598e40c84666cc311a42c256bbf880db3ac99sewardj   // With brk(), result (of kernel syscall, not glibc wrapper) is a heap
2538024598e40c84666cc311a42c256bbf880db3ac99sewardj   // pointer.  Make the shadow UNKNOWN.
2539024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno ==  __NR_brk) {
2540024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)(
2541024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, /* retval */ (UWord)UNKNOWN, 0,
2542024598e40c84666cc311a42c256bbf880db3ac99sewardj              /* error */  (UWord)NONPTR,  0
2543024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
2544024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2545024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2546024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2547024598e40c84666cc311a42c256bbf880db3ac99sewardj
2548024598e40c84666cc311a42c256bbf880db3ac99sewardj   // With mmap, new_mem_mmap() has already been called and added the
2549024598e40c84666cc311a42c256bbf880db3ac99sewardj   // segment (we did it there because we had the result address and size
2550024598e40c84666cc311a42c256bbf880db3ac99sewardj   // handy).  So just set the return value shadow.
2551024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_mmap
2552024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_mmap2)
2553024598e40c84666cc311a42c256bbf880db3ac99sewardj       || sysno == __NR_mmap2
2554024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2555024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_AIX5___loadx)
2556024598e40c84666cc311a42c256bbf880db3ac99sewardj       || (sysno == __NR_AIX5___loadx && __NR_AIX5___loadx != __NR_AIX5_UNKNOWN)
2557024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2558024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_AIX5_kload)
2559024598e40c84666cc311a42c256bbf880db3ac99sewardj       || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN)
2560024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2561024598e40c84666cc311a42c256bbf880db3ac99sewardj      ) {
2562024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (res.isError) {
2563024598e40c84666cc311a42c256bbf880db3ac99sewardj         // mmap() had an error, return value is a small negative integer
2564024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2565024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2566024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ mmap res -> NONPTR\n");
2567024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2568024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2569024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2570024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ mmap res -> UNKNOWN\n");
2571024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2572024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2573024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2574024598e40c84666cc311a42c256bbf880db3ac99sewardj
2575024598e40c84666cc311a42c256bbf880db3ac99sewardj   // shmat uses the same scheme.  We will just have had a
2576024598e40c84666cc311a42c256bbf880db3ac99sewardj   // notification via new_mem_mmap.  Just set the return value shadow.
2577024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_shmat)
2578024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_shmat) {
2579024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (res.isError) {
2580024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2581024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2582024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ shmat res -> NONPTR\n");
2583024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2584024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2585024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2586024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ shmat res -> UNKNOWN\n");
2587024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2588024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2589024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2590024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2591024598e40c84666cc311a42c256bbf880db3ac99sewardj
2592024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_shmget)
2593024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_shmget) {
2594024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: is this correct?
2595024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2596024598e40c84666cc311a42c256bbf880db3ac99sewardj                                            /*err*/ (UWord)NONPTR, 0 );
2597024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2598024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2599024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2600024598e40c84666cc311a42c256bbf880db3ac99sewardj
2601024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* If we get here, it implies the corresponding entry in
2602024598e40c84666cc311a42c256bbf880db3ac99sewardj      post_syscall_table has .w2 == 1, which in turn implies there
2603024598e40c84666cc311a42c256bbf880db3ac99sewardj      should be special-case code for it above. */
2604024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
2605024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2606024598e40c84666cc311a42c256bbf880db3ac99sewardj
2607024598e40c84666cc311a42c256bbf880db3ac99sewardj
2608024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2609024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Functions called from generated code                         ---*/
2610024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2611024598e40c84666cc311a42c256bbf880db3ac99sewardj
2612024598e40c84666cc311a42c256bbf880db3ac99sewardj#if SC_SEGS
2613024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void checkSeg ( Seg vseg ) {
2614024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(vseg == UNKNOWN || vseg == NONPTR || vseg == BOTTOM
2615024598e40c84666cc311a42c256bbf880db3ac99sewardj             || Seg__plausible(vseg) );
2616024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2617024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
2618024598e40c84666cc311a42c256bbf880db3ac99sewardj
2619024598e40c84666cc311a42c256bbf880db3ac99sewardj// XXX: could be more sophisticated -- actually track the lowest/highest
2620024598e40c84666cc311a42c256bbf880db3ac99sewardj// valid address used by the program, and then return False for anything
2621024598e40c84666cc311a42c256bbf880db3ac99sewardj// below that (using a suitable safety margin).  Also, nothing above
2622024598e40c84666cc311a42c256bbf880db3ac99sewardj// 0xc0000000 is valid [unless you've changed that in your kernel]
2623024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool looks_like_a_pointer(Addr a)
2624024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2625024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86) || defined(VGA_ppc32)
2626024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4);
2627024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (a > 0x01000000UL && a < 0xFF000000UL);
2628024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64)
2629024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8);
2630024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (a >= 16 * 0x10000UL && a < 0xFF00000000000000UL);
2631024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
2632024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "Unsupported architecture"
2633024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2634024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2635024598e40c84666cc311a42c256bbf880db3ac99sewardj
2636024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline VG_REGPARM(1)
2637024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* nonptr_or_unknown(UWord x)
2638024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2639024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* res = looks_like_a_pointer(x) ? UNKNOWN : NONPTR;
2640024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("nonptr_or_unknown %s %#lx\n",
2641024598e40c84666cc311a42c256bbf880db3ac99sewardj                      res==UNKNOWN ? "UUU" : "nnn", x);
2642024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
2643024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2644024598e40c84666cc311a42c256bbf880db3ac99sewardj
2645024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static __attribute__((regparm(1)))
2646024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz void print_BB_entry(UInt bb)
2647024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2648024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    VG_(printf)("%u =\n", bb);
2649024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2650024598e40c84666cc311a42c256bbf880db3ac99sewardj
265159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__tot_mem_refs  = 0;
265259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__refs_in_a_seg = 0;
265359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__refs_lost_seg = 0;
2654024598e40c84666cc311a42c256bbf880db3ac99sewardj
2655024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
2656024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct { ExeContext* ec; UWord count; }
2657024598e40c84666cc311a42c256bbf880db3ac99sewardj   Lossage;
2658024598e40c84666cc311a42c256bbf880db3ac99sewardj
2659024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic OSet* lossage = NULL;
2660024598e40c84666cc311a42c256bbf880db3ac99sewardj
266159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static void inc_lossage ( ExeContext* ec )
266259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//{
266359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   Lossage key, *res, *nyu;
266459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   key.ec = ec;
266559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   key.count = 0; /* frivolous */
266659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   res = VG_(OSetGen_Lookup)(lossage, &key);
266759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   if (res) {
266859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      tl_assert(res->ec == ec);
266959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      res->count++;
267059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   } else {
267159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      nyu = (Lossage*)VG_(OSetGen_AllocNode)(lossage, sizeof(Lossage));
267259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      tl_assert(nyu);
267359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      nyu->ec = ec;
267459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      nyu->count = 1;
267559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      VG_(OSetGen_Insert)( lossage, nyu );
267659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   }
267759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//}
2678024598e40c84666cc311a42c256bbf880db3ac99sewardj
2679024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_lossage ( void )
2680024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2681024598e40c84666cc311a42c256bbf880db3ac99sewardj   lossage = VG_(OSetGen_Create)( /*keyOff*/ offsetof(Lossage,ec),
2682024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  /*fastCmp*/NULL,
2683024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  VG_(malloc), "pc.h_main.il.1",
2684024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  VG_(free) );
2685024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(lossage);
2686024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2687024598e40c84666cc311a42c256bbf880db3ac99sewardj
268859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static void show_lossage ( void )
268959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//{
269059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   Lossage* elem;
269159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   VG_(OSetGen_ResetIter)( lossage );
269259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   while ( (elem = VG_(OSetGen_Next)(lossage)) ) {
269359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      if (elem->count < 10) continue;
269459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //Char buf[100];
269559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //(void)VG_(describe_IP)(elem->ec, buf, sizeof(buf)-1);
269659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //buf[sizeof(buf)-1] = 0;
269759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //VG_(printf)("  %,8lu  %s\n", elem->count, buf);
269859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      VG_(message)(Vg_UserMsg, "Lossage count %'lu at", elem->count);
269959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      VG_(pp_ExeContext)(elem->ec);
270059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   }
270159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//}
2702024598e40c84666cc311a42c256bbf880db3ac99sewardj
2703024598e40c84666cc311a42c256bbf880db3ac99sewardj// This function is called *a lot*; inlining it sped up Konqueror by 20%.
2704024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
2705024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load_or_store(Bool is_write, Addr m, UWord sz, Seg* mptr_vseg)
2706024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2707024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
27084815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj   tl_assert(0);
27094815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj   if (h_clo_lossage_check) {
2710024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* seg;
2711024598e40c84666cc311a42c256bbf880db3ac99sewardj      stats__tot_mem_refs++;
2712024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (ISList__findI0( seglist, (Addr)m, &seg )) {
2713024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* m falls inside 'seg' (that is, we are making a memory
2714024598e40c84666cc311a42c256bbf880db3ac99sewardj            reference inside 'seg').  Now, really mptr_vseg should be
2715024598e40c84666cc311a42c256bbf880db3ac99sewardj            a tracked segment of some description.  Badness is when
2716024598e40c84666cc311a42c256bbf880db3ac99sewardj            mptr_vseg is UNKNOWN, BOTTOM or NONPTR at this point,
2717024598e40c84666cc311a42c256bbf880db3ac99sewardj            since that means we've lost the type of it somehow: it
2718024598e40c84666cc311a42c256bbf880db3ac99sewardj            shoud say that m points into a real segment (preferable
2719024598e40c84666cc311a42c256bbf880db3ac99sewardj            'seg'), but it doesn't. */
2720024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (Seg__status_is_SegHeap(seg)) {
2721024598e40c84666cc311a42c256bbf880db3ac99sewardj            stats__refs_in_a_seg++;
2722024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (UNKNOWN == mptr_vseg
2723024598e40c84666cc311a42c256bbf880db3ac99sewardj                || BOTTOM == mptr_vseg || NONPTR == mptr_vseg) {
2724024598e40c84666cc311a42c256bbf880db3ac99sewardj               ExeContext* ec;
2725024598e40c84666cc311a42c256bbf880db3ac99sewardj               Char buf[100];
2726024598e40c84666cc311a42c256bbf880db3ac99sewardj               static UWord xx = 0;
2727024598e40c84666cc311a42c256bbf880db3ac99sewardj               stats__refs_lost_seg++;
2728024598e40c84666cc311a42c256bbf880db3ac99sewardj               ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 );
2729024598e40c84666cc311a42c256bbf880db3ac99sewardj               inc_lossage(ec);
2730024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (0) {
2731024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(message)(Vg_DebugMsg, "");
2732024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(message)(Vg_DebugMsg,
2733024598e40c84666cc311a42c256bbf880db3ac99sewardj                               "Lossage %s %#lx sz %lu inside block alloc'd",
2734024598e40c84666cc311a42c256bbf880db3ac99sewardj                               is_write ? "wr" : "rd", m, (UWord)sz);
2735024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(pp_ExeContext)(Seg__where(seg));
2736024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
2737024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (xx++ < 0) {
2738024598e40c84666cc311a42c256bbf880db3ac99sewardj                  Addr ip = VG_(get_IP)( VG_(get_running_tid)() );
2739024598e40c84666cc311a42c256bbf880db3ac99sewardj                  (void)VG_(describe_IP)( ip, buf, sizeof(buf)-1);
2740024598e40c84666cc311a42c256bbf880db3ac99sewardj                  buf[sizeof(buf)-1] = 0;
2741024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(printf)("lossage at %p %s\n", ec, buf );
2742024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
2743024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
2744024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
2745024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2746024598e40c84666cc311a42c256bbf880db3ac99sewardj   } /* clo_lossage_check */
27474815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#endif
2748024598e40c84666cc311a42c256bbf880db3ac99sewardj
2749024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2750024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2751024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2752024598e40c84666cc311a42c256bbf880db3ac99sewardj
2753024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (UNKNOWN == mptr_vseg) {
2754024598e40c84666cc311a42c256bbf880db3ac99sewardj      // do nothing
2755024598e40c84666cc311a42c256bbf880db3ac99sewardj
2756024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (BOTTOM == mptr_vseg) {
2757024598e40c84666cc311a42c256bbf880db3ac99sewardj      // do nothing
2758024598e40c84666cc311a42c256bbf880db3ac99sewardj
2759024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (NONPTR == mptr_vseg) {
2760024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_heap_error( m, sz, mptr_vseg, is_write );
2761024598e40c84666cc311a42c256bbf880db3ac99sewardj
2762024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2763024598e40c84666cc311a42c256bbf880db3ac99sewardj      // check all segment ranges in the circle
2764024598e40c84666cc311a42c256bbf880db3ac99sewardj      // if none match, warn about 1st seg
2765024598e40c84666cc311a42c256bbf880db3ac99sewardj      // else,          check matching one isn't freed
2766024598e40c84666cc311a42c256bbf880db3ac99sewardj      Bool is_ok = False;
2767024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* curr  = mptr_vseg;
2768024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr mhi;
2769024598e40c84666cc311a42c256bbf880db3ac99sewardj
2770024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Accesses partly outside range are an error, unless it's an aligned
2771024598e40c84666cc311a42c256bbf880db3ac99sewardj      // word-sized read, and --partial-loads-ok=yes.  This is to cope with
2772024598e40c84666cc311a42c256bbf880db3ac99sewardj      // gcc's/glibc's habits of doing word-sized accesses that read past
2773024598e40c84666cc311a42c256bbf880db3ac99sewardj      // the ends of arrays/strings.
2774024598e40c84666cc311a42c256bbf880db3ac99sewardj      // JRS 2008-sept-11: couldn't this be moved off the critical path?
2775024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (!is_write && sz == sizeof(UWord)
2776024598e40c84666cc311a42c256bbf880db3ac99sewardj          && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
2777024598e40c84666cc311a42c256bbf880db3ac99sewardj         mhi = m;
2778024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2779024598e40c84666cc311a42c256bbf880db3ac99sewardj         mhi = m+sz-1;
2780024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2781024598e40c84666cc311a42c256bbf880db3ac99sewardj
2782024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (0) VG_(printf)("calling seg_ci %p %#lx %#lx\n", curr,m,mhi);
2783024598e40c84666cc311a42c256bbf880db3ac99sewardj      is_ok = curr->addr <= m && mhi < curr->addr + curr->szB;
2784024598e40c84666cc311a42c256bbf880db3ac99sewardj
2785024598e40c84666cc311a42c256bbf880db3ac99sewardj      // If it's an overrun/underrun of a freed block, don't give both
2786024598e40c84666cc311a42c256bbf880db3ac99sewardj      // warnings, since the first one mentions that the block has been
2787024598e40c84666cc311a42c256bbf880db3ac99sewardj      // freed.
2788024598e40c84666cc311a42c256bbf880db3ac99sewardj      if ( ! is_ok || Seg__is_freed(curr) )
2789024598e40c84666cc311a42c256bbf880db3ac99sewardj         h_record_heap_error( m, sz, mptr_vseg, is_write );
2790024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2791024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2792024598e40c84666cc311a42c256bbf880db3ac99sewardj
2793024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Load handlers ------------------ //
2794024598e40c84666cc311a42c256bbf880db3ac99sewardj
2795024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use:
2796024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load1 check_load2 check_load4_P
2797024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load4  (for 32-bit FP reads)
2798024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load8  (for 64-bit FP reads)
2799024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load16 (for xmm/altivec reads)
2800024598e40c84666cc311a42c256bbf880db3ac99sewardj   On 64 bit targets, we will use:
2801024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load1 check_load2 check_load4 check_load8_P
2802024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load8  (for 64-bit FP reads)
2803024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load16 (for xmm/altivec reads)
2804024598e40c84666cc311a42c256bbf880db3ac99sewardj
2805024598e40c84666cc311a42c256bbf880db3ac99sewardj   A "_P" handler reads a pointer from memory, and so returns a value
2806024598e40c84666cc311a42c256bbf880db3ac99sewardj   to the generated code -- the pointer's shadow value.  That implies
2807024598e40c84666cc311a42c256bbf880db3ac99sewardj   that check_load4_P is only to be called on a 32 bit host and
2808024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load8_P is only to be called on a 64 bit host.  For all other
2809024598e40c84666cc311a42c256bbf880db3ac99sewardj   cases no shadow value is returned; we merely check that the pointer
2810024598e40c84666cc311a42c256bbf880db3ac99sewardj   (m) matches the block described by its shadow value (mptr_vseg).
2811024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
2812024598e40c84666cc311a42c256bbf880db3ac99sewardj
2813024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit loads on both 32 bit and 64 bit targets.
2814024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2815024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load16(Addr m, Seg* mptr_vseg)
2816024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2817024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2818024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2819024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2820024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 16, mptr_vseg);
2821024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2822024598e40c84666cc311a42c256bbf880db3ac99sewardj
2823024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit FP-or-otherwise-nonpointer loads on both
2824024598e40c84666cc311a42c256bbf880db3ac99sewardj// 32 bit and 64 bit targets.
2825024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2826024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load8(Addr m, Seg* mptr_vseg)
2827024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2828024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2829024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2830024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2831024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2832024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2833024598e40c84666cc311a42c256bbf880db3ac99sewardj
2834024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit loads on 64 bit targets.  It must
2835024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets.
2836024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg
2837024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2838024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load8_P(Addr m, Seg* mptr_vseg)
2839024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2840024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* vseg;
2841024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2842024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2843024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2844024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2845024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2846024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_8_ALIGNED(m)) {
2847024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = get_mem_vseg(m);
2848024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2849024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = nonptr_or_unknown( *(ULong*)m );
2850024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2851024598e40c84666cc311a42c256bbf880db3ac99sewardj   return vseg;
2852024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2853024598e40c84666cc311a42c256bbf880db3ac99sewardj
2854024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit loads on 32 bit targets.  It must
2855024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets.
2856024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg
2857024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2858024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load4_P(Addr m, Seg* mptr_vseg)
2859024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2860024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* vseg;
2861024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2862024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2863024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2864024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2865024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2866024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_4_ALIGNED(m)) {
2867024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = get_mem_vseg(m);
2868024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2869024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = nonptr_or_unknown( *(UInt*)m );
2870024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2871024598e40c84666cc311a42c256bbf880db3ac99sewardj   return vseg;
2872024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2873024598e40c84666cc311a42c256bbf880db3ac99sewardj
2874024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2875024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2876024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load4(Addr m, Seg* mptr_vseg)
2877024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2878024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2879024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2880024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2881024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2882024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2883024598e40c84666cc311a42c256bbf880db3ac99sewardj
2884024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2885024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2886024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load2(Addr m, Seg* mptr_vseg)
2887024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2888024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2889024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2890024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2891024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 2, mptr_vseg);
2892024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2893024598e40c84666cc311a42c256bbf880db3ac99sewardj
2894024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2895024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2896024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load1(Addr m, Seg* mptr_vseg)
2897024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2898024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2899024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2900024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2901024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 1, mptr_vseg);
2902024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2903024598e40c84666cc311a42c256bbf880db3ac99sewardj
2904024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Store handlers ------------------ //
2905024598e40c84666cc311a42c256bbf880db3ac99sewardj
2906024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use:
2907024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store1 check_store2 check_store4_P
2908024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store4 (for 32-bit nonpointer stores)
2909024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store8_ms4B_ls4B (for 64-bit stores)
2910024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store16_ms4B_4B_4B_ls4B (for xmm/altivec stores)
2911024598e40c84666cc311a42c256bbf880db3ac99sewardj
2912024598e40c84666cc311a42c256bbf880db3ac99sewardj   On 64 bit targets, we will use:
2913024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store1 check_store2 check_store4 check_store8_P
2914024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store8_all8B (for 64-bit nonpointer stores)
2915024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store16_ms8B_ls8B (for xmm/altivec stores)
2916024598e40c84666cc311a42c256bbf880db3ac99sewardj
2917024598e40c84666cc311a42c256bbf880db3ac99sewardj   A "_P" handler writes a pointer to memory, and so has an extra
2918024598e40c84666cc311a42c256bbf880db3ac99sewardj   argument -- the pointer's shadow value.  That implies that
2919024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_store4_P is only to be called on a 32 bit host and
2920024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_store8_P is only to be called on a 64 bit host.  For all
2921024598e40c84666cc311a42c256bbf880db3ac99sewardj   other cases, and for the misaligned _P cases, the strategy is to
2922024598e40c84666cc311a42c256bbf880db3ac99sewardj   let the store go through, and then snoop around with
2923024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown to fix up the shadow values of any affected
2924024598e40c84666cc311a42c256bbf880db3ac99sewardj   words. */
2925024598e40c84666cc311a42c256bbf880db3ac99sewardj
2926024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Apply nonptr_or_unknown to all the words intersecting
2927024598e40c84666cc311a42c256bbf880db3ac99sewardj   [a, a+len). */
2928024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2929024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid nonptr_or_unknown_range ( Addr a, SizeT len )
2930024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2931024598e40c84666cc311a42c256bbf880db3ac99sewardj   const SizeT wszB = sizeof(UWord);
2932024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr wfirst = VG_ROUNDDN(a,       wszB);
2933024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr wlast  = VG_ROUNDDN(a+len-1, wszB);
2934024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr a2;
2935024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(wfirst <= wlast);
2936024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (a2 = wfirst ; a2 <= wlast; a2 += wszB) {
2937024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( a2, nonptr_or_unknown( *(UWord*)a2 ));
2938024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2939024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2940024598e40c84666cc311a42c256bbf880db3ac99sewardj
2941024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets.  The
2942024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
2943024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
2944024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2945024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms8B_ls8B(Addr m, Seg* mptr_vseg,
2946024598e40c84666cc311a42c256bbf880db3ac99sewardj                             UWord ms8B, UWord ls8B)
2947024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2948024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2949024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2950024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2951024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2952024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2953024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2954024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
2955024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
2956024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
2957024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 0) = ls8B;
2958024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 8) = ms8B;
2959024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2960024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 0) = ms8B;
2961024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 8) = ls8B;
2962024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2963024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 16);
2964024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2965024598e40c84666cc311a42c256bbf880db3ac99sewardj
2966024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets.  The
2967024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
2968024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
2969024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2970024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms4B_4B_4B_ls4B(Addr m, Seg* mptr_vseg,
2971024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   UWord ms4B, UWord w2,
2972024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   UWord w1,   UWord ls4B)
2973024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2974024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2975024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2976024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2977024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2978024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2979024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2980024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
2981024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
2982024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
2983024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  0) = ls4B;
2984024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  4) = w1;
2985024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  8) = w2;
2986024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 12) = ms4B;
2987024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2988024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  0) = ms4B;
2989024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  4) = w2;
2990024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  8) = w1;
2991024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 12) = ls4B;
2992024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2993024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 16);
2994024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2995024598e40c84666cc311a42c256bbf880db3ac99sewardj
2996024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 32 bit targets.  The
2997024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
2998024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
2999024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3000024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_ms4B_ls4B(Addr m, Seg* mptr_vseg,
3001024598e40c84666cc311a42c256bbf880db3ac99sewardj                            UWord ms4B, UWord ls4B)
3002024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3003024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3004024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3005024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3006024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3007024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3008024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3009024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
3010024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
3011024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
3012024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 0) = ls4B;
3013024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 4) = ms4B;
3014024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3015024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 0) = ms4B;
3016024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 4) = ls4B;
3017024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3018024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 8);
3019024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3020024598e40c84666cc311a42c256bbf880db3ac99sewardj
3021024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit non pointer stores on 64 bit targets.
3022024598e40c84666cc311a42c256bbf880db3ac99sewardj// It must not be called on 32 bit targets.
3023024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3024024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_all8B(Addr m, Seg* mptr_vseg, UWord all8B)
3025024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3026024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3027024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3028024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3029024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3030024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3031024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3032024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(ULong*)m = all8B;
3033024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 8);
3034024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3035024598e40c84666cc311a42c256bbf880db3ac99sewardj
3036024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 64 bit targets.  It must
3037024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets.
3038024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3039024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3040024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3041024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3042024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3043024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(t_vseg);
3044024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3045024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3046024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3047024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3048024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(ULong*)m = t;
3049024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_8_ALIGNED(m)) {
3050024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( m, t_vseg );
3051024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3052024598e40c84666cc311a42c256bbf880db3ac99sewardj      // straddling two words
3053024598e40c84666cc311a42c256bbf880db3ac99sewardj      nonptr_or_unknown_range(m, 8);
3054024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3055024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3056024598e40c84666cc311a42c256bbf880db3ac99sewardj
3057024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit stores on 32 bit targets.  It must
3058024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets.
3059024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3060024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3061024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3062024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3063024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3064024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(t_vseg);
3065024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3066024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3067024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3068024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3069024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UInt*)m = t;
3070024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_4_ALIGNED(m)) {
3071024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( m, t_vseg );
3072024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3073024598e40c84666cc311a42c256bbf880db3ac99sewardj      // straddling two words
3074024598e40c84666cc311a42c256bbf880db3ac99sewardj      nonptr_or_unknown_range(m, 4);
3075024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3076024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3077024598e40c84666cc311a42c256bbf880db3ac99sewardj
3078024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
3079024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3080024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4(Addr m, Seg* mptr_vseg, UWord t)
3081024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3082024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3083024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3084024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3085024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3086024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 4-byte type!)
3087024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UInt*)m = t;
3088024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 4);
3089024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3090024598e40c84666cc311a42c256bbf880db3ac99sewardj
3091024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
3092024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3093024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store2(Addr m, Seg* mptr_vseg, UWord t)
3094024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3095024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3096024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3097024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3098024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 2, mptr_vseg);
3099024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 2-byte type!)
3100024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UShort*)m = t;
3101024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 2);
3102024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3103024598e40c84666cc311a42c256bbf880db3ac99sewardj
3104024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
3105024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3106024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store1(Addr m, Seg* mptr_vseg, UWord t)
3107024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3108024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3109024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3110024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3111024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 1, mptr_vseg);
3112024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 1-byte type!)
3113024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UChar*)m = t;
3114024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 1);
3115024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3116024598e40c84666cc311a42c256bbf880db3ac99sewardj
3117024598e40c84666cc311a42c256bbf880db3ac99sewardj
3118024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: if the result is BOTTOM, return immedately -- don't let BOTTOM
3119024598e40c84666cc311a42c256bbf880db3ac99sewardj//     be changed to NONPTR by a range check on the result.
3120024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINOP(bt, nn, nu, np, un, uu, up, pn, pu, pp) \
3121024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (BOTTOM == seg1 || BOTTOM == seg2) { bt;                   \
3122024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (NONPTR == seg1)  { if      (NONPTR == seg2)  { nn; }  \
3123024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { nu; }    \
3124024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { np; }    \
3125024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (UNKNOWN == seg1) { if      (NONPTR == seg2)  { un; }    \
3126024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { uu; }    \
3127024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { up; }    \
3128024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else                      { if      (NONPTR == seg2)  { pn; }    \
3129024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { pu; }    \
3130024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { pp; }    \
3131024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3132024598e40c84666cc311a42c256bbf880db3ac99sewardj
3133024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINERROR(opname)                    \
3134024598e40c84666cc311a42c256bbf880db3ac99sewardj   h_record_arith_error(seg1, seg2, opname);  \
3135024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = NONPTR
3136024598e40c84666cc311a42c256bbf880db3ac99sewardj
3137024598e40c84666cc311a42c256bbf880db3ac99sewardj
3138024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3139024598e40c84666cc311a42c256bbf880db3ac99sewardj//  + | n  ?  p
3140024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3141024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3142024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3143024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  e   (all results become n if they look like a non-pointer)
3144024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3145024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* do_addW_result(Seg* seg1, Seg* seg2, UWord result, HChar* opname)
3146024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3147024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3148024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3149024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3150024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3151024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3152024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3153024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3154024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN, out = seg2,
3155024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3156024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = UNKNOWN,       BINERROR(opname)
3157024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3158024598e40c84666cc311a42c256bbf880db3ac99sewardj   return ( looks_like_a_pointer(result) ? out : NONPTR );
3159024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3160024598e40c84666cc311a42c256bbf880db3ac99sewardj
3161024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_addW(Seg* seg1, Seg* seg2, UWord result)
3162024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3163024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3164024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3165024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3166024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3167024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3168024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = do_addW_result(seg1, seg2, result, "Add32/Add64");
3169024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3170024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(out);
3171024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3172024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3173024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3174024598e40c84666cc311a42c256bbf880db3ac99sewardj
3175024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3176024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - | n  ?  p      (Nb: operation is seg1 - seg2)
3177024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3178024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  n+     (+) happens a lot due to "cmp", but result should never
3179024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  n/B        be used, so give 'n'
3180024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  p? n*/B   (*) and possibly link the segments
3181024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3182024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_subW(Seg* seg1, Seg* seg2, UWord result)
3183024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3184024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3185024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3186024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3187024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3188024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3189024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Nb: when returning BOTTOM, don't let it go through the range-check;
3190024598e40c84666cc311a42c256bbf880db3ac99sewardj   //     a segment linking offset can easily look like a nonptr.
3191024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3192024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3193024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN,    out = NONPTR,
3194024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN,    return BOTTOM,
3195024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = seg1/*??*/, return BOTTOM
3196024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3197024598e40c84666cc311a42c256bbf880db3ac99sewardj   #if 0
3198024598e40c84666cc311a42c256bbf880db3ac99sewardj         // This is for the p-p segment-linking case
3199024598e40c84666cc311a42c256bbf880db3ac99sewardj         Seg end2 = seg2;
3200024598e40c84666cc311a42c256bbf880db3ac99sewardj         while (end2->links != seg2) end2 = end2->links;
3201024598e40c84666cc311a42c256bbf880db3ac99sewardj         end2->links = seg1->links;
3202024598e40c84666cc311a42c256bbf880db3ac99sewardj         seg1->links = seg2;
3203024598e40c84666cc311a42c256bbf880db3ac99sewardj         return NONPTR;
3204024598e40c84666cc311a42c256bbf880db3ac99sewardj   #endif
3205024598e40c84666cc311a42c256bbf880db3ac99sewardj   return ( looks_like_a_pointer(result) ? out : NONPTR );
3206024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3207024598e40c84666cc311a42c256bbf880db3ac99sewardj
3208024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3209024598e40c84666cc311a42c256bbf880db3ac99sewardj//  & | n  ?  p
3210024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3211024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3212024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3213024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  *  (*) if p1==p2 then p else e (see comment)
3214024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3215024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Seems to be OK to And two pointers:
3216024598e40c84666cc311a42c256bbf880db3ac99sewardj     testq %ptr1,%ptr2
3217024598e40c84666cc311a42c256bbf880db3ac99sewardj     jnz ..
3218024598e40c84666cc311a42c256bbf880db3ac99sewardj   which possibly derives from
3219024598e40c84666cc311a42c256bbf880db3ac99sewardj     if (ptr1 & ptr2) { A } else { B }
3220024598e40c84666cc311a42c256bbf880db3ac99sewardj   not sure what that means
3221024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3222024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_andW(Seg* seg1, Seg* seg2,
3223024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  UWord result, UWord args_diff)
3224024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3225024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3226024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0 == args_diff) {
3227024598e40c84666cc311a42c256bbf880db3ac99sewardj      // p1==p2
3228024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1;
3229024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3230024598e40c84666cc311a42c256bbf880db3ac99sewardj      BINOP(
3231024598e40c84666cc311a42c256bbf880db3ac99sewardj         return BOTTOM,
3232024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = NONPTR,  out = UNKNOWN, out = seg2,
3233024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3234024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = seg1,    out = UNKNOWN, out = NONPTR
3235024598e40c84666cc311a42c256bbf880db3ac99sewardj                                       /*BINERROR("And32/And64")*/
3236024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
3237024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3238024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = ( looks_like_a_pointer(result) ? out : NONPTR );
3239024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3240024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3241024598e40c84666cc311a42c256bbf880db3ac99sewardj
3242024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3243024598e40c84666cc311a42c256bbf880db3ac99sewardj// `|`| n  ?  p
3244024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3245024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3246024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3247024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  n
3248024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3249024598e40c84666cc311a42c256bbf880db3ac99sewardj/* It's OK to Or two pointers together, but the result definitely
3250024598e40c84666cc311a42c256bbf880db3ac99sewardj   isn't a pointer.  Why would you want to do that?  Because of this:
3251024598e40c84666cc311a42c256bbf880db3ac99sewardj     char* p1 = malloc(..);
3252024598e40c84666cc311a42c256bbf880db3ac99sewardj     char* p2 = malloc(..);
3253024598e40c84666cc311a42c256bbf880db3ac99sewardj     ...
3254024598e40c84666cc311a42c256bbf880db3ac99sewardj     if (p1 || p2) { .. }
3255024598e40c84666cc311a42c256bbf880db3ac99sewardj   In this case gcc on x86/amd64 quite literally or-s the two pointers
3256024598e40c84666cc311a42c256bbf880db3ac99sewardj   together and throws away the result, the purpose of which is merely
3257024598e40c84666cc311a42c256bbf880db3ac99sewardj   to sets %eflags.Z/%rflags.Z.  So we have to allow it.
3258024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3259024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_orW(Seg* seg1, Seg* seg2, UWord result)
3260024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3261024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3262024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3263024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3264024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN, out = seg2,
3265024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3266024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = UNKNOWN, out = NONPTR
3267024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3268024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = ( looks_like_a_pointer(result) ? out : NONPTR );
3269024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3270024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3271024598e40c84666cc311a42c256bbf880db3ac99sewardj
3272024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3273024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ~ | n  ?  p
3274024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3275024598e40c84666cc311a42c256bbf880db3ac99sewardj//    | n  n  n
3276024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3277024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_notW(Seg* seg1, UWord result)
3278024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3279024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3280024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3281024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3282024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (BOTTOM == seg1) return BOTTOM;
3283024598e40c84666cc311a42c256bbf880db3ac99sewardj   return NONPTR;
3284024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3285024598e40c84666cc311a42c256bbf880db3ac99sewardj
3286024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pointers are rarely multiplied, but sometimes legitimately, eg. as hash
3287024598e40c84666cc311a42c256bbf880db3ac99sewardj// function inputs.  But two pointers args --> error.
3288024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pretend it always returns a nonptr.  Maybe improve later.
3289024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_mulW(Seg* seg1, Seg* seg2)
3290024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3291024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3292024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3293024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3294024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3295024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seg1) && is_known_segment(seg2))
3296024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_arith_error(seg1, seg2, "Mul32/Mul64");
3297024598e40c84666cc311a42c256bbf880db3ac99sewardj   return NONPTR;
3298024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3299024598e40c84666cc311a42c256bbf880db3ac99sewardj
3300024598e40c84666cc311a42c256bbf880db3ac99sewardj
3301024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3302024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Instrumentation                                              ---*/
3303024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3304024598e40c84666cc311a42c256bbf880db3ac99sewardj
3305024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The h_ instrumenter that follows is complex, since it deals with
3306024598e40c84666cc311a42c256bbf880db3ac99sewardj   shadow value computation.
3307024598e40c84666cc311a42c256bbf880db3ac99sewardj
3308024598e40c84666cc311a42c256bbf880db3ac99sewardj   It also needs to generate instrumentation for the sg_ side of
3309024598e40c84666cc311a42c256bbf880db3ac99sewardj   things.  That's relatively straightforward.  However, rather than
3310024598e40c84666cc311a42c256bbf880db3ac99sewardj   confuse the code herein any further, we simply delegate the problem
3311024598e40c84666cc311a42c256bbf880db3ac99sewardj   to sg_main.c, by using the four functions
3312024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_{init,fini,IRStmt,final_jump}.  These four completely
3313024598e40c84666cc311a42c256bbf880db3ac99sewardj   abstractify the sg_ instrumentation.  See comments in sg_main.c's
3314024598e40c84666cc311a42c256bbf880db3ac99sewardj   instrumentation section for further details. */
3315024598e40c84666cc311a42c256bbf880db3ac99sewardj
3316024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Carries around state during Ptrcheck instrumentation. */
3317024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
3318024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
3319024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* MODIFIED: the superblock being constructed.  IRStmts are
3320024598e40c84666cc311a42c256bbf880db3ac99sewardj         added. */
3321024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRSB* bb;
3322024598e40c84666cc311a42c256bbf880db3ac99sewardj      Bool  trace;
3323024598e40c84666cc311a42c256bbf880db3ac99sewardj
3324024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
3325024598e40c84666cc311a42c256bbf880db3ac99sewardj         original temps to their current their current shadow temp.
3326024598e40c84666cc311a42c256bbf880db3ac99sewardj         Initially all entries are IRTemp_INVALID.  Entries are added
3327024598e40c84666cc311a42c256bbf880db3ac99sewardj         lazily since many original temps are not used due to
3328024598e40c84666cc311a42c256bbf880db3ac99sewardj         optimisation prior to instrumentation.  Note that only
3329024598e40c84666cc311a42c256bbf880db3ac99sewardj         integer temps of the guest word size are shadowed, since it
3330024598e40c84666cc311a42c256bbf880db3ac99sewardj         is impossible (or meaningless) to hold a pointer in any other
3331024598e40c84666cc311a42c256bbf880db3ac99sewardj         type of temp. */
3332024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRTemp* tmpMap;
3333024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int     n_originalTmps; /* for range checking */
3334024598e40c84666cc311a42c256bbf880db3ac99sewardj
3335024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the host word type.  Needed for constructing
3336024598e40c84666cc311a42c256bbf880db3ac99sewardj         arguments of type 'HWord' to be passed to helper functions.
3337024598e40c84666cc311a42c256bbf880db3ac99sewardj         Ity_I32 or Ity_I64 only. */
3338024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRType hWordTy;
3339024598e40c84666cc311a42c256bbf880db3ac99sewardj
3340024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
3341024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRType gWordTy;
3342024598e40c84666cc311a42c256bbf880db3ac99sewardj
3343024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the guest state size, so we can generate shadow
3344024598e40c84666cc311a42c256bbf880db3ac99sewardj         offsets correctly. */
3345024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int guest_state_sizeB;
3346024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3347024598e40c84666cc311a42c256bbf880db3ac99sewardj   PCEnv;
3348024598e40c84666cc311a42c256bbf880db3ac99sewardj
3349024598e40c84666cc311a42c256bbf880db3ac99sewardj/* SHADOW TMP MANAGEMENT.  Shadow tmps are allocated lazily (on
3350024598e40c84666cc311a42c256bbf880db3ac99sewardj   demand), as they are encountered.  This is for two reasons.
3351024598e40c84666cc311a42c256bbf880db3ac99sewardj
3352024598e40c84666cc311a42c256bbf880db3ac99sewardj   (1) (less important reason): Many original tmps are unused due to
3353024598e40c84666cc311a42c256bbf880db3ac99sewardj   initial IR optimisation, and we do not want to spaces in tables
3354024598e40c84666cc311a42c256bbf880db3ac99sewardj   tracking them.
3355024598e40c84666cc311a42c256bbf880db3ac99sewardj
3356024598e40c84666cc311a42c256bbf880db3ac99sewardj   Shadow IRTemps are therefore allocated on demand.  pce.tmpMap is a
3357024598e40c84666cc311a42c256bbf880db3ac99sewardj   table indexed [0 .. n_types-1], which gives the current shadow for
3358024598e40c84666cc311a42c256bbf880db3ac99sewardj   each original tmp, or INVALID_IRTEMP if none is so far assigned.
3359024598e40c84666cc311a42c256bbf880db3ac99sewardj   It is necessary to support making multiple assignments to a shadow
3360024598e40c84666cc311a42c256bbf880db3ac99sewardj   -- specifically, after testing a shadow for definedness, it needs
3361024598e40c84666cc311a42c256bbf880db3ac99sewardj   to be made defined.  But IR's SSA property disallows this.
3362024598e40c84666cc311a42c256bbf880db3ac99sewardj
3363024598e40c84666cc311a42c256bbf880db3ac99sewardj   (2) (more important reason): Therefore, when a shadow needs to get
3364024598e40c84666cc311a42c256bbf880db3ac99sewardj   a new value, a new temporary is created, the value is assigned to
3365024598e40c84666cc311a42c256bbf880db3ac99sewardj   that, and the tmpMap is updated to reflect the new binding.
3366024598e40c84666cc311a42c256bbf880db3ac99sewardj
3367024598e40c84666cc311a42c256bbf880db3ac99sewardj   A corollary is that if the tmpMap maps a given tmp to
3368024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp_INVALID and we are hoping to read that shadow tmp, it means
3369024598e40c84666cc311a42c256bbf880db3ac99sewardj   there's a read-before-write error in the original tmps.  The IR
3370024598e40c84666cc311a42c256bbf880db3ac99sewardj   sanity checker should catch all such anomalies, however.
3371024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3372024598e40c84666cc311a42c256bbf880db3ac99sewardj
3373024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Find the tmp currently shadowing the given original tmp.  If none
3374024598e40c84666cc311a42c256bbf880db3ac99sewardj   so far exists, allocate one.  */
3375024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp findShadowTmp ( PCEnv* pce, IRTemp orig )
3376024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3377024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(orig < pce->n_originalTmps);
3378024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3379024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->tmpMap[orig] == IRTemp_INVALID) {
3380024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
3381024598e40c84666cc311a42c256bbf880db3ac99sewardj      pce->tmpMap[orig]
3382024598e40c84666cc311a42c256bbf880db3ac99sewardj         = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3383024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3384024598e40c84666cc311a42c256bbf880db3ac99sewardj   return pce->tmpMap[orig];
3385024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3386024598e40c84666cc311a42c256bbf880db3ac99sewardj
3387024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Allocate a new shadow for the given original tmp.  This means any
3388024598e40c84666cc311a42c256bbf880db3ac99sewardj   previous shadow is abandoned.  This is needed because it is
3389024598e40c84666cc311a42c256bbf880db3ac99sewardj   necessary to give a new value to a shadow once it has been tested
3390024598e40c84666cc311a42c256bbf880db3ac99sewardj   for undefinedness, but unfortunately IR's SSA property disallows
3391024598e40c84666cc311a42c256bbf880db3ac99sewardj   this.  Instead we must abandon the old shadow, allocate a new one
3392024598e40c84666cc311a42c256bbf880db3ac99sewardj   and use that instead. */
3393024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((noinline))
3394024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp newShadowTmp ( PCEnv* pce, IRTemp orig )
3395024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3396024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(orig < pce->n_originalTmps);
3397024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3398024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce->tmpMap[orig]
3399024598e40c84666cc311a42c256bbf880db3ac99sewardj      = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3400024598e40c84666cc311a42c256bbf880db3ac99sewardj   return pce->tmpMap[orig];
3401024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3402024598e40c84666cc311a42c256bbf880db3ac99sewardj
3403024598e40c84666cc311a42c256bbf880db3ac99sewardj
3404024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3405024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- IRAtoms -- a subset of IRExprs                       ---*/
3406024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3407024598e40c84666cc311a42c256bbf880db3ac99sewardj
3408024598e40c84666cc311a42c256bbf880db3ac99sewardj/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
3409024598e40c84666cc311a42c256bbf880db3ac99sewardj   isIRAtom() in libvex_ir.h.  Because this instrumenter expects flat
3410024598e40c84666cc311a42c256bbf880db3ac99sewardj   input, most of this code deals in atoms.  Usefully, a value atom
3411024598e40c84666cc311a42c256bbf880db3ac99sewardj   always has a V-value which is also an atom: constants are shadowed
3412024598e40c84666cc311a42c256bbf880db3ac99sewardj   by constants, and temps are shadowed by the corresponding shadow
3413024598e40c84666cc311a42c256bbf880db3ac99sewardj   temporary. */
3414024598e40c84666cc311a42c256bbf880db3ac99sewardj
3415024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef  IRExpr  IRAtom;
3416024598e40c84666cc311a42c256bbf880db3ac99sewardj
3417024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks
3418024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    like it's from original code? */
3419024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isOriginalAtom ( PCEnv* pce, IRAtom* a1 )
3420024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3421024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const)
3422024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3423024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < pce->n_originalTmps)
3424024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3425024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3426024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3427024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
3428024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks
3429024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    like it's from shadow code? */
3430024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isShadowAtom ( PCEnv* pce, IRAtom* a1 )
3431024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3432024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const)
3433024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3434024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= pce->n_originalTmps)
3435024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3436024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3437024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3438024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
3439024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): check that both args are atoms and
3440024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    are identically-kinded. */
3441024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
3442024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3443024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
3444024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3445024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const && a2->tag == Iex_Const)
3446024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3447024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3448024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3449024598e40c84666cc311a42c256bbf880db3ac99sewardj
3450024598e40c84666cc311a42c256bbf880db3ac99sewardj
3451024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3452024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Constructing IR fragments                            ---*/
3453024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3454024598e40c84666cc311a42c256bbf880db3ac99sewardj
3455024598e40c84666cc311a42c256bbf880db3ac99sewardj/* add stmt to a bb */
3456024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
3457024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->trace) {
3458024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("  %c: ", cat);
3459024598e40c84666cc311a42c256bbf880db3ac99sewardj      ppIRStmt(st);
3460024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("\n");
3461024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3462024598e40c84666cc311a42c256bbf880db3ac99sewardj   addStmtToIRSB(pce->bb, st);
3463024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3464024598e40c84666cc311a42c256bbf880db3ac99sewardj
3465024598e40c84666cc311a42c256bbf880db3ac99sewardj/* assign value to tmp */
3466024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
3467024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid assign ( HChar cat, PCEnv* pce, IRTemp tmp, IRExpr* expr ) {
3468024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt(cat, pce, IRStmt_WrTmp(tmp,expr));
3469024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3470024598e40c84666cc311a42c256bbf880db3ac99sewardj
3471024598e40c84666cc311a42c256bbf880db3ac99sewardj/* build various kinds of expressions */
3472024598e40c84666cc311a42c256bbf880db3ac99sewardj#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
3473024598e40c84666cc311a42c256bbf880db3ac99sewardj#define unop(_op, _arg)          IRExpr_Unop((_op),(_arg))
3474024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU8(_n)                 IRExpr_Const(IRConst_U8(_n))
3475024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU16(_n)                IRExpr_Const(IRConst_U16(_n))
3476024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU32(_n)                IRExpr_Const(IRConst_U32(_n))
3477024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU64(_n)                IRExpr_Const(IRConst_U64(_n))
3478024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkV128(_n)               IRExpr_Const(IRConst_V128(_n))
3479024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkexpr(_tmp)             IRExpr_RdTmp((_tmp))
3480024598e40c84666cc311a42c256bbf880db3ac99sewardj
3481024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Bind the given expression to a new temporary, and return the
3482024598e40c84666cc311a42c256bbf880db3ac99sewardj   temporary.  This effectively converts an arbitrary expression into
3483024598e40c84666cc311a42c256bbf880db3ac99sewardj   an atom.
3484024598e40c84666cc311a42c256bbf880db3ac99sewardj
3485024598e40c84666cc311a42c256bbf880db3ac99sewardj   'ty' is the type of 'e' and hence the type that the new temporary
3486024598e40c84666cc311a42c256bbf880db3ac99sewardj   needs to be.  But passing it is redundant, since we can deduce the
3487024598e40c84666cc311a42c256bbf880db3ac99sewardj   type merely by inspecting 'e'.  So at least that fact to assert
3488024598e40c84666cc311a42c256bbf880db3ac99sewardj   that the two types agree. */
3489024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* assignNew ( HChar cat, PCEnv* pce, IRType ty, IRExpr* e ) {
3490024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp t;
3491024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRType tyE = typeOfIRExpr(pce->bb->tyenv, e);
3492024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
3493024598e40c84666cc311a42c256bbf880db3ac99sewardj   t = newIRTemp(pce->bb->tyenv, ty);
3494024598e40c84666cc311a42c256bbf880db3ac99sewardj   assign(cat, pce, t, e);
3495024598e40c84666cc311a42c256bbf880db3ac99sewardj   return mkexpr(t);
3496024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3497024598e40c84666cc311a42c256bbf880db3ac99sewardj
3498024598e40c84666cc311a42c256bbf880db3ac99sewardj
3499024598e40c84666cc311a42c256bbf880db3ac99sewardj
3500024598e40c84666cc311a42c256bbf880db3ac99sewardj//-----------------------------------------------------------------------
3501024598e40c84666cc311a42c256bbf880db3ac99sewardj// Approach taken for range-checking for NONPTR/UNKNOWN-ness as follows.
3502024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3503024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/seg):
3504024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after modifying a word-sized value in/into a TempReg:
3505024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - {ADD, SUB, ADC, SBB, AND, OR, XOR, LEA, LEA2, NEG, NOT}L
3506024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - BSWAP
3507024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3508024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/UNKNOWN):
3509024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when introducing a new word-sized value into a TempReg:
3510024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOVL l, t2
3511024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3512024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying a word-sized value which lacks a corresponding segment
3513024598e40c84666cc311a42c256bbf880db3ac99sewardj//   into a TempReg:
3514024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled LDL
3515024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3516024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when a sub-word of a word (or two) is updated:
3517024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - SHROTL
3518024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - {ADD, SUB, ADC, SBB, AND, OR, XOR, SHROT, NEG, NOT}[WB]
3519024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - PUT[WB]
3520024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   STL (2 range checks)
3521024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   STW (2 range checks)
3522024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled STW
3523024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - STB
3524024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3525024598e40c84666cc311a42c256bbf880db3ac99sewardj// Just copy:
3526024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying word-sized values:
3527024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOVL t1, t2 (--optimise=no only)
3528024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - CMOV
3529024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GETL, PUTL
3530024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled LDL, unstraddled STL
3531024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3532024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when barely changing
3533024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - INC[LWB]/DEC[LWB]
3534024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3535024598e40c84666cc311a42c256bbf880db3ac99sewardj// Set to NONPTR:
3536024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying a sub-word value into a TempReg:
3537024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOV[WB] l, t2
3538024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GET[WB]
3539024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled LDW
3540024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   LDW
3541024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - LDB
3542024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - POP[WB]
3543024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3544024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a TempReg:
3545024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GETF
3546024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - CC2VAL
3547024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - POPL
3548024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3549024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a memory word:
3550024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - FPU_W
3551024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3552024598e40c84666cc311a42c256bbf880db3ac99sewardj// Do nothing:
3553024598e40c84666cc311a42c256bbf880db3ac99sewardj// - LOCK, INCEIP
3554024598e40c84666cc311a42c256bbf880db3ac99sewardj// - WIDEN[WB]
3555024598e40c84666cc311a42c256bbf880db3ac99sewardj// - JMP, JIFZ
3556024598e40c84666cc311a42c256bbf880db3ac99sewardj// - CALLM_[SE], PUSHL, CALLM, CLEAR
3557024598e40c84666cc311a42c256bbf880db3ac99sewardj// - FPU, FPU_R (and similar MMX/SSE ones)
3558024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3559024598e40c84666cc311a42c256bbf880db3ac99sewardj
3560024598e40c84666cc311a42c256bbf880db3ac99sewardj
3561024598e40c84666cc311a42c256bbf880db3ac99sewardj
3562024598e40c84666cc311a42c256bbf880db3ac99sewardj
3563024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Call h_fn (name h_nm) with the given arg, and return a new IRTemp
3564024598e40c84666cc311a42c256bbf880db3ac99sewardj   holding the result.  The arg must be a word-typed atom.  Callee
3565024598e40c84666cc311a42c256bbf880db3ac99sewardj   must be a VG_REGPARM(1) function. */
3566024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((noinline))
3567024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3568024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr* a1 )
3569024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3570024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3571024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3572024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3573024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3574024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3575024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 1/*regparms*/,
3576024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3577024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_1( a1 ) );
3578024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3579024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3580024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3581024598e40c84666cc311a42c256bbf880db3ac99sewardj
3582024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Two-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(2)
3583024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3584024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3585024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a1, IRExpr* a2 )
3586024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3587024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3588024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3589024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3590024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3591024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3592024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3593024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3594024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 2/*regparms*/,
3595024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3596024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_2( a1, a2 ) );
3597024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3598024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3599024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3600024598e40c84666cc311a42c256bbf880db3ac99sewardj
3601024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Three-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(3)
3602024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3603024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3604024598e40c84666cc311a42c256bbf880db3ac99sewardj                                IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3605024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3606024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3607024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3608024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3609024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3610024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3611024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3612024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3613024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3614024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3615024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3616024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3617024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_3( a1, a2, a3 ) );
3618024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3619024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3620024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3621024598e40c84666cc311a42c256bbf880db3ac99sewardj
3622024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Four-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(3)
3623024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3624024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3625024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 IRExpr* a1, IRExpr* a2,
3626024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 IRExpr* a3, IRExpr* a4 )
3627024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3628024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3629024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3630024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3631024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3632024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3633024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3634024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3635024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3636024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3637024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3638024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3639024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3640024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3641024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_4( a1, a2, a3, a4 ) );
3642024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3643024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3644024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3645024598e40c84666cc311a42c256bbf880db3ac99sewardj
3646024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WW with no return value.  Callee must be a
3647024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(2) function.*/
3648024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3649024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a1, IRExpr* a2 )
3650024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3651024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3652024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3653024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3654024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3655024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3656024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 2/*regparms*/,
3657024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3658024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_2( a1, a2 ) );
3659024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3660024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3661024598e40c84666cc311a42c256bbf880db3ac99sewardj
3662024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WWW with no return value.  Callee must be a
3663024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3664024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3665024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3666024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3667024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3668024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3669024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3670024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3671024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3672024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3673024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3674024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3675024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3676024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_3( a1, a2, a3 ) );
3677024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3678024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3679024598e40c84666cc311a42c256bbf880db3ac99sewardj
3680024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 4 arguments.  Callee must be a
3681024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3682024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3683024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a1, IRExpr* a2,
3684024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a3, IRExpr* a4 )
3685024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3686024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3687024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3688024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3689024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3690024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3691024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3692024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3693024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3694024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3695024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3696024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3697024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_4( a1, a2, a3, a4 ) );
3698024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3699024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3700024598e40c84666cc311a42c256bbf880db3ac99sewardj
3701024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 6 arguments.  Callee must be a
3702024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3703024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_6W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3704024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a1, IRExpr* a2, IRExpr* a3,
3705024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a4, IRExpr* a5, IRExpr* a6 )
3706024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3707024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3708024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3709024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3710024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3711024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3712024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a5));
3713024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a6));
3714024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3715024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3716024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3717024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3718024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a5) == pce->gWordTy);
3719024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a6) == pce->gWordTy);
3720024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3721024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3722024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_6( a1, a2, a3, a4, a5, a6 ) );
3723024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3724024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3725024598e40c84666cc311a42c256bbf880db3ac99sewardj
3726024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* uwiden_to_host_word ( PCEnv* pce, IRAtom* a )
3727024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3728024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRType a_ty = typeOfIRExpr(pce->bb->tyenv, a);
3729024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a));
3730024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->hWordTy == Ity_I32) {
3731024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (a_ty) {
3732024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I8:
3733024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I32, unop(Iop_8Uto32, a) );
3734024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I16:
3735024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I32, unop(Iop_16Uto32, a) );
3736024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3737024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType(a_ty);
3738024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3739024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3740024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3741024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->hWordTy == Ity_I64);
3742024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (a_ty) {
3743024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I8:
3744024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_8Uto64, a) );
3745024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I16:
3746024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_16Uto64, a) );
3747024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I32:
3748024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_32Uto64, a) );
3749024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3750024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType(a_ty);
3751024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3752024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3753024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3754024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3755024598e40c84666cc311a42c256bbf880db3ac99sewardj
3756024598e40c84666cc311a42c256bbf880db3ac99sewardj/* 'e' is a word-sized atom.  Call nonptr_or_unknown with it, bind the
3757024598e40c84666cc311a42c256bbf880db3ac99sewardj   results to a new temporary, and return the temporary.  Note this
3758024598e40c84666cc311a42c256bbf880db3ac99sewardj   takes an original expression but returns a shadow value. */
3759024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_call_nonptr_or_unknown_w ( PCEnv* pce, IRExpr* e )
3760024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3761024598e40c84666cc311a42c256bbf880db3ac99sewardj   return gen_dirty_W_W( pce, &nonptr_or_unknown,
3762024598e40c84666cc311a42c256bbf880db3ac99sewardj                              "nonptr_or_unknown", e );
3763024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3764024598e40c84666cc311a42c256bbf880db3ac99sewardj
3765024598e40c84666cc311a42c256bbf880db3ac99sewardj
3766024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Generate the shadow value for an IRExpr which is an atom and
3767024598e40c84666cc311a42c256bbf880db3ac99sewardj   guaranteed to be word-sized. */
3768024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* schemeEw_Atom ( PCEnv* pce, IRExpr* e )
3769024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3770024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->gWordTy == Ity_I32) {
3771024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U32) {
3772024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp t;
3773024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(sizeof(UWord) == 4);
3774024598e40c84666cc311a42c256bbf880db3ac99sewardj         t = gen_call_nonptr_or_unknown_w(pce, e);
3775024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr(t);
3776024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3777024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_RdTmp
3778024598e40c84666cc311a42c256bbf880db3ac99sewardj          && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I32) {
3779024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3780024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3781024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* there are no other word-sized atom cases */
3782024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3783024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U64) {
3784024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp t;
3785024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(sizeof(UWord) == 8);
3786024598e40c84666cc311a42c256bbf880db3ac99sewardj         //return mkU64( (ULong)(UWord)NONPTR );
3787024598e40c84666cc311a42c256bbf880db3ac99sewardj         t = gen_call_nonptr_or_unknown_w(pce, e);
3788024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr(t);
3789024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3790024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_RdTmp
3791024598e40c84666cc311a42c256bbf880db3ac99sewardj          && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I64) {
3792024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3793024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3794024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* there are no other word-sized atom cases */
3795024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3796024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRExpr(e);
3797024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
3798024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3799024598e40c84666cc311a42c256bbf880db3ac99sewardj
3800024598e40c84666cc311a42c256bbf880db3ac99sewardj
3801024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
3802024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid instrument_arithop ( PCEnv* pce,
3803024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRTemp dst, /* already holds result */
3804024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRTemp dstv, /* generate an assignment to this */
3805024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IROp op,
3806024598e40c84666cc311a42c256bbf880db3ac99sewardj                          /* original args, guaranteed to be atoms */
3807024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRExpr* a1, IRExpr* a2, IRExpr* a3, IRExpr* a4 )
3808024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3809024598e40c84666cc311a42c256bbf880db3ac99sewardj   HChar*  nm  = NULL;
3810024598e40c84666cc311a42c256bbf880db3ac99sewardj   void*   fn  = NULL;
3811024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRExpr* a1v = NULL;
3812024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRExpr* a2v = NULL;
3813024598e40c84666cc311a42c256bbf880db3ac99sewardj   //IRExpr* a3v = NULL;
3814024598e40c84666cc311a42c256bbf880db3ac99sewardj   //IRExpr* a4v = NULL;
3815024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp  res = IRTemp_INVALID;
3816024598e40c84666cc311a42c256bbf880db3ac99sewardj
3817024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->gWordTy == Ity_I32) {
3818024598e40c84666cc311a42c256bbf880db3ac99sewardj
3819024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->hWordTy == Ity_I32);
3820024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (op) {
3821024598e40c84666cc311a42c256bbf880db3ac99sewardj
3822024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* For these cases, pass Segs for both arguments, and the
3823024598e40c84666cc311a42c256bbf880db3ac99sewardj            result value. */
3824024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Add32: nm = "do_addW"; fn = &do_addW; goto ssr32;
3825024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sub32: nm = "do_subW"; fn = &do_subW; goto ssr32;
3826024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Or32:  nm = "do_orW";  fn = &do_orW;  goto ssr32;
3827024598e40c84666cc311a42c256bbf880db3ac99sewardj         ssr32:
3828024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3829024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3830024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3831024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3832024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3833024598e40c84666cc311a42c256bbf880db3ac99sewardj
3834024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* In this case, pass Segs for both arguments, the result
3835024598e40c84666cc311a42c256bbf880db3ac99sewardj            value, and the difference between the (original) values of
3836024598e40c84666cc311a42c256bbf880db3ac99sewardj            the arguments. */
3837024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_And32:
3838024598e40c84666cc311a42c256bbf880db3ac99sewardj            nm = "do_andW"; fn = &do_andW;
3839024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3840024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3841024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWWW(
3842024598e40c84666cc311a42c256bbf880db3ac99sewardj                     pce, fn, nm, a1v, a2v, mkexpr(dst),
3843024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assignNew( 'I', pce, Ity_I32,
3844024598e40c84666cc311a42c256bbf880db3ac99sewardj                                binop(Iop_Sub32,a1,a2) ) );
3845024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3846024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3847024598e40c84666cc311a42c256bbf880db3ac99sewardj
3848024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass one shadow arg and the result to the helper. */
3849024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Not32: nm = "do_notW"; fn = &do_notW; goto vr32;
3850024598e40c84666cc311a42c256bbf880db3ac99sewardj         vr32:
3851024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3852024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3853024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3854024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3855024598e40c84666cc311a42c256bbf880db3ac99sewardj
3856024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass two shadow args only to the helper. */
3857024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul32: nm = "do_mulW"; fn = &do_mulW; goto vv32;
3858024598e40c84666cc311a42c256bbf880db3ac99sewardj         vv32:
3859024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3860024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3861024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3862024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3863024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3864024598e40c84666cc311a42c256bbf880db3ac99sewardj
3865024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We don't really know what the result could be; test at run
3866024598e40c84666cc311a42c256bbf880db3ac99sewardj            time. */
3867024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_64HIto32: goto n_or_u_32;
3868024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_64to32:   goto n_or_u_32;
3869024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Xor32:    goto n_or_u_32;
3870024598e40c84666cc311a42c256bbf880db3ac99sewardj         n_or_u_32:
3871024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv,
3872024598e40c84666cc311a42c256bbf880db3ac99sewardj                    mkexpr(
3873024598e40c84666cc311a42c256bbf880db3ac99sewardj                       gen_call_nonptr_or_unknown_w( pce,
3874024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                     mkexpr(dst) ) ) );
3875024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3876024598e40c84666cc311a42c256bbf880db3ac99sewardj
3877024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Cases where it's very obvious that the result cannot be a
3878024598e40c84666cc311a42c256bbf880db3ac99sewardj            pointer.  Hence declare directly that it's NONPTR; don't
3879024598e40c84666cc311a42c256bbf880db3ac99sewardj            bother with the overhead of calling nonptr_or_unknown. */
3880024598e40c84666cc311a42c256bbf880db3ac99sewardj
3881024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where it makes no sense for the result to be a ptr */
3882024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3883024598e40c84666cc311a42c256bbf880db3ac99sewardj            arg, so that shift by zero preserves the original
3884024598e40c84666cc311a42c256bbf880db3ac99sewardj            value. */
3885024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shl32:    goto n32;
3886024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sar32:    goto n32;
3887024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shr32:    goto n32;
3888024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Uto32:  goto n32;
3889024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Sto32:  goto n32;
3890024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_F64toI32: goto n32;
3891024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16HLto32: goto n32;
3892024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullS16:  goto n32;
3893024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullU16:  goto n32;
3894024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_PRemC3210F64: goto n32;
3895024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivU32:   goto n32;
3896024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivS32:   goto n32;
3897024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128to32: goto n32;
3898024598e40c84666cc311a42c256bbf880db3ac99sewardj
3899024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where result range is very limited and clearly cannot
3900024598e40c84666cc311a42c256bbf880db3ac99sewardj            be a pointer */
3901024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Uto32: goto n32;
3902024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Sto32: goto n32;
3903024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Uto32: goto n32;
3904024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Sto32: goto n32;
3905024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Clz32:  goto n32;
3906024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Ctz32:  goto n32;
3907024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpF64: goto n32;
3908024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD32S: goto n32;
3909024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD32U: goto n32;
3910024598e40c84666cc311a42c256bbf880db3ac99sewardj         n32:
3911024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
3912024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3913024598e40c84666cc311a42c256bbf880db3ac99sewardj
3914024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3915024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("instrument_arithop(32-bit): unhandled: ");
3916024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIROp(op);
3917024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3918024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3919024598e40c84666cc311a42c256bbf880db3ac99sewardj
3920024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3921024598e40c84666cc311a42c256bbf880db3ac99sewardj
3922024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->gWordTy == Ity_I64);
3923024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (op) {
3924024598e40c84666cc311a42c256bbf880db3ac99sewardj
3925024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* For these cases, pass Segs for both arguments, and the
3926024598e40c84666cc311a42c256bbf880db3ac99sewardj            result value. */
3927024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Add64: nm = "do_addW"; fn = &do_addW; goto ssr64;
3928024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sub64: nm = "do_subW"; fn = &do_subW; goto ssr64;
3929024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Or64:  nm = "do_orW";  fn = &do_orW;  goto ssr64;
3930024598e40c84666cc311a42c256bbf880db3ac99sewardj         ssr64:
3931024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3932024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3933024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3934024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3935024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3936024598e40c84666cc311a42c256bbf880db3ac99sewardj
3937024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* In this case, pass Segs for both arguments, the result
3938024598e40c84666cc311a42c256bbf880db3ac99sewardj            value, and the difference between the (original) values of
3939024598e40c84666cc311a42c256bbf880db3ac99sewardj            the arguments. */
3940024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_And64:
3941024598e40c84666cc311a42c256bbf880db3ac99sewardj            nm = "do_andW"; fn = &do_andW;
3942024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3943024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3944024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWWW(
3945024598e40c84666cc311a42c256bbf880db3ac99sewardj                     pce, fn, nm, a1v, a2v, mkexpr(dst),
3946024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assignNew( 'I', pce, Ity_I64,
3947024598e40c84666cc311a42c256bbf880db3ac99sewardj                                binop(Iop_Sub64,a1,a2) ) );
3948024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3949024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3950024598e40c84666cc311a42c256bbf880db3ac99sewardj
3951024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass one shadow arg and the result to the helper. */
3952024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Not64: nm = "do_notW"; fn = &do_notW; goto vr64;
3953024598e40c84666cc311a42c256bbf880db3ac99sewardj         vr64:
3954024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3955024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3956024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3957024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3958024598e40c84666cc311a42c256bbf880db3ac99sewardj
3959024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass two shadow args only to the helper. */
3960024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul64: nm = "do_mulW"; fn = &do_mulW; goto vv64;
3961024598e40c84666cc311a42c256bbf880db3ac99sewardj         vv64:
3962024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3963024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3964024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3965024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3966024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3967024598e40c84666cc311a42c256bbf880db3ac99sewardj
3968024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We don't really know what the result could be; test at run
3969024598e40c84666cc311a42c256bbf880db3ac99sewardj            time. */
3970024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Xor64:      goto n_or_u_64;
3971024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_128HIto64:  goto n_or_u_64;
3972024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_128to64:    goto n_or_u_64;
3973024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128HIto64: goto n_or_u_64;
3974024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128to64:   goto n_or_u_64;
3975024598e40c84666cc311a42c256bbf880db3ac99sewardj         n_or_u_64:
3976024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv,
3977024598e40c84666cc311a42c256bbf880db3ac99sewardj                    mkexpr(
3978024598e40c84666cc311a42c256bbf880db3ac99sewardj                       gen_call_nonptr_or_unknown_w( pce,
3979024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                     mkexpr(dst) ) ) );
3980024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3981024598e40c84666cc311a42c256bbf880db3ac99sewardj
3982024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Cases where it's very obvious that the result cannot be a
3983024598e40c84666cc311a42c256bbf880db3ac99sewardj            pointer.  Hence declare directly that it's NONPTR; don't
3984024598e40c84666cc311a42c256bbf880db3ac99sewardj            bother with the overhead of calling nonptr_or_unknown. */
3985024598e40c84666cc311a42c256bbf880db3ac99sewardj
3986024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where it makes no sense for the result to be a ptr */
3987024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3988024598e40c84666cc311a42c256bbf880db3ac99sewardj            arg, so that shift by zero preserves the original
3989024598e40c84666cc311a42c256bbf880db3ac99sewardj            value. */
3990024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shl64:      goto n64;
3991024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sar64:      goto n64;
3992024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shr64:      goto n64;
3993024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32Uto64:    goto n64;
3994024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32Sto64:    goto n64;
3995024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Uto64:    goto n64;
3996024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Sto64:    goto n64;
3997024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32HLto64:   goto n64;
3998024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivModU64to32: goto n64;
3999024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivModS64to32: goto n64;
4000024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_F64toI64:      goto n64;
4001024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullS32:    goto n64;
4002024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullU32:    goto n64;
4003024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivU64:     goto n64;
4004024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivS64:     goto n64;
4005024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_ReinterpF64asI64: goto n64;
4006024598e40c84666cc311a42c256bbf880db3ac99sewardj
4007024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where result range is very limited and clearly cannot
4008024598e40c84666cc311a42c256bbf880db3ac99sewardj            be a pointer */
4009024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Uto64:        goto n64;
4010024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Uto64:        goto n64;
4011024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Sto64:        goto n64;
4012024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Ctz64:         goto n64;
4013024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Clz64:         goto n64;
4014024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD64S:     goto n64;
4015024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD64U:     goto n64;
4016024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* 64-bit simd */
4017024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Avg8Ux8: case Iop_Avg16Ux4:
4018024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Max16Sx4: case Iop_Max8Ux8: case Iop_Min16Sx4:
4019024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Min8Ux8: case Iop_MulHi16Ux4:
4020024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QNarrow32Sx2: case Iop_QNarrow16Sx4:
4021024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QNarrow16Ux4: case Iop_Add8x8: case Iop_Add32x2:
4022024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd8Ux8:
4023024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QAdd16Ux4: case Iop_Add16x4: case Iop_CmpEQ8x8:
4024024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpEQ32x2: case Iop_CmpEQ16x4: case Iop_CmpGT8Sx8:
4025024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpGT32Sx2: case Iop_CmpGT16Sx4: case Iop_MulHi16Sx4:
4026024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul16x4: case Iop_ShlN32x2: case Iop_ShlN16x4:
4027024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_SarN32x2: case Iop_SarN16x4: case Iop_ShrN32x2:
4028024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_ShrN16x4: case Iop_Sub8x8: case Iop_Sub32x2:
4029024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub8Ux8:
4030024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QSub16Ux4: case Iop_Sub16x4: case Iop_InterleaveHI8x8:
4031024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveHI32x2: case Iop_InterleaveHI16x4:
4032024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveLO8x8: case Iop_InterleaveLO32x2:
4033024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveLO16x4: case Iop_SarN8x8:
4034024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Perm8x8: case Iop_ShlN8x8: case Iop_Mul32x2:
4035024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CatEvenLanes16x4: case Iop_CatOddLanes16x4:
4036024598e40c84666cc311a42c256bbf880db3ac99sewardj         n64:
4037024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4038024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4039024598e40c84666cc311a42c256bbf880db3ac99sewardj
4040024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
4041024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("instrument_arithop(64-bit): unhandled: ");
4042024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIROp(op);
4043024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
4044024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4045024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4046024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4047024598e40c84666cc311a42c256bbf880db3ac99sewardj
4048024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
4049024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid gen_call_nonptr_or_unknown_range ( PCEnv* pce,
4050024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        IRAtom* addr, IRAtom* len )
4051024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4052024598e40c84666cc311a42c256bbf880db3ac99sewardj   gen_dirty_v_WW( pce,
4053024598e40c84666cc311a42c256bbf880db3ac99sewardj                   &nonptr_or_unknown_range,
4054024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "nonptr_or_unknown_range",
4055024598e40c84666cc311a42c256bbf880db3ac99sewardj                   addr, len );
4056024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4057024598e40c84666cc311a42c256bbf880db3ac99sewardj
4058024598e40c84666cc311a42c256bbf880db3ac99sewardj/* iii describes zero or more non-exact integer register updates.  For
4059024598e40c84666cc311a42c256bbf880db3ac99sewardj   each one, generate IR to get the containing register, apply
4060024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown to it, and write it back again. */
4061024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_nonptr_or_unknown_for_III( PCEnv* pce, IntRegInfo* iii )
4062024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4063024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i;
4064024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(iii && iii->n_offsets >= 0);
4065024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < iii->n_offsets; i++) {
4066024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRAtom* a1 = assignNew( 'I', pce, pce->gWordTy,
4067024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr_Get( iii->offsets[i], pce->gWordTy ));
4068024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4069024598e40c84666cc311a42c256bbf880db3ac99sewardj      stmt( 'I', pce, IRStmt_Put( iii->offsets[i]
4070024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     + pce->guest_state_sizeB,
4071024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  mkexpr(a2) ));
4072024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4073024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4074024598e40c84666cc311a42c256bbf880db3ac99sewardj
4075024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Generate into 'ane', instrumentation for 'st'.  Also copy 'st'
4076024598e40c84666cc311a42c256bbf880db3ac99sewardj   itself into 'ane' (the caller does not do so).  This is somewhat
4077024598e40c84666cc311a42c256bbf880db3ac99sewardj   complex and relies heavily on the assumption that the incoming IR
4078024598e40c84666cc311a42c256bbf880db3ac99sewardj   is in flat form.
4079024598e40c84666cc311a42c256bbf880db3ac99sewardj
4080024598e40c84666cc311a42c256bbf880db3ac99sewardj   Generally speaking, the instrumentation is placed after the
4081024598e40c84666cc311a42c256bbf880db3ac99sewardj   original statement, so that results computed by the original can be
4082024598e40c84666cc311a42c256bbf880db3ac99sewardj   used in the instrumentation.  However, that isn't safe for memory
4083024598e40c84666cc311a42c256bbf880db3ac99sewardj   references, since we need the instrumentation (hence bounds check
4084024598e40c84666cc311a42c256bbf880db3ac99sewardj   and potential error message) to happen before the reference itself,
4085024598e40c84666cc311a42c256bbf880db3ac99sewardj   as the latter could cause a fault. */
4086024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void schemeS ( PCEnv* pce, IRStmt* st )
4087024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4088024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(st);
4089024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isFlatIRStmt(st));
4090024598e40c84666cc311a42c256bbf880db3ac99sewardj
4091024598e40c84666cc311a42c256bbf880db3ac99sewardj   switch (st->tag) {
4092024598e40c84666cc311a42c256bbf880db3ac99sewardj
4093024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Dirty: {
4094024598e40c84666cc311a42c256bbf880db3ac99sewardj         Int i;
4095024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRDirty* di;
4096024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4097024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* nasty.  assumes that (1) all helpers are unconditional,
4098024598e40c84666cc311a42c256bbf880db3ac99sewardj            and (2) all outputs are non-ptr */
4099024598e40c84666cc311a42c256bbf880db3ac99sewardj         di = st->Ist.Dirty.details;
4100024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* deal with the return tmp, if any */
4101024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (di->tmp != IRTemp_INVALID
4102024598e40c84666cc311a42c256bbf880db3ac99sewardj             && typeOfIRTemp(pce->bb->tyenv, di->tmp) == pce->gWordTy) {
4103024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* di->tmp is shadowed.  Set it to NONPTR. */
4104024598e40c84666cc311a42c256bbf880db3ac99sewardj            IRTemp dstv = newShadowTmp( pce, di->tmp );
4105024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (pce->gWordTy == Ity_I32) {
4106024598e40c84666cc311a42c256bbf880db3ac99sewardj              assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4107024598e40c84666cc311a42c256bbf880db3ac99sewardj            } else {
4108024598e40c84666cc311a42c256bbf880db3ac99sewardj              assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4109024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4110024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4111024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* apply the nonptr_or_unknown technique to any parts of
4112024598e40c84666cc311a42c256bbf880db3ac99sewardj            the guest state that happen to get written */
4113024598e40c84666cc311a42c256bbf880db3ac99sewardj         for (i = 0; i < di->nFxState; i++) {
4114024598e40c84666cc311a42c256bbf880db3ac99sewardj            IntRegInfo iii;
4115024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->fxState[i].fx != Ifx_None);
4116024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (di->fxState[i].fx == Ifx_Read)
4117024598e40c84666cc311a42c256bbf880db3ac99sewardj               continue; /* this bit is only read -- not interesting */
4118024598e40c84666cc311a42c256bbf880db3ac99sewardj            get_IntRegInfo( &iii, di->fxState[i].offset,
4119024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  di->fxState[i].size );
4120024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(iii.n_offsets >= -1
4121024598e40c84666cc311a42c256bbf880db3ac99sewardj                      && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4122024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* Deal with 3 possible cases, same as with Ist_Put
4123024598e40c84666cc311a42c256bbf880db3ac99sewardj               elsewhere in this function. */
4124024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (iii.n_offsets == -1) {
4125024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* case (1): exact write of an integer register. */
4126024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRAtom* a1
4127024598e40c84666cc311a42c256bbf880db3ac99sewardj                  = assignNew( 'I', pce, pce->gWordTy,
4128024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr_Get( iii.offsets[i], pce->gWordTy ));
4129024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4130024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'I', pce, IRStmt_Put( iii.offsets[i]
4131024598e40c84666cc311a42c256bbf880db3ac99sewardj                                              + pce->guest_state_sizeB,
4132024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           mkexpr(a2) ));
4133024598e40c84666cc311a42c256bbf880db3ac99sewardj            } else {
4134024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* when == 0: case (3): no instrumentation needed */
4135024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* when > 0: case (2) .. complex case.  Fish out the
4136024598e40c84666cc311a42c256bbf880db3ac99sewardj                  stored value for the whole register, heave it
4137024598e40c84666cc311a42c256bbf880db3ac99sewardj                  through nonptr_or_unknown, and use that as the new
4138024598e40c84666cc311a42c256bbf880db3ac99sewardj                  shadow value. */
4139024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(iii.n_offsets >= 0
4140024598e40c84666cc311a42c256bbf880db3ac99sewardj                         && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4141024598e40c84666cc311a42c256bbf880db3ac99sewardj               gen_nonptr_or_unknown_for_III( pce, &iii );
4142024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4143024598e40c84666cc311a42c256bbf880db3ac99sewardj         } /* for (i = 0; i < di->nFxState; i++) */
4144024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* finally, deal with memory outputs */
4145024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (di->mFx != Ifx_None) {
4146024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->mAddr && isIRAtom(di->mAddr));
4147024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->mSize > 0);
4148024598e40c84666cc311a42c256bbf880db3ac99sewardj            gen_call_nonptr_or_unknown_range( pce, di->mAddr,
4149024598e40c84666cc311a42c256bbf880db3ac99sewardj                                              mkIRExpr_HWord(di->mSize));
4150024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4151024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4152024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4153024598e40c84666cc311a42c256bbf880db3ac99sewardj
4154024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_NoOp:
4155024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4156024598e40c84666cc311a42c256bbf880db3ac99sewardj
4157024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* nothing interesting in these; just copy them through */
4158024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_AbiHint:
4159024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_MBE:
4160024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Exit:
4161024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_IMark:
4162024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4163024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4164024598e40c84666cc311a42c256bbf880db3ac99sewardj
4165024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_PutI: {
4166024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRRegArray* descr = st->Ist.PutI.descr;
4167024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4168024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(descr && descr->elemTy);
4169024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (is_integer_guest_reg_array(descr)) {
4170024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* if this fails, is_integer_guest_reg_array is returning
4171024598e40c84666cc311a42c256bbf880db3ac99sewardj               bogus results */
4172024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(descr->elemTy == pce->gWordTy);
4173024598e40c84666cc311a42c256bbf880db3ac99sewardj            stmt(
4174024598e40c84666cc311a42c256bbf880db3ac99sewardj               'I', pce,
4175024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRStmt_PutI(
4176024598e40c84666cc311a42c256bbf880db3ac99sewardj                  mkIRRegArray(descr->base + pce->guest_state_sizeB,
4177024598e40c84666cc311a42c256bbf880db3ac99sewardj                               descr->elemTy, descr->nElems),
4178024598e40c84666cc311a42c256bbf880db3ac99sewardj                  st->Ist.PutI.ix,
4179024598e40c84666cc311a42c256bbf880db3ac99sewardj                  st->Ist.PutI.bias,
4180024598e40c84666cc311a42c256bbf880db3ac99sewardj                  schemeEw_Atom( pce, st->Ist.PutI.data)
4181024598e40c84666cc311a42c256bbf880db3ac99sewardj               )
4182024598e40c84666cc311a42c256bbf880db3ac99sewardj            );
4183024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4184024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4185024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4186024598e40c84666cc311a42c256bbf880db3ac99sewardj
4187024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Put: {
4188024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* PUT(offset) = atom */
4189024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* 3 cases:
4190024598e40c84666cc311a42c256bbf880db3ac99sewardj            1. It's a complete write of an integer register.  Get hold of
4191024598e40c84666cc311a42c256bbf880db3ac99sewardj               'atom's shadow value and write it in the shadow state.
4192024598e40c84666cc311a42c256bbf880db3ac99sewardj            2. It's a partial write of an integer register.  Let the write
4193024598e40c84666cc311a42c256bbf880db3ac99sewardj               happen, then fish out the complete register value and see if,
4194024598e40c84666cc311a42c256bbf880db3ac99sewardj               via range checking, consultation of tea leaves, etc, its
4195024598e40c84666cc311a42c256bbf880db3ac99sewardj               shadow value can be upgraded to anything useful.
4196024598e40c84666cc311a42c256bbf880db3ac99sewardj            3. It is none of the above.  Generate no instrumentation. */
4197024598e40c84666cc311a42c256bbf880db3ac99sewardj         IntRegInfo iii;
4198024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType     ty;
4199024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4200024598e40c84666cc311a42c256bbf880db3ac99sewardj         ty = typeOfIRExpr(pce->bb->tyenv, st->Ist.Put.data);
4201024598e40c84666cc311a42c256bbf880db3ac99sewardj         get_IntRegInfo( &iii, st->Ist.Put.offset,
4202024598e40c84666cc311a42c256bbf880db3ac99sewardj                         sizeofIRType(ty) );
4203024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (iii.n_offsets == -1) {
4204024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* case (1): exact write of an integer register. */
4205024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(ty == pce->gWordTy);
4206024598e40c84666cc311a42c256bbf880db3ac99sewardj            stmt( 'I', pce,
4207024598e40c84666cc311a42c256bbf880db3ac99sewardj                       IRStmt_Put( st->Ist.Put.offset
4208024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      + pce->guest_state_sizeB,
4209024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   schemeEw_Atom( pce, st->Ist.Put.data)) );
4210024598e40c84666cc311a42c256bbf880db3ac99sewardj         } else {
4211024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* when == 0: case (3): no instrumentation needed */
4212024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* when > 0: case (2) .. complex case.  Fish out the
4213024598e40c84666cc311a42c256bbf880db3ac99sewardj               stored value for the whole register, heave it through
4214024598e40c84666cc311a42c256bbf880db3ac99sewardj               nonptr_or_unknown, and use that as the new shadow
4215024598e40c84666cc311a42c256bbf880db3ac99sewardj               value. */
4216024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(iii.n_offsets >= 0
4217024598e40c84666cc311a42c256bbf880db3ac99sewardj                      && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4218024598e40c84666cc311a42c256bbf880db3ac99sewardj            gen_nonptr_or_unknown_for_III( pce, &iii );
4219024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4220024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4221024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_Put */
4222024598e40c84666cc311a42c256bbf880db3ac99sewardj
4223024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Store: {
4224024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We have: STle(addr) = data
4225024598e40c84666cc311a42c256bbf880db3ac99sewardj            if data is int-word sized, do
4226024598e40c84666cc311a42c256bbf880db3ac99sewardj            check_store4(addr, addr#, data, data#)
4227024598e40c84666cc311a42c256bbf880db3ac99sewardj            for all other stores
4228024598e40c84666cc311a42c256bbf880db3ac99sewardj            check_store{1,2}(addr, addr#, data)
4229024598e40c84666cc311a42c256bbf880db3ac99sewardj
4230024598e40c84666cc311a42c256bbf880db3ac99sewardj            The helper actually *does* the store, so that it can do
4231024598e40c84666cc311a42c256bbf880db3ac99sewardj            the post-hoc ugly hack of inspecting and "improving" the
4232024598e40c84666cc311a42c256bbf880db3ac99sewardj            shadow data after the store, in the case where it isn't an
4233024598e40c84666cc311a42c256bbf880db3ac99sewardj            aligned word store.
4234024598e40c84666cc311a42c256bbf880db3ac99sewardj         */
4235024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* data  = st->Ist.Store.data;
4236024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* addr  = st->Ist.Store.addr;
4237024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType  d_ty  = typeOfIRExpr(pce->bb->tyenv, data);
4238024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* addrv = schemeEw_Atom( pce, addr );
4239024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (pce->gWordTy == Ity_I32) {
4240024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* ------ 32 bit host/guest (cough, cough) ------ */
4241024598e40c84666cc311a42c256bbf880db3ac99sewardj            switch (d_ty) {
4242024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer word case */
4243024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I32: {
4244024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRExpr* datav = schemeEw_Atom( pce, data );
4245024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4246024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store4_P, "check_store4_P",
4247024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, data, datav );
4248024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4249024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4250024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer subword cases */
4251024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I16:
4252024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4253024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store2, "check_store2",
4254024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4255024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4256024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4257024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I8:
4258024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4259024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store1, "check_store1",
4260024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4261024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4262024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4263024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit float.  Pass store data in 2 32-bit pieces. */
4264024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F64: {
4265024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* d64 = assignNew( 'I', pce, Ity_I64,
4266024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF64asI64, data) );
4267024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4268024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, d64) );
4269024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4270024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, d64) );
4271024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4272024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_ms4B_ls4B,
4273024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store8_ms4B_ls4B",
4274024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi32, dLo32 );
4275024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4276024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4277024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 32-bit float.  We can just use _store4, but need
4278024598e40c84666cc311a42c256bbf880db3ac99sewardj                  to futz with the argument type. */
4279024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F32: {
4280024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4281024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF32asI32,
4282024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4283024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4284024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4,
4285024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store4",
4286024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, i32 );
4287024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4288024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4289024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit int.  Pass store data in 2 32-bit pieces. */
4290024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I64: {
4291024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4292024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, data) );
4293024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4294024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, data) );
4295024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4296024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_ms4B_ls4B,
4297024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store8_ms4B_ls4B",
4298024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi32, dLo32 );
4299024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4300024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4301024598e40c84666cc311a42c256bbf880db3ac99sewardj
4302024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 128-bit vector.  Pass store data in 4 32-bit pieces.
4303024598e40c84666cc311a42c256bbf880db3ac99sewardj                  This is all very ugly and inefficient, but it is
4304024598e40c84666cc311a42c256bbf880db3ac99sewardj                  hard to better without considerably complicating the
4305024598e40c84666cc311a42c256bbf880db3ac99sewardj                  store-handling schemes. */
4306024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_V128: {
4307024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4308024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128HIto64, data) );
4309024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4310024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128to64, data) );
4311024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w3    = assignNew( 'I', pce, Ity_I32,
4312024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, dHi64) );
4313024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w2    = assignNew( 'I', pce, Ity_I32,
4314024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, dHi64) );
4315024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w1    = assignNew( 'I', pce, Ity_I32,
4316024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, dLo64) );
4317024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w0    = assignNew( 'I', pce, Ity_I32,
4318024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, dLo64) );
4319024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_6W( pce,
4320024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  &check_store16_ms4B_4B_4B_ls4B,
4321024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  "check_store16_ms4B_4B_4B_ls4B",
4322024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  addr, addrv, w3, w2, w1, w0 );
4323024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4324024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4325024598e40c84666cc311a42c256bbf880db3ac99sewardj
4326024598e40c84666cc311a42c256bbf880db3ac99sewardj
4327024598e40c84666cc311a42c256bbf880db3ac99sewardj               default:
4328024598e40c84666cc311a42c256bbf880db3ac99sewardj                  ppIRType(d_ty); tl_assert(0);
4329024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4330024598e40c84666cc311a42c256bbf880db3ac99sewardj         } else {
4331024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* ------ 64 bit host/guest (cough, cough) ------ */
4332024598e40c84666cc311a42c256bbf880db3ac99sewardj            switch (d_ty) {
4333024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer word case */
4334024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I64: {
4335024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRExpr* datav = schemeEw_Atom( pce, data );
4336024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4337024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_P, "check_store8_P",
4338024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, data, datav );
4339024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4340024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4341024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer subword cases */
4342024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I32:
4343024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4344024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4, "check_store4",
4345024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4346024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4347024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4348024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I16:
4349024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4350024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store2, "check_store2",
4351024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4352024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4353024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4354024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I8:
4355024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4356024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store1, "check_store1",
4357024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4358024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4359024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4360024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 128-bit vector.  Pass store data in 2 64-bit pieces. */
4361024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_V128: {
4362024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4363024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128HIto64, data) );
4364024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4365024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128to64, data) );
4366024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4367024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store16_ms8B_ls8B,
4368024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store16_ms8B_ls8B",
4369024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi64, dLo64 );
4370024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4371024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4372024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit float. */
4373024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F64: {
4374024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dI = assignNew( 'I', pce, Ity_I64,
4375024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF64asI64,
4376024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4377024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4378024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store8_all8B,
4379024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store8_all8B",
4380024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, dI );
4381024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4382024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4383024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 32-bit float.  We can just use _store4, but need
4384024598e40c84666cc311a42c256bbf880db3ac99sewardj                  to futz with the argument type. */
4385024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F32: {
4386024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4387024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF32asI32,
4388024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4389024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i64 = assignNew( 'I', pce, Ity_I64,
4390024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_32Uto64,
4391024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                i32 ) );
4392024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4393024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4,
4394024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store4",
4395024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, i64 );
4396024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4397024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4398024598e40c84666cc311a42c256bbf880db3ac99sewardj               default:
4399024598e40c84666cc311a42c256bbf880db3ac99sewardj                  ppIRType(d_ty); tl_assert(0);
4400024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4401024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4402024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* And don't copy the original, since the helper does the
4403024598e40c84666cc311a42c256bbf880db3ac99sewardj            store.  Ick. */
4404024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4405024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_Store */
4406024598e40c84666cc311a42c256bbf880db3ac99sewardj
4407024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_WrTmp: {
4408024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* This is the only place we have to deal with the full
4409024598e40c84666cc311a42c256bbf880db3ac99sewardj            IRExpr range.  In all other places where an IRExpr could
4410024598e40c84666cc311a42c256bbf880db3ac99sewardj            appear, we in fact only get an atom (Iex_RdTmp or
4411024598e40c84666cc311a42c256bbf880db3ac99sewardj            Iex_Const). */
4412024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* e      = st->Ist.WrTmp.data;
4413024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType  e_ty   = typeOfIRExpr( pce->bb->tyenv, e );
4414024598e40c84666cc311a42c256bbf880db3ac99sewardj         Bool    isWord = e_ty == pce->gWordTy;
4415024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp  dst    = st->Ist.WrTmp.tmp;
4416024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp  dstv   = isWord ? newShadowTmp( pce, dst )
4417024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 : IRTemp_INVALID;
4418024598e40c84666cc311a42c256bbf880db3ac99sewardj
4419024598e40c84666cc311a42c256bbf880db3ac99sewardj         switch (e->tag) {
4420024598e40c84666cc311a42c256bbf880db3ac99sewardj
4421024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Const: {
4422024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4423024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4424024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv, schemeEw_Atom( pce, e ) );
4425024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4426024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4427024598e40c84666cc311a42c256bbf880db3ac99sewardj
4428024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_CCall: {
4429024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4430024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4431024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv,
4432024598e40c84666cc311a42c256bbf880db3ac99sewardj                          mkexpr( gen_call_nonptr_or_unknown_w(
4433024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     pce, mkexpr(dst))));
4434024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4435024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4436024598e40c84666cc311a42c256bbf880db3ac99sewardj
4437024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Mux0X: {
4438024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Just steer the shadow values in the same way as the
4439024598e40c84666cc311a42c256bbf880db3ac99sewardj                  originals. */
4440024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4441024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4442024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv,
4443024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRExpr_Mux0X(
4444024598e40c84666cc311a42c256bbf880db3ac99sewardj                             e->Iex.Mux0X.cond,
4445024598e40c84666cc311a42c256bbf880db3ac99sewardj                             schemeEw_Atom( pce, e->Iex.Mux0X.expr0 ),
4446024598e40c84666cc311a42c256bbf880db3ac99sewardj                             schemeEw_Atom( pce, e->Iex.Mux0X.exprX ) ));
4447024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4448024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4449024598e40c84666cc311a42c256bbf880db3ac99sewardj
4450024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_RdTmp: {
4451024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4452024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4453024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv, schemeEw_Atom( pce, e ));
4454024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4455024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4456024598e40c84666cc311a42c256bbf880db3ac99sewardj
4457024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Load: {
4458024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRExpr* addr  = e->Iex.Load.addr;
4459024598e40c84666cc311a42c256bbf880db3ac99sewardj               HChar*  h_nm  = NULL;
4460024598e40c84666cc311a42c256bbf880db3ac99sewardj               void*   h_fn  = NULL;
4461024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRExpr* addrv = NULL;
4462024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (pce->gWordTy == Ity_I32) {
4463024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* 32 bit host/guest (cough, cough) */
4464024598e40c84666cc311a42c256bbf880db3ac99sewardj                  switch (e_ty) {
4465024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* Ity_I32: helper returns shadow value. */
4466024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I32:  h_fn = &check_load4_P;
4467024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4_P"; break;
4468024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* all others: helper does not return a shadow
4469024598e40c84666cc311a42c256bbf880db3ac99sewardj                        value. */
4470024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_V128: h_fn = &check_load16;
4471024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load16"; break;
4472024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I64:
4473024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F64:  h_fn = &check_load8;
4474024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8"; break;
4475024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F32:  h_fn = &check_load4;
4476024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4"; break;
4477024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I16:  h_fn = &check_load2;
4478024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load2"; break;
4479024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I8:   h_fn = &check_load1;
4480024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load1"; break;
4481024598e40c84666cc311a42c256bbf880db3ac99sewardj                     default: ppIRType(e_ty); tl_assert(0);
4482024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4483024598e40c84666cc311a42c256bbf880db3ac99sewardj                  addrv = schemeEw_Atom( pce, addr );
4484024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (e_ty == Ity_I32) {
4485024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4486024598e40c84666cc311a42c256bbf880db3ac99sewardj                              mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4487024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                           addr, addrv )) );
4488024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4489024598e40c84666cc311a42c256bbf880db3ac99sewardj                     gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4490024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4491024598e40c84666cc311a42c256bbf880db3ac99sewardj               } else {
4492024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* 64 bit host/guest (cough, cough) */
4493024598e40c84666cc311a42c256bbf880db3ac99sewardj                  switch (e_ty) {
4494024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* Ity_I64: helper returns shadow value. */
4495024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I64:  h_fn = &check_load8_P;
4496024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8_P"; break;
4497024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* all others: helper does not return a shadow
4498024598e40c84666cc311a42c256bbf880db3ac99sewardj                        value. */
4499024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_V128: h_fn = &check_load16;
4500024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load16"; break;
4501024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F64:  h_fn = &check_load8;
4502024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8"; break;
4503024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F32:
4504024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I32:  h_fn = &check_load4;
4505024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4"; break;
4506024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I16:  h_fn = &check_load2;
4507024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load2"; break;
4508024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I8:   h_fn = &check_load1;
4509024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load1"; break;
4510024598e40c84666cc311a42c256bbf880db3ac99sewardj                     default: ppIRType(e_ty); tl_assert(0);
4511024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4512024598e40c84666cc311a42c256bbf880db3ac99sewardj                  addrv = schemeEw_Atom( pce, addr );
4513024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (e_ty == Ity_I64) {
4514024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4515024598e40c84666cc311a42c256bbf880db3ac99sewardj                              mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4516024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                           addr, addrv )) );
4517024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4518024598e40c84666cc311a42c256bbf880db3ac99sewardj                     gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4519024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4520024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4521024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* copy the original -- must happen after the helper call */
4522024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4523024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4524024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4525024598e40c84666cc311a42c256bbf880db3ac99sewardj
4526024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_GetI: {
4527024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRRegArray* descr = e->Iex.GetI.descr;
4528024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4529024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(descr && descr->elemTy);
4530024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (is_integer_guest_reg_array(descr)) {
4531024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* if this fails, is_integer_guest_reg_array is
4532024598e40c84666cc311a42c256bbf880db3ac99sewardj                     returning bogus results */
4533024598e40c84666cc311a42c256bbf880db3ac99sewardj                  tl_assert(isWord);
4534024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign(
4535024598e40c84666cc311a42c256bbf880db3ac99sewardj                     'I', pce, dstv,
4536024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRExpr_GetI(
4537024598e40c84666cc311a42c256bbf880db3ac99sewardj                        mkIRRegArray(descr->base + pce->guest_state_sizeB,
4538024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     descr->elemTy, descr->nElems),
4539024598e40c84666cc311a42c256bbf880db3ac99sewardj                        e->Iex.GetI.ix,
4540024598e40c84666cc311a42c256bbf880db3ac99sewardj                        e->Iex.GetI.bias
4541024598e40c84666cc311a42c256bbf880db3ac99sewardj                     )
4542024598e40c84666cc311a42c256bbf880db3ac99sewardj                  );
4543024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4544024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4545024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4546024598e40c84666cc311a42c256bbf880db3ac99sewardj
4547024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Get: {
4548024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4549024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord) {
4550024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* guest-word-typed tmp assignment, so it will have a
4551024598e40c84666cc311a42c256bbf880db3ac99sewardj                     shadow tmp, and we must make an assignment to
4552024598e40c84666cc311a42c256bbf880db3ac99sewardj                     that */
4553024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (is_integer_guest_reg(e->Iex.Get.offset,
4554024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           sizeofIRType(e->Iex.Get.ty))) {
4555024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4556024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr_Get( e->Iex.Get.offset
4557024598e40c84666cc311a42c256bbf880db3ac99sewardj                                            + pce->guest_state_sizeB,
4558024598e40c84666cc311a42c256bbf880db3ac99sewardj                                         e->Iex.Get.ty) );
4559024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4560024598e40c84666cc311a42c256bbf880db3ac99sewardj                     if (pce->hWordTy == Ity_I32) {
4561024598e40c84666cc311a42c256bbf880db3ac99sewardj                        assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4562024598e40c84666cc311a42c256bbf880db3ac99sewardj                     } else {
4563024598e40c84666cc311a42c256bbf880db3ac99sewardj                       assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4564024598e40c84666cc311a42c256bbf880db3ac99sewardj                     }
4565024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4566024598e40c84666cc311a42c256bbf880db3ac99sewardj               } else {
4567024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* tmp isn't guest-word-typed, so isn't shadowed, so
4568024598e40c84666cc311a42c256bbf880db3ac99sewardj                     generate no instrumentation */
4569024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4570024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4571024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4572024598e40c84666cc311a42c256bbf880db3ac99sewardj
4573024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Unop: {
4574024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4575024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Unop.arg));
4576024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4577024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Unop.op,
4578024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Unop.arg,
4579024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      NULL, NULL, NULL );
4580024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4581024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4582024598e40c84666cc311a42c256bbf880db3ac99sewardj
4583024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Binop: {
4584024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4585024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Binop.arg1));
4586024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Binop.arg2));
4587024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4588024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Binop.op,
4589024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Binop.arg1, e->Iex.Binop.arg2,
4590024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      NULL, NULL );
4591024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4592024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4593024598e40c84666cc311a42c256bbf880db3ac99sewardj
4594024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Triop: {
4595024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4596024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg1));
4597024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg2));
4598024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg3));
4599024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4600024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Triop.op,
4601024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Triop.arg1, e->Iex.Triop.arg2,
4602024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Triop.arg3, NULL );
4603024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4604024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4605024598e40c84666cc311a42c256bbf880db3ac99sewardj
4606024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Qop: {
4607024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4608024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg1));
4609024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg2));
4610024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg3));
4611024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg4));
4612024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4613024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Qop.op,
4614024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Qop.arg1, e->Iex.Qop.arg2,
4615024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Qop.arg3, e->Iex.Qop.arg4 );
4616024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4617024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4618024598e40c84666cc311a42c256bbf880db3ac99sewardj
4619024598e40c84666cc311a42c256bbf880db3ac99sewardj            default:
4620024598e40c84666cc311a42c256bbf880db3ac99sewardj               goto unhandled;
4621024598e40c84666cc311a42c256bbf880db3ac99sewardj         } /* switch (e->tag) */
4622024598e40c84666cc311a42c256bbf880db3ac99sewardj
4623024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4624024598e40c84666cc311a42c256bbf880db3ac99sewardj
4625024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_WrTmp */
4626024598e40c84666cc311a42c256bbf880db3ac99sewardj
4627024598e40c84666cc311a42c256bbf880db3ac99sewardj      default:
4628024598e40c84666cc311a42c256bbf880db3ac99sewardj      unhandled:
4629024598e40c84666cc311a42c256bbf880db3ac99sewardj         ppIRStmt(st);
4630024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(0);
4631024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4632024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4633024598e40c84666cc311a42c256bbf880db3ac99sewardj
4634024598e40c84666cc311a42c256bbf880db3ac99sewardj
4635024598e40c84666cc311a42c256bbf880db3ac99sewardjIRSB* h_instrument ( VgCallbackClosure* closure,
4636024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRSB* sbIn,
4637024598e40c84666cc311a42c256bbf880db3ac99sewardj                     VexGuestLayout* layout,
4638024598e40c84666cc311a42c256bbf880db3ac99sewardj                     VexGuestExtents* vge,
4639024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRType gWordTy, IRType hWordTy )
4640024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4641024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool  verboze = 0||False;
4642024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int   i /*, j*/;
4643024598e40c84666cc311a42c256bbf880db3ac99sewardj   PCEnv pce;
4644024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct _SGEnv* sgenv;
4645024598e40c84666cc311a42c256bbf880db3ac99sewardj
4646024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (gWordTy != hWordTy) {
4647024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* We don't currently support this case. */
4648024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("host/guest word size mismatch");
4649024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4650024598e40c84666cc311a42c256bbf880db3ac99sewardj
4651024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Check we're not completely nuts */
4652024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord)  == sizeof(void*));
4653024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Word)   == sizeof(void*));
4654024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr)   == sizeof(void*));
4655024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(ULong)  == 8);
4656024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Long)   == 8);
4657024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr64) == 8);
4658024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UInt)   == 4);
4659024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Int)    == 4);
4660024598e40c84666cc311a42c256bbf880db3ac99sewardj
4661024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set up the running environment.  Only .bb is modified as we go
4662024598e40c84666cc311a42c256bbf880db3ac99sewardj      along. */
4663024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.bb                = deepCopyIRSBExceptStmts(sbIn);
4664024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.trace             = verboze;
4665024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.n_originalTmps    = sbIn->tyenv->types_used;
4666024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.hWordTy           = hWordTy;
4667024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.gWordTy           = gWordTy;
4668024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.guest_state_sizeB = layout->total_sizeB;
4669024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.tmpMap            = LibVEX_Alloc(pce.n_originalTmps * sizeof(IRTemp));
4670024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < pce.n_originalTmps; i++)
4671024598e40c84666cc311a42c256bbf880db3ac99sewardj      pce.tmpMap[i] = IRTemp_INVALID;
4672024598e40c84666cc311a42c256bbf880db3ac99sewardj
4673024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Also set up for the sg_ instrumenter.  See comments
4674024598e40c84666cc311a42c256bbf880db3ac99sewardj      at the top of this instrumentation section for details. */
4675024598e40c84666cc311a42c256bbf880db3ac99sewardj   sgenv = sg_instrument_init();
4676024598e40c84666cc311a42c256bbf880db3ac99sewardj
4677024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Stay sane.  These two should agree! */
4678024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(layout->total_sizeB == MC_SIZEOF_GUEST_STATE);
4679024598e40c84666cc311a42c256bbf880db3ac99sewardj
4680024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Copy verbatim any IR preamble preceding the first IMark */
4681024598e40c84666cc311a42c256bbf880db3ac99sewardj
4682024598e40c84666cc311a42c256bbf880db3ac99sewardj   i = 0;
4683024598e40c84666cc311a42c256bbf880db3ac99sewardj   while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
4684024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRStmt* st = sbIn->stmts[i];
4685024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(st);
4686024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(isFlatIRStmt(st));
4687024598e40c84666cc311a42c256bbf880db3ac99sewardj      stmt( 'C', &pce, sbIn->stmts[i] );
4688024598e40c84666cc311a42c256bbf880db3ac99sewardj      i++;
4689024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4690024598e40c84666cc311a42c256bbf880db3ac99sewardj
4691024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Nasty problem.  IR optimisation of the pre-instrumented IR may
4692024598e40c84666cc311a42c256bbf880db3ac99sewardj      cause the IR following the preamble to contain references to IR
4693024598e40c84666cc311a42c256bbf880db3ac99sewardj      temporaries defined in the preamble.  Because the preamble isn't
4694024598e40c84666cc311a42c256bbf880db3ac99sewardj      instrumented, these temporaries don't have any shadows.
4695024598e40c84666cc311a42c256bbf880db3ac99sewardj      Nevertheless uses of them following the preamble will cause
4696024598e40c84666cc311a42c256bbf880db3ac99sewardj      memcheck to generate references to their shadows.  End effect is
4697024598e40c84666cc311a42c256bbf880db3ac99sewardj      to cause IR sanity check failures, due to references to
4698024598e40c84666cc311a42c256bbf880db3ac99sewardj      non-existent shadows.  This is only evident for the complex
4699024598e40c84666cc311a42c256bbf880db3ac99sewardj      preambles used for function wrapping on TOC-afflicted platforms
4700024598e40c84666cc311a42c256bbf880db3ac99sewardj      (ppc64-linux, ppc32-aix5, ppc64-aix5).
4701024598e40c84666cc311a42c256bbf880db3ac99sewardj
4702024598e40c84666cc311a42c256bbf880db3ac99sewardj      The following loop therefore scans the preamble looking for
4703024598e40c84666cc311a42c256bbf880db3ac99sewardj      assignments to temporaries.  For each one found it creates an
4704024598e40c84666cc311a42c256bbf880db3ac99sewardj      assignment to the corresponding shadow temp, marking it as
4705024598e40c84666cc311a42c256bbf880db3ac99sewardj      'defined'.  This is the same resulting IR as if the main
4706024598e40c84666cc311a42c256bbf880db3ac99sewardj      instrumentation loop before had been applied to the statement
4707024598e40c84666cc311a42c256bbf880db3ac99sewardj      'tmp = CONSTANT'.
4708024598e40c84666cc311a42c256bbf880db3ac99sewardj   */
4709024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
4710024598e40c84666cc311a42c256bbf880db3ac99sewardj   // FIXME: this isn't exactly right; only needs to generate shadows
4711024598e40c84666cc311a42c256bbf880db3ac99sewardj   // for guest-word-typed temps
4712024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (j = 0; j < i; j++) {
4713024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (sbIn->stmts[j]->tag == Ist_WrTmp) {
4714024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* findShadowTmpV checks its arg is an original tmp;
4715024598e40c84666cc311a42c256bbf880db3ac99sewardj            no need to assert that here. */
4716024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp tmp_o = sbIn->stmts[j]->Ist.WrTmp.tmp;
4717024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp tmp_s = findShadowTmp(&pce, tmp_o);
4718024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType ty_s  = typeOfIRTemp(sbIn->tyenv, tmp_s);
4719024598e40c84666cc311a42c256bbf880db3ac99sewardj         assign( 'V', &pce, tmp_s, definedOfType( ty_s ) );
4720024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) {
4721024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j);
4722024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType( ty_s );
4723024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("\n");
4724024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4725024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4726024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4727024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
4728024598e40c84666cc311a42c256bbf880db3ac99sewardj
4729024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Iterate over the remaining stmts to generate instrumentation. */
4730024598e40c84666cc311a42c256bbf880db3ac99sewardj
4731024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sbIn->stmts_used > 0);
4732024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0);
4733024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i < sbIn->stmts_used);
4734024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
4735024598e40c84666cc311a42c256bbf880db3ac99sewardj
4736024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (/*use current i*/; i < sbIn->stmts_used; i++) {
4737024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* generate sg_ instrumentation for this stmt */
4738024598e40c84666cc311a42c256bbf880db3ac99sewardj      sg_instrument_IRStmt( sgenv, pce.bb, sbIn->stmts[i],
4739024598e40c84666cc311a42c256bbf880db3ac99sewardj                            layout, gWordTy, hWordTy );
4740024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* generate h_ instrumentation for this stmt */
4741024598e40c84666cc311a42c256bbf880db3ac99sewardj      schemeS( &pce, sbIn->stmts[i] );
4742024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4743024598e40c84666cc311a42c256bbf880db3ac99sewardj
4744024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* generate sg_ instrumentation for the final jump */
4745024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_final_jump( sgenv, pce.bb, sbIn->next, sbIn->jumpkind,
4746024598e40c84666cc311a42c256bbf880db3ac99sewardj                             layout, gWordTy, hWordTy );
4747024598e40c84666cc311a42c256bbf880db3ac99sewardj
4748024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* and finalise .. */
4749024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_fini( sgenv );
4750024598e40c84666cc311a42c256bbf880db3ac99sewardj
4751024598e40c84666cc311a42c256bbf880db3ac99sewardj   return pce.bb;
4752024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4753024598e40c84666cc311a42c256bbf880db3ac99sewardj
4754024598e40c84666cc311a42c256bbf880db3ac99sewardj
4755024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4756024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Initialisation                                               ---*/
4757024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4758024598e40c84666cc311a42c256bbf880db3ac99sewardj
4759024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_clo_init ( void )
4760024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4761024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Other initialisation
4762024598e40c84666cc311a42c256bbf880db3ac99sewardj   init_shadow_memory();
4763024598e40c84666cc311a42c256bbf880db3ac99sewardj   init_lossage();
4764024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4765024598e40c84666cc311a42c256bbf880db3ac99sewardj
4766024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_clo_init ( void )
4767024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4768024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4769024598e40c84666cc311a42c256bbf880db3ac99sewardj
4770024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4771024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Finalisation                                                 ---*/
4772024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4773024598e40c84666cc311a42c256bbf880db3ac99sewardj
4774024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_fini ( Int exitcode )
4775024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4776024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_(clo_verbosity) >= 2) {
4777024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_DebugMsg,
4778024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "  h_:  %'10llu client allocs, %'10llu client frees",
4779024598e40c84666cc311a42c256bbf880db3ac99sewardj                   stats__client_mallocs, stats__client_frees);
4780024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_DebugMsg,
4781024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "  h_:  %'10llu Segs allocd,   %'10llu Segs recycled",
4782024598e40c84666cc311a42c256bbf880db3ac99sewardj                   stats__segs_allocd, stats__segs_recycled);
4783024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4784024598e40c84666cc311a42c256bbf880db3ac99sewardj
47854815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#if 0
4786024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (h_clo_lossage_check) {
4787024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
4788024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld total memory references",
4789024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__tot_mem_refs);
4790024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld   of which are in a known segment",
4791024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__refs_in_a_seg);
4792024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld   of which are 'lost' w.r.t the seg",
4793024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__refs_lost_seg);
4794024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
4795024598e40c84666cc311a42c256bbf880db3ac99sewardj      show_lossage();
4796024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
4797024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
4798024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert( 0 == VG_(OSetGen_Size)(lossage) );
4799024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
48004815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#endif
4801024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4802024598e40c84666cc311a42c256bbf880db3ac99sewardj
4803024598e40c84666cc311a42c256bbf880db3ac99sewardj
4804024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4805024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- end                                                 h_main.c ---*/
4806024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4807