h_main.c revision e6451332ee19f6d70821bf8e24781ff8868bdb3c
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
149f207460d70d38c46c9e81996a3dcdf90961c6dbnjn   Copyright (C) 2003-2009 Nicholas Nethercote
15024598e40c84666cc311a42c256bbf880db3ac99sewardj      njn@valgrind.org
16024598e40c84666cc311a42c256bbf880db3ac99sewardj
17024598e40c84666cc311a42c256bbf880db3ac99sewardj   Valgrind-3.X port:
18024598e40c84666cc311a42c256bbf880db3ac99sewardj
199f207460d70d38c46c9e81996a3dcdf90961c6dbnjn   Copyright (C) 2008-2009 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
1167024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Don't check code being translated -- very slow, and not much point
1168024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (Vg_CoreTranslate == part) return;
1169024598e40c84666cc311a42c256bbf880db3ac99sewardj
1170024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Don't check the signal case -- only happens in core, no need to check
1171024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (Vg_CoreSignal == part) return;
1172024598e40c84666cc311a42c256bbf880db3ac99sewardj
1173024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Only expect syscalls after this point
1174024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (part != Vg_CoreSysCall) {
1175024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("part = %d\n", part);
1176024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("unknown corepart in pre_mem_access2");
1177024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1178024598e40c84666cc311a42c256bbf880db3ac99sewardj
1179024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Check first and last bytes match
11809520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   seglo = get_Seg_containing_addr( s );
11819520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj   seghi = get_Seg_containing_addr( e );
1182024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert( BOTTOM != seglo && NONPTR != seglo );
1183024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert( BOTTOM != seghi && NONPTR != seghi );
1184024598e40c84666cc311a42c256bbf880db3ac99sewardj
11854c245e595b9f6300d3120408ca873f7115d9cc7dnjn   /* record an error if start and end are in different, but known segments */
1186024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seglo) && is_known_segment(seghi)
1187024598e40c84666cc311a42c256bbf880db3ac99sewardj       && seglo != seghi) {
1188024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, seglo, seghi);
1189024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1190024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
1191024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if start is in a known segment but end isn't */
1192024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seglo) && !is_known_segment(seghi)) {
1193024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
1194024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1195024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
1196024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if end is in a known segment but start isn't */
1197024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!is_known_segment(seglo) && is_known_segment(seghi)) {
1198024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, UNKNOWN, seghi);
1199024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1200024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1201024598e40c84666cc311a42c256bbf880db3ac99sewardj
1202024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
1203024598e40c84666cc311a42c256bbf880db3ac99sewardj                        Addr base, SizeT size )
1204024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1205024598e40c84666cc311a42c256bbf880db3ac99sewardj   pre_mem_access2( part, tid, s, base, base + size - 1 );
1206024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1207024598e40c84666cc311a42c256bbf880db3ac99sewardj
1208024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
1209024598e40c84666cc311a42c256bbf880db3ac99sewardj                             Char* s, Addr lo )
1210024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1211024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr hi = lo;
1212024598e40c84666cc311a42c256bbf880db3ac99sewardj
1213024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Nb: the '\0' must be included in the lo...hi range
1214024598e40c84666cc311a42c256bbf880db3ac99sewardj   while ('\0' != *(Char*)hi) hi++;
1215024598e40c84666cc311a42c256bbf880db3ac99sewardj   pre_mem_access2( part, tid, s, lo, hi );
1216024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1217024598e40c84666cc311a42c256bbf880db3ac99sewardj
1218024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_mem_write(Addr a, UInt len)
1219024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1220024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem_unknown(a, len);
1221024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1222024598e40c84666cc311a42c256bbf880db3ac99sewardj
1223024598e40c84666cc311a42c256bbf880db3ac99sewardj
1224024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1225024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Register event handlers                              ---*/
1226024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1227024598e40c84666cc311a42c256bbf880db3ac99sewardj
1228024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_regs_write_init ( void )
1229024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1230024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    UInt i;
1231024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    for (i = R_EAX; i <= R_EDI; i++)
1232024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       VG_(set_shadow_archreg)( i, (UInt)UNKNOWN );
1233024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1234024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    // Don't bother about eflags
1235024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1236024598e40c84666cc311a42c256bbf880db3ac99sewardj
1237024598e40c84666cc311a42c256bbf880db3ac99sewardj// BEGIN move this uglyness to pc_machine.c
1238024598e40c84666cc311a42c256bbf880db3ac99sewardj
1239024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_big_endian ( void ) {
1240024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt x = 0x11223344;
1241024598e40c84666cc311a42c256bbf880db3ac99sewardj   return 0x1122 == *(UShort*)(&x);
1242024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1243024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_little_endian ( void ) {
1244024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt x = 0x11223344;
1245024598e40c84666cc311a42c256bbf880db3ac99sewardj   return 0x3344 == *(UShort*)(&x);
1246024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1247024598e40c84666cc311a42c256bbf880db3ac99sewardj
1248024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_INTREGINFO_OFFSETS 4
1249024598e40c84666cc311a42c256bbf880db3ac99sewardj
1250024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Holds the result of a query to 'get_IntRegInfo'.  Valid values for
1251024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_offsets are:
1252024598e40c84666cc311a42c256bbf880db3ac99sewardj
1253024598e40c84666cc311a42c256bbf880db3ac99sewardj   -1: means the queried guest state slice exactly matches
1254024598e40c84666cc311a42c256bbf880db3ac99sewardj       one integer register
1255024598e40c84666cc311a42c256bbf880db3ac99sewardj
1256024598e40c84666cc311a42c256bbf880db3ac99sewardj   0: means the queried guest state slice does not overlap any
1257024598e40c84666cc311a42c256bbf880db3ac99sewardj      integer registers
1258024598e40c84666cc311a42c256bbf880db3ac99sewardj
1259024598e40c84666cc311a42c256bbf880db3ac99sewardj   1 .. N_INTREGINFO_OFFSETS: means the queried guest state offset
1260024598e40c84666cc311a42c256bbf880db3ac99sewardj      overlaps n_offsets different integer registers, and their base
1261024598e40c84666cc311a42c256bbf880db3ac99sewardj      offsets are placed in the offsets array.
1262024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
1263024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
1264024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
1265024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int offsets[N_INTREGINFO_OFFSETS];
1266024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int n_offsets;
1267024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1268024598e40c84666cc311a42c256bbf880db3ac99sewardj   IntRegInfo;
1269024598e40c84666cc311a42c256bbf880db3ac99sewardj
1270024598e40c84666cc311a42c256bbf880db3ac99sewardj
1271024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_x86)
1272024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_x86.h"
1273024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestX86State)
1274024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1275024598e40c84666cc311a42c256bbf880db3ac99sewardj
1276024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_amd64)
1277024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_amd64.h"
1278024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestAMD64State)
1279024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_OFF_FS_ZERO offsetof(VexGuestAMD64State,guest_FS_ZERO)
1280024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_SZB_FS_ZERO sizeof( ((VexGuestAMD64State*)0)->guest_FS_ZERO)
1281024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1282024598e40c84666cc311a42c256bbf880db3ac99sewardj
1283024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc32)
1284024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc32.h"
1285024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC32State)
1286024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1287024598e40c84666cc311a42c256bbf880db3ac99sewardj
1288024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc64)
1289024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc64.h"
1290024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State)
1291024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1292024598e40c84666cc311a42c256bbf880db3ac99sewardj
1293024598e40c84666cc311a42c256bbf880db3ac99sewardj
1294024598e40c84666cc311a42c256bbf880db3ac99sewardj/* See description on definition of type IntRegInfo. */
1295024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB )
1296024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1297024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------------- x86 --------------------- */
1298024598e40c84666cc311a42c256bbf880db3ac99sewardj
1299024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86)
1300024598e40c84666cc311a42c256bbf880db3ac99sewardj
1301024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1302024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestX86State,guest_##_fieldname))
1303024598e40c84666cc311a42c256bbf880db3ac99sewardj
1304024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1305024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1306024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1307024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is21 = sz == 2 || sz == 1;
1308024598e40c84666cc311a42c256bbf880db3ac99sewardj
1309024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1310024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_little_endian());
1311024598e40c84666cc311a42c256bbf880db3ac99sewardj
1312024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1313024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1314024598e40c84666cc311a42c256bbf880db3ac99sewardj
1315024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1316024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)     && is4) goto exactly1;
1317024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)     && is4) goto exactly1;
1318024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)     && is4) goto exactly1;
1319024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBX)     && is4) goto exactly1;
1320024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESP)     && is4) goto exactly1;
1321024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBP)     && is4) goto exactly1;
1322024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESI)     && is4) goto exactly1;
1323024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDI)     && is4) goto exactly1;
1324024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EIP)     && is4) goto none;
13255685ade0e6988c118c0451c50c72a3f2533b7efesewardj   if (o == GOF(IP_AT_SYSCALL) && is4) goto none;
1326024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_OP)   && is4) goto none;
1327024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP1) && is4) goto none;
1328024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP2) && is4) goto none;
1329024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_NDEP) && is4) goto none;
1330024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(DFLAG)   && is4) goto none;
1331024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(IDFLAG)  && is4) goto none;
1332024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ACFLAG)  && is4) goto none;
1333024598e40c84666cc311a42c256bbf880db3ac99sewardj
1334024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Partial accesses to integer registers */
1335024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)     && is21) {         o -= 0; goto contains_o; }
1336024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1337024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)     && is21) {         o -= 0; goto contains_o; }
1338024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1339024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBX)     && is21) {         o -= 0; goto contains_o; }
1340db44098732d646126c8f9168e4f05e08a4040cafsewardj   if (o == GOF(EBX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1341024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)     && is21) {         o -= 0; goto contains_o; }
1342024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1343024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESI)     && is21) {         o -= 0; goto contains_o; }
1344024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDI)     && is21) {         o -= 0; goto contains_o; }
1345024598e40c84666cc311a42c256bbf880db3ac99sewardj
1346024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Segment related guff */
1347024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GS)  && sz == 2) goto none;
1348024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LDT) && is4) goto none;
1349024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GDT) && is4) goto none;
1350024598e40c84666cc311a42c256bbf880db3ac99sewardj
1351024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1352024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(SSEROUND) && is4) goto none;
1353024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND)  && is4) goto none;
1354024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)   && is4) goto none;
1355024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FTOP)     && is4) goto none;
1356024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPTAG)    && sz == 8) goto none;
1357024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FC3210)   && is4) goto none;
1358024598e40c84666cc311a42c256bbf880db3ac99sewardj
1359024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* xmm registers, including arbitrary sub-parts */
1360024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1361024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1362024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1363024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1364024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1365024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1366024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1367024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1368024598e40c84666cc311a42c256bbf880db3ac99sewardj
1369024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1370024598e40c84666cc311a42c256bbf880db3ac99sewardj      to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1371024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1372024598e40c84666cc311a42c256bbf880db3ac99sewardj
1373024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* the entire mmx/x87 register bank in one big piece */
1374024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPREG) && sz == 64) goto none;
1375024598e40c84666cc311a42c256bbf880db3ac99sewardj
1376024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(x86):failing on (%d,%d)\n", o, sz);
1377024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1378024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1379024598e40c84666cc311a42c256bbf880db3ac99sewardj
1380024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- amd64 -------------------- */
1381024598e40c84666cc311a42c256bbf880db3ac99sewardj
1382024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64)
1383024598e40c84666cc311a42c256bbf880db3ac99sewardj
1384024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1385024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestAMD64State,guest_##_fieldname))
1386024598e40c84666cc311a42c256bbf880db3ac99sewardj
1387024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o     = offset;
1388024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz    = szB;
1389024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is421 = sz == 4 || sz == 2 || sz == 1;
1390024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8   = sz == 8;
1391024598e40c84666cc311a42c256bbf880db3ac99sewardj
1392024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1393024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_little_endian());
1394024598e40c84666cc311a42c256bbf880db3ac99sewardj
1395024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1396024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1397024598e40c84666cc311a42c256bbf880db3ac99sewardj
1398024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1399024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)     && is8) goto exactly1;
1400024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)     && is8) goto exactly1;
1401024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)     && is8) goto exactly1;
1402024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)     && is8) goto exactly1;
1403024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSP)     && is8) goto exactly1;
1404024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBP)     && is8) goto exactly1;
1405024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSI)     && is8) goto exactly1;
1406024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDI)     && is8) goto exactly1;
1407024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R8)      && is8) goto exactly1;
1408024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R9)      && is8) goto exactly1;
1409024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R10)     && is8) goto exactly1;
1410024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R11)     && is8) goto exactly1;
1411024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R12)     && is8) goto exactly1;
1412024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R13)     && is8) goto exactly1;
1413024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R14)     && is8) goto exactly1;
1414024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R15)     && is8) goto exactly1;
1415024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RIP)     && is8) goto exactly1;
14165685ade0e6988c118c0451c50c72a3f2533b7efesewardj   if (o == GOF(IP_AT_SYSCALL) && is8) goto none;
1417024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_OP)   && is8) goto none;
1418024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP1) && is8) goto none;
1419024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP2) && is8) goto none;
1420024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_NDEP) && is8) goto none;
1421024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(DFLAG)   && is8) goto none;
1422024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(IDFLAG)  && is8) goto none;
1423024598e40c84666cc311a42c256bbf880db3ac99sewardj
1424024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Partial accesses to integer registers */
1425024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)     && is421) {         o -= 0; goto contains_o; }
1426024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1427024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)     && is421) {         o -= 0; goto contains_o; }
1428024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1429024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)     && is421) {         o -= 0; goto contains_o; }
1430024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1431024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)     && is421) {         o -= 0; goto contains_o; }
1432024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1433024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBP)     && is421) {         o -= 0; goto contains_o; }
1434024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSI)     && is421) {         o -= 0; goto contains_o; }
1435024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDI)     && is421) {         o -= 0; goto contains_o; }
1436024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R8)      && is421) {         o -= 0; goto contains_o; }
1437024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R9)      && is421) {         o -= 0; goto contains_o; }
1438024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R10)     && is421) {         o -= 0; goto contains_o; }
1439024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R11)     && is421) {         o -= 0; goto contains_o; }
1440024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R12)     && is421) {         o -= 0; goto contains_o; }
1441024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R13)     && is421) {         o -= 0; goto contains_o; }
1442024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R14)     && is421) {         o -= 0; goto contains_o; }
1443024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R15)     && is421) {         o -= 0; goto contains_o; }
1444024598e40c84666cc311a42c256bbf880db3ac99sewardj
1445024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Segment related guff */
1446024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FS_ZERO) && is8) goto exactly1;
1447024598e40c84666cc311a42c256bbf880db3ac99sewardj
1448024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1449024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(SSEROUND) && is8) goto none;
1450024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND)  && is8) goto none;
1451024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)   && sz == 4) goto none;
1452024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FTOP)     && sz == 4) goto none;
1453024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPTAG)    && is8) goto none;
1454024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FC3210)   && is8) goto none;
1455024598e40c84666cc311a42c256bbf880db3ac99sewardj
1456024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* xmm registers, including arbitrary sub-parts */
1457024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM0)  && o+sz <= GOF(XMM0)+16)  goto none;
1458024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM1)  && o+sz <= GOF(XMM1)+16)  goto none;
1459024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM2)  && o+sz <= GOF(XMM2)+16)  goto none;
1460024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM3)  && o+sz <= GOF(XMM3)+16)  goto none;
1461024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM4)  && o+sz <= GOF(XMM4)+16)  goto none;
1462024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM5)  && o+sz <= GOF(XMM5)+16)  goto none;
1463024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM6)  && o+sz <= GOF(XMM6)+16)  goto none;
1464024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM7)  && o+sz <= GOF(XMM7)+16)  goto none;
1465024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM8)  && o+sz <= GOF(XMM8)+16)  goto none;
1466024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM9)  && o+sz <= GOF(XMM9)+16)  goto none;
1467024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+16) goto none;
1468024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+16) goto none;
1469024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+16) goto none;
1470024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+16) goto none;
1471024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+16) goto none;
1472024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+16) goto none;
1473024598e40c84666cc311a42c256bbf880db3ac99sewardj
1474024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1475024598e40c84666cc311a42c256bbf880db3ac99sewardj      to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1476024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1477024598e40c84666cc311a42c256bbf880db3ac99sewardj
1478024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(amd64):failing on (%d,%d)\n", o, sz);
1479024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1480024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1481024598e40c84666cc311a42c256bbf880db3ac99sewardj
1482024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc32 -------------------- */
1483024598e40c84666cc311a42c256bbf880db3ac99sewardj
1484024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc32)
1485024598e40c84666cc311a42c256bbf880db3ac99sewardj
1486024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1487024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestPPC32State,guest_##_fieldname))
1488024598e40c84666cc311a42c256bbf880db3ac99sewardj
1489024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1490024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1491024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1492024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8  = sz == 8;
1493024598e40c84666cc311a42c256bbf880db3ac99sewardj
1494024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1495024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_big_endian());
1496024598e40c84666cc311a42c256bbf880db3ac99sewardj
1497024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1498024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1499024598e40c84666cc311a42c256bbf880db3ac99sewardj
1500024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1501024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR0)  && is4) goto exactly1;
1502024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR1)  && is4) goto exactly1;
1503024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR2)  && is4) goto exactly1;
1504024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR3)  && is4) goto exactly1;
1505024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR4)  && is4) goto exactly1;
1506024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR5)  && is4) goto exactly1;
1507024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR6)  && is4) goto exactly1;
1508024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR7)  && is4) goto exactly1;
1509024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR8)  && is4) goto exactly1;
1510024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR9)  && is4) goto exactly1;
1511024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR10) && is4) goto exactly1;
1512024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR11) && is4) goto exactly1;
1513024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR12) && is4) goto exactly1;
1514024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR13) && is4) goto exactly1;
1515024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR14) && is4) goto exactly1;
1516024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR15) && is4) goto exactly1;
1517024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR16) && is4) goto exactly1;
1518024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR17) && is4) goto exactly1;
1519024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR18) && is4) goto exactly1;
1520024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR19) && is4) goto exactly1;
1521024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR20) && is4) goto exactly1;
1522024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR21) && is4) goto exactly1;
1523024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR22) && is4) goto exactly1;
1524024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR23) && is4) goto exactly1;
1525024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR24) && is4) goto exactly1;
1526024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR25) && is4) goto exactly1;
1527024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR26) && is4) goto exactly1;
1528024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR27) && is4) goto exactly1;
1529024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR28) && is4) goto exactly1;
1530024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR29) && is4) goto exactly1;
1531024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR30) && is4) goto exactly1;
1532024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR31) && is4) goto exactly1;
1533024598e40c84666cc311a42c256bbf880db3ac99sewardj
1534024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Misc integer reg and condition code accesses */
1535024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LR)        && is4) goto exactly1;
1536024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CTR)       && is4) goto exactly1;
1537024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA)       && is4) goto none;
153890fc9d77441966837004dc5a9b2b97c435cdb105sewardj   if (o == GOF(IP_AT_SYSCALL) && is4) goto none;
1539024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TISTART)   && is4) goto none;
1540024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TILEN)     && is4) goto none;
1541024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(REDIR_SP)  && is4) goto none;
1542024598e40c84666cc311a42c256bbf880db3ac99sewardj
1543024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sz == 1) {
1544024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_SO))  goto none;
1545024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_OV))  goto none;
1546024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_CA))  goto none;
1547024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_BC))  goto none;
1548024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_321)) goto none;
1549024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_0))   goto none;
1550024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_321)) goto none;
1551024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_0))   goto none;
1552024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_321)) goto none;
1553024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_0))   goto none;
1554024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_321)) goto none;
1555024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_0))   goto none;
1556024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_321)) goto none;
1557024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_0))   goto none;
1558024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_321)) goto none;
1559024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_0))   goto none;
1560024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_321)) goto none;
1561024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_0))   goto none;
1562024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_321)) goto none;
1563024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_0))   goto none;
1564024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1565024598e40c84666cc311a42c256bbf880db3ac99sewardj
1566024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to FP registers */
1567024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR0)  && is8) goto none;
1568024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR1)  && is8) goto none;
1569024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR2)  && is8) goto none;
1570024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR3)  && is8) goto none;
1571024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR4)  && is8) goto none;
1572024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR5)  && is8) goto none;
1573024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR6)  && is8) goto none;
1574024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR7)  && is8) goto none;
1575024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR8)  && is8) goto none;
1576024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR9)  && is8) goto none;
1577024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR10) && is8) goto none;
1578024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR11) && is8) goto none;
1579024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR12) && is8) goto none;
1580024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR13) && is8) goto none;
1581024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR14) && is8) goto none;
1582024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR15) && is8) goto none;
1583024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR16) && is8) goto none;
1584024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR17) && is8) goto none;
1585024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR18) && is8) goto none;
1586024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR19) && is8) goto none;
1587024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR20) && is8) goto none;
1588024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR21) && is8) goto none;
1589024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR22) && is8) goto none;
1590024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR23) && is8) goto none;
1591024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR24) && is8) goto none;
1592024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR25) && is8) goto none;
1593024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR26) && is8) goto none;
1594024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR27) && is8) goto none;
1595024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR28) && is8) goto none;
1596024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR29) && is8) goto none;
1597024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR30) && is8) goto none;
1598024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR31) && is8) goto none;
1599024598e40c84666cc311a42c256bbf880db3ac99sewardj
1600024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1601024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND) && is4) goto none;
1602024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)  && is4) goto none;
1603024598e40c84666cc311a42c256bbf880db3ac99sewardj
1604024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Altivec registers */
1605024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR0)  && sz == 16) goto none;
1606024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR1)  && sz == 16) goto none;
1607024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR2)  && sz == 16) goto none;
1608024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR3)  && sz == 16) goto none;
1609024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR4)  && sz == 16) goto none;
1610024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR5)  && sz == 16) goto none;
1611024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR6)  && sz == 16) goto none;
1612024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR7)  && sz == 16) goto none;
1613024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR8)  && sz == 16) goto none;
1614024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR9)  && sz == 16) goto none;
1615024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR10) && sz == 16) goto none;
1616024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR11) && sz == 16) goto none;
1617024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR12) && sz == 16) goto none;
1618024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR13) && sz == 16) goto none;
1619024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR14) && sz == 16) goto none;
1620024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR15) && sz == 16) goto none;
1621024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR16) && sz == 16) goto none;
1622024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR17) && sz == 16) goto none;
1623024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR18) && sz == 16) goto none;
1624024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR19) && sz == 16) goto none;
1625024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR20) && sz == 16) goto none;
1626024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR21) && sz == 16) goto none;
1627024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR22) && sz == 16) goto none;
1628024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR23) && sz == 16) goto none;
1629024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR24) && sz == 16) goto none;
1630024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR25) && sz == 16) goto none;
1631024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR26) && sz == 16) goto none;
1632024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR27) && sz == 16) goto none;
1633024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR28) && sz == 16) goto none;
1634024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR29) && sz == 16) goto none;
1635024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR30) && sz == 16) goto none;
1636024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR31) && sz == 16) goto none;
1637024598e40c84666cc311a42c256bbf880db3ac99sewardj
1638aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   /* Altivec admin related */
1639aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   if (o == GOF(VRSAVE) && is4) goto none;
1640aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj
1641024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(ppc32):failing on (%d,%d)\n", o, sz);
1642024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1643024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1644024598e40c84666cc311a42c256bbf880db3ac99sewardj
1645024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc64 -------------------- */
1646024598e40c84666cc311a42c256bbf880db3ac99sewardj
1647024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc64)
1648024598e40c84666cc311a42c256bbf880db3ac99sewardj
1649024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1650024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestPPC64State,guest_##_fieldname))
1651024598e40c84666cc311a42c256bbf880db3ac99sewardj
1652024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1653024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1654024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1655024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8  = sz == 8;
1656024598e40c84666cc311a42c256bbf880db3ac99sewardj
1657024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1658024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_big_endian());
1659024598e40c84666cc311a42c256bbf880db3ac99sewardj
1660024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1661024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1662024598e40c84666cc311a42c256bbf880db3ac99sewardj
1663024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1664024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR0)  && is8) goto exactly1;
1665024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR1)  && is8) goto exactly1;
1666024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR2)  && is8) goto exactly1;
1667024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR3)  && is8) goto exactly1;
1668024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR4)  && is8) goto exactly1;
1669024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR5)  && is8) goto exactly1;
1670024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR6)  && is8) goto exactly1;
1671024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR7)  && is8) goto exactly1;
1672024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR8)  && is8) goto exactly1;
1673024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR9)  && is8) goto exactly1;
1674024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR10) && is8) goto exactly1;
1675024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR11) && is8) goto exactly1;
1676024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR12) && is8) goto exactly1;
1677024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR13) && is8) goto exactly1;
1678024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR14) && is8) goto exactly1;
1679024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR15) && is8) goto exactly1;
1680024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR16) && is8) goto exactly1;
1681024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR17) && is8) goto exactly1;
1682024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR18) && is8) goto exactly1;
1683024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR19) && is8) goto exactly1;
1684024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR20) && is8) goto exactly1;
1685024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR21) && is8) goto exactly1;
1686024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR22) && is8) goto exactly1;
1687024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR23) && is8) goto exactly1;
1688024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR24) && is8) goto exactly1;
1689024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR25) && is8) goto exactly1;
1690024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR26) && is8) goto exactly1;
1691024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR27) && is8) goto exactly1;
1692024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR28) && is8) goto exactly1;
1693024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR29) && is8) goto exactly1;
1694024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR30) && is8) goto exactly1;
1695024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR31) && is8) goto exactly1;
1696024598e40c84666cc311a42c256bbf880db3ac99sewardj
1697024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Misc integer reg and condition code accesses */
1698024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LR)        && is8) goto exactly1;
1699024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CTR)       && is8) goto exactly1;
1700024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA)       && is8) goto none;
170190fc9d77441966837004dc5a9b2b97c435cdb105sewardj   if (o == GOF(IP_AT_SYSCALL) && is8) goto none;
1702024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TISTART)   && is8) goto none;
1703024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TILEN)     && is8) goto none;
1704024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(REDIR_SP)  && is8) goto none;
1705024598e40c84666cc311a42c256bbf880db3ac99sewardj
1706024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sz == 1) {
1707024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_SO))  goto none;
1708024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_OV))  goto none;
1709024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_CA))  goto none;
1710024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_BC))  goto none;
1711024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_321)) goto none;
1712024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_0))   goto none;
1713024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_321)) goto none;
1714024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_0))   goto none;
1715024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_321)) goto none;
1716024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_0))   goto none;
1717024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_321)) goto none;
1718024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_0))   goto none;
1719024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_321)) goto none;
1720024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_0))   goto none;
1721024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_321)) goto none;
1722024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_0))   goto none;
1723024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_321)) goto none;
1724024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_0))   goto none;
1725024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_321)) goto none;
1726024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_0))   goto none;
1727024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1728024598e40c84666cc311a42c256bbf880db3ac99sewardj
1729024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to FP registers */
1730024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR0)  && is8) goto none;
1731024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR1)  && is8) goto none;
1732024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR2)  && is8) goto none;
1733024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR3)  && is8) goto none;
1734024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR4)  && is8) goto none;
1735024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR5)  && is8) goto none;
1736024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR6)  && is8) goto none;
1737024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR7)  && is8) goto none;
1738024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR8)  && is8) goto none;
1739024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR9)  && is8) goto none;
1740024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR10) && is8) goto none;
1741024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR11) && is8) goto none;
1742024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR12) && is8) goto none;
1743024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR13) && is8) goto none;
1744024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR14) && is8) goto none;
1745024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR15) && is8) goto none;
1746024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR16) && is8) goto none;
1747024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR17) && is8) goto none;
1748024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR18) && is8) goto none;
1749024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR19) && is8) goto none;
1750024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR20) && is8) goto none;
1751024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR21) && is8) goto none;
1752024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR22) && is8) goto none;
1753024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR23) && is8) goto none;
1754024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR24) && is8) goto none;
1755024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR25) && is8) goto none;
1756024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR26) && is8) goto none;
1757024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR27) && is8) goto none;
1758024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR28) && is8) goto none;
1759024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR29) && is8) goto none;
1760024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR30) && is8) goto none;
1761024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR31) && is8) goto none;
1762024598e40c84666cc311a42c256bbf880db3ac99sewardj
1763024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1764024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND) && is4) goto none;
1765024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)  && is4) goto none;
1766024598e40c84666cc311a42c256bbf880db3ac99sewardj
1767024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Altivec registers */
1768024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR0)  && sz == 16) goto none;
1769024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR1)  && sz == 16) goto none;
1770024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR2)  && sz == 16) goto none;
1771024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR3)  && sz == 16) goto none;
1772024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR4)  && sz == 16) goto none;
1773024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR5)  && sz == 16) goto none;
1774024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR6)  && sz == 16) goto none;
1775024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR7)  && sz == 16) goto none;
1776024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR8)  && sz == 16) goto none;
1777024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR9)  && sz == 16) goto none;
1778024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR10) && sz == 16) goto none;
1779024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR11) && sz == 16) goto none;
1780024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR12) && sz == 16) goto none;
1781024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR13) && sz == 16) goto none;
1782024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR14) && sz == 16) goto none;
1783024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR15) && sz == 16) goto none;
1784024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR16) && sz == 16) goto none;
1785024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR17) && sz == 16) goto none;
1786024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR18) && sz == 16) goto none;
1787024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR19) && sz == 16) goto none;
1788024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR20) && sz == 16) goto none;
1789024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR21) && sz == 16) goto none;
1790024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR22) && sz == 16) goto none;
1791024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR23) && sz == 16) goto none;
1792024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR24) && sz == 16) goto none;
1793024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR25) && sz == 16) goto none;
1794024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR26) && sz == 16) goto none;
1795024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR27) && sz == 16) goto none;
1796024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR28) && sz == 16) goto none;
1797024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR29) && sz == 16) goto none;
1798024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR30) && sz == 16) goto none;
1799024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR31) && sz == 16) goto none;
1800024598e40c84666cc311a42c256bbf880db3ac99sewardj
1801aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   /* Altivec admin related */
1802aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj   if (o == GOF(VRSAVE) && is4) goto none;
1803aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj
1804024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(ppc64):failing on (%d,%d)\n", o, sz);
1805024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1806024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1807024598e40c84666cc311a42c256bbf880db3ac99sewardj
1808024598e40c84666cc311a42c256bbf880db3ac99sewardj
1809024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
1810024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "FIXME: not implemented for this architecture"
1811024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
1812024598e40c84666cc311a42c256bbf880db3ac99sewardj
1813024598e40c84666cc311a42c256bbf880db3ac99sewardj  exactly1:
1814024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = -1;
1815024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1816024598e40c84666cc311a42c256bbf880db3ac99sewardj  none:
1817024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = 0;
1818024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1819024598e40c84666cc311a42c256bbf880db3ac99sewardj  contains_o:
1820024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(o >= 0 && 0 == (o % sizeof(UWord)));
1821024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = 1;
1822024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->offsets[0] = o;
1823024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1824024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1825024598e40c84666cc311a42c256bbf880db3ac99sewardj
1826024598e40c84666cc311a42c256bbf880db3ac99sewardj
1827024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Does 'arr' describe an indexed guest state section containing host
1828024598e40c84666cc311a42c256bbf880db3ac99sewardj   words, that we want to shadow? */
1829024598e40c84666cc311a42c256bbf880db3ac99sewardj
1830024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg_array ( IRRegArray* arr )
1831024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1832024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------------- x86 --------------------- */
1833024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86)
1834024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 tag array. */
1835024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestX86State,guest_FPTAG[0])
1836024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I8 && arr->nElems == 8)
1837024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1838024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 register array. */
1839024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestX86State,guest_FPREG[0])
1840024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_F64 && arr->nElems == 8)
1841024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1842024598e40c84666cc311a42c256bbf880db3ac99sewardj
1843024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(x86): unhandled: ");
1844024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1845024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1846024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1847024598e40c84666cc311a42c256bbf880db3ac99sewardj
1848024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- amd64 -------------------- */
1849024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64)
1850024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 tag array. */
1851024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestAMD64State,guest_FPTAG[0])
1852024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I8 && arr->nElems == 8)
1853024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1854024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 register array. */
1855024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestAMD64State,guest_FPREG[0])
1856024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_F64 && arr->nElems == 8)
1857024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1858024598e40c84666cc311a42c256bbf880db3ac99sewardj
1859024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(amd64): unhandled: ");
1860024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1861024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1862024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1863024598e40c84666cc311a42c256bbf880db3ac99sewardj
1864024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc32 -------------------- */
1865024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc32)
1866024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The redir stack. */
1867024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestPPC32State,guest_REDIR_STACK[0])
1868024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I32
1869024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->nElems == VEX_GUEST_PPC32_REDIR_STACK_SIZE)
1870024598e40c84666cc311a42c256bbf880db3ac99sewardj      return True;
1871024598e40c84666cc311a42c256bbf880db3ac99sewardj
1872024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(ppc32): unhandled: ");
1873024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1874024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1875024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1876024598e40c84666cc311a42c256bbf880db3ac99sewardj
1877024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc64 -------------------- */
1878024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc64)
1879024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The redir stack. */
1880024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestPPC64State,guest_REDIR_STACK[0])
1881024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I64
1882024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->nElems == VEX_GUEST_PPC64_REDIR_STACK_SIZE)
1883024598e40c84666cc311a42c256bbf880db3ac99sewardj      return True;
1884024598e40c84666cc311a42c256bbf880db3ac99sewardj
1885024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(ppc64): unhandled: ");
1886024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1887024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1888024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1889024598e40c84666cc311a42c256bbf880db3ac99sewardj
1890024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
1891024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "FIXME: not implemented for this architecture"
1892024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
1893024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1894024598e40c84666cc311a42c256bbf880db3ac99sewardj
1895024598e40c84666cc311a42c256bbf880db3ac99sewardj
1896024598e40c84666cc311a42c256bbf880db3ac99sewardj// END move this uglyness to pc_machine.c
1897024598e40c84666cc311a42c256bbf880db3ac99sewardj
1898024598e40c84666cc311a42c256bbf880db3ac99sewardj/* returns True iff given slice exactly matches an int reg.  Merely
1899024598e40c84666cc311a42c256bbf880db3ac99sewardj   a convenience wrapper around get_IntRegInfo. */
1900024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg ( Int offset, Int szB )
1901024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1902024598e40c84666cc311a42c256bbf880db3ac99sewardj   IntRegInfo iii;
1903024598e40c84666cc311a42c256bbf880db3ac99sewardj   get_IntRegInfo( &iii, offset, szB );
1904024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(iii.n_offsets >= -1 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
1905024598e40c84666cc311a42c256bbf880db3ac99sewardj   return iii.n_offsets == -1;
1906024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1907024598e40c84666cc311a42c256bbf880db3ac99sewardj
1908024598e40c84666cc311a42c256bbf880db3ac99sewardj/* these assume guest and host have the same endianness and
1909024598e40c84666cc311a42c256bbf880db3ac99sewardj   word size (probably). */
1910024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UWord get_guest_intreg ( ThreadId tid, Int shadowNo,
1911c4431bfe04c7490ea2d74939d222d87f13f30960njn                                PtrdiffT offset, SizeT size )
1912024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1913024598e40c84666cc311a42c256bbf880db3ac99sewardj   UChar tmp[ 2 + sizeof(UWord) ];
1914024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(size == sizeof(UWord));
1915024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (offset % sizeof(UWord)));
1916024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)(tmp, 0, sizeof(tmp));
1917024598e40c84666cc311a42c256bbf880db3ac99sewardj   tmp[0] = 0x31;
1918024598e40c84666cc311a42c256bbf880db3ac99sewardj   tmp[ sizeof(tmp)-1 ] = 0x27;
1919024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(get_shadow_regs_area)(tid, &tmp[1], shadowNo, offset, size);
1920024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tmp[0] == 0x31);
1921024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tmp[ sizeof(tmp)-1 ] == 0x27);
1922024598e40c84666cc311a42c256bbf880db3ac99sewardj   return * ((UWord*) &tmp[1] ); /* MISALIGNED LOAD */
1923024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1924024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void put_guest_intreg ( ThreadId tid, Int shadowNo,
1925c4431bfe04c7490ea2d74939d222d87f13f30960njn                               PtrdiffT offset, SizeT size, UWord w )
1926024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1927024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(size == sizeof(UWord));
1928024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (offset % sizeof(UWord)));
1929024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(set_shadow_regs_area)(tid, shadowNo, offset, size,
1930024598e40c84666cc311a42c256bbf880db3ac99sewardj                             (const UChar*)&w);
1931024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1932024598e40c84666cc311a42c256bbf880db3ac99sewardj
1933024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Initialise the integer shadow registers to UNKNOWN.  This is a bit
1934024598e40c84666cc311a42c256bbf880db3ac99sewardj   of a nasty kludge, but it does mean we don't need to know which
1935024598e40c84666cc311a42c256bbf880db3ac99sewardj   registers we really need to initialise -- simply assume that all
1936024598e40c84666cc311a42c256bbf880db3ac99sewardj   integer registers will be naturally aligned w.r.t. the start of the
1937024598e40c84666cc311a42c256bbf880db3ac99sewardj   guest state, and fill in all possible entries. */
1938024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_shadow_registers ( ThreadId tid )
1939024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1940024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i, wordSzB = sizeof(UWord);
1941024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < MC_SIZEOF_GUEST_STATE-wordSzB; i += wordSzB) {
1942024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg( tid, 1, i, wordSzB, (UWord)UNKNOWN );
1943024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1944024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1945024598e40c84666cc311a42c256bbf880db3ac99sewardj
1946c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic void post_reg_write_nonptr ( ThreadId tid, PtrdiffT offset, SizeT size )
1947024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1948024598e40c84666cc311a42c256bbf880db3ac99sewardj   // syscall_return: Default is non-pointer.  If it really is a pointer
1949024598e40c84666cc311a42c256bbf880db3ac99sewardj   // (eg. for mmap()), SK_(post_syscall) sets it again afterwards.
1950024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1951024598e40c84666cc311a42c256bbf880db3ac99sewardj   // clientreq_return: All the global client requests return non-pointers
1952024598e40c84666cc311a42c256bbf880db3ac99sewardj   // (except possibly CLIENT_CALL[0123], but they're handled by
1953024598e40c84666cc311a42c256bbf880db3ac99sewardj   // post_reg_write_clientcall, not here).
1954024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1955024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1956024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg( tid, 1, offset, size, (UWord)NONPTR );
1957024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
1958f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // DDD: on Darwin, this assertion fails because we currently do a
1959f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // 'post_reg_write' on the 'guest_CC_DEP1' pseudo-register.
1960024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
1961024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1962024598e40c84666cc311a42c256bbf880db3ac99sewardj   //   VG_(set_thread_shadow_archreg)( tid, reg, (UInt)NONPTR );
1963024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1964024598e40c84666cc311a42c256bbf880db3ac99sewardj
1965024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void post_reg_write_nonptr_or_unknown ( ThreadId tid,
1966c4431bfe04c7490ea2d74939d222d87f13f30960njn                                               PtrdiffT offset, SizeT size )
1967024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1968024598e40c84666cc311a42c256bbf880db3ac99sewardj   // deliver_signal: called from two places; one sets the reg to zero, the
1969024598e40c84666cc311a42c256bbf880db3ac99sewardj   // other sets the stack pointer.
1970024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1971024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1972024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg(
1973024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, 1/*shadowno*/, offset, size,
1974024598e40c84666cc311a42c256bbf880db3ac99sewardj         (UWord)nonptr_or_unknown(
1975024598e40c84666cc311a42c256bbf880db3ac99sewardj                   get_guest_intreg( tid, 0/*shadowno*/,
1976024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     offset, size )));
1977024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
1978024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
1979024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1980024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1981024598e40c84666cc311a42c256bbf880db3ac99sewardj
1982024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_reg_write_demux ( CorePart part, ThreadId tid,
1983c4431bfe04c7490ea2d74939d222d87f13f30960njn                              PtrdiffT guest_state_offset, SizeT size)
1984024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1985024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0)
1986024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n",
1987024598e40c84666cc311a42c256bbf880db3ac99sewardj               (Int)tid, (Int)part,
1988024598e40c84666cc311a42c256bbf880db3ac99sewardj              guest_state_offset, size);
1989024598e40c84666cc311a42c256bbf880db3ac99sewardj   switch (part) {
1990024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreStartup:
1991024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* This is a bit of a kludge since for any Vg_CoreStartup
1992024598e40c84666cc311a42c256bbf880db3ac99sewardj            event we overwrite the entire shadow register set.  But
1993024598e40c84666cc311a42c256bbf880db3ac99sewardj            that's ok - we're only called once with
1994024598e40c84666cc311a42c256bbf880db3ac99sewardj            part==Vg_CoreStartup event, and in that case the supplied
1995024598e40c84666cc311a42c256bbf880db3ac99sewardj            offset & size cover the entire guest state anyway. */
1996024598e40c84666cc311a42c256bbf880db3ac99sewardj         init_shadow_registers(tid);
1997024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
1998024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreSysCall:
1999024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ p_r_w    -> NONPTR\n");
2000024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr( tid, guest_state_offset, size );
2001024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2002024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreClientReq:
2003024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr( tid, guest_state_offset, size );
2004024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2005024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreSignal:
2006024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr_or_unknown( tid, guest_state_offset, size );
2007024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2008024598e40c84666cc311a42c256bbf880db3ac99sewardj      default:
2009024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(0);
2010024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2011024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2012024598e40c84666cc311a42c256bbf880db3ac99sewardj
2013c4431bfe04c7490ea2d74939d222d87f13f30960njnvoid h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset,
2014024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 SizeT size, Addr f )
2015024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2016024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord p;
2017024598e40c84666cc311a42c256bbf880db3ac99sewardj
2018024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Having to do this is a bit nasty...
2019024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (f == (Addr)h_replace_malloc
2020024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace___builtin_new
2021024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace___builtin_vec_new
2022024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_calloc
2023024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_memalign
2024024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_realloc)
2025024598e40c84666cc311a42c256bbf880db3ac99sewardj   {
2026024598e40c84666cc311a42c256bbf880db3ac99sewardj      // We remembered the last added segment;  make sure it's the right one.
2027024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* What's going on: at this point, the scheduler has just called
2028024598e40c84666cc311a42c256bbf880db3ac99sewardj         'f' -- one of our malloc replacement functions -- and it has
2029024598e40c84666cc311a42c256bbf880db3ac99sewardj         returned.  The return value has been written to the guest
2030024598e40c84666cc311a42c256bbf880db3ac99sewardj         state of thread 'tid', offset 'guest_state_offset' length
2031024598e40c84666cc311a42c256bbf880db3ac99sewardj         'size'.  We need to look at that return value and set the
2032024598e40c84666cc311a42c256bbf880db3ac99sewardj         shadow return value accordingly.  The shadow return value
2033024598e40c84666cc311a42c256bbf880db3ac99sewardj         required is handed to us "under the counter" through the
2034024598e40c84666cc311a42c256bbf880db3ac99sewardj         global variable 'last_seg_added'.  This is all very ugly, not
2035024598e40c84666cc311a42c256bbf880db3ac99sewardj         to mention, non-thread-safe should V ever become
2036024598e40c84666cc311a42c256bbf880db3ac99sewardj         multithreaded. */
2037024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* assert the place where the return value is is a legit int reg */
2038024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(is_integer_guest_reg(guest_state_offset, size));
2039024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Now we need to look at the returned value, to see whether the
2040024598e40c84666cc311a42c256bbf880db3ac99sewardj         malloc succeeded or not. */
2041024598e40c84666cc311a42c256bbf880db3ac99sewardj      p = get_guest_intreg(tid, 0/*non-shadow*/, guest_state_offset, size);
2042024598e40c84666cc311a42c256bbf880db3ac99sewardj      if ((UWord)NULL == p) {
2043024598e40c84666cc311a42c256bbf880db3ac99sewardj         // if alloc failed, eg. realloc on bogus pointer
2044024598e40c84666cc311a42c256bbf880db3ac99sewardj         put_guest_intreg(tid, 1/*first-shadow*/,
2045024598e40c84666cc311a42c256bbf880db3ac99sewardj                          guest_state_offset, size, (UWord)NONPTR );
2046024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2047024598e40c84666cc311a42c256bbf880db3ac99sewardj         // alloc didn't fail.  Check we have the correct segment.
2048024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(p == last_seg_added->addr);
2049024598e40c84666cc311a42c256bbf880db3ac99sewardj         put_guest_intreg(tid, 1/*first-shadow*/,
2050024598e40c84666cc311a42c256bbf880db3ac99sewardj                          guest_state_offset, size, (UWord)last_seg_added );
2051024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2052024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2053024598e40c84666cc311a42c256bbf880db3ac99sewardj   else if (f == (Addr)h_replace_free
2054024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)h_replace___builtin_delete
2055024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)h_replace___builtin_vec_delete
2056024598e40c84666cc311a42c256bbf880db3ac99sewardj   //            || f == (Addr)VG_(cli_block_size)
2057024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)VG_(message))
2058024598e40c84666cc311a42c256bbf880db3ac99sewardj   {
2059024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Probably best to set the (non-existent!) return value to
2060024598e40c84666cc311a42c256bbf880db3ac99sewardj      // non-pointer.
2061024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(is_integer_guest_reg(guest_state_offset, size));
2062024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg(tid, 1/*first-shadow*/,
2063024598e40c84666cc311a42c256bbf880db3ac99sewardj                       guest_state_offset, size, (UWord)NONPTR );
2064024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2065024598e40c84666cc311a42c256bbf880db3ac99sewardj   else {
2066024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Anything else, probably best to set return value to non-pointer.
2067024598e40c84666cc311a42c256bbf880db3ac99sewardj      //VG_(set_thread_shadow_archreg)(tid, reg, (UInt)UNKNOWN);
2068024598e40c84666cc311a42c256bbf880db3ac99sewardj      Char fbuf[100];
2069024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("f = %#lx\n", f);
2070024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(get_fnname)(f, fbuf, 100);
2071024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("name = %s\n", fbuf);
2072024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("argh: clientcall");
2073024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2074024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2075024598e40c84666cc311a42c256bbf880db3ac99sewardj
2076024598e40c84666cc311a42c256bbf880db3ac99sewardj
2077024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/
2078024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--- Sanity checking                                              ---*/
2079024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/
2080024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2081024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* Check that nobody has spuriously claimed that the first or last 16
2082024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    pages (64 KB) of address space have become accessible.  Failure of
2083024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    the following do not per se indicate an internal consistency
2084024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    problem, but they are so likely to that we really want to know
2085024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    about it if so. */
2086024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool pc_replace_cheap_sanity_check) ( void )
2087024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2088024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (IS_DISTINGUISHED_SM(primary_map[0])
2089024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz        /* kludge: kernel drops a page up at top of address range for
2090024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz           magic "optimized syscalls", so we can no longer check the
2091024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz           highest page */
2092024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz        /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
2093024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       )
2094024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
2095024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    else
2096024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return False;
2097024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2098024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2099024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool SK_(expensive_sanity_check) ( void )
2100024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2101024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    Int i;
2102024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2103024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    /* Make sure nobody changed the distinguished secondary. */
2104024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    for (i = 0; i < SEC_MAP_WORDS; i++)
2105024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (distinguished_secondary_map.vseg[i] != UNKNOWN)
2106024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          return False;
2107024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2108024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return True;
2109024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2110024598e40c84666cc311a42c256bbf880db3ac99sewardj
2111024598e40c84666cc311a42c256bbf880db3ac99sewardj
2112024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2113024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- System calls                                                 ---*/
2114024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2115024598e40c84666cc311a42c256bbf880db3ac99sewardj
21161c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjvoid h_pre_syscall ( ThreadId tid, UInt sysno,
21171c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     UWord* args, UInt nArgs )
2118024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2119024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* we don't do anything at the pre-syscall point */
2120024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2121024598e40c84666cc311a42c256bbf880db3ac99sewardj
2122024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The post-syscall table is a table of pairs (number, flag).
2123024598e40c84666cc311a42c256bbf880db3ac99sewardj
2124024598e40c84666cc311a42c256bbf880db3ac99sewardj   'flag' is only ever zero or one.  If it is zero, it indicates that
2125024598e40c84666cc311a42c256bbf880db3ac99sewardj   default handling for that syscall is required -- namely that the
2126024598e40c84666cc311a42c256bbf880db3ac99sewardj   syscall is deemed to return NONPTR.  This is the case for the vast
2127024598e40c84666cc311a42c256bbf880db3ac99sewardj   majority of syscalls.  If it is one then some special
2128024598e40c84666cc311a42c256bbf880db3ac99sewardj   syscall-specific handling is is required.  No further details of it
2129024598e40c84666cc311a42c256bbf880db3ac99sewardj   are stored in the table.
2130024598e40c84666cc311a42c256bbf880db3ac99sewardj
2131f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   On Linux and Darwin, 'number' is a __NR_xxx constant.
2132024598e40c84666cc311a42c256bbf880db3ac99sewardj
2133024598e40c84666cc311a42c256bbf880db3ac99sewardj   On AIX5, 'number' is an Int*, which points to the Int variable
2134024598e40c84666cc311a42c256bbf880db3ac99sewardj   holding the currently assigned number for this syscall.
2135024598e40c84666cc311a42c256bbf880db3ac99sewardj
2136024598e40c84666cc311a42c256bbf880db3ac99sewardj   When querying the table, we compare the supplied syscall number
2137f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   with the 'number' field (directly on Linux and Darwin, after
2138f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   dereferencing on AIX5), to find the relevant entry.  This requires a
2139f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   linear search of the table.  To stop the costs getting too high, the
2140f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   table is incrementally rearranged after each search, to move commonly
2141024598e40c84666cc311a42c256bbf880db3ac99sewardj   requested items a bit closer to the front.
2142024598e40c84666cc311a42c256bbf880db3ac99sewardj
2143024598e40c84666cc311a42c256bbf880db3ac99sewardj   The table is built once, the first time it is used.  After that we
2144024598e40c84666cc311a42c256bbf880db3ac99sewardj   merely query it (and reorder the entries as a result). */
2145024598e40c84666cc311a42c256bbf880db3ac99sewardj
2146024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic XArray* /* of UWordPair */ post_syscall_table = NULL;
2147024598e40c84666cc311a42c256bbf880db3ac99sewardj
2148024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void setup_post_syscall_table ( void )
2149024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2150024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!post_syscall_table);
2151024598e40c84666cc311a42c256bbf880db3ac99sewardj   post_syscall_table = VG_(newXA)( VG_(malloc), "pc.h_main.spst.1",
2152024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(free), sizeof(UWordPair) );
2153024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(post_syscall_table);
2154024598e40c84666cc311a42c256bbf880db3ac99sewardj
2155024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------- LINUX --------------- */
2156024598e40c84666cc311a42c256bbf880db3ac99sewardj
2157024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGO_linux)
2158024598e40c84666cc311a42c256bbf880db3ac99sewardj
2159024598e40c84666cc311a42c256bbf880db3ac99sewardj#     define ADD(_flag, _syscallname) \
2160024598e40c84666cc311a42c256bbf880db3ac99sewardj         do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2161024598e40c84666cc311a42c256bbf880db3ac99sewardj              VG_(addToXA)( post_syscall_table, &p ); \
2162024598e40c84666cc311a42c256bbf880db3ac99sewardj         } while (0)
2163024598e40c84666cc311a42c256bbf880db3ac99sewardj
2164024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* These ones definitely don't return pointers.  They're not
2165024598e40c84666cc311a42c256bbf880db3ac99sewardj         particularly grammatical, either. */
2166024598e40c84666cc311a42c256bbf880db3ac99sewardj
2167024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR__llseek)
2168024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__llseek);
2169024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2170024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__sysctl);
2171024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR__newselect)
2172024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__newselect);
2173024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2174024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_accept)
2175024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_accept);
2176024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2177024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_access);
2178332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_alarm);
2179024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_bind)
2180024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_bind);
2181024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2182024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_chdir)
2183024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chdir);
2184024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2185024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chmod);
2186024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chown);
218741d5dea0b6d0672bd3986b5886e89b66941eef8asewardj#     if defined(__NR_chown32)
218841d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_chown32);
218941d5dea0b6d0672bd3986b5886e89b66941eef8asewardj#     endif
2190024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clock_getres);
2191024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clock_gettime);
2192024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clone);
2193024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_close);
2194024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_connect)
2195024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_connect);
2196024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2197332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_creat);
2198024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_dup);
2199024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_dup2);
2200024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_execve); /* presumably we see this because the call failed? */
2201024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_exit); /* hmm, why are we still alive? */
2202024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_exit_group);
2203024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fadvise64);
22049f52ee49259e285335f2112e929b4183e354bc22sewardj      ADD(0, __NR_fallocate);
2205024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchmod);
2206024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchown);
2207024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fchown32)
2208024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchown32);
2209024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2210024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fcntl);
2211024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fcntl64)
2212024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fcntl64);
2213024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2214024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fdatasync);
221533c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_flock);
2216024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstat);
2217024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fstat64)
2218024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstat64);
2219024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2220024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstatfs);
2221024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fsync);
2222024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ftruncate);
2223024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_ftruncate64)
2224024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ftruncate64);
2225024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2226024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_futex);
2227024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getcwd);
2228024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getdents); // something to do with teeth
2229024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getdents64);
2230024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getegid);
2231024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getegid32)
2232024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getegid32);
2233024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2234024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_geteuid);
2235024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_geteuid32)
2236024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_geteuid32);
2237024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2238024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getgid);
2239024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getgid32)
2240024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getgid32);
2241024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2242ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_getgroups);
2243024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getitimer);
2244024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getpeername)
2245024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getpeername);
2246024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2247024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getpid);
22487d7691194ba0f1011b341ccc517f8a474169f403sewardj      ADD(0, __NR_getpgrp);
2249024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getppid);
2250024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getresgid);
2251024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getresuid);
22529f52ee49259e285335f2112e929b4183e354bc22sewardj#     if defined(__NR_getresuid32)
22539f52ee49259e285335f2112e929b4183e354bc22sewardj      ADD(0, __NR_getresuid32);
22549f52ee49259e285335f2112e929b4183e354bc22sewardj#     endif
2255024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getrlimit);
2256332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_getrusage);
2257024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getsockname)
2258024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getsockname);
2259024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2260024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getsockopt)
2261024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getsockopt);
2262024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
226341d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_gettid);
2264024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_gettimeofday);
2265024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getuid);
2266024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getuid32)
2267024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getuid32);
2268024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2269024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getxattr);
2270738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_inotify_add_watch);
2271024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_inotify_init);
2272738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_inotify_rm_watch);
2273024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ioctl); // ioctl -- assuming no pointers returned
227433c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_ioprio_get);
2275024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_kill);
2276024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_link);
2277024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_listen)
2278024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_listen);
2279024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2280024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lseek);
2281024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lstat);
2282024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_lstat64)
2283024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lstat64);
2284024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2285024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_madvise);
2286024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_mkdir);
228733c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_mlock);
2288024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_mprotect);
2289024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_munmap); // die_mem_munmap already called, segment remove);
2290738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_nanosleep);
2291024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_open);
2292024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pipe);
2293024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_poll);
2294024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pread64);
2295024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pwrite64);
2296024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_read);
2297024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_readlink);
2298024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_readv);
2299024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_recvfrom)
2300024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_recvfrom);
2301024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2302024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_recvmsg)
2303024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_recvmsg);
2304024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2305024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rename);
2306024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rmdir);
2307024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigaction);
2308024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigprocmask);
2309024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigreturn); /* not sure if we should see this or not */
2310024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_get_priority_max);
2311024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_get_priority_min);
2312738db7b86be4355d672d05bde9ad522d05fd2dfasewardj      ADD(0, __NR_sched_getaffinity);
2313024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_getparam);
2314024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_getscheduler);
231541d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_sched_setaffinity);
2316024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_setscheduler);
2317024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_yield);
2318024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_select);
231933c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     if defined(__NR_semctl)
232033c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_semctl);
232133c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     endif
232233c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     if defined(__NR_semget)
232333c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_semget);
232433c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     endif
232533c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     if defined(__NR_semop)
232633c57f23131e434e28cd7993f17e5efbafff5db0sewardj      ADD(0, __NR_semop);
232733c57f23131e434e28cd7993f17e5efbafff5db0sewardj#     endif
2328024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_sendto)
2329024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sendto);
2330024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2331332ffecd96becfaea1a67ddfab3e70372922393btom#     if defined(__NR_sendmsg)
2332332ffecd96becfaea1a67ddfab3e70372922393btom      ADD(0, __NR_sendmsg);
2333332ffecd96becfaea1a67ddfab3e70372922393btom#     endif
2334024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_robust_list);
2335024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_set_thread_area)
2336024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_thread_area);
2337024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2338024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_tid_address);
2339ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setfsgid);
2340ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setfsuid);
2341ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setgid);
2342024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setitimer);
23437d7691194ba0f1011b341ccc517f8a474169f403sewardj      ADD(0, __NR_setpgid);
2344ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setresgid);
2345024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setrlimit);
2346024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setsid);
2347024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_setsockopt)
2348024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setsockopt);
2349024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2350ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj      ADD(0, __NR_setuid);
2351024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmctl)
2352024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shmctl);
2353024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shmdt);
2354024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2355024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shutdown)
2356024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shutdown);
2357024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
235841d5dea0b6d0672bd3986b5886e89b66941eef8asewardj      ADD(0, __NR_sigaltstack);
2359024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_socket)
2360024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_socket);
2361024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2362024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_socketcall)
2363024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_socketcall); /* the nasty x86-linux socket multiplexor */
2364024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
236523e8a29882812f4b1d33d6fb9719f779becfba6esewardj#     if defined(__NR_socketpair)
236623e8a29882812f4b1d33d6fb9719f779becfba6esewardj      ADD(0, __NR_socketpair);
236723e8a29882812f4b1d33d6fb9719f779becfba6esewardj#     endif
2368024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_statfs64)
2369024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_statfs64);
2370024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2371024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_sigreturn)
2372024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sigreturn); /* not sure if we should see this or not */
2373024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2374024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_stat64)
2375024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_stat64);
2376024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2377024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_stat);
2378024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_statfs);
2379024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_symlink);
2380024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sysinfo);
2381024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_tgkill);
2382024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_time);
2383024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_times);
2384024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_truncate);
2385024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_truncate64)
2386024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_truncate64);
2387024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2388024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_ugetrlimit)
2389024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ugetrlimit);
2390024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2391024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_umask);
2392024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_uname);
2393024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_unlink);
2394024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_utime);
2395024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_waitpid)
2396024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_waitpid);
2397024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2398024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_wait4);
2399024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_write);
2400024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_writev);
2401024598e40c84666cc311a42c256bbf880db3ac99sewardj
2402024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Whereas the following need special treatment */
2403024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_arch_prctl)
2404024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_arch_prctl);
2405024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2406024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_brk);
2407024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_mmap);
2408024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_mmap2)
2409024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_mmap2);
2410024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2411024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmat)
2412024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_shmat);
2413024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2414024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmget)
2415024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_shmget);
2416024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
24171c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#     if defined(__NR_ipc) && defined(VKI_SHMAT)
24181c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      ADD(1, __NR_ipc); /* ppc{32,64}-linux horrors */
24191c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#     endif
2420024598e40c84666cc311a42c256bbf880db3ac99sewardj
2421024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------- AIX5 --------------- */
2422024598e40c84666cc311a42c256bbf880db3ac99sewardj
2423024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGO_aix5)
2424024598e40c84666cc311a42c256bbf880db3ac99sewardj
2425024598e40c84666cc311a42c256bbf880db3ac99sewardj#     define ADD(_flag, _syscallname) \
2426024598e40c84666cc311a42c256bbf880db3ac99sewardj         do { \
2427024598e40c84666cc311a42c256bbf880db3ac99sewardj            UWordPair p; \
2428024598e40c84666cc311a42c256bbf880db3ac99sewardj            if ((_syscallname) != __NR_AIX5_UNKNOWN) { \
2429024598e40c84666cc311a42c256bbf880db3ac99sewardj               p.uw1 = (UWord)&(_syscallname); p.uw2 = (_flag); \
2430024598e40c84666cc311a42c256bbf880db3ac99sewardj               VG_(addToXA)( post_syscall_table, &p ); \
2431024598e40c84666cc311a42c256bbf880db3ac99sewardj            } \
2432024598e40c84666cc311a42c256bbf880db3ac99sewardj         } while (0)
2433024598e40c84666cc311a42c256bbf880db3ac99sewardj
2434024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Just a minimal set of handlers, enough to make
2435024598e40c84666cc311a42c256bbf880db3ac99sewardj         a 32- and 64-bit hello-world program run. */
2436024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_AIX5___loadx); /* not sure what to do here */
2437024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5__exit);
2438024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_access);
2439024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_getgidx);
2440024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_getuidx);
2441024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kfcntl);
2442024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kioctl);
2443024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_AIX5_kload); /* not sure what to do here */
2444024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kwrite);
2445024598e40c84666cc311a42c256bbf880db3ac99sewardj
2446f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* --------------- DARWIN ------------- */
2447f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2448f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  elif defined(VGO_darwin)
2449f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2450f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#     define ADD(_flag, _syscallname) \
2451f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2452f76d27a697a7b0bf3b84490baf60623fc96a23afnjn              VG_(addToXA)( post_syscall_table, &p ); \
2453f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         } while (0)
2454f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2455f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // DDD: a desultory attempt thus far...
2456f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2457f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // Unix/BSD syscalls.
2458f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2459f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // Mach traps.
2460f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ADD(0, __NR_host_self_trap);
2461f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ADD(0, __NR_mach_msg_trap);
2462f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ADD(0, __NR_mach_reply_port);
2463f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ADD(0, __NR_task_self_trap);
2464f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2465f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // Machine-dependent syscalls.
24664e8808b021205659734885e2ca2665e225109b83njn      ADD(0, __NR_thread_fast_set_cthread_self);
2467f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2468f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* ------------------------------------ */
2469f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2470024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
2471024598e40c84666cc311a42c256bbf880db3ac99sewardj#     error "Unsupported OS"
2472024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2473024598e40c84666cc311a42c256bbf880db3ac99sewardj
2474024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef ADD
2475024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2476024598e40c84666cc311a42c256bbf880db3ac99sewardj
2477024598e40c84666cc311a42c256bbf880db3ac99sewardj
24781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjvoid h_post_syscall ( ThreadId tid, UInt sysno,
24791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                      UWord* args, UInt nArgs, SysRes res )
2480024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2481024598e40c84666cc311a42c256bbf880db3ac99sewardj   Word i, n;
2482024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWordPair* pair;
2483024598e40c84666cc311a42c256bbf880db3ac99sewardj
2484024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!post_syscall_table)
2485024598e40c84666cc311a42c256bbf880db3ac99sewardj      setup_post_syscall_table();
2486024598e40c84666cc311a42c256bbf880db3ac99sewardj
2487024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* search for 'sysno' in the post_syscall_table */
2488024598e40c84666cc311a42c256bbf880db3ac99sewardj   n = VG_(sizeXA)( post_syscall_table );
2489024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < n; i++) {
2490024598e40c84666cc311a42c256bbf880db3ac99sewardj      pair = VG_(indexXA)( post_syscall_table, i );
2491f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#     if defined(VGO_linux) || defined(VGO_darwin)
2492024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (pair->uw1 == (UWord)sysno)
2493024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2494024598e40c84666cc311a42c256bbf880db3ac99sewardj#     elif defined(VGO_aix5)
2495024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (*(Int*)(pair->uw1) == (Int)sysno)
2496024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2497024598e40c84666cc311a42c256bbf880db3ac99sewardj#     else
2498024598e40c84666cc311a42c256bbf880db3ac99sewardj#        error "Unsupported OS"
2499024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2500024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2501024598e40c84666cc311a42c256bbf880db3ac99sewardj
2502024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0 && i <= n);
2503024598e40c84666cc311a42c256bbf880db3ac99sewardj
2504024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i == n) {
25051a1e95c1f385a9b3b4f13f231eebaafff6e56450njn      VG_(printf)("sysno == %s", VG_SYSNUM_STRING_EXTRA(sysno));
2506024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("unhandled syscall");
2507024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2508024598e40c84666cc311a42c256bbf880db3ac99sewardj
2509024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* So we found the relevant entry.  Move it one step
2510024598e40c84666cc311a42c256bbf880db3ac99sewardj      forward so as to speed future accesses to it. */
2511024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i > 0) {
2512024598e40c84666cc311a42c256bbf880db3ac99sewardj      UWordPair tmp, *p, *q;
2513024598e40c84666cc311a42c256bbf880db3ac99sewardj      p = VG_(indexXA)( post_syscall_table, i-1 );
2514024598e40c84666cc311a42c256bbf880db3ac99sewardj      q = VG_(indexXA)( post_syscall_table, i-0 );
2515024598e40c84666cc311a42c256bbf880db3ac99sewardj      tmp = *p;
2516024598e40c84666cc311a42c256bbf880db3ac99sewardj      *p = *q;
2517024598e40c84666cc311a42c256bbf880db3ac99sewardj      *q = tmp;
2518024598e40c84666cc311a42c256bbf880db3ac99sewardj      i--;
2519024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2520024598e40c84666cc311a42c256bbf880db3ac99sewardj
2521024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Deal with the common case */
2522024598e40c84666cc311a42c256bbf880db3ac99sewardj   pair = VG_(indexXA)( post_syscall_table, i );
25231c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   if (pair->uw2 == 0)
25241c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      /* the common case */
25251c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      goto res_NONPTR_err_NONPTR;
2526024598e40c84666cc311a42c256bbf880db3ac99sewardj
2527024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Special handling for all remaining cases */
2528024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(pair->uw2 == 1);
2529024598e40c84666cc311a42c256bbf880db3ac99sewardj
2530024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_arch_prctl)
2531024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_arch_prctl) {
2532024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* This is nasty.  On amd64-linux, arch_prctl may write a
2533024598e40c84666cc311a42c256bbf880db3ac99sewardj         value to guest_FS_ZERO, and we need to shadow that value.
2534024598e40c84666cc311a42c256bbf880db3ac99sewardj         Hence apply nonptr_or_unknown to it here, after the
2535024598e40c84666cc311a42c256bbf880db3ac99sewardj         syscall completes. */
2536024598e40c84666cc311a42c256bbf880db3ac99sewardj      post_reg_write_nonptr_or_unknown( tid, PC_OFF_FS_ZERO,
2537024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             PC_SZB_FS_ZERO );
25381c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      goto res_NONPTR_err_NONPTR;
2539024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2540024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2541024598e40c84666cc311a42c256bbf880db3ac99sewardj
2542024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_brk)
2543024598e40c84666cc311a42c256bbf880db3ac99sewardj   // With brk(), result (of kernel syscall, not glibc wrapper) is a heap
2544024598e40c84666cc311a42c256bbf880db3ac99sewardj   // pointer.  Make the shadow UNKNOWN.
25451c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   if (sysno == __NR_brk)
25461c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      goto res_UNKNOWN_err_NONPTR;
2547024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2548024598e40c84666cc311a42c256bbf880db3ac99sewardj
2549024598e40c84666cc311a42c256bbf880db3ac99sewardj   // With mmap, new_mem_mmap() has already been called and added the
2550024598e40c84666cc311a42c256bbf880db3ac99sewardj   // segment (we did it there because we had the result address and size
2551024598e40c84666cc311a42c256bbf880db3ac99sewardj   // handy).  So just set the return value shadow.
2552024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_mmap
2553024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_mmap2)
2554024598e40c84666cc311a42c256bbf880db3ac99sewardj       || sysno == __NR_mmap2
2555024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2556024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_AIX5___loadx)
2557024598e40c84666cc311a42c256bbf880db3ac99sewardj       || (sysno == __NR_AIX5___loadx && __NR_AIX5___loadx != __NR_AIX5_UNKNOWN)
2558024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2559024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_AIX5_kload)
2560024598e40c84666cc311a42c256bbf880db3ac99sewardj       || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN)
2561024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2562024598e40c84666cc311a42c256bbf880db3ac99sewardj      ) {
2563cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(res)) {
2564024598e40c84666cc311a42c256bbf880db3ac99sewardj         // mmap() had an error, return value is a small negative integer
25651c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         goto res_NONPTR_err_NONPTR;
2566024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
25671c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         goto res_UNKNOWN_err_NONPTR;
2568024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2569024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2570024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2571024598e40c84666cc311a42c256bbf880db3ac99sewardj
2572024598e40c84666cc311a42c256bbf880db3ac99sewardj   // shmat uses the same scheme.  We will just have had a
2573024598e40c84666cc311a42c256bbf880db3ac99sewardj   // notification via new_mem_mmap.  Just set the return value shadow.
2574024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_shmat)
2575024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_shmat) {
2576cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(res)) {
25771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         goto res_NONPTR_err_NONPTR;
2578024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
25791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         goto res_UNKNOWN_err_NONPTR;
2580024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2581024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2582024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2583024598e40c84666cc311a42c256bbf880db3ac99sewardj
2584024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_shmget)
25851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   if (sysno == __NR_shmget)
2586024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: is this correct?
25871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      goto res_UNKNOWN_err_NONPTR;
25881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  endif
25891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
25901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  if defined(__NR_ipc) && defined(VKI_SHMAT)
25911c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   /* perhaps this should be further conditionalised with
25921c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      && (defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
25931c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      Note, this just copies the behaviour of __NR_shmget above.
25941c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
25951c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      JRS 2009 June 02: it seems that the return value from
25961c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      sys_ipc(VKI_SHMAT, ...) doesn't have much relationship to the
25971c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      result returned by the originating user-level shmat call.  It's
25981c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      different (and much lower) by a large but integral number of
25991c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      pages.  I don't have time to chase this right now.  Observed on
26001c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      ppc{32,64}-linux.  Result appears to be false errors from apps
26011c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      using shmat.  Confusion though -- shouldn't be related to the
26021c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      actual numeric values returned by the syscall, though, should
26031c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      it?  Confused.  Maybe some bad interaction with a
26041c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      nonpointer-or-unknown heuristic? */
26051c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   if (sysno == __NR_ipc) {
26061c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      if (args[0] == VKI_SHMAT) {
26071c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         goto res_UNKNOWN_err_NONPTR;
26081c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      } else {
26091c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         goto res_NONPTR_err_NONPTR;
26101c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      }
2611024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2612024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2613024598e40c84666cc311a42c256bbf880db3ac99sewardj
2614024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* If we get here, it implies the corresponding entry in
2615024598e40c84666cc311a42c256bbf880db3ac99sewardj      post_syscall_table has .w2 == 1, which in turn implies there
2616024598e40c84666cc311a42c256bbf880db3ac99sewardj      should be special-case code for it above. */
2617024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
26181c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
26191c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj  res_NONPTR_err_NONPTR:
26201c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   VG_(set_syscall_return_shadows)( tid, /* retval */ (UWord)NONPTR, 0,
26211c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                         /* error */  (UWord)NONPTR, 0 );
26221c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   return;
26231c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
26241c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj  res_UNKNOWN_err_NONPTR:
26251c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   VG_(set_syscall_return_shadows)( tid, /* retval */ (UWord)UNKNOWN, 0,
26261c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                         /* error */  (UWord)NONPTR, 0 );
26271c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   return;
2628024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2629024598e40c84666cc311a42c256bbf880db3ac99sewardj
2630024598e40c84666cc311a42c256bbf880db3ac99sewardj
2631024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2632024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Functions called from generated code                         ---*/
2633024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2634024598e40c84666cc311a42c256bbf880db3ac99sewardj
2635024598e40c84666cc311a42c256bbf880db3ac99sewardj#if SC_SEGS
2636024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void checkSeg ( Seg vseg ) {
2637024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(vseg == UNKNOWN || vseg == NONPTR || vseg == BOTTOM
2638024598e40c84666cc311a42c256bbf880db3ac99sewardj             || Seg__plausible(vseg) );
2639024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2640024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
2641024598e40c84666cc311a42c256bbf880db3ac99sewardj
2642024598e40c84666cc311a42c256bbf880db3ac99sewardj// XXX: could be more sophisticated -- actually track the lowest/highest
2643024598e40c84666cc311a42c256bbf880db3ac99sewardj// valid address used by the program, and then return False for anything
2644024598e40c84666cc311a42c256bbf880db3ac99sewardj// below that (using a suitable safety margin).  Also, nothing above
2645024598e40c84666cc311a42c256bbf880db3ac99sewardj// 0xc0000000 is valid [unless you've changed that in your kernel]
2646024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool looks_like_a_pointer(Addr a)
2647024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2648024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86) || defined(VGA_ppc32)
2649024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4);
2650024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (a > 0x01000000UL && a < 0xFF000000UL);
2651024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64)
2652024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8);
2653024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (a >= 16 * 0x10000UL && a < 0xFF00000000000000UL);
2654024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
2655024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "Unsupported architecture"
2656024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2657024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2658024598e40c84666cc311a42c256bbf880db3ac99sewardj
2659024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline VG_REGPARM(1)
2660024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* nonptr_or_unknown(UWord x)
2661024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2662024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* res = looks_like_a_pointer(x) ? UNKNOWN : NONPTR;
2663024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("nonptr_or_unknown %s %#lx\n",
2664024598e40c84666cc311a42c256bbf880db3ac99sewardj                      res==UNKNOWN ? "UUU" : "nnn", x);
2665024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
2666024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2667024598e40c84666cc311a42c256bbf880db3ac99sewardj
2668024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static __attribute__((regparm(1)))
2669024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz void print_BB_entry(UInt bb)
2670024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2671024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    VG_(printf)("%u =\n", bb);
2672024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2673024598e40c84666cc311a42c256bbf880db3ac99sewardj
267459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__tot_mem_refs  = 0;
267559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__refs_in_a_seg = 0;
267659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__refs_lost_seg = 0;
2677024598e40c84666cc311a42c256bbf880db3ac99sewardj
2678024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
2679024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct { ExeContext* ec; UWord count; }
2680024598e40c84666cc311a42c256bbf880db3ac99sewardj   Lossage;
2681024598e40c84666cc311a42c256bbf880db3ac99sewardj
2682024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic OSet* lossage = NULL;
2683024598e40c84666cc311a42c256bbf880db3ac99sewardj
268459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static void inc_lossage ( ExeContext* ec )
268559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//{
268659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   Lossage key, *res, *nyu;
268759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   key.ec = ec;
268859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   key.count = 0; /* frivolous */
268959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   res = VG_(OSetGen_Lookup)(lossage, &key);
269059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   if (res) {
269159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      tl_assert(res->ec == ec);
269259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      res->count++;
269359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   } else {
269459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      nyu = (Lossage*)VG_(OSetGen_AllocNode)(lossage, sizeof(Lossage));
269559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      tl_assert(nyu);
269659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      nyu->ec = ec;
269759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      nyu->count = 1;
269859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      VG_(OSetGen_Insert)( lossage, nyu );
269959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   }
270059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//}
2701024598e40c84666cc311a42c256bbf880db3ac99sewardj
2702024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_lossage ( void )
2703024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2704024598e40c84666cc311a42c256bbf880db3ac99sewardj   lossage = VG_(OSetGen_Create)( /*keyOff*/ offsetof(Lossage,ec),
2705024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  /*fastCmp*/NULL,
2706024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  VG_(malloc), "pc.h_main.il.1",
2707024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  VG_(free) );
2708024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(lossage);
2709024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2710024598e40c84666cc311a42c256bbf880db3ac99sewardj
271159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static void show_lossage ( void )
271259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//{
271359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   Lossage* elem;
271459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   VG_(OSetGen_ResetIter)( lossage );
271559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   while ( (elem = VG_(OSetGen_Next)(lossage)) ) {
271659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      if (elem->count < 10) continue;
271759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //Char buf[100];
271859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //(void)VG_(describe_IP)(elem->ec, buf, sizeof(buf)-1);
271959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //buf[sizeof(buf)-1] = 0;
272059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      //VG_(printf)("  %,8lu  %s\n", elem->count, buf);
272159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      VG_(message)(Vg_UserMsg, "Lossage count %'lu at", elem->count);
272259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//      VG_(pp_ExeContext)(elem->ec);
272359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//   }
272459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//}
2725024598e40c84666cc311a42c256bbf880db3ac99sewardj
2726024598e40c84666cc311a42c256bbf880db3ac99sewardj// This function is called *a lot*; inlining it sped up Konqueror by 20%.
2727024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
2728024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load_or_store(Bool is_write, Addr m, UWord sz, Seg* mptr_vseg)
2729024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2730024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
27314815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj   tl_assert(0);
27324815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj   if (h_clo_lossage_check) {
2733024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* seg;
2734024598e40c84666cc311a42c256bbf880db3ac99sewardj      stats__tot_mem_refs++;
2735024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (ISList__findI0( seglist, (Addr)m, &seg )) {
2736024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* m falls inside 'seg' (that is, we are making a memory
2737024598e40c84666cc311a42c256bbf880db3ac99sewardj            reference inside 'seg').  Now, really mptr_vseg should be
2738024598e40c84666cc311a42c256bbf880db3ac99sewardj            a tracked segment of some description.  Badness is when
2739024598e40c84666cc311a42c256bbf880db3ac99sewardj            mptr_vseg is UNKNOWN, BOTTOM or NONPTR at this point,
2740024598e40c84666cc311a42c256bbf880db3ac99sewardj            since that means we've lost the type of it somehow: it
2741024598e40c84666cc311a42c256bbf880db3ac99sewardj            shoud say that m points into a real segment (preferable
2742024598e40c84666cc311a42c256bbf880db3ac99sewardj            'seg'), but it doesn't. */
2743024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (Seg__status_is_SegHeap(seg)) {
2744024598e40c84666cc311a42c256bbf880db3ac99sewardj            stats__refs_in_a_seg++;
2745024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (UNKNOWN == mptr_vseg
2746024598e40c84666cc311a42c256bbf880db3ac99sewardj                || BOTTOM == mptr_vseg || NONPTR == mptr_vseg) {
2747024598e40c84666cc311a42c256bbf880db3ac99sewardj               ExeContext* ec;
2748024598e40c84666cc311a42c256bbf880db3ac99sewardj               Char buf[100];
2749024598e40c84666cc311a42c256bbf880db3ac99sewardj               static UWord xx = 0;
2750024598e40c84666cc311a42c256bbf880db3ac99sewardj               stats__refs_lost_seg++;
2751024598e40c84666cc311a42c256bbf880db3ac99sewardj               ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 );
2752024598e40c84666cc311a42c256bbf880db3ac99sewardj               inc_lossage(ec);
2753024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (0) {
2754024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(message)(Vg_DebugMsg, "");
2755024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(message)(Vg_DebugMsg,
2756024598e40c84666cc311a42c256bbf880db3ac99sewardj                               "Lossage %s %#lx sz %lu inside block alloc'd",
2757024598e40c84666cc311a42c256bbf880db3ac99sewardj                               is_write ? "wr" : "rd", m, (UWord)sz);
2758024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(pp_ExeContext)(Seg__where(seg));
2759024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
2760024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (xx++ < 0) {
2761024598e40c84666cc311a42c256bbf880db3ac99sewardj                  Addr ip = VG_(get_IP)( VG_(get_running_tid)() );
2762024598e40c84666cc311a42c256bbf880db3ac99sewardj                  (void)VG_(describe_IP)( ip, buf, sizeof(buf)-1);
2763024598e40c84666cc311a42c256bbf880db3ac99sewardj                  buf[sizeof(buf)-1] = 0;
2764024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(printf)("lossage at %p %s\n", ec, buf );
2765024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
2766024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
2767024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
2768024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2769024598e40c84666cc311a42c256bbf880db3ac99sewardj   } /* clo_lossage_check */
27704815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#endif
2771024598e40c84666cc311a42c256bbf880db3ac99sewardj
2772024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2773024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2774024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2775024598e40c84666cc311a42c256bbf880db3ac99sewardj
2776024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (UNKNOWN == mptr_vseg) {
2777024598e40c84666cc311a42c256bbf880db3ac99sewardj      // do nothing
2778024598e40c84666cc311a42c256bbf880db3ac99sewardj
2779024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (BOTTOM == mptr_vseg) {
2780024598e40c84666cc311a42c256bbf880db3ac99sewardj      // do nothing
2781024598e40c84666cc311a42c256bbf880db3ac99sewardj
2782024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (NONPTR == mptr_vseg) {
2783024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_heap_error( m, sz, mptr_vseg, is_write );
2784024598e40c84666cc311a42c256bbf880db3ac99sewardj
2785024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2786024598e40c84666cc311a42c256bbf880db3ac99sewardj      // check all segment ranges in the circle
2787024598e40c84666cc311a42c256bbf880db3ac99sewardj      // if none match, warn about 1st seg
2788024598e40c84666cc311a42c256bbf880db3ac99sewardj      // else,          check matching one isn't freed
2789024598e40c84666cc311a42c256bbf880db3ac99sewardj      Bool is_ok = False;
2790024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* curr  = mptr_vseg;
2791024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr mhi;
2792024598e40c84666cc311a42c256bbf880db3ac99sewardj
2793024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Accesses partly outside range are an error, unless it's an aligned
2794024598e40c84666cc311a42c256bbf880db3ac99sewardj      // word-sized read, and --partial-loads-ok=yes.  This is to cope with
2795024598e40c84666cc311a42c256bbf880db3ac99sewardj      // gcc's/glibc's habits of doing word-sized accesses that read past
2796024598e40c84666cc311a42c256bbf880db3ac99sewardj      // the ends of arrays/strings.
2797024598e40c84666cc311a42c256bbf880db3ac99sewardj      // JRS 2008-sept-11: couldn't this be moved off the critical path?
2798024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (!is_write && sz == sizeof(UWord)
2799024598e40c84666cc311a42c256bbf880db3ac99sewardj          && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
2800024598e40c84666cc311a42c256bbf880db3ac99sewardj         mhi = m;
2801024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2802024598e40c84666cc311a42c256bbf880db3ac99sewardj         mhi = m+sz-1;
2803024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2804024598e40c84666cc311a42c256bbf880db3ac99sewardj
2805024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (0) VG_(printf)("calling seg_ci %p %#lx %#lx\n", curr,m,mhi);
2806024598e40c84666cc311a42c256bbf880db3ac99sewardj      is_ok = curr->addr <= m && mhi < curr->addr + curr->szB;
2807024598e40c84666cc311a42c256bbf880db3ac99sewardj
2808024598e40c84666cc311a42c256bbf880db3ac99sewardj      // If it's an overrun/underrun of a freed block, don't give both
2809024598e40c84666cc311a42c256bbf880db3ac99sewardj      // warnings, since the first one mentions that the block has been
2810024598e40c84666cc311a42c256bbf880db3ac99sewardj      // freed.
2811024598e40c84666cc311a42c256bbf880db3ac99sewardj      if ( ! is_ok || Seg__is_freed(curr) )
2812024598e40c84666cc311a42c256bbf880db3ac99sewardj         h_record_heap_error( m, sz, mptr_vseg, is_write );
2813024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2814024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2815024598e40c84666cc311a42c256bbf880db3ac99sewardj
2816024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Load handlers ------------------ //
2817024598e40c84666cc311a42c256bbf880db3ac99sewardj
2818024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use:
2819024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load1 check_load2 check_load4_P
2820024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load4  (for 32-bit FP reads)
2821024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load8  (for 64-bit FP reads)
2822024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load16 (for xmm/altivec reads)
2823024598e40c84666cc311a42c256bbf880db3ac99sewardj   On 64 bit targets, we will use:
2824024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load1 check_load2 check_load4 check_load8_P
2825024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load8  (for 64-bit FP reads)
2826024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load16 (for xmm/altivec reads)
2827024598e40c84666cc311a42c256bbf880db3ac99sewardj
2828024598e40c84666cc311a42c256bbf880db3ac99sewardj   A "_P" handler reads a pointer from memory, and so returns a value
2829024598e40c84666cc311a42c256bbf880db3ac99sewardj   to the generated code -- the pointer's shadow value.  That implies
2830024598e40c84666cc311a42c256bbf880db3ac99sewardj   that check_load4_P is only to be called on a 32 bit host and
2831024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load8_P is only to be called on a 64 bit host.  For all other
2832024598e40c84666cc311a42c256bbf880db3ac99sewardj   cases no shadow value is returned; we merely check that the pointer
2833024598e40c84666cc311a42c256bbf880db3ac99sewardj   (m) matches the block described by its shadow value (mptr_vseg).
2834024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
2835024598e40c84666cc311a42c256bbf880db3ac99sewardj
2836024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit loads on both 32 bit and 64 bit targets.
2837024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2838024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load16(Addr m, Seg* mptr_vseg)
2839024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2840024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2841024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2842024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2843024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 16, mptr_vseg);
2844024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2845024598e40c84666cc311a42c256bbf880db3ac99sewardj
2846024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit FP-or-otherwise-nonpointer loads on both
2847024598e40c84666cc311a42c256bbf880db3ac99sewardj// 32 bit and 64 bit targets.
2848024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2849024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load8(Addr m, Seg* mptr_vseg)
2850024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2851024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2852024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2853024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2854024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2855024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2856024598e40c84666cc311a42c256bbf880db3ac99sewardj
2857024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit loads on 64 bit targets.  It must
2858024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets.
2859024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg
2860024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2861024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load8_P(Addr m, Seg* mptr_vseg)
2862024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2863024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* vseg;
2864024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2865024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2866024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2867024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2868024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2869024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_8_ALIGNED(m)) {
2870024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = get_mem_vseg(m);
2871024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2872024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = nonptr_or_unknown( *(ULong*)m );
2873024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2874024598e40c84666cc311a42c256bbf880db3ac99sewardj   return vseg;
2875024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2876024598e40c84666cc311a42c256bbf880db3ac99sewardj
2877024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit loads on 32 bit targets.  It must
2878024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets.
2879024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg
2880024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2881024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load4_P(Addr m, Seg* mptr_vseg)
2882024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2883024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* vseg;
2884024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2885024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2886024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2887024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2888024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2889024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_4_ALIGNED(m)) {
2890024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = get_mem_vseg(m);
2891024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2892024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = nonptr_or_unknown( *(UInt*)m );
2893024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2894024598e40c84666cc311a42c256bbf880db3ac99sewardj   return vseg;
2895024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2896024598e40c84666cc311a42c256bbf880db3ac99sewardj
2897024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2898024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2899024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load4(Addr m, Seg* mptr_vseg)
2900024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2901024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2902024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2903024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2904024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2905024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2906024598e40c84666cc311a42c256bbf880db3ac99sewardj
2907024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2908024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2909024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load2(Addr m, Seg* mptr_vseg)
2910024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2911024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2912024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2913024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2914024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 2, mptr_vseg);
2915024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2916024598e40c84666cc311a42c256bbf880db3ac99sewardj
2917024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2918024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2919024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load1(Addr m, Seg* mptr_vseg)
2920024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2921024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2922024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2923024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2924024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 1, mptr_vseg);
2925024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2926024598e40c84666cc311a42c256bbf880db3ac99sewardj
2927024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Store handlers ------------------ //
2928024598e40c84666cc311a42c256bbf880db3ac99sewardj
2929024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use:
29301c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      check_store1 check_store2 check_store4_P check_store4C_P
2931024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store4 (for 32-bit nonpointer stores)
2932024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store8_ms4B_ls4B (for 64-bit stores)
2933024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store16_ms4B_4B_4B_ls4B (for xmm/altivec stores)
2934024598e40c84666cc311a42c256bbf880db3ac99sewardj
2935024598e40c84666cc311a42c256bbf880db3ac99sewardj   On 64 bit targets, we will use:
29361c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      check_store1 check_store2 check_store4 check_store4C
29371c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      check_store8_P check_store_8C_P
2938024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store8_all8B (for 64-bit nonpointer stores)
2939024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store16_ms8B_ls8B (for xmm/altivec stores)
2940024598e40c84666cc311a42c256bbf880db3ac99sewardj
2941024598e40c84666cc311a42c256bbf880db3ac99sewardj   A "_P" handler writes a pointer to memory, and so has an extra
2942024598e40c84666cc311a42c256bbf880db3ac99sewardj   argument -- the pointer's shadow value.  That implies that
29431c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   check_store4{,C}_P is only to be called on a 32 bit host and
29441c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   check_store8{,C}_P is only to be called on a 64 bit host.  For all
2945024598e40c84666cc311a42c256bbf880db3ac99sewardj   other cases, and for the misaligned _P cases, the strategy is to
2946024598e40c84666cc311a42c256bbf880db3ac99sewardj   let the store go through, and then snoop around with
2947024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown to fix up the shadow values of any affected
2948024598e40c84666cc311a42c256bbf880db3ac99sewardj   words. */
2949024598e40c84666cc311a42c256bbf880db3ac99sewardj
29501c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj/* Helpers for store-conditionals.  Ugly kludge :-(
29511c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   They all return 1 if the SC was successful and 0 if it failed. */
29521c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic inline UWord do_store_conditional_32( Addr m/*dst*/, UInt t/*val*/ )
29531c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{
29541c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  if defined(VGA_ppc32) || defined(VGA_ppc64)
29551c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   UWord success;
29561c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   /* If this assertion fails, the underlying IR is (semantically) ill-formed
29571c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      as per the IR spec for IRStmt_Store. */
29581c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   tl_assert(VG_IS_4_ALIGNED(m));
29591c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   __asm__ __volatile__(
29601c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      "stwcx. %2,0,%1"    "\n\t" /* data,0,addr */
29611c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      "mfcr   %0"         "\n\t"
29621c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      "srwi   %0,%0,29"   "\n\t" /* move relevant CR bit to LSB */
29631c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      : /*out*/"=b"(success)
29641c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      : /*in*/ "b"(m), "b"( (UWord)t )
29651c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      : /*trash*/ "memory", "cc"
29661c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj        /* Note: srwi is OK even on 64-bit host because the we're
29671c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj           after bit 29 (normal numbering) and we mask off all the
29681c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj           other junk just below. */
29691c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   );
29701c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   return success & (UWord)1;
29711c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  else
29721c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   tl_assert(0); /* not implemented on other platforms */
29731c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  endif
29741c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj}
29751c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
29761c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic inline UWord do_store_conditional_64( Addr m/*dst*/, ULong t/*val*/ )
29771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{
29781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  if defined(VGA_ppc64)
29791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   UWord success;
29801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   /* If this assertion fails, the underlying IR is (semantically) ill-formed
29811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      as per the IR spec for IRStmt_Store. */
29821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   tl_assert(VG_IS_8_ALIGNED(m));
29831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   __asm__ __volatile__(
29841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      "stdcx. %2,0,%1"    "\n\t" /* data,0,addr */
29851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      "mfcr   %0"         "\n\t"
29861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      "srdi   %0,%0,29"   "\n\t" /* move relevant CR bit to LSB */
29871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      : /*out*/"=b"(success)
29881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      : /*in*/ "b"(m), "b"( (UWord)t )
29891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      : /*trash*/ "memory", "cc"
29901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   );
29911c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   return success & (UWord)1;
29921c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  else
29931c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   tl_assert(0); /* not implemented on other platforms */
29941c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  endif
29951c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj}
29961c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
2997024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Apply nonptr_or_unknown to all the words intersecting
2998024598e40c84666cc311a42c256bbf880db3ac99sewardj   [a, a+len). */
2999024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
3000024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid nonptr_or_unknown_range ( Addr a, SizeT len )
3001024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3002024598e40c84666cc311a42c256bbf880db3ac99sewardj   const SizeT wszB = sizeof(UWord);
3003024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr wfirst = VG_ROUNDDN(a,       wszB);
3004024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr wlast  = VG_ROUNDDN(a+len-1, wszB);
3005024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr a2;
3006024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(wfirst <= wlast);
3007024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (a2 = wfirst ; a2 <= wlast; a2 += wszB) {
3008024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( a2, nonptr_or_unknown( *(UWord*)a2 ));
3009024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3010024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3011024598e40c84666cc311a42c256bbf880db3ac99sewardj
3012024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets.  The
3013024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
3014024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
3015024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3016024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms8B_ls8B(Addr m, Seg* mptr_vseg,
3017024598e40c84666cc311a42c256bbf880db3ac99sewardj                             UWord ms8B, UWord ls8B)
3018024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3019024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3020024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3021024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3022024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3023024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
3024024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3025024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
3026024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
3027024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
3028024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 0) = ls8B;
3029024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 8) = ms8B;
3030024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3031024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 0) = ms8B;
3032024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 8) = ls8B;
3033024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3034024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 16);
3035024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3036024598e40c84666cc311a42c256bbf880db3ac99sewardj
3037024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets.  The
3038024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
3039024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
3040024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3041024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms4B_4B_4B_ls4B(Addr m, Seg* mptr_vseg,
3042024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   UWord ms4B, UWord w2,
3043024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   UWord w1,   UWord ls4B)
3044024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3045024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3046024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3047024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3048024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3049024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
3050024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3051024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
3052024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
3053024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
3054024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  0) = ls4B;
3055024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  4) = w1;
3056024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  8) = w2;
3057024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 12) = ms4B;
3058024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3059024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  0) = ms4B;
3060024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  4) = w2;
3061024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  8) = w1;
3062024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 12) = ls4B;
3063024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3064024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 16);
3065024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3066024598e40c84666cc311a42c256bbf880db3ac99sewardj
3067024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 32 bit targets.  The
3068024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
3069024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
3070024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3071024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_ms4B_ls4B(Addr m, Seg* mptr_vseg,
3072024598e40c84666cc311a42c256bbf880db3ac99sewardj                            UWord ms4B, UWord ls4B)
3073024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3074024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3075024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3076024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3077024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3078024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3079024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3080024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
3081024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
3082024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
3083024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 0) = ls4B;
3084024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 4) = ms4B;
3085024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3086024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 0) = ms4B;
3087024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 4) = ls4B;
3088024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3089024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 8);
3090024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3091024598e40c84666cc311a42c256bbf880db3ac99sewardj
3092024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit non pointer stores on 64 bit targets.
3093024598e40c84666cc311a42c256bbf880db3ac99sewardj// It must not be called on 32 bit targets.
3094024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3095024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_all8B(Addr m, Seg* mptr_vseg, UWord all8B)
3096024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3097024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3098024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3099024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3100024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3101024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3102024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3103024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(ULong*)m = all8B;
3104024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 8);
3105024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3106024598e40c84666cc311a42c256bbf880db3ac99sewardj
3107024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 64 bit targets.  It must
3108024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets.
3109024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3110024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3111024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3112024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3113024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3114024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(t_vseg);
3115024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3116024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3117024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3118024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3119024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(ULong*)m = t;
3120024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_8_ALIGNED(m)) {
3121024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( m, t_vseg );
3122024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3123024598e40c84666cc311a42c256bbf880db3ac99sewardj      // straddling two words
3124024598e40c84666cc311a42c256bbf880db3ac99sewardj      nonptr_or_unknown_range(m, 8);
3125024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3126024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3127024598e40c84666cc311a42c256bbf880db3ac99sewardj
31281c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// This handles 64 bit store-conditionals on 64 bit targets.  It must
31291c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// not be called on 32 bit targets.
31301c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic VG_REGPARM(3)
31311c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjUWord check_store8C_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
31321c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{
31331c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   UWord success;
31341c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
31351c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  if SC_SEGS
31361c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   checkSeg(t_vseg);
31371c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   checkSeg(mptr_vseg);
31381c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  endif
31391c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
31401c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   // Actually *do* the STORE here
31411c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   success = do_store_conditional_64( m, t );
31421c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   if (VG_IS_8_ALIGNED(m)) {
31431c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      set_mem_vseg( m, t_vseg );
31441c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   } else {
31451c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      // straddling two words
31461c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      nonptr_or_unknown_range(m, 8);
31471c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   }
31481c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   return success;
31491c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj}
31501c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
3151024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit stores on 32 bit targets.  It must
3152024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets.
3153024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3154024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3155024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3156024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3157024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3158024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(t_vseg);
3159024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3160024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3161024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3162024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
3163024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UInt*)m = t;
3164024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_4_ALIGNED(m)) {
3165024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( m, t_vseg );
3166024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3167024598e40c84666cc311a42c256bbf880db3ac99sewardj      // straddling two words
3168024598e40c84666cc311a42c256bbf880db3ac99sewardj      nonptr_or_unknown_range(m, 4);
3169024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3170024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3171024598e40c84666cc311a42c256bbf880db3ac99sewardj
31721c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// This handles 32 bit store-conditionals on 32 bit targets.  It must
31731c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// not be called on 64 bit targets.
31741c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic VG_REGPARM(3)
31751c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjUWord check_store4C_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
31761c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{
31771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   UWord success;
31781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
31791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  if SC_SEGS
31801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   checkSeg(t_vseg);
31811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   checkSeg(mptr_vseg);
31821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  endif
31831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
31841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   // Actually *do* the STORE here
31851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   success = do_store_conditional_32( m, t );
31861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   if (VG_IS_4_ALIGNED(m)) {
31871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      set_mem_vseg( m, t_vseg );
31881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   } else {
31891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      // straddling two words
31901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj      nonptr_or_unknown_range(m, 4);
31911c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   }
31921c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   return success;
31931c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj}
31941c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
3195024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
3196024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3197024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4(Addr m, Seg* mptr_vseg, UWord t)
3198024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3199024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3200024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3201024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3202024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3203024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 4-byte type!)
3204024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UInt*)m = t;
3205024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 4);
3206024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3207024598e40c84666cc311a42c256bbf880db3ac99sewardj
32081c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// Used for 32-bit store-conditionals on 64 bit targets only.  It must
32091c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// not be called on 32 bit targets.
32101c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic VG_REGPARM(3)
32111c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjUWord check_store4C(Addr m, Seg* mptr_vseg, UWord t)
32121c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{
32131c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   UWord success;
32141c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
32151c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  if SC_SEGS
32161c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   checkSeg(mptr_vseg);
32171c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj#  endif
32181c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
32191c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   // Actually *do* the STORE here
32201c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   success = do_store_conditional_32( m, t );
32211c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   nonptr_or_unknown_range(m, 4);
32221c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   return success;
32231c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj}
32241c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
3225024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
3226024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3227024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store2(Addr m, Seg* mptr_vseg, UWord t)
3228024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3229024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3230024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3231024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3232024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 2, mptr_vseg);
3233024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 2-byte type!)
3234024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UShort*)m = t;
3235024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 2);
3236024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3237024598e40c84666cc311a42c256bbf880db3ac99sewardj
3238024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
3239024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
3240024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store1(Addr m, Seg* mptr_vseg, UWord t)
3241024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3242024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3243024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
3244024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3245024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 1, mptr_vseg);
3246024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 1-byte type!)
3247024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UChar*)m = t;
3248024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 1);
3249024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3250024598e40c84666cc311a42c256bbf880db3ac99sewardj
3251024598e40c84666cc311a42c256bbf880db3ac99sewardj
3252024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: if the result is BOTTOM, return immedately -- don't let BOTTOM
3253024598e40c84666cc311a42c256bbf880db3ac99sewardj//     be changed to NONPTR by a range check on the result.
3254024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINOP(bt, nn, nu, np, un, uu, up, pn, pu, pp) \
3255024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (BOTTOM == seg1 || BOTTOM == seg2) { bt;                   \
3256024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (NONPTR == seg1)  { if      (NONPTR == seg2)  { nn; }  \
3257024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { nu; }    \
3258024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { np; }    \
3259024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (UNKNOWN == seg1) { if      (NONPTR == seg2)  { un; }    \
3260024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { uu; }    \
3261024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { up; }    \
3262024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else                      { if      (NONPTR == seg2)  { pn; }    \
3263024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { pu; }    \
3264024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { pp; }    \
3265024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3266024598e40c84666cc311a42c256bbf880db3ac99sewardj
3267024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINERROR(opname)                    \
3268024598e40c84666cc311a42c256bbf880db3ac99sewardj   h_record_arith_error(seg1, seg2, opname);  \
3269024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = NONPTR
3270024598e40c84666cc311a42c256bbf880db3ac99sewardj
3271024598e40c84666cc311a42c256bbf880db3ac99sewardj
3272024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3273024598e40c84666cc311a42c256bbf880db3ac99sewardj//  + | n  ?  p
3274024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3275024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3276024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3277024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  e   (all results become n if they look like a non-pointer)
3278024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3279024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* do_addW_result(Seg* seg1, Seg* seg2, UWord result, HChar* opname)
3280024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3281024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3282024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3283024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3284024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3285024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3286024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3287024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3288024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN, out = seg2,
3289024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3290024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = UNKNOWN,       BINERROR(opname)
3291024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3292024598e40c84666cc311a42c256bbf880db3ac99sewardj   return ( looks_like_a_pointer(result) ? out : NONPTR );
3293024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3294024598e40c84666cc311a42c256bbf880db3ac99sewardj
3295024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_addW(Seg* seg1, Seg* seg2, UWord result)
3296024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3297024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3298024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3299024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3300024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3301024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3302024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = do_addW_result(seg1, seg2, result, "Add32/Add64");
3303024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3304024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(out);
3305024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3306024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3307024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3308024598e40c84666cc311a42c256bbf880db3ac99sewardj
3309024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3310024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - | n  ?  p      (Nb: operation is seg1 - seg2)
3311024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3312024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  n+     (+) happens a lot due to "cmp", but result should never
3313024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  n/B        be used, so give 'n'
3314024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  p? n*/B   (*) and possibly link the segments
3315024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3316024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_subW(Seg* seg1, Seg* seg2, UWord result)
3317024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3318024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3319024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3320024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3321024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3322024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3323024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Nb: when returning BOTTOM, don't let it go through the range-check;
3324024598e40c84666cc311a42c256bbf880db3ac99sewardj   //     a segment linking offset can easily look like a nonptr.
3325024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3326024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3327024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN,    out = NONPTR,
3328024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN,    return BOTTOM,
3329024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = seg1/*??*/, return BOTTOM
3330024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3331024598e40c84666cc311a42c256bbf880db3ac99sewardj   #if 0
3332024598e40c84666cc311a42c256bbf880db3ac99sewardj         // This is for the p-p segment-linking case
3333024598e40c84666cc311a42c256bbf880db3ac99sewardj         Seg end2 = seg2;
3334024598e40c84666cc311a42c256bbf880db3ac99sewardj         while (end2->links != seg2) end2 = end2->links;
3335024598e40c84666cc311a42c256bbf880db3ac99sewardj         end2->links = seg1->links;
3336024598e40c84666cc311a42c256bbf880db3ac99sewardj         seg1->links = seg2;
3337024598e40c84666cc311a42c256bbf880db3ac99sewardj         return NONPTR;
3338024598e40c84666cc311a42c256bbf880db3ac99sewardj   #endif
3339024598e40c84666cc311a42c256bbf880db3ac99sewardj   return ( looks_like_a_pointer(result) ? out : NONPTR );
3340024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3341024598e40c84666cc311a42c256bbf880db3ac99sewardj
3342024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3343024598e40c84666cc311a42c256bbf880db3ac99sewardj//  & | n  ?  p
3344024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3345024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3346024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3347024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  *  (*) if p1==p2 then p else e (see comment)
3348024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3349024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Seems to be OK to And two pointers:
3350024598e40c84666cc311a42c256bbf880db3ac99sewardj     testq %ptr1,%ptr2
3351024598e40c84666cc311a42c256bbf880db3ac99sewardj     jnz ..
3352024598e40c84666cc311a42c256bbf880db3ac99sewardj   which possibly derives from
3353024598e40c84666cc311a42c256bbf880db3ac99sewardj     if (ptr1 & ptr2) { A } else { B }
3354024598e40c84666cc311a42c256bbf880db3ac99sewardj   not sure what that means
3355024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3356024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_andW(Seg* seg1, Seg* seg2,
3357024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  UWord result, UWord args_diff)
3358024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3359024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3360024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0 == args_diff) {
3361024598e40c84666cc311a42c256bbf880db3ac99sewardj      // p1==p2
3362024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1;
3363024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3364024598e40c84666cc311a42c256bbf880db3ac99sewardj      BINOP(
3365024598e40c84666cc311a42c256bbf880db3ac99sewardj         return BOTTOM,
3366024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = NONPTR,  out = UNKNOWN, out = seg2,
3367024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3368024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = seg1,    out = UNKNOWN, out = NONPTR
3369024598e40c84666cc311a42c256bbf880db3ac99sewardj                                       /*BINERROR("And32/And64")*/
3370024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
3371024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3372024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = ( looks_like_a_pointer(result) ? out : NONPTR );
3373024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3374024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3375024598e40c84666cc311a42c256bbf880db3ac99sewardj
3376024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3377024598e40c84666cc311a42c256bbf880db3ac99sewardj// `|`| n  ?  p
3378024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3379024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3380024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3381024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  n
3382024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3383024598e40c84666cc311a42c256bbf880db3ac99sewardj/* It's OK to Or two pointers together, but the result definitely
3384024598e40c84666cc311a42c256bbf880db3ac99sewardj   isn't a pointer.  Why would you want to do that?  Because of this:
3385024598e40c84666cc311a42c256bbf880db3ac99sewardj     char* p1 = malloc(..);
3386024598e40c84666cc311a42c256bbf880db3ac99sewardj     char* p2 = malloc(..);
3387024598e40c84666cc311a42c256bbf880db3ac99sewardj     ...
3388024598e40c84666cc311a42c256bbf880db3ac99sewardj     if (p1 || p2) { .. }
3389024598e40c84666cc311a42c256bbf880db3ac99sewardj   In this case gcc on x86/amd64 quite literally or-s the two pointers
3390024598e40c84666cc311a42c256bbf880db3ac99sewardj   together and throws away the result, the purpose of which is merely
3391024598e40c84666cc311a42c256bbf880db3ac99sewardj   to sets %eflags.Z/%rflags.Z.  So we have to allow it.
3392024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3393024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_orW(Seg* seg1, Seg* seg2, UWord result)
3394024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3395024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3396024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3397024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3398024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN, out = seg2,
3399024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3400024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = UNKNOWN, out = NONPTR
3401024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3402024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = ( looks_like_a_pointer(result) ? out : NONPTR );
3403024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3404024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3405024598e40c84666cc311a42c256bbf880db3ac99sewardj
3406024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3407024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ~ | n  ?  p
3408024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3409024598e40c84666cc311a42c256bbf880db3ac99sewardj//    | n  n  n
3410024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3411024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_notW(Seg* seg1, UWord result)
3412024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3413024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3414024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3415024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3416024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (BOTTOM == seg1) return BOTTOM;
3417024598e40c84666cc311a42c256bbf880db3ac99sewardj   return NONPTR;
3418024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3419024598e40c84666cc311a42c256bbf880db3ac99sewardj
3420024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pointers are rarely multiplied, but sometimes legitimately, eg. as hash
3421024598e40c84666cc311a42c256bbf880db3ac99sewardj// function inputs.  But two pointers args --> error.
3422024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pretend it always returns a nonptr.  Maybe improve later.
3423024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_mulW(Seg* seg1, Seg* seg2)
3424024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3425024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3426024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3427024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3428024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3429024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seg1) && is_known_segment(seg2))
3430024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_arith_error(seg1, seg2, "Mul32/Mul64");
3431024598e40c84666cc311a42c256bbf880db3ac99sewardj   return NONPTR;
3432024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3433024598e40c84666cc311a42c256bbf880db3ac99sewardj
3434024598e40c84666cc311a42c256bbf880db3ac99sewardj
3435024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3436024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Instrumentation                                              ---*/
3437024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3438024598e40c84666cc311a42c256bbf880db3ac99sewardj
3439024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The h_ instrumenter that follows is complex, since it deals with
3440024598e40c84666cc311a42c256bbf880db3ac99sewardj   shadow value computation.
3441024598e40c84666cc311a42c256bbf880db3ac99sewardj
3442024598e40c84666cc311a42c256bbf880db3ac99sewardj   It also needs to generate instrumentation for the sg_ side of
3443024598e40c84666cc311a42c256bbf880db3ac99sewardj   things.  That's relatively straightforward.  However, rather than
3444024598e40c84666cc311a42c256bbf880db3ac99sewardj   confuse the code herein any further, we simply delegate the problem
3445024598e40c84666cc311a42c256bbf880db3ac99sewardj   to sg_main.c, by using the four functions
3446024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_{init,fini,IRStmt,final_jump}.  These four completely
3447024598e40c84666cc311a42c256bbf880db3ac99sewardj   abstractify the sg_ instrumentation.  See comments in sg_main.c's
3448024598e40c84666cc311a42c256bbf880db3ac99sewardj   instrumentation section for further details. */
3449024598e40c84666cc311a42c256bbf880db3ac99sewardj
3450e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3451e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj/* Carries info about a particular tmp.  The tmp's number is not
3452e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   recorded, as this is implied by (equal to) its index in the tmpMap
3453e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   in PCEnv.  The tmp's type is also not recorded, as this is present
3454e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   in PCEnv.sb->tyenv.
3455e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3456e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   When .kind is NonShad, .shadow may give the identity of the temp
3457e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   currently holding the associated shadow value, or it may be
3458e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   IRTemp_INVALID if code to compute the shadow has not yet been
3459e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   emitted.
3460e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3461e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   When .kind is Shad tmp holds a shadow value, and so .shadow must be
3462e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   IRTemp_INVALID, since it is illogical for a shadow tmp itself to be
3463e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   shadowed.
3464e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj*/
3465e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjtypedef
3466e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   enum { NonShad=1, Shad=2 }
3467e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   TempKind;
3468e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3469e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjtypedef
3470e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   struct {
3471e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      TempKind kind;
3472e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      IRTemp   shadow;
3473e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   }
3474e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   TempMapEnt;
3475e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3476e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3477e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3478024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Carries around state during Ptrcheck instrumentation. */
3479024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
3480024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
3481024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* MODIFIED: the superblock being constructed.  IRStmts are
3482024598e40c84666cc311a42c256bbf880db3ac99sewardj         added. */
3483e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      IRSB* sb;
3484024598e40c84666cc311a42c256bbf880db3ac99sewardj      Bool  trace;
3485024598e40c84666cc311a42c256bbf880db3ac99sewardj
3486e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
3487e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         current kind and possibly shadow temps for each temp in the
3488e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         IRSB being constructed.  Note that it does not contain the
3489e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         type of each tmp.  If you want to know the type, look at the
3490e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         relevant entry in sb->tyenv.  It follows that at all times
3491e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         during the instrumentation process, the valid indices for
3492e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is
3493e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         total number of NonShad and Shad temps allocated so far.
3494e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3495e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         The reason for this strange split (types in one place, all
3496e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         other info in another) is that we need the types to be
3497e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         attached to sb so as to make it possible to do
3498e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the
3499e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         instrumentation process.
3500e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3501e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         Note that only integer temps of the guest word size are
3502e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         shadowed, since it is impossible (or meaningless) to hold a
3503e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         pointer in any other type of temp. */
3504e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      XArray* /* of TempMapEnt */ qmpMap;
3505024598e40c84666cc311a42c256bbf880db3ac99sewardj
3506024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the host word type.  Needed for constructing
3507024598e40c84666cc311a42c256bbf880db3ac99sewardj         arguments of type 'HWord' to be passed to helper functions.
3508024598e40c84666cc311a42c256bbf880db3ac99sewardj         Ity_I32 or Ity_I64 only. */
3509024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRType hWordTy;
3510024598e40c84666cc311a42c256bbf880db3ac99sewardj
3511024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
3512024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRType gWordTy;
3513024598e40c84666cc311a42c256bbf880db3ac99sewardj
3514024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the guest state size, so we can generate shadow
3515024598e40c84666cc311a42c256bbf880db3ac99sewardj         offsets correctly. */
3516024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int guest_state_sizeB;
3517024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3518024598e40c84666cc311a42c256bbf880db3ac99sewardj   PCEnv;
3519024598e40c84666cc311a42c256bbf880db3ac99sewardj
3520024598e40c84666cc311a42c256bbf880db3ac99sewardj/* SHADOW TMP MANAGEMENT.  Shadow tmps are allocated lazily (on
3521024598e40c84666cc311a42c256bbf880db3ac99sewardj   demand), as they are encountered.  This is for two reasons.
3522024598e40c84666cc311a42c256bbf880db3ac99sewardj
3523024598e40c84666cc311a42c256bbf880db3ac99sewardj   (1) (less important reason): Many original tmps are unused due to
3524024598e40c84666cc311a42c256bbf880db3ac99sewardj   initial IR optimisation, and we do not want to spaces in tables
3525024598e40c84666cc311a42c256bbf880db3ac99sewardj   tracking them.
3526024598e40c84666cc311a42c256bbf880db3ac99sewardj
3527024598e40c84666cc311a42c256bbf880db3ac99sewardj   Shadow IRTemps are therefore allocated on demand.  pce.tmpMap is a
3528024598e40c84666cc311a42c256bbf880db3ac99sewardj   table indexed [0 .. n_types-1], which gives the current shadow for
3529024598e40c84666cc311a42c256bbf880db3ac99sewardj   each original tmp, or INVALID_IRTEMP if none is so far assigned.
3530024598e40c84666cc311a42c256bbf880db3ac99sewardj   It is necessary to support making multiple assignments to a shadow
3531024598e40c84666cc311a42c256bbf880db3ac99sewardj   -- specifically, after testing a shadow for definedness, it needs
3532024598e40c84666cc311a42c256bbf880db3ac99sewardj   to be made defined.  But IR's SSA property disallows this.
3533024598e40c84666cc311a42c256bbf880db3ac99sewardj
3534024598e40c84666cc311a42c256bbf880db3ac99sewardj   (2) (more important reason): Therefore, when a shadow needs to get
3535024598e40c84666cc311a42c256bbf880db3ac99sewardj   a new value, a new temporary is created, the value is assigned to
3536024598e40c84666cc311a42c256bbf880db3ac99sewardj   that, and the tmpMap is updated to reflect the new binding.
3537024598e40c84666cc311a42c256bbf880db3ac99sewardj
3538024598e40c84666cc311a42c256bbf880db3ac99sewardj   A corollary is that if the tmpMap maps a given tmp to
3539024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp_INVALID and we are hoping to read that shadow tmp, it means
3540024598e40c84666cc311a42c256bbf880db3ac99sewardj   there's a read-before-write error in the original tmps.  The IR
3541024598e40c84666cc311a42c256bbf880db3ac99sewardj   sanity checker should catch all such anomalies, however.
3542024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3543024598e40c84666cc311a42c256bbf880db3ac99sewardj
3544e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
3545e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   both the table in pce->sb and to our auxiliary mapping.  Note that
3546e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   newTemp may cause pce->tmpMap to resize, hence previous results
3547e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   from VG_(indexXA)(pce->tmpMap) are invalidated. */
3548e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjstatic IRTemp newTemp ( PCEnv* pce, IRType ty, TempKind kind )
3549e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj{
3550e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   Word       newIx;
3551e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   TempMapEnt ent;
3552e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   IRTemp     tmp = newIRTemp(pce->sb->tyenv, ty);
3553e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   ent.kind   = kind;
3554e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   ent.shadow = IRTemp_INVALID;
3555e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   newIx = VG_(addToXA)( pce->qmpMap, &ent );
3556e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(newIx == (Word)tmp);
3557e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   return tmp;
3558e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj}
3559e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3560024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Find the tmp currently shadowing the given original tmp.  If none
3561024598e40c84666cc311a42c256bbf880db3ac99sewardj   so far exists, allocate one.  */
3562024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp findShadowTmp ( PCEnv* pce, IRTemp orig )
3563024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3564e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   TempMapEnt* ent;
3565e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   /* VG_(indexXA) range-checks 'orig', hence no need to check
3566e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      here. */
3567e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3568e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(ent->kind == NonShad);
3569e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   if (ent->shadow == IRTemp_INVALID) {
3570e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      IRTemp shadow = newTemp( pce, pce->gWordTy, Shad );
3571e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      /* newTemp may cause pce->tmpMap to resize, hence previous results
3572e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         from VG_(indexXA) are invalid. */
3573e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3574e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      tl_assert(ent->kind == NonShad);
3575e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      tl_assert(ent->shadow == IRTemp_INVALID);
3576e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      ent->shadow = shadow;
3577024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3578e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   return ent->shadow;
3579024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3580024598e40c84666cc311a42c256bbf880db3ac99sewardj
3581024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Allocate a new shadow for the given original tmp.  This means any
3582024598e40c84666cc311a42c256bbf880db3ac99sewardj   previous shadow is abandoned.  This is needed because it is
3583024598e40c84666cc311a42c256bbf880db3ac99sewardj   necessary to give a new value to a shadow once it has been tested
3584024598e40c84666cc311a42c256bbf880db3ac99sewardj   for undefinedness, but unfortunately IR's SSA property disallows
3585024598e40c84666cc311a42c256bbf880db3ac99sewardj   this.  Instead we must abandon the old shadow, allocate a new one
3586e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   and use that instead.
3587e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
3588e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   This is the same as findShadowTmp, except we don't bother to see
3589e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   if a shadow temp already existed -- we simply allocate a new one
3590e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   regardless. */
3591024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp newShadowTmp ( PCEnv* pce, IRTemp orig )
3592024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3593e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   TempMapEnt* ent;
3594e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   /* VG_(indexXA) range-checks 'orig', hence no need to check
3595e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      here. */
3596e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3597e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(ent->kind == NonShad);
3598e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   if (1) {
3599e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      IRTemp shadow = newTemp( pce, pce->gWordTy, Shad );
3600e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      /* newTemp may cause pce->tmpMap to resize, hence previous results
3601e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         from VG_(indexXA) are invalid. */
3602e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3603e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      tl_assert(ent->kind == NonShad);
3604e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      ent->shadow = shadow;
3605e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      return shadow;
3606e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   }
3607e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   /* NOTREACHED */
3608e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(0);
3609024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3610024598e40c84666cc311a42c256bbf880db3ac99sewardj
3611024598e40c84666cc311a42c256bbf880db3ac99sewardj
3612024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3613024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- IRAtoms -- a subset of IRExprs                       ---*/
3614024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3615024598e40c84666cc311a42c256bbf880db3ac99sewardj
3616024598e40c84666cc311a42c256bbf880db3ac99sewardj/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
3617024598e40c84666cc311a42c256bbf880db3ac99sewardj   isIRAtom() in libvex_ir.h.  Because this instrumenter expects flat
3618024598e40c84666cc311a42c256bbf880db3ac99sewardj   input, most of this code deals in atoms.  Usefully, a value atom
3619024598e40c84666cc311a42c256bbf880db3ac99sewardj   always has a V-value which is also an atom: constants are shadowed
3620024598e40c84666cc311a42c256bbf880db3ac99sewardj   by constants, and temps are shadowed by the corresponding shadow
3621024598e40c84666cc311a42c256bbf880db3ac99sewardj   temporary. */
3622024598e40c84666cc311a42c256bbf880db3ac99sewardj
3623024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef  IRExpr  IRAtom;
3624024598e40c84666cc311a42c256bbf880db3ac99sewardj
3625024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks
3626024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    like it's from original code? */
3627024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isOriginalAtom ( PCEnv* pce, IRAtom* a1 )
3628024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3629024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const)
3630024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3631024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < pce->n_originalTmps)
3632024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3633024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3634024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3635024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
3636024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks
3637024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    like it's from shadow code? */
3638024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isShadowAtom ( PCEnv* pce, IRAtom* a1 )
3639024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3640024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const)
3641024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3642024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= pce->n_originalTmps)
3643024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3644024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3645024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3646024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
3647024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): check that both args are atoms and
3648024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    are identically-kinded. */
3649024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
3650024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3651024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
3652024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3653024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const && a2->tag == Iex_Const)
3654024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3655024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3656024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3657024598e40c84666cc311a42c256bbf880db3ac99sewardj
3658024598e40c84666cc311a42c256bbf880db3ac99sewardj
3659024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3660024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Constructing IR fragments                            ---*/
3661024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3662024598e40c84666cc311a42c256bbf880db3ac99sewardj
3663024598e40c84666cc311a42c256bbf880db3ac99sewardj/* add stmt to a bb */
3664024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
3665024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->trace) {
3666024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("  %c: ", cat);
3667024598e40c84666cc311a42c256bbf880db3ac99sewardj      ppIRStmt(st);
3668024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("\n");
3669024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3670e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   addStmtToIRSB(pce->sb, st);
3671024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3672024598e40c84666cc311a42c256bbf880db3ac99sewardj
3673024598e40c84666cc311a42c256bbf880db3ac99sewardj/* assign value to tmp */
3674024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
3675024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid assign ( HChar cat, PCEnv* pce, IRTemp tmp, IRExpr* expr ) {
3676024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt(cat, pce, IRStmt_WrTmp(tmp,expr));
3677024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3678024598e40c84666cc311a42c256bbf880db3ac99sewardj
3679024598e40c84666cc311a42c256bbf880db3ac99sewardj/* build various kinds of expressions */
3680024598e40c84666cc311a42c256bbf880db3ac99sewardj#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
3681024598e40c84666cc311a42c256bbf880db3ac99sewardj#define unop(_op, _arg)          IRExpr_Unop((_op),(_arg))
3682024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU8(_n)                 IRExpr_Const(IRConst_U8(_n))
3683024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU16(_n)                IRExpr_Const(IRConst_U16(_n))
3684024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU32(_n)                IRExpr_Const(IRConst_U32(_n))
3685024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU64(_n)                IRExpr_Const(IRConst_U64(_n))
3686024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkV128(_n)               IRExpr_Const(IRConst_V128(_n))
3687024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkexpr(_tmp)             IRExpr_RdTmp((_tmp))
3688024598e40c84666cc311a42c256bbf880db3ac99sewardj
3689024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Bind the given expression to a new temporary, and return the
3690024598e40c84666cc311a42c256bbf880db3ac99sewardj   temporary.  This effectively converts an arbitrary expression into
3691024598e40c84666cc311a42c256bbf880db3ac99sewardj   an atom.
3692024598e40c84666cc311a42c256bbf880db3ac99sewardj
3693024598e40c84666cc311a42c256bbf880db3ac99sewardj   'ty' is the type of 'e' and hence the type that the new temporary
3694024598e40c84666cc311a42c256bbf880db3ac99sewardj   needs to be.  But passing it is redundant, since we can deduce the
3695024598e40c84666cc311a42c256bbf880db3ac99sewardj   type merely by inspecting 'e'.  So at least that fact to assert
3696024598e40c84666cc311a42c256bbf880db3ac99sewardj   that the two types agree. */
3697024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* assignNew ( HChar cat, PCEnv* pce, IRType ty, IRExpr* e ) {
3698024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp t;
3699e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   IRType tyE = typeOfIRExpr(pce->sb->tyenv, e);
3700024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
3701e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   t = newTemp(pce, ty, Shad);
3702024598e40c84666cc311a42c256bbf880db3ac99sewardj   assign(cat, pce, t, e);
3703024598e40c84666cc311a42c256bbf880db3ac99sewardj   return mkexpr(t);
3704024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3705024598e40c84666cc311a42c256bbf880db3ac99sewardj
3706024598e40c84666cc311a42c256bbf880db3ac99sewardj
3707024598e40c84666cc311a42c256bbf880db3ac99sewardj
3708024598e40c84666cc311a42c256bbf880db3ac99sewardj//-----------------------------------------------------------------------
3709024598e40c84666cc311a42c256bbf880db3ac99sewardj// Approach taken for range-checking for NONPTR/UNKNOWN-ness as follows.
3710024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3711024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/seg):
3712024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after modifying a word-sized value in/into a TempReg:
3713024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - {ADD, SUB, ADC, SBB, AND, OR, XOR, LEA, LEA2, NEG, NOT}L
3714024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - BSWAP
3715024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3716024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/UNKNOWN):
3717024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when introducing a new word-sized value into a TempReg:
3718024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOVL l, t2
3719024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3720024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying a word-sized value which lacks a corresponding segment
3721024598e40c84666cc311a42c256bbf880db3ac99sewardj//   into a TempReg:
3722024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled LDL
3723024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3724024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when a sub-word of a word (or two) is updated:
3725024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - SHROTL
3726024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - {ADD, SUB, ADC, SBB, AND, OR, XOR, SHROT, NEG, NOT}[WB]
3727024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - PUT[WB]
3728024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   STL (2 range checks)
3729024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   STW (2 range checks)
3730024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled STW
3731024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - STB
3732024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3733024598e40c84666cc311a42c256bbf880db3ac99sewardj// Just copy:
3734024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying word-sized values:
3735024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOVL t1, t2 (--optimise=no only)
3736024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - CMOV
3737024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GETL, PUTL
3738024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled LDL, unstraddled STL
3739024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3740024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when barely changing
3741024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - INC[LWB]/DEC[LWB]
3742024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3743024598e40c84666cc311a42c256bbf880db3ac99sewardj// Set to NONPTR:
3744024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying a sub-word value into a TempReg:
3745024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOV[WB] l, t2
3746024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GET[WB]
3747024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled LDW
3748024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   LDW
3749024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - LDB
3750024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - POP[WB]
3751024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3752024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a TempReg:
3753024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GETF
3754024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - CC2VAL
3755024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - POPL
3756024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3757024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a memory word:
3758024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - FPU_W
3759024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3760024598e40c84666cc311a42c256bbf880db3ac99sewardj// Do nothing:
3761024598e40c84666cc311a42c256bbf880db3ac99sewardj// - LOCK, INCEIP
3762024598e40c84666cc311a42c256bbf880db3ac99sewardj// - WIDEN[WB]
3763024598e40c84666cc311a42c256bbf880db3ac99sewardj// - JMP, JIFZ
3764024598e40c84666cc311a42c256bbf880db3ac99sewardj// - CALLM_[SE], PUSHL, CALLM, CLEAR
3765024598e40c84666cc311a42c256bbf880db3ac99sewardj// - FPU, FPU_R (and similar MMX/SSE ones)
3766024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3767024598e40c84666cc311a42c256bbf880db3ac99sewardj
3768024598e40c84666cc311a42c256bbf880db3ac99sewardj
3769024598e40c84666cc311a42c256bbf880db3ac99sewardj
3770024598e40c84666cc311a42c256bbf880db3ac99sewardj
3771024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Call h_fn (name h_nm) with the given arg, and return a new IRTemp
3772024598e40c84666cc311a42c256bbf880db3ac99sewardj   holding the result.  The arg must be a word-typed atom.  Callee
3773024598e40c84666cc311a42c256bbf880db3ac99sewardj   must be a VG_REGPARM(1) function. */
3774024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((noinline))
3775024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3776024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr* a1 )
3777024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3778024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3779024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3780024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3781e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3782e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   res = newTemp(pce, pce->gWordTy, Shad);
3783024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 1/*regparms*/,
3784024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3785024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_1( a1 ) );
3786024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3787024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3788024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3789024598e40c84666cc311a42c256bbf880db3ac99sewardj
3790024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Two-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(2)
3791024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3792024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3793024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a1, IRExpr* a2 )
3794024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3795024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3796024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3797024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3798024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3799e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3800e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3801e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   res = newTemp(pce, pce->gWordTy, Shad);
3802024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 2/*regparms*/,
3803024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3804024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_2( a1, a2 ) );
3805024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3806024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3807024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3808024598e40c84666cc311a42c256bbf880db3ac99sewardj
3809024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Three-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(3)
3810024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3811024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3812024598e40c84666cc311a42c256bbf880db3ac99sewardj                                IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3813024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3814024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3815024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3816024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3817024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3818024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3819e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3820e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3821e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3822e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   res = newTemp(pce, pce->gWordTy, Shad);
3823024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3824024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3825024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_3( a1, a2, a3 ) );
3826024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3827024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3828024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3829024598e40c84666cc311a42c256bbf880db3ac99sewardj
3830024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Four-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(3)
3831024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3832024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3833024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 IRExpr* a1, IRExpr* a2,
3834024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 IRExpr* a3, IRExpr* a4 )
3835024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3836024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3837024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3838024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3839024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3840024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3841024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3842e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3843e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3844e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3845e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy);
3846e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   res = newTemp(pce, pce->gWordTy, Shad);
3847024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3848024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3849024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_4( a1, a2, a3, a4 ) );
3850024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3851024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3852024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3853024598e40c84666cc311a42c256bbf880db3ac99sewardj
3854024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WW with no return value.  Callee must be a
3855024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(2) function.*/
3856024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3857024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a1, IRExpr* a2 )
3858024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3859024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3860024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3861024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3862e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3863e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3864024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 2/*regparms*/,
3865024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3866024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_2( a1, a2 ) );
3867024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3868024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3869024598e40c84666cc311a42c256bbf880db3ac99sewardj
3870024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WWW with no return value.  Callee must be a
3871024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3872024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3873024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3874024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3875024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3876024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3877024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3878024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3879e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3880e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3881e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3882024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3883024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3884024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_3( a1, a2, a3 ) );
3885024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3886024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3887024598e40c84666cc311a42c256bbf880db3ac99sewardj
3888024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 4 arguments.  Callee must be a
3889024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3890024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3891024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a1, IRExpr* a2,
3892024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a3, IRExpr* a4 )
3893024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3894024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3895024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3896024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3897024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3898024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3899e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3900e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3901e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3902e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy);
3903024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3904024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3905024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_4( a1, a2, a3, a4 ) );
3906024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3907024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3908024598e40c84666cc311a42c256bbf880db3ac99sewardj
3909024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 6 arguments.  Callee must be a
3910024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3911024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_6W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3912024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a1, IRExpr* a2, IRExpr* a3,
3913024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a4, IRExpr* a5, IRExpr* a6 )
3914024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3915024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3916024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3917024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3918024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3919024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3920024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a5));
3921024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a6));
3922e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3923e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3924e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3925e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy);
3926e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a5) == pce->gWordTy);
3927e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert(typeOfIRExpr(pce->sb->tyenv, a6) == pce->gWordTy);
3928024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3929024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3930024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_6( a1, a2, a3, a4, a5, a6 ) );
3931024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3932024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3933024598e40c84666cc311a42c256bbf880db3ac99sewardj
3934024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* uwiden_to_host_word ( PCEnv* pce, IRAtom* a )
3935024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3936e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   IRType a_ty = typeOfIRExpr(pce->sb->tyenv, a);
3937024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a));
3938024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->hWordTy == Ity_I32) {
3939024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (a_ty) {
3940024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I8:
3941024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I32, unop(Iop_8Uto32, a) );
3942024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I16:
3943024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I32, unop(Iop_16Uto32, a) );
3944024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3945024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType(a_ty);
3946024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3947024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3948024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3949024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->hWordTy == Ity_I64);
3950024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (a_ty) {
3951024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I8:
3952024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_8Uto64, a) );
3953024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I16:
3954024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_16Uto64, a) );
3955024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I32:
3956024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_32Uto64, a) );
3957024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3958024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType(a_ty);
3959024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3960024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3961024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3962024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3963024598e40c84666cc311a42c256bbf880db3ac99sewardj
3964024598e40c84666cc311a42c256bbf880db3ac99sewardj/* 'e' is a word-sized atom.  Call nonptr_or_unknown with it, bind the
3965024598e40c84666cc311a42c256bbf880db3ac99sewardj   results to a new temporary, and return the temporary.  Note this
3966024598e40c84666cc311a42c256bbf880db3ac99sewardj   takes an original expression but returns a shadow value. */
3967024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_call_nonptr_or_unknown_w ( PCEnv* pce, IRExpr* e )
3968024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3969024598e40c84666cc311a42c256bbf880db3ac99sewardj   return gen_dirty_W_W( pce, &nonptr_or_unknown,
3970024598e40c84666cc311a42c256bbf880db3ac99sewardj                              "nonptr_or_unknown", e );
3971024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3972024598e40c84666cc311a42c256bbf880db3ac99sewardj
3973024598e40c84666cc311a42c256bbf880db3ac99sewardj
3974024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Generate the shadow value for an IRExpr which is an atom and
3975024598e40c84666cc311a42c256bbf880db3ac99sewardj   guaranteed to be word-sized. */
3976024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* schemeEw_Atom ( PCEnv* pce, IRExpr* e )
3977024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3978024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->gWordTy == Ity_I32) {
3979024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U32) {
3980024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp t;
3981024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(sizeof(UWord) == 4);
3982024598e40c84666cc311a42c256bbf880db3ac99sewardj         t = gen_call_nonptr_or_unknown_w(pce, e);
3983024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr(t);
3984024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3985024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_RdTmp
3986e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj          && typeOfIRExpr(pce->sb->tyenv, e) == Ity_I32) {
3987024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3988024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3989024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* there are no other word-sized atom cases */
3990024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3991024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U64) {
3992024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp t;
3993024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(sizeof(UWord) == 8);
3994024598e40c84666cc311a42c256bbf880db3ac99sewardj         //return mkU64( (ULong)(UWord)NONPTR );
3995024598e40c84666cc311a42c256bbf880db3ac99sewardj         t = gen_call_nonptr_or_unknown_w(pce, e);
3996024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr(t);
3997024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3998024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_RdTmp
3999e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj          && typeOfIRExpr(pce->sb->tyenv, e) == Ity_I64) {
4000024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
4001024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4002024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* there are no other word-sized atom cases */
4003024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4004024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRExpr(e);
4005024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
4006024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4007024598e40c84666cc311a42c256bbf880db3ac99sewardj
4008024598e40c84666cc311a42c256bbf880db3ac99sewardj
4009024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
4010024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid instrument_arithop ( PCEnv* pce,
4011024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRTemp dst, /* already holds result */
4012024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRTemp dstv, /* generate an assignment to this */
4013024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IROp op,
4014024598e40c84666cc311a42c256bbf880db3ac99sewardj                          /* original args, guaranteed to be atoms */
4015024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRExpr* a1, IRExpr* a2, IRExpr* a3, IRExpr* a4 )
4016024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4017024598e40c84666cc311a42c256bbf880db3ac99sewardj   HChar*  nm  = NULL;
4018024598e40c84666cc311a42c256bbf880db3ac99sewardj   void*   fn  = NULL;
4019024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRExpr* a1v = NULL;
4020024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRExpr* a2v = NULL;
4021024598e40c84666cc311a42c256bbf880db3ac99sewardj   //IRExpr* a3v = NULL;
4022024598e40c84666cc311a42c256bbf880db3ac99sewardj   //IRExpr* a4v = NULL;
4023024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp  res = IRTemp_INVALID;
4024024598e40c84666cc311a42c256bbf880db3ac99sewardj
4025024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->gWordTy == Ity_I32) {
4026024598e40c84666cc311a42c256bbf880db3ac99sewardj
4027024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->hWordTy == Ity_I32);
4028024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (op) {
4029024598e40c84666cc311a42c256bbf880db3ac99sewardj
4030024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* For these cases, pass Segs for both arguments, and the
4031024598e40c84666cc311a42c256bbf880db3ac99sewardj            result value. */
4032024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Add32: nm = "do_addW"; fn = &do_addW; goto ssr32;
4033024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sub32: nm = "do_subW"; fn = &do_subW; goto ssr32;
4034024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Or32:  nm = "do_orW";  fn = &do_orW;  goto ssr32;
4035024598e40c84666cc311a42c256bbf880db3ac99sewardj         ssr32:
4036024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4037024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
4038024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
4039024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4040024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4041024598e40c84666cc311a42c256bbf880db3ac99sewardj
4042024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* In this case, pass Segs for both arguments, the result
4043024598e40c84666cc311a42c256bbf880db3ac99sewardj            value, and the difference between the (original) values of
4044024598e40c84666cc311a42c256bbf880db3ac99sewardj            the arguments. */
4045024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_And32:
4046024598e40c84666cc311a42c256bbf880db3ac99sewardj            nm = "do_andW"; fn = &do_andW;
4047024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4048024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
4049024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWWW(
4050024598e40c84666cc311a42c256bbf880db3ac99sewardj                     pce, fn, nm, a1v, a2v, mkexpr(dst),
4051024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assignNew( 'I', pce, Ity_I32,
4052024598e40c84666cc311a42c256bbf880db3ac99sewardj                                binop(Iop_Sub32,a1,a2) ) );
4053024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4054024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4055024598e40c84666cc311a42c256bbf880db3ac99sewardj
4056024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass one shadow arg and the result to the helper. */
4057024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Not32: nm = "do_notW"; fn = &do_notW; goto vr32;
4058024598e40c84666cc311a42c256bbf880db3ac99sewardj         vr32:
4059024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4060024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
4061024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4062024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4063024598e40c84666cc311a42c256bbf880db3ac99sewardj
4064024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass two shadow args only to the helper. */
4065024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul32: nm = "do_mulW"; fn = &do_mulW; goto vv32;
4066024598e40c84666cc311a42c256bbf880db3ac99sewardj         vv32:
4067024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4068024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
4069024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
4070024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4071024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4072024598e40c84666cc311a42c256bbf880db3ac99sewardj
4073024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We don't really know what the result could be; test at run
4074024598e40c84666cc311a42c256bbf880db3ac99sewardj            time. */
4075024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_64HIto32: goto n_or_u_32;
4076024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_64to32:   goto n_or_u_32;
4077024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Xor32:    goto n_or_u_32;
4078024598e40c84666cc311a42c256bbf880db3ac99sewardj         n_or_u_32:
4079024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv,
4080024598e40c84666cc311a42c256bbf880db3ac99sewardj                    mkexpr(
4081024598e40c84666cc311a42c256bbf880db3ac99sewardj                       gen_call_nonptr_or_unknown_w( pce,
4082024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                     mkexpr(dst) ) ) );
4083024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4084024598e40c84666cc311a42c256bbf880db3ac99sewardj
4085024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Cases where it's very obvious that the result cannot be a
4086024598e40c84666cc311a42c256bbf880db3ac99sewardj            pointer.  Hence declare directly that it's NONPTR; don't
4087024598e40c84666cc311a42c256bbf880db3ac99sewardj            bother with the overhead of calling nonptr_or_unknown. */
4088024598e40c84666cc311a42c256bbf880db3ac99sewardj
4089024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where it makes no sense for the result to be a ptr */
4090024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
4091024598e40c84666cc311a42c256bbf880db3ac99sewardj            arg, so that shift by zero preserves the original
4092024598e40c84666cc311a42c256bbf880db3ac99sewardj            value. */
4093024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shl32:    goto n32;
4094024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sar32:    goto n32;
4095024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shr32:    goto n32;
4096024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Uto32:  goto n32;
4097024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Sto32:  goto n32;
4098024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_F64toI32: goto n32;
4099024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16HLto32: goto n32;
4100024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullS16:  goto n32;
4101024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullU16:  goto n32;
4102024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_PRemC3210F64: goto n32;
4103024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivU32:   goto n32;
4104024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivS32:   goto n32;
4105024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128to32: goto n32;
4106024598e40c84666cc311a42c256bbf880db3ac99sewardj
4107024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where result range is very limited and clearly cannot
4108024598e40c84666cc311a42c256bbf880db3ac99sewardj            be a pointer */
4109024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Uto32: goto n32;
4110024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Sto32: goto n32;
4111024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Uto32: goto n32;
4112024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Sto32: goto n32;
4113024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Clz32:  goto n32;
4114024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Ctz32:  goto n32;
4115024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpF64: goto n32;
4116024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD32S: goto n32;
4117024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD32U: goto n32;
4118024598e40c84666cc311a42c256bbf880db3ac99sewardj         n32:
4119024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4120024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4121024598e40c84666cc311a42c256bbf880db3ac99sewardj
4122024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
4123024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("instrument_arithop(32-bit): unhandled: ");
4124024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIROp(op);
4125024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
4126024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4127024598e40c84666cc311a42c256bbf880db3ac99sewardj
4128024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
4129024598e40c84666cc311a42c256bbf880db3ac99sewardj
4130024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->gWordTy == Ity_I64);
4131024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (op) {
4132024598e40c84666cc311a42c256bbf880db3ac99sewardj
4133024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* For these cases, pass Segs for both arguments, and the
4134024598e40c84666cc311a42c256bbf880db3ac99sewardj            result value. */
4135024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Add64: nm = "do_addW"; fn = &do_addW; goto ssr64;
4136024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sub64: nm = "do_subW"; fn = &do_subW; goto ssr64;
4137024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Or64:  nm = "do_orW";  fn = &do_orW;  goto ssr64;
4138024598e40c84666cc311a42c256bbf880db3ac99sewardj         ssr64:
4139024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4140024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
4141024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
4142024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4143024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4144024598e40c84666cc311a42c256bbf880db3ac99sewardj
4145024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* In this case, pass Segs for both arguments, the result
4146024598e40c84666cc311a42c256bbf880db3ac99sewardj            value, and the difference between the (original) values of
4147024598e40c84666cc311a42c256bbf880db3ac99sewardj            the arguments. */
4148024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_And64:
4149024598e40c84666cc311a42c256bbf880db3ac99sewardj            nm = "do_andW"; fn = &do_andW;
4150024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4151024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
4152024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWWW(
4153024598e40c84666cc311a42c256bbf880db3ac99sewardj                     pce, fn, nm, a1v, a2v, mkexpr(dst),
4154024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assignNew( 'I', pce, Ity_I64,
4155024598e40c84666cc311a42c256bbf880db3ac99sewardj                                binop(Iop_Sub64,a1,a2) ) );
4156024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4157024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4158024598e40c84666cc311a42c256bbf880db3ac99sewardj
4159024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass one shadow arg and the result to the helper. */
4160024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Not64: nm = "do_notW"; fn = &do_notW; goto vr64;
4161024598e40c84666cc311a42c256bbf880db3ac99sewardj         vr64:
4162024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4163024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
4164024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4165024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4166024598e40c84666cc311a42c256bbf880db3ac99sewardj
4167024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass two shadow args only to the helper. */
4168024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul64: nm = "do_mulW"; fn = &do_mulW; goto vv64;
4169024598e40c84666cc311a42c256bbf880db3ac99sewardj         vv64:
4170024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
4171024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
4172024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
4173024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
4174024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4175024598e40c84666cc311a42c256bbf880db3ac99sewardj
4176024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We don't really know what the result could be; test at run
4177024598e40c84666cc311a42c256bbf880db3ac99sewardj            time. */
4178024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Xor64:      goto n_or_u_64;
4179024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_128HIto64:  goto n_or_u_64;
4180024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_128to64:    goto n_or_u_64;
4181024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128HIto64: goto n_or_u_64;
4182024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128to64:   goto n_or_u_64;
4183024598e40c84666cc311a42c256bbf880db3ac99sewardj         n_or_u_64:
4184024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv,
4185024598e40c84666cc311a42c256bbf880db3ac99sewardj                    mkexpr(
4186024598e40c84666cc311a42c256bbf880db3ac99sewardj                       gen_call_nonptr_or_unknown_w( pce,
4187024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                     mkexpr(dst) ) ) );
4188024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4189024598e40c84666cc311a42c256bbf880db3ac99sewardj
4190024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Cases where it's very obvious that the result cannot be a
4191024598e40c84666cc311a42c256bbf880db3ac99sewardj            pointer.  Hence declare directly that it's NONPTR; don't
4192024598e40c84666cc311a42c256bbf880db3ac99sewardj            bother with the overhead of calling nonptr_or_unknown. */
4193024598e40c84666cc311a42c256bbf880db3ac99sewardj
4194024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where it makes no sense for the result to be a ptr */
4195024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
4196024598e40c84666cc311a42c256bbf880db3ac99sewardj            arg, so that shift by zero preserves the original
4197024598e40c84666cc311a42c256bbf880db3ac99sewardj            value. */
4198024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shl64:      goto n64;
4199024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sar64:      goto n64;
4200024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shr64:      goto n64;
4201024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32Uto64:    goto n64;
4202024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32Sto64:    goto n64;
4203024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Uto64:    goto n64;
4204024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Sto64:    goto n64;
4205024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32HLto64:   goto n64;
4206024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivModU64to32: goto n64;
4207024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivModS64to32: goto n64;
4208024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_F64toI64:      goto n64;
4209024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullS32:    goto n64;
4210024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullU32:    goto n64;
4211024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivU64:     goto n64;
4212024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivS64:     goto n64;
4213024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_ReinterpF64asI64: goto n64;
4214024598e40c84666cc311a42c256bbf880db3ac99sewardj
4215024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where result range is very limited and clearly cannot
4216024598e40c84666cc311a42c256bbf880db3ac99sewardj            be a pointer */
4217024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Uto64:        goto n64;
4218024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Uto64:        goto n64;
4219024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Sto64:        goto n64;
4220024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Ctz64:         goto n64;
4221024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Clz64:         goto n64;
4222024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD64S:     goto n64;
4223024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD64U:     goto n64;
4224024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* 64-bit simd */
4225024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Avg8Ux8: case Iop_Avg16Ux4:
4226024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Max16Sx4: case Iop_Max8Ux8: case Iop_Min16Sx4:
4227024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Min8Ux8: case Iop_MulHi16Ux4:
4228024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QNarrow32Sx2: case Iop_QNarrow16Sx4:
4229024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QNarrow16Ux4: case Iop_Add8x8: case Iop_Add32x2:
4230024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd8Ux8:
4231024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QAdd16Ux4: case Iop_Add16x4: case Iop_CmpEQ8x8:
4232024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpEQ32x2: case Iop_CmpEQ16x4: case Iop_CmpGT8Sx8:
4233024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpGT32Sx2: case Iop_CmpGT16Sx4: case Iop_MulHi16Sx4:
4234024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul16x4: case Iop_ShlN32x2: case Iop_ShlN16x4:
4235024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_SarN32x2: case Iop_SarN16x4: case Iop_ShrN32x2:
4236024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_ShrN16x4: case Iop_Sub8x8: case Iop_Sub32x2:
4237024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub8Ux8:
4238024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QSub16Ux4: case Iop_Sub16x4: case Iop_InterleaveHI8x8:
4239024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveHI32x2: case Iop_InterleaveHI16x4:
4240024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveLO8x8: case Iop_InterleaveLO32x2:
4241024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveLO16x4: case Iop_SarN8x8:
4242024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Perm8x8: case Iop_ShlN8x8: case Iop_Mul32x2:
4243024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CatEvenLanes16x4: case Iop_CatOddLanes16x4:
4244024598e40c84666cc311a42c256bbf880db3ac99sewardj         n64:
4245024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4246024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
4247024598e40c84666cc311a42c256bbf880db3ac99sewardj
4248024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
4249024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("instrument_arithop(64-bit): unhandled: ");
4250024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIROp(op);
4251024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
4252024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4253024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4254024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4255024598e40c84666cc311a42c256bbf880db3ac99sewardj
4256024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
4257024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid gen_call_nonptr_or_unknown_range ( PCEnv* pce,
4258024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        IRAtom* addr, IRAtom* len )
4259024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4260024598e40c84666cc311a42c256bbf880db3ac99sewardj   gen_dirty_v_WW( pce,
4261024598e40c84666cc311a42c256bbf880db3ac99sewardj                   &nonptr_or_unknown_range,
4262024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "nonptr_or_unknown_range",
4263024598e40c84666cc311a42c256bbf880db3ac99sewardj                   addr, len );
4264024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4265024598e40c84666cc311a42c256bbf880db3ac99sewardj
4266024598e40c84666cc311a42c256bbf880db3ac99sewardj/* iii describes zero or more non-exact integer register updates.  For
4267024598e40c84666cc311a42c256bbf880db3ac99sewardj   each one, generate IR to get the containing register, apply
4268024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown to it, and write it back again. */
4269024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_nonptr_or_unknown_for_III( PCEnv* pce, IntRegInfo* iii )
4270024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4271024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i;
4272024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(iii && iii->n_offsets >= 0);
4273024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < iii->n_offsets; i++) {
4274024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRAtom* a1 = assignNew( 'I', pce, pce->gWordTy,
4275024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr_Get( iii->offsets[i], pce->gWordTy ));
4276024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4277024598e40c84666cc311a42c256bbf880db3ac99sewardj      stmt( 'I', pce, IRStmt_Put( iii->offsets[i]
4278024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     + pce->guest_state_sizeB,
4279024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  mkexpr(a2) ));
4280024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4281024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4282024598e40c84666cc311a42c256bbf880db3ac99sewardj
42831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj/* Generate into 'pce', instrumentation for 'st'.  Also copy 'st'
42841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj   itself into 'pce' (the caller does not do so).  This is somewhat
4285024598e40c84666cc311a42c256bbf880db3ac99sewardj   complex and relies heavily on the assumption that the incoming IR
4286024598e40c84666cc311a42c256bbf880db3ac99sewardj   is in flat form.
4287024598e40c84666cc311a42c256bbf880db3ac99sewardj
4288024598e40c84666cc311a42c256bbf880db3ac99sewardj   Generally speaking, the instrumentation is placed after the
4289024598e40c84666cc311a42c256bbf880db3ac99sewardj   original statement, so that results computed by the original can be
4290024598e40c84666cc311a42c256bbf880db3ac99sewardj   used in the instrumentation.  However, that isn't safe for memory
4291024598e40c84666cc311a42c256bbf880db3ac99sewardj   references, since we need the instrumentation (hence bounds check
4292024598e40c84666cc311a42c256bbf880db3ac99sewardj   and potential error message) to happen before the reference itself,
4293024598e40c84666cc311a42c256bbf880db3ac99sewardj   as the latter could cause a fault. */
4294024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void schemeS ( PCEnv* pce, IRStmt* st )
4295024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4296024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(st);
4297024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isFlatIRStmt(st));
4298024598e40c84666cc311a42c256bbf880db3ac99sewardj
4299024598e40c84666cc311a42c256bbf880db3ac99sewardj   switch (st->tag) {
4300024598e40c84666cc311a42c256bbf880db3ac99sewardj
4301024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Dirty: {
4302024598e40c84666cc311a42c256bbf880db3ac99sewardj         Int i;
4303024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRDirty* di;
4304024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4305024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* nasty.  assumes that (1) all helpers are unconditional,
4306024598e40c84666cc311a42c256bbf880db3ac99sewardj            and (2) all outputs are non-ptr */
4307024598e40c84666cc311a42c256bbf880db3ac99sewardj         di = st->Ist.Dirty.details;
4308024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* deal with the return tmp, if any */
4309024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (di->tmp != IRTemp_INVALID
4310e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj             && typeOfIRTemp(pce->sb->tyenv, di->tmp) == pce->gWordTy) {
4311024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* di->tmp is shadowed.  Set it to NONPTR. */
4312024598e40c84666cc311a42c256bbf880db3ac99sewardj            IRTemp dstv = newShadowTmp( pce, di->tmp );
4313024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (pce->gWordTy == Ity_I32) {
4314024598e40c84666cc311a42c256bbf880db3ac99sewardj              assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4315024598e40c84666cc311a42c256bbf880db3ac99sewardj            } else {
4316024598e40c84666cc311a42c256bbf880db3ac99sewardj              assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4317024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4318024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4319024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* apply the nonptr_or_unknown technique to any parts of
4320024598e40c84666cc311a42c256bbf880db3ac99sewardj            the guest state that happen to get written */
4321024598e40c84666cc311a42c256bbf880db3ac99sewardj         for (i = 0; i < di->nFxState; i++) {
4322024598e40c84666cc311a42c256bbf880db3ac99sewardj            IntRegInfo iii;
4323024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->fxState[i].fx != Ifx_None);
4324024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (di->fxState[i].fx == Ifx_Read)
4325024598e40c84666cc311a42c256bbf880db3ac99sewardj               continue; /* this bit is only read -- not interesting */
4326024598e40c84666cc311a42c256bbf880db3ac99sewardj            get_IntRegInfo( &iii, di->fxState[i].offset,
4327024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  di->fxState[i].size );
4328024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(iii.n_offsets >= -1
4329024598e40c84666cc311a42c256bbf880db3ac99sewardj                      && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4330024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* Deal with 3 possible cases, same as with Ist_Put
4331024598e40c84666cc311a42c256bbf880db3ac99sewardj               elsewhere in this function. */
4332024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (iii.n_offsets == -1) {
4333024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* case (1): exact write of an integer register. */
4334024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRAtom* a1
4335024598e40c84666cc311a42c256bbf880db3ac99sewardj                  = assignNew( 'I', pce, pce->gWordTy,
4336024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr_Get( iii.offsets[i], pce->gWordTy ));
4337024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4338024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'I', pce, IRStmt_Put( iii.offsets[i]
4339024598e40c84666cc311a42c256bbf880db3ac99sewardj                                              + pce->guest_state_sizeB,
4340024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           mkexpr(a2) ));
4341024598e40c84666cc311a42c256bbf880db3ac99sewardj            } else {
4342024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* when == 0: case (3): no instrumentation needed */
4343024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* when > 0: case (2) .. complex case.  Fish out the
4344024598e40c84666cc311a42c256bbf880db3ac99sewardj                  stored value for the whole register, heave it
4345024598e40c84666cc311a42c256bbf880db3ac99sewardj                  through nonptr_or_unknown, and use that as the new
4346024598e40c84666cc311a42c256bbf880db3ac99sewardj                  shadow value. */
4347024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(iii.n_offsets >= 0
4348024598e40c84666cc311a42c256bbf880db3ac99sewardj                         && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4349024598e40c84666cc311a42c256bbf880db3ac99sewardj               gen_nonptr_or_unknown_for_III( pce, &iii );
4350024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4351024598e40c84666cc311a42c256bbf880db3ac99sewardj         } /* for (i = 0; i < di->nFxState; i++) */
4352024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* finally, deal with memory outputs */
4353024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (di->mFx != Ifx_None) {
4354024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->mAddr && isIRAtom(di->mAddr));
4355024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->mSize > 0);
4356024598e40c84666cc311a42c256bbf880db3ac99sewardj            gen_call_nonptr_or_unknown_range( pce, di->mAddr,
4357024598e40c84666cc311a42c256bbf880db3ac99sewardj                                              mkIRExpr_HWord(di->mSize));
4358024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4359024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4360024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4361024598e40c84666cc311a42c256bbf880db3ac99sewardj
4362024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_NoOp:
4363024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4364024598e40c84666cc311a42c256bbf880db3ac99sewardj
4365024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* nothing interesting in these; just copy them through */
4366024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_AbiHint:
4367024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_MBE:
4368024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Exit:
4369024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_IMark:
4370024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4371024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4372024598e40c84666cc311a42c256bbf880db3ac99sewardj
4373024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_PutI: {
4374024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRRegArray* descr = st->Ist.PutI.descr;
4375024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4376024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(descr && descr->elemTy);
4377024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (is_integer_guest_reg_array(descr)) {
4378024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* if this fails, is_integer_guest_reg_array is returning
4379024598e40c84666cc311a42c256bbf880db3ac99sewardj               bogus results */
4380024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(descr->elemTy == pce->gWordTy);
4381024598e40c84666cc311a42c256bbf880db3ac99sewardj            stmt(
4382024598e40c84666cc311a42c256bbf880db3ac99sewardj               'I', pce,
4383024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRStmt_PutI(
4384024598e40c84666cc311a42c256bbf880db3ac99sewardj                  mkIRRegArray(descr->base + pce->guest_state_sizeB,
4385024598e40c84666cc311a42c256bbf880db3ac99sewardj                               descr->elemTy, descr->nElems),
4386024598e40c84666cc311a42c256bbf880db3ac99sewardj                  st->Ist.PutI.ix,
4387024598e40c84666cc311a42c256bbf880db3ac99sewardj                  st->Ist.PutI.bias,
4388024598e40c84666cc311a42c256bbf880db3ac99sewardj                  schemeEw_Atom( pce, st->Ist.PutI.data)
4389024598e40c84666cc311a42c256bbf880db3ac99sewardj               )
4390024598e40c84666cc311a42c256bbf880db3ac99sewardj            );
4391024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4392024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4393024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4394024598e40c84666cc311a42c256bbf880db3ac99sewardj
4395024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Put: {
4396024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* PUT(offset) = atom */
4397024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* 3 cases:
4398024598e40c84666cc311a42c256bbf880db3ac99sewardj            1. It's a complete write of an integer register.  Get hold of
4399024598e40c84666cc311a42c256bbf880db3ac99sewardj               'atom's shadow value and write it in the shadow state.
4400024598e40c84666cc311a42c256bbf880db3ac99sewardj            2. It's a partial write of an integer register.  Let the write
4401024598e40c84666cc311a42c256bbf880db3ac99sewardj               happen, then fish out the complete register value and see if,
4402024598e40c84666cc311a42c256bbf880db3ac99sewardj               via range checking, consultation of tea leaves, etc, its
4403024598e40c84666cc311a42c256bbf880db3ac99sewardj               shadow value can be upgraded to anything useful.
4404024598e40c84666cc311a42c256bbf880db3ac99sewardj            3. It is none of the above.  Generate no instrumentation. */
4405024598e40c84666cc311a42c256bbf880db3ac99sewardj         IntRegInfo iii;
4406024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType     ty;
4407024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4408e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         ty = typeOfIRExpr(pce->sb->tyenv, st->Ist.Put.data);
4409024598e40c84666cc311a42c256bbf880db3ac99sewardj         get_IntRegInfo( &iii, st->Ist.Put.offset,
4410024598e40c84666cc311a42c256bbf880db3ac99sewardj                         sizeofIRType(ty) );
4411024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (iii.n_offsets == -1) {
4412024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* case (1): exact write of an integer register. */
4413024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(ty == pce->gWordTy);
4414024598e40c84666cc311a42c256bbf880db3ac99sewardj            stmt( 'I', pce,
4415024598e40c84666cc311a42c256bbf880db3ac99sewardj                       IRStmt_Put( st->Ist.Put.offset
4416024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      + pce->guest_state_sizeB,
4417024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   schemeEw_Atom( pce, st->Ist.Put.data)) );
4418024598e40c84666cc311a42c256bbf880db3ac99sewardj         } else {
4419024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* when == 0: case (3): no instrumentation needed */
4420024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* when > 0: case (2) .. complex case.  Fish out the
4421024598e40c84666cc311a42c256bbf880db3ac99sewardj               stored value for the whole register, heave it through
4422024598e40c84666cc311a42c256bbf880db3ac99sewardj               nonptr_or_unknown, and use that as the new shadow
4423024598e40c84666cc311a42c256bbf880db3ac99sewardj               value. */
4424024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(iii.n_offsets >= 0
4425024598e40c84666cc311a42c256bbf880db3ac99sewardj                      && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4426024598e40c84666cc311a42c256bbf880db3ac99sewardj            gen_nonptr_or_unknown_for_III( pce, &iii );
4427024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4428024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4429024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_Put */
4430024598e40c84666cc311a42c256bbf880db3ac99sewardj
4431024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Store: {
4432024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We have: STle(addr) = data
4433024598e40c84666cc311a42c256bbf880db3ac99sewardj            if data is int-word sized, do
4434024598e40c84666cc311a42c256bbf880db3ac99sewardj            check_store4(addr, addr#, data, data#)
4435024598e40c84666cc311a42c256bbf880db3ac99sewardj            for all other stores
4436024598e40c84666cc311a42c256bbf880db3ac99sewardj            check_store{1,2}(addr, addr#, data)
4437024598e40c84666cc311a42c256bbf880db3ac99sewardj
4438024598e40c84666cc311a42c256bbf880db3ac99sewardj            The helper actually *does* the store, so that it can do
4439024598e40c84666cc311a42c256bbf880db3ac99sewardj            the post-hoc ugly hack of inspecting and "improving" the
4440024598e40c84666cc311a42c256bbf880db3ac99sewardj            shadow data after the store, in the case where it isn't an
4441024598e40c84666cc311a42c256bbf880db3ac99sewardj            aligned word store.
44421c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj
44431c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            Only word-sized values are shadowed.  If this is a
44441c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            store-conditional, .resSC will denote a non-word-typed
44451c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            temp, and so we don't need to shadow it.  Assert about the
44461c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            type, tho.  However, since we're not re-emitting the
44471c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            original IRStmt_Store, but rather doing it as part of the
44481c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            helper function, we need to actually do a SC in the
44491c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            helper, and assign the result bit to .resSC.  Ugly.
4450024598e40c84666cc311a42c256bbf880db3ac99sewardj         */
4451024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* data  = st->Ist.Store.data;
4452024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* addr  = st->Ist.Store.addr;
4453e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         IRType  d_ty  = typeOfIRExpr(pce->sb->tyenv, data);
4454024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* addrv = schemeEw_Atom( pce, addr );
44551c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         IRTemp  resSC = st->Ist.Store.resSC;
44561c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         if (resSC != IRTemp_INVALID) {
4457e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj            tl_assert(typeOfIRTemp(pce->sb->tyenv, resSC) == Ity_I1);
44581c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            /* viz, not something we want to shadow */
44591c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            /* also, throw out all store-conditional cases that
44601c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj               we can't handle */
44611c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            if (pce->gWordTy == Ity_I32 && d_ty != Ity_I32)
44621c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj               goto unhandled;
44631c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj            if (pce->gWordTy == Ity_I64 && d_ty != Ity_I32 && d_ty != Ity_I64)
44641c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj               goto unhandled;
44651c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj         }
4466024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (pce->gWordTy == Ity_I32) {
4467024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* ------ 32 bit host/guest (cough, cough) ------ */
4468024598e40c84666cc311a42c256bbf880db3ac99sewardj            switch (d_ty) {
4469024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer word case */
4470024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I32: {
4471024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRExpr* datav = schemeEw_Atom( pce, data );
44721c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  if (resSC == IRTemp_INVALID) {
44731c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     /* "normal" store */
44741c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     gen_dirty_v_WWWW( pce,
44751c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                       &check_store4_P, "check_store4_P",
44761c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                       addr, addrv, data, datav );
44771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  } else {
44781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     /* store-conditional; need to snarf the success bit */
44791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     IRTemp resSC32
44801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                         = gen_dirty_W_WWWW( pce,
44811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                             &check_store4C_P,
44821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                             "check_store4C_P",
44831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                             addr, addrv, data, datav );
44841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     /* presumably resSC32 will really be Ity_I32.  In
44851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                        any case we'll get jumped by the IR sanity
44861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                        checker if it's not, when it sees the
44871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                        following statement. */
44881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     assign( 'I', pce, resSC, unop(Iop_32to1, mkexpr(resSC32)) );
44891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  }
4490024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4491024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4492024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer subword cases */
4493024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I16:
4494024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4495024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store2, "check_store2",
4496024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4497024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4498024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4499024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I8:
4500024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4501024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store1, "check_store1",
4502024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4503024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4504024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4505024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit float.  Pass store data in 2 32-bit pieces. */
4506024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F64: {
4507024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* d64 = assignNew( 'I', pce, Ity_I64,
4508024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF64asI64, data) );
4509024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4510024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, d64) );
4511024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4512024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, d64) );
4513024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4514024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_ms4B_ls4B,
4515024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store8_ms4B_ls4B",
4516024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi32, dLo32 );
4517024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4518024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4519024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 32-bit float.  We can just use _store4, but need
4520024598e40c84666cc311a42c256bbf880db3ac99sewardj                  to futz with the argument type. */
4521024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F32: {
4522024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4523024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF32asI32,
4524024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4525024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4526024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4,
4527024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store4",
4528024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, i32 );
4529024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4530024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4531024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit int.  Pass store data in 2 32-bit pieces. */
4532024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I64: {
4533024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4534024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, data) );
4535024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4536024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, data) );
4537024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4538024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_ms4B_ls4B,
4539024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store8_ms4B_ls4B",
4540024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi32, dLo32 );
4541024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4542024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4543024598e40c84666cc311a42c256bbf880db3ac99sewardj
4544024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 128-bit vector.  Pass store data in 4 32-bit pieces.
4545024598e40c84666cc311a42c256bbf880db3ac99sewardj                  This is all very ugly and inefficient, but it is
4546024598e40c84666cc311a42c256bbf880db3ac99sewardj                  hard to better without considerably complicating the
4547024598e40c84666cc311a42c256bbf880db3ac99sewardj                  store-handling schemes. */
4548024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_V128: {
4549024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4550024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128HIto64, data) );
4551024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4552024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128to64, data) );
4553024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w3    = assignNew( 'I', pce, Ity_I32,
4554024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, dHi64) );
4555024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w2    = assignNew( 'I', pce, Ity_I32,
4556024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, dHi64) );
4557024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w1    = assignNew( 'I', pce, Ity_I32,
4558024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, dLo64) );
4559024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w0    = assignNew( 'I', pce, Ity_I32,
4560024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, dLo64) );
4561024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_6W( pce,
4562024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  &check_store16_ms4B_4B_4B_ls4B,
4563024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  "check_store16_ms4B_4B_4B_ls4B",
4564024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  addr, addrv, w3, w2, w1, w0 );
4565024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4566024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4567024598e40c84666cc311a42c256bbf880db3ac99sewardj
4568024598e40c84666cc311a42c256bbf880db3ac99sewardj
4569024598e40c84666cc311a42c256bbf880db3ac99sewardj               default:
4570024598e40c84666cc311a42c256bbf880db3ac99sewardj                  ppIRType(d_ty); tl_assert(0);
4571024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4572024598e40c84666cc311a42c256bbf880db3ac99sewardj         } else {
4573024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* ------ 64 bit host/guest (cough, cough) ------ */
4574024598e40c84666cc311a42c256bbf880db3ac99sewardj            switch (d_ty) {
4575024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer word case */
4576024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I64: {
4577024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRExpr* datav = schemeEw_Atom( pce, data );
45781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  if (resSC == IRTemp_INVALID) {
45791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     /* "normal" store */
45801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     gen_dirty_v_WWWW( pce,
45811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                       &check_store8_P, "check_store8_P",
45821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                       addr, addrv, data, datav );
45831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  } else {
45841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     IRTemp resSC64
45851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                         = gen_dirty_W_WWWW( pce,
45861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                             &check_store8C_P,
45871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                             "check_store8C_P",
45881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                             addr, addrv, data, datav );
45891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     assign( 'I', pce, resSC, unop(Iop_64to1, mkexpr(resSC64)) );
45901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  }
4591024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4592024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4593024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer subword cases */
4594024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I32:
45951c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  if (resSC == IRTemp_INVALID) {
45961c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     /* "normal" store */
45971c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     gen_dirty_v_WWW( pce,
45981c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                      &check_store4, "check_store4",
45991c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                      addr, addrv,
46001c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                      uwiden_to_host_word( pce, data ));
46011c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  } else {
46021c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     /* store-conditional; need to snarf the success bit */
46031c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     IRTemp resSC64
46041c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                         = gen_dirty_W_WWW( pce,
46051c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                            &check_store4C,
46061c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                            "check_store4C",
46071c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                            addr, addrv,
46081c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                                            uwiden_to_host_word( pce, data ));
46091c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                     assign( 'I', pce, resSC, unop(Iop_64to1, mkexpr(resSC64)) );
46101c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj                  }
4611024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4612024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I16:
4613024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4614024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store2, "check_store2",
4615024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4616024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4617024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4618024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I8:
4619024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4620024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store1, "check_store1",
4621024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4622024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4623024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4624024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 128-bit vector.  Pass store data in 2 64-bit pieces. */
4625024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_V128: {
4626024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4627024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128HIto64, data) );
4628024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4629024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128to64, data) );
4630024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4631024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store16_ms8B_ls8B,
4632024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store16_ms8B_ls8B",
4633024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi64, dLo64 );
4634024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4635024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4636024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit float. */
4637024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F64: {
4638024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dI = assignNew( 'I', pce, Ity_I64,
4639024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF64asI64,
4640024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4641024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4642024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store8_all8B,
4643024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store8_all8B",
4644024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, dI );
4645024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4646024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4647024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 32-bit float.  We can just use _store4, but need
4648024598e40c84666cc311a42c256bbf880db3ac99sewardj                  to futz with the argument type. */
4649024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F32: {
4650024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4651024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF32asI32,
4652024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4653024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i64 = assignNew( 'I', pce, Ity_I64,
4654024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_32Uto64,
4655024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                i32 ) );
4656024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4657024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4,
4658024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store4",
4659024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, i64 );
4660024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4661024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4662024598e40c84666cc311a42c256bbf880db3ac99sewardj               default:
4663024598e40c84666cc311a42c256bbf880db3ac99sewardj                  ppIRType(d_ty); tl_assert(0);
4664024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4665024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4666024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* And don't copy the original, since the helper does the
4667024598e40c84666cc311a42c256bbf880db3ac99sewardj            store.  Ick. */
4668024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4669024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_Store */
4670024598e40c84666cc311a42c256bbf880db3ac99sewardj
4671024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_WrTmp: {
4672024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* This is the only place we have to deal with the full
4673024598e40c84666cc311a42c256bbf880db3ac99sewardj            IRExpr range.  In all other places where an IRExpr could
4674024598e40c84666cc311a42c256bbf880db3ac99sewardj            appear, we in fact only get an atom (Iex_RdTmp or
4675024598e40c84666cc311a42c256bbf880db3ac99sewardj            Iex_Const). */
4676024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* e      = st->Ist.WrTmp.data;
4677e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj         IRType  e_ty   = typeOfIRExpr( pce->sb->tyenv, e );
4678024598e40c84666cc311a42c256bbf880db3ac99sewardj         Bool    isWord = e_ty == pce->gWordTy;
4679024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp  dst    = st->Ist.WrTmp.tmp;
4680024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp  dstv   = isWord ? newShadowTmp( pce, dst )
4681024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 : IRTemp_INVALID;
4682024598e40c84666cc311a42c256bbf880db3ac99sewardj
4683024598e40c84666cc311a42c256bbf880db3ac99sewardj         switch (e->tag) {
4684024598e40c84666cc311a42c256bbf880db3ac99sewardj
4685024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Const: {
4686024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4687024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4688024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv, schemeEw_Atom( pce, e ) );
4689024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4690024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4691024598e40c84666cc311a42c256bbf880db3ac99sewardj
4692024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_CCall: {
4693024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4694024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4695024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv,
4696024598e40c84666cc311a42c256bbf880db3ac99sewardj                          mkexpr( gen_call_nonptr_or_unknown_w(
4697024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     pce, mkexpr(dst))));
4698024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4699024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4700024598e40c84666cc311a42c256bbf880db3ac99sewardj
4701024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Mux0X: {
4702024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Just steer the shadow values in the same way as the
4703024598e40c84666cc311a42c256bbf880db3ac99sewardj                  originals. */
4704024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4705024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4706024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv,
4707024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRExpr_Mux0X(
4708024598e40c84666cc311a42c256bbf880db3ac99sewardj                             e->Iex.Mux0X.cond,
4709024598e40c84666cc311a42c256bbf880db3ac99sewardj                             schemeEw_Atom( pce, e->Iex.Mux0X.expr0 ),
4710024598e40c84666cc311a42c256bbf880db3ac99sewardj                             schemeEw_Atom( pce, e->Iex.Mux0X.exprX ) ));
4711024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4712024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4713024598e40c84666cc311a42c256bbf880db3ac99sewardj
4714024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_RdTmp: {
4715024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4716024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4717024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv, schemeEw_Atom( pce, e ));
4718024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4719024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4720024598e40c84666cc311a42c256bbf880db3ac99sewardj
4721024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Load: {
4722024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRExpr* addr  = e->Iex.Load.addr;
4723024598e40c84666cc311a42c256bbf880db3ac99sewardj               HChar*  h_nm  = NULL;
4724024598e40c84666cc311a42c256bbf880db3ac99sewardj               void*   h_fn  = NULL;
4725024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRExpr* addrv = NULL;
4726024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (pce->gWordTy == Ity_I32) {
4727024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* 32 bit host/guest (cough, cough) */
4728024598e40c84666cc311a42c256bbf880db3ac99sewardj                  switch (e_ty) {
4729024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* Ity_I32: helper returns shadow value. */
4730024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I32:  h_fn = &check_load4_P;
4731024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4_P"; break;
4732024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* all others: helper does not return a shadow
4733024598e40c84666cc311a42c256bbf880db3ac99sewardj                        value. */
4734024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_V128: h_fn = &check_load16;
4735024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load16"; break;
4736024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I64:
4737024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F64:  h_fn = &check_load8;
4738024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8"; break;
4739024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F32:  h_fn = &check_load4;
4740024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4"; break;
4741024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I16:  h_fn = &check_load2;
4742024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load2"; break;
4743024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I8:   h_fn = &check_load1;
4744024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load1"; break;
4745024598e40c84666cc311a42c256bbf880db3ac99sewardj                     default: ppIRType(e_ty); tl_assert(0);
4746024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4747024598e40c84666cc311a42c256bbf880db3ac99sewardj                  addrv = schemeEw_Atom( pce, addr );
4748024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (e_ty == Ity_I32) {
4749024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4750024598e40c84666cc311a42c256bbf880db3ac99sewardj                              mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4751024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                           addr, addrv )) );
4752024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4753024598e40c84666cc311a42c256bbf880db3ac99sewardj                     gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4754024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4755024598e40c84666cc311a42c256bbf880db3ac99sewardj               } else {
4756024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* 64 bit host/guest (cough, cough) */
4757024598e40c84666cc311a42c256bbf880db3ac99sewardj                  switch (e_ty) {
4758024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* Ity_I64: helper returns shadow value. */
4759024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I64:  h_fn = &check_load8_P;
4760024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8_P"; break;
4761024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* all others: helper does not return a shadow
4762024598e40c84666cc311a42c256bbf880db3ac99sewardj                        value. */
4763024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_V128: h_fn = &check_load16;
4764024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load16"; break;
4765024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F64:  h_fn = &check_load8;
4766024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8"; break;
4767024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F32:
4768024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I32:  h_fn = &check_load4;
4769024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4"; break;
4770024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I16:  h_fn = &check_load2;
4771024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load2"; break;
4772024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I8:   h_fn = &check_load1;
4773024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load1"; break;
4774024598e40c84666cc311a42c256bbf880db3ac99sewardj                     default: ppIRType(e_ty); tl_assert(0);
4775024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4776024598e40c84666cc311a42c256bbf880db3ac99sewardj                  addrv = schemeEw_Atom( pce, addr );
4777024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (e_ty == Ity_I64) {
4778024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4779024598e40c84666cc311a42c256bbf880db3ac99sewardj                              mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4780024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                           addr, addrv )) );
4781024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4782024598e40c84666cc311a42c256bbf880db3ac99sewardj                     gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4783024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4784024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4785024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* copy the original -- must happen after the helper call */
4786024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4787024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4788024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4789024598e40c84666cc311a42c256bbf880db3ac99sewardj
4790024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_GetI: {
4791024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRRegArray* descr = e->Iex.GetI.descr;
4792024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4793024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(descr && descr->elemTy);
4794024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (is_integer_guest_reg_array(descr)) {
4795024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* if this fails, is_integer_guest_reg_array is
4796024598e40c84666cc311a42c256bbf880db3ac99sewardj                     returning bogus results */
4797024598e40c84666cc311a42c256bbf880db3ac99sewardj                  tl_assert(isWord);
4798024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign(
4799024598e40c84666cc311a42c256bbf880db3ac99sewardj                     'I', pce, dstv,
4800024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRExpr_GetI(
4801024598e40c84666cc311a42c256bbf880db3ac99sewardj                        mkIRRegArray(descr->base + pce->guest_state_sizeB,
4802024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     descr->elemTy, descr->nElems),
4803024598e40c84666cc311a42c256bbf880db3ac99sewardj                        e->Iex.GetI.ix,
4804024598e40c84666cc311a42c256bbf880db3ac99sewardj                        e->Iex.GetI.bias
4805024598e40c84666cc311a42c256bbf880db3ac99sewardj                     )
4806024598e40c84666cc311a42c256bbf880db3ac99sewardj                  );
4807024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4808024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4809024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4810024598e40c84666cc311a42c256bbf880db3ac99sewardj
4811024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Get: {
4812024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4813024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord) {
4814024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* guest-word-typed tmp assignment, so it will have a
4815024598e40c84666cc311a42c256bbf880db3ac99sewardj                     shadow tmp, and we must make an assignment to
4816024598e40c84666cc311a42c256bbf880db3ac99sewardj                     that */
4817024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (is_integer_guest_reg(e->Iex.Get.offset,
4818024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           sizeofIRType(e->Iex.Get.ty))) {
4819024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4820024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr_Get( e->Iex.Get.offset
4821024598e40c84666cc311a42c256bbf880db3ac99sewardj                                            + pce->guest_state_sizeB,
4822024598e40c84666cc311a42c256bbf880db3ac99sewardj                                         e->Iex.Get.ty) );
4823024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4824024598e40c84666cc311a42c256bbf880db3ac99sewardj                     if (pce->hWordTy == Ity_I32) {
4825024598e40c84666cc311a42c256bbf880db3ac99sewardj                        assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4826024598e40c84666cc311a42c256bbf880db3ac99sewardj                     } else {
4827024598e40c84666cc311a42c256bbf880db3ac99sewardj                       assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4828024598e40c84666cc311a42c256bbf880db3ac99sewardj                     }
4829024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4830024598e40c84666cc311a42c256bbf880db3ac99sewardj               } else {
4831024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* tmp isn't guest-word-typed, so isn't shadowed, so
4832024598e40c84666cc311a42c256bbf880db3ac99sewardj                     generate no instrumentation */
4833024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4834024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4835024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4836024598e40c84666cc311a42c256bbf880db3ac99sewardj
4837024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Unop: {
4838024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4839024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Unop.arg));
4840024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4841024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Unop.op,
4842024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Unop.arg,
4843024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      NULL, NULL, NULL );
4844024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4845024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4846024598e40c84666cc311a42c256bbf880db3ac99sewardj
4847024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Binop: {
4848024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4849024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Binop.arg1));
4850024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Binop.arg2));
4851024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4852024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Binop.op,
4853024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Binop.arg1, e->Iex.Binop.arg2,
4854024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      NULL, NULL );
4855024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4856024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4857024598e40c84666cc311a42c256bbf880db3ac99sewardj
4858024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Triop: {
4859024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4860024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg1));
4861024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg2));
4862024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg3));
4863024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4864024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Triop.op,
4865024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Triop.arg1, e->Iex.Triop.arg2,
4866024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Triop.arg3, NULL );
4867024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4868024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4869024598e40c84666cc311a42c256bbf880db3ac99sewardj
4870024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Qop: {
4871024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4872024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg1));
4873024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg2));
4874024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg3));
4875024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg4));
4876024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4877024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Qop.op,
4878024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Qop.arg1, e->Iex.Qop.arg2,
4879024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Qop.arg3, e->Iex.Qop.arg4 );
4880024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4881024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4882024598e40c84666cc311a42c256bbf880db3ac99sewardj
4883024598e40c84666cc311a42c256bbf880db3ac99sewardj            default:
4884024598e40c84666cc311a42c256bbf880db3ac99sewardj               goto unhandled;
4885024598e40c84666cc311a42c256bbf880db3ac99sewardj         } /* switch (e->tag) */
4886024598e40c84666cc311a42c256bbf880db3ac99sewardj
4887024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4888024598e40c84666cc311a42c256bbf880db3ac99sewardj
4889024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_WrTmp */
4890024598e40c84666cc311a42c256bbf880db3ac99sewardj
4891024598e40c84666cc311a42c256bbf880db3ac99sewardj      default:
4892024598e40c84666cc311a42c256bbf880db3ac99sewardj      unhandled:
4893024598e40c84666cc311a42c256bbf880db3ac99sewardj         ppIRStmt(st);
4894024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(0);
4895024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4896024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4897024598e40c84666cc311a42c256bbf880db3ac99sewardj
4898024598e40c84666cc311a42c256bbf880db3ac99sewardj
4899e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjstatic IRTemp for_sg__newIRTemp_cb ( IRType ty, void* opaque )
4900e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj{
4901e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   PCEnv* pce = (PCEnv*)opaque;
4902e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   return newTemp( pce, ty, NonShad );
4903e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj}
4904e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
4905e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
4906024598e40c84666cc311a42c256bbf880db3ac99sewardjIRSB* h_instrument ( VgCallbackClosure* closure,
4907024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRSB* sbIn,
4908024598e40c84666cc311a42c256bbf880db3ac99sewardj                     VexGuestLayout* layout,
4909024598e40c84666cc311a42c256bbf880db3ac99sewardj                     VexGuestExtents* vge,
4910024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRType gWordTy, IRType hWordTy )
4911024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4912024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool  verboze = 0||False;
4913024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int   i /*, j*/;
4914024598e40c84666cc311a42c256bbf880db3ac99sewardj   PCEnv pce;
4915024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct _SGEnv* sgenv;
4916024598e40c84666cc311a42c256bbf880db3ac99sewardj
4917024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (gWordTy != hWordTy) {
4918024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* We don't currently support this case. */
4919024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("host/guest word size mismatch");
4920024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4921024598e40c84666cc311a42c256bbf880db3ac99sewardj
4922024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Check we're not completely nuts */
4923024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord)  == sizeof(void*));
4924024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Word)   == sizeof(void*));
4925024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr)   == sizeof(void*));
4926024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(ULong)  == 8);
4927024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Long)   == 8);
4928024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr64) == 8);
4929024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UInt)   == 4);
4930024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Int)    == 4);
4931024598e40c84666cc311a42c256bbf880db3ac99sewardj
4932e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   /* Set up the running environment.  Both .sb and .tmpMap are
4933e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      modified as we go along.  Note that tmps are added to both
4934e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      .sb->tyenv and .tmpMap together, so the valid index-set for
4935e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      those two arrays should always be identical. */
4936e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   VG_(memset)(&pce, 0, sizeof(pce));
4937e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   pce.sb                = deepCopyIRSBExceptStmts(sbIn);
4938024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.trace             = verboze;
4939024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.hWordTy           = hWordTy;
4940024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.gWordTy           = gWordTy;
4941024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.guest_state_sizeB = layout->total_sizeB;
4942024598e40c84666cc311a42c256bbf880db3ac99sewardj
4943e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   pce.qmpMap = VG_(newXA)( VG_(malloc), "pc.h_instrument.1", VG_(free),
4944e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj                            sizeof(TempMapEnt));
4945e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   for (i = 0; i < sbIn->tyenv->types_used; i++) {
4946e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      TempMapEnt ent;
4947e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      ent.kind   = NonShad;
4948e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      ent.shadow = IRTemp_INVALID;
4949e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      VG_(addToXA)( pce.qmpMap, &ent );
4950e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   }
4951e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert( VG_(sizeXA)( pce.qmpMap ) == sbIn->tyenv->types_used );
4952e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
4953e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   /* Also set up for the sg_ instrumenter.  See comments at the top
4954e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      of this instrumentation section for details.  The two parameters
4955e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      constitute a closure, which sg_ can use to correctly generate
4956e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      new IRTemps as needed. */
4957e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   sgenv = sg_instrument_init( for_sg__newIRTemp_cb,
4958e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj                               (void*)&pce );
4959024598e40c84666cc311a42c256bbf880db3ac99sewardj
4960024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Stay sane.  These two should agree! */
4961024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(layout->total_sizeB == MC_SIZEOF_GUEST_STATE);
4962024598e40c84666cc311a42c256bbf880db3ac99sewardj
4963024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Copy verbatim any IR preamble preceding the first IMark */
4964024598e40c84666cc311a42c256bbf880db3ac99sewardj
4965024598e40c84666cc311a42c256bbf880db3ac99sewardj   i = 0;
4966024598e40c84666cc311a42c256bbf880db3ac99sewardj   while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
4967024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRStmt* st = sbIn->stmts[i];
4968024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(st);
4969024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(isFlatIRStmt(st));
4970024598e40c84666cc311a42c256bbf880db3ac99sewardj      stmt( 'C', &pce, sbIn->stmts[i] );
4971024598e40c84666cc311a42c256bbf880db3ac99sewardj      i++;
4972024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4973024598e40c84666cc311a42c256bbf880db3ac99sewardj
4974024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Nasty problem.  IR optimisation of the pre-instrumented IR may
4975024598e40c84666cc311a42c256bbf880db3ac99sewardj      cause the IR following the preamble to contain references to IR
4976024598e40c84666cc311a42c256bbf880db3ac99sewardj      temporaries defined in the preamble.  Because the preamble isn't
4977024598e40c84666cc311a42c256bbf880db3ac99sewardj      instrumented, these temporaries don't have any shadows.
4978024598e40c84666cc311a42c256bbf880db3ac99sewardj      Nevertheless uses of them following the preamble will cause
4979024598e40c84666cc311a42c256bbf880db3ac99sewardj      memcheck to generate references to their shadows.  End effect is
4980024598e40c84666cc311a42c256bbf880db3ac99sewardj      to cause IR sanity check failures, due to references to
4981024598e40c84666cc311a42c256bbf880db3ac99sewardj      non-existent shadows.  This is only evident for the complex
4982024598e40c84666cc311a42c256bbf880db3ac99sewardj      preambles used for function wrapping on TOC-afflicted platforms
4983024598e40c84666cc311a42c256bbf880db3ac99sewardj      (ppc64-linux, ppc32-aix5, ppc64-aix5).
4984024598e40c84666cc311a42c256bbf880db3ac99sewardj
4985024598e40c84666cc311a42c256bbf880db3ac99sewardj      The following loop therefore scans the preamble looking for
4986024598e40c84666cc311a42c256bbf880db3ac99sewardj      assignments to temporaries.  For each one found it creates an
4987024598e40c84666cc311a42c256bbf880db3ac99sewardj      assignment to the corresponding shadow temp, marking it as
4988024598e40c84666cc311a42c256bbf880db3ac99sewardj      'defined'.  This is the same resulting IR as if the main
4989024598e40c84666cc311a42c256bbf880db3ac99sewardj      instrumentation loop before had been applied to the statement
4990024598e40c84666cc311a42c256bbf880db3ac99sewardj      'tmp = CONSTANT'.
4991024598e40c84666cc311a42c256bbf880db3ac99sewardj   */
4992024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
4993024598e40c84666cc311a42c256bbf880db3ac99sewardj   // FIXME: this isn't exactly right; only needs to generate shadows
4994024598e40c84666cc311a42c256bbf880db3ac99sewardj   // for guest-word-typed temps
4995024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (j = 0; j < i; j++) {
4996024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (sbIn->stmts[j]->tag == Ist_WrTmp) {
4997024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* findShadowTmpV checks its arg is an original tmp;
4998024598e40c84666cc311a42c256bbf880db3ac99sewardj            no need to assert that here. */
4999024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp tmp_o = sbIn->stmts[j]->Ist.WrTmp.tmp;
5000024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp tmp_s = findShadowTmp(&pce, tmp_o);
5001024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType ty_s  = typeOfIRTemp(sbIn->tyenv, tmp_s);
5002024598e40c84666cc311a42c256bbf880db3ac99sewardj         assign( 'V', &pce, tmp_s, definedOfType( ty_s ) );
5003024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) {
5004024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j);
5005024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType( ty_s );
5006024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("\n");
5007024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
5008024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
5009024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
5010024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
5011024598e40c84666cc311a42c256bbf880db3ac99sewardj
5012024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Iterate over the remaining stmts to generate instrumentation. */
5013024598e40c84666cc311a42c256bbf880db3ac99sewardj
5014024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sbIn->stmts_used > 0);
5015024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0);
5016024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i < sbIn->stmts_used);
5017024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
5018024598e40c84666cc311a42c256bbf880db3ac99sewardj
5019024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (/*use current i*/; i < sbIn->stmts_used; i++) {
5020024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* generate sg_ instrumentation for this stmt */
5021e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      sg_instrument_IRStmt( sgenv, pce.sb, sbIn->stmts[i],
5022024598e40c84666cc311a42c256bbf880db3ac99sewardj                            layout, gWordTy, hWordTy );
5023024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* generate h_ instrumentation for this stmt */
5024024598e40c84666cc311a42c256bbf880db3ac99sewardj      schemeS( &pce, sbIn->stmts[i] );
5025024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
5026024598e40c84666cc311a42c256bbf880db3ac99sewardj
5027024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* generate sg_ instrumentation for the final jump */
5028e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   sg_instrument_final_jump( sgenv, pce.sb, sbIn->next, sbIn->jumpkind,
5029024598e40c84666cc311a42c256bbf880db3ac99sewardj                             layout, gWordTy, hWordTy );
5030024598e40c84666cc311a42c256bbf880db3ac99sewardj
5031024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* and finalise .. */
5032024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_fini( sgenv );
5033024598e40c84666cc311a42c256bbf880db3ac99sewardj
5034e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   /* If this fails, there's been some serious snafu with tmp management,
5035e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj      that should be investigated. */
5036e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   tl_assert( VG_(sizeXA)( pce.qmpMap ) == pce.sb->tyenv->types_used );
5037e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   VG_(deleteXA)( pce.qmpMap );
5038e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj
5039e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj   return pce.sb;
5040024598e40c84666cc311a42c256bbf880db3ac99sewardj}
5041024598e40c84666cc311a42c256bbf880db3ac99sewardj
5042024598e40c84666cc311a42c256bbf880db3ac99sewardj
5043024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
5044024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Initialisation                                               ---*/
5045024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
5046024598e40c84666cc311a42c256bbf880db3ac99sewardj
5047024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_clo_init ( void )
5048024598e40c84666cc311a42c256bbf880db3ac99sewardj{
5049024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Other initialisation
5050024598e40c84666cc311a42c256bbf880db3ac99sewardj   init_shadow_memory();
5051024598e40c84666cc311a42c256bbf880db3ac99sewardj   init_lossage();
5052024598e40c84666cc311a42c256bbf880db3ac99sewardj}
5053024598e40c84666cc311a42c256bbf880db3ac99sewardj
5054024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_clo_init ( void )
5055024598e40c84666cc311a42c256bbf880db3ac99sewardj{
5056024598e40c84666cc311a42c256bbf880db3ac99sewardj}
5057024598e40c84666cc311a42c256bbf880db3ac99sewardj
5058024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
5059024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Finalisation                                                 ---*/
5060024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
5061024598e40c84666cc311a42c256bbf880db3ac99sewardj
5062024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_fini ( Int exitcode )
5063024598e40c84666cc311a42c256bbf880db3ac99sewardj{
5064024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_(clo_verbosity) >= 2) {
5065024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_DebugMsg,
5066024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "  h_:  %'10llu client allocs, %'10llu client frees",
5067024598e40c84666cc311a42c256bbf880db3ac99sewardj                   stats__client_mallocs, stats__client_frees);
5068024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_DebugMsg,
5069024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "  h_:  %'10llu Segs allocd,   %'10llu Segs recycled",
5070024598e40c84666cc311a42c256bbf880db3ac99sewardj                   stats__segs_allocd, stats__segs_recycled);
5071024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
5072024598e40c84666cc311a42c256bbf880db3ac99sewardj
50734815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#if 0
5074024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (h_clo_lossage_check) {
5075024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
5076024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld total memory references",
5077024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__tot_mem_refs);
5078024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld   of which are in a known segment",
5079024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__refs_in_a_seg);
5080024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld   of which are 'lost' w.r.t the seg",
5081024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__refs_lost_seg);
5082024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
5083024598e40c84666cc311a42c256bbf880db3ac99sewardj      show_lossage();
5084024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
5085024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
5086024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert( 0 == VG_(OSetGen_Size)(lossage) );
5087024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
50884815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#endif
5089024598e40c84666cc311a42c256bbf880db3ac99sewardj}
5090024598e40c84666cc311a42c256bbf880db3ac99sewardj
5091024598e40c84666cc311a42c256bbf880db3ac99sewardj
5092024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
5093024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- end                                                 h_main.c ---*/
5094024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
5095