blob: 896aa15cbe951ce9d197d8e011f6485e8799a777 [file] [log] [blame]
njnf536bbb2005-06-13 04:21:38 +00001
2/*--------------------------------------------------------------------*/
3/*--- Machine-related stuff. m_machine.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2005 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
njnf536bbb2005-06-13 04:21:38 +000033#include "pub_core_libcassert.h"
34#include "pub_core_libcbase.h"
35#include "pub_core_machine.h"
36
njnaf839f52005-06-23 03:27:57 +000037#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
38#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
39#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
njnf536bbb2005-06-13 04:21:38 +000040
41Addr VG_(get_SP) ( ThreadId tid )
42{
43 return STACK_PTR( VG_(threads)[tid].arch );
44}
45
46Addr VG_(get_IP) ( ThreadId tid )
47{
48 return INSTR_PTR( VG_(threads)[tid].arch );
49}
50
51Addr VG_(get_FP) ( ThreadId tid )
52{
53 return FRAME_PTR( VG_(threads)[tid].arch );
54}
55
sewardjacaec5f2005-08-19 16:02:59 +000056Addr VG_(get_LR) ( ThreadId tid )
57{
58# if defined(VGA_ppc32)
59 return VG_(threads)[tid].arch.vex.guest_LR;
60# elif defined(VGA_x86) || defined(VGA_amd64)
61 return 0;
62# else
63# error "Unknown arch"
64# endif
65}
66
njnf536bbb2005-06-13 04:21:38 +000067void VG_(set_SP) ( ThreadId tid, Addr sp )
68{
69 STACK_PTR( VG_(threads)[tid].arch ) = sp;
70}
71
72void VG_(set_IP) ( ThreadId tid, Addr ip )
73{
74 INSTR_PTR( VG_(threads)[tid].arch ) = ip;
75}
76
77
78void VG_(get_shadow_regs_area) ( ThreadId tid, OffT offset, SizeT size,
79 UChar* area )
80{
81 ThreadState* tst;
82
83 vg_assert(VG_(is_valid_tid)(tid));
84 tst = & VG_(threads)[tid];
85
86 // Bounds check
87 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
88 vg_assert(offset + size <= sizeof(VexGuestArchState));
89
90 VG_(memcpy)( area, (void*)(((Addr)&(tst->arch.vex_shadow)) + offset), size);
91}
92
93void VG_(set_shadow_regs_area) ( ThreadId tid, OffT offset, SizeT size,
94 const UChar* area )
95{
96 ThreadState* tst;
97
98 vg_assert(VG_(is_valid_tid)(tid));
99 tst = & VG_(threads)[tid];
100
101 // Bounds check
102 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
103 vg_assert(offset + size <= sizeof(VexGuestArchState));
104
105 VG_(memcpy)( (void*)(((Addr)(&tst->arch.vex_shadow)) + offset), area, size);
106}
107
108
njn6ace3ea2005-06-17 03:06:27 +0000109static void apply_to_GPs_of_tid(VexGuestArchState* vex, void (*f)(Addr))
110{
111#if defined(VGA_x86)
112 (*f)(vex->guest_EAX);
113 (*f)(vex->guest_ECX);
114 (*f)(vex->guest_EDX);
115 (*f)(vex->guest_EBX);
116 (*f)(vex->guest_ESI);
117 (*f)(vex->guest_EDI);
118 (*f)(vex->guest_ESP);
119 (*f)(vex->guest_EBP);
120#elif defined(VGA_amd64)
121 (*f)(vex->guest_RAX);
122 (*f)(vex->guest_RCX);
123 (*f)(vex->guest_RDX);
124 (*f)(vex->guest_RBX);
125 (*f)(vex->guest_RSI);
126 (*f)(vex->guest_RDI);
127 (*f)(vex->guest_RSP);
128 (*f)(vex->guest_RBP);
129 (*f)(vex->guest_R8);
130 (*f)(vex->guest_R9);
131 (*f)(vex->guest_R10);
132 (*f)(vex->guest_R11);
133 (*f)(vex->guest_R12);
134 (*f)(vex->guest_R13);
135 (*f)(vex->guest_R14);
136 (*f)(vex->guest_R15);
cerion85665ca2005-06-20 15:51:07 +0000137#elif defined(VGA_ppc32)
138 /* XXX ask tool about validity? */
139 (*f)(vex->guest_GPR0);
140 (*f)(vex->guest_GPR1);
141 (*f)(vex->guest_GPR2);
142 (*f)(vex->guest_GPR3);
143 (*f)(vex->guest_GPR4);
144 (*f)(vex->guest_GPR5);
145 (*f)(vex->guest_GPR6);
146 (*f)(vex->guest_GPR7);
147 (*f)(vex->guest_GPR8);
148 (*f)(vex->guest_GPR9);
149 (*f)(vex->guest_GPR10);
150 (*f)(vex->guest_GPR11);
151 (*f)(vex->guest_GPR12);
152 (*f)(vex->guest_GPR13);
153 (*f)(vex->guest_GPR14);
154 (*f)(vex->guest_GPR15);
155 (*f)(vex->guest_GPR16);
156 (*f)(vex->guest_GPR17);
157 (*f)(vex->guest_GPR18);
158 (*f)(vex->guest_GPR19);
159 (*f)(vex->guest_GPR20);
160 (*f)(vex->guest_GPR21);
161 (*f)(vex->guest_GPR22);
162 (*f)(vex->guest_GPR23);
163 (*f)(vex->guest_GPR24);
164 (*f)(vex->guest_GPR25);
165 (*f)(vex->guest_GPR26);
166 (*f)(vex->guest_GPR27);
167 (*f)(vex->guest_GPR28);
168 (*f)(vex->guest_GPR29);
169 (*f)(vex->guest_GPR30);
170 (*f)(vex->guest_GPR31);
171 (*f)(vex->guest_CTR);
172 (*f)(vex->guest_LR);
173
njn6ace3ea2005-06-17 03:06:27 +0000174#else
175# error Unknown arch
176#endif
177}
178
179
180void VG_(apply_to_GP_regs)(void (*f)(UWord))
181{
182 ThreadId tid;
183
184 for (tid = 1; tid < VG_N_THREADS; tid++) {
185 if (VG_(is_valid_tid)(tid)) {
186 ThreadState* tst = VG_(get_ThreadState)(tid);
187 apply_to_GPs_of_tid(&(tst->arch.vex), f);
188 }
189 }
190}
191
njn1d0cb0d2005-08-15 01:52:02 +0000192static ThreadId thread_stack_iter = VG_INVALID_THREADID;
193
194void VG_(thread_stack_reset_iter)(void)
njnb506bd82005-06-21 04:01:51 +0000195{
njn1d0cb0d2005-08-15 01:52:02 +0000196 thread_stack_iter = 1;
njnb506bd82005-06-21 04:01:51 +0000197}
njn6ace3ea2005-06-17 03:06:27 +0000198
njn1d0cb0d2005-08-15 01:52:02 +0000199Bool VG_(thread_stack_next)(ThreadId* tid, Addr* stack_min, Addr* stack_max)
200{
201 ThreadId i;
202 for (i = thread_stack_iter; i < VG_N_THREADS; i++) {
203 if (VG_(threads)[i].status != VgTs_Empty) {
204 *tid = i;
205 *stack_min = VG_(get_SP)(i);
206 *stack_max = VG_(threads)[i].client_stack_highest_word;
207 thread_stack_iter = i + 1;
208 return True;
209 }
210 }
211 return False;
212}
sewardj7821e2e2005-08-08 00:35:46 +0000213
sewardj10f08cf2005-06-29 10:16:14 +0000214//////////////////////////////////////////////////////////////////
215// Architecture specifics
216
sewardj7821e2e2005-08-08 00:35:46 +0000217// PPC: what is the cache line size (for dcbz etc) ? This info is
218// harvested on Linux at startup from the AT_SYSINFO entries. 0 means
219// not-yet-set.
sewardj10f08cf2005-06-29 10:16:14 +0000220#if defined(VGA_ppc32)
221Int VG_(cache_line_size_ppc32) = 0;
222#endif
223
sewardj7821e2e2005-08-08 00:35:46 +0000224// X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
225// the SSE control/status register. For most modern CPUs this will be
226// 1. It is set to 1, if possible, by m_translate.getArchAndArchInfo.
227// The value is read by m_dispatch.dispatch-x86.S, which is why it
228// is an Int rather than a Bool.
229//
230// Ugly hack: this has to start as 0 and be set to 1 in the normal
231// case, rather than the other way round, because the dispatch
232// loop needs it, and it runs before the first translation is
233// made. Yet it is the act of making that first translation which
234// causes getArchAndArchInfo to set this value to its final value.
235// So it is necessary to start this value off at 0 as only that
236// guarantees that the dispatch loop will not SIGILL on its first
237// attempt.
238#if defined(VGA_x86)
239Int VG_(have_mxcsr_x86) = 0;
240#endif
241
242
njnf536bbb2005-06-13 04:21:38 +0000243/*--------------------------------------------------------------------*/
244/*--- end ---*/
245/*--------------------------------------------------------------------*/