xref: /haiku/src/kits/debugger/arch/x86_64/CpuStateX8664.cpp (revision 87f4776937505e3014251c9c3434be78ae29d7d0)
1 /*
2  * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Copyright 2011-2013, Rene Gollent, rene@gollent.com.
5  * Distributed under the terms of the MIT License.
6  */
7 
8 #include "CpuStateX8664.h"
9 
10 #include <new>
11 
12 #include <string.h>
13 
14 #include "Register.h"
15 
16 
17 CpuStateX8664::CpuStateX8664()
18 	:
19 	fSetRegisters()
20 {
21 }
22 
23 
24 CpuStateX8664::CpuStateX8664(const x86_64_debug_cpu_state& state)
25 	:
26 	fSetRegisters(),
27 	fInterruptVector(0)
28 {
29 	SetIntRegister(X86_64_REGISTER_RIP, state.rip);
30 	SetIntRegister(X86_64_REGISTER_RSP, state.rsp);
31 	SetIntRegister(X86_64_REGISTER_RBP, state.rbp);
32 	SetIntRegister(X86_64_REGISTER_RAX, state.rax);
33 	SetIntRegister(X86_64_REGISTER_RBX, state.rbx);
34 	SetIntRegister(X86_64_REGISTER_RCX, state.rcx);
35 	SetIntRegister(X86_64_REGISTER_RDX, state.rdx);
36 	SetIntRegister(X86_64_REGISTER_RSI, state.rsi);
37 	SetIntRegister(X86_64_REGISTER_RDI, state.rdi);
38 	SetIntRegister(X86_64_REGISTER_R8, state.r8);
39 	SetIntRegister(X86_64_REGISTER_R9, state.r9);
40 	SetIntRegister(X86_64_REGISTER_R10, state.r10);
41 	SetIntRegister(X86_64_REGISTER_R11, state.r11);
42 	SetIntRegister(X86_64_REGISTER_R12, state.r12);
43 	SetIntRegister(X86_64_REGISTER_R13, state.r13);
44 	SetIntRegister(X86_64_REGISTER_R14, state.r14);
45 	SetIntRegister(X86_64_REGISTER_R15, state.r15);
46 	SetIntRegister(X86_64_REGISTER_CS, state.cs);
47 	SetIntRegister(X86_64_REGISTER_DS, state.ds);
48 	SetIntRegister(X86_64_REGISTER_ES, state.es);
49 	SetIntRegister(X86_64_REGISTER_FS, state.fs);
50 	SetIntRegister(X86_64_REGISTER_GS, state.gs);
51 	SetIntRegister(X86_64_REGISTER_SS, state.ss);
52 
53 	const struct savefpu& extended = state.extended_registers;
54 
55 	SetFloatRegister(X86_64_REGISTER_ST0,
56 		(double)(*(long double*)(extended.fp_fxsave.fp[0].value)));
57 	SetFloatRegister(X86_64_REGISTER_ST1,
58 		(double)(*(long double*)(extended.fp_fxsave.fp[1].value)));
59 	SetFloatRegister(X86_64_REGISTER_ST2,
60 		(double)(*(long double*)(extended.fp_fxsave.fp[2].value)));
61 	SetFloatRegister(X86_64_REGISTER_ST3,
62 		(double)(*(long double*)(extended.fp_fxsave.fp[3].value)));
63 	SetFloatRegister(X86_64_REGISTER_ST4,
64 		(double)(*(long double*)(extended.fp_fxsave.fp[4].value)));
65 	SetFloatRegister(X86_64_REGISTER_ST5,
66 		(double)(*(long double*)(extended.fp_fxsave.fp[5].value)));
67 	SetFloatRegister(X86_64_REGISTER_ST6,
68 		(double)(*(long double*)(extended.fp_fxsave.fp[6].value)));
69 	SetFloatRegister(X86_64_REGISTER_ST7,
70 		(double)(*(long double*)(extended.fp_fxsave.fp[7].value)));
71 
72 	SetMMXRegister(X86_64_REGISTER_MM0, extended.fp_fxsave.mmx[0].value);
73 	SetMMXRegister(X86_64_REGISTER_MM1, extended.fp_fxsave.mmx[1].value);
74 	SetMMXRegister(X86_64_REGISTER_MM2, extended.fp_fxsave.mmx[2].value);
75 	SetMMXRegister(X86_64_REGISTER_MM3, extended.fp_fxsave.mmx[3].value);
76 	SetMMXRegister(X86_64_REGISTER_MM4, extended.fp_fxsave.mmx[4].value);
77 	SetMMXRegister(X86_64_REGISTER_MM5, extended.fp_fxsave.mmx[5].value);
78 	SetMMXRegister(X86_64_REGISTER_MM6, extended.fp_fxsave.mmx[6].value);
79 	SetMMXRegister(X86_64_REGISTER_MM7, extended.fp_fxsave.mmx[7].value);
80 
81 	// The YMM register value is split in two halves in the saved CPU context,
82 	// so we have to reassemble it here.
83 	// TODO check extended.xstate_hdr to see if the YMM values are present at
84 	// all.
85 	SetXMMRegister(X86_64_REGISTER_XMM0, extended.fp_ymm[0].value,
86 		extended.fp_fxsave.xmm[0].value);
87 	SetXMMRegister(X86_64_REGISTER_XMM1, extended.fp_ymm[1].value,
88 		extended.fp_fxsave.xmm[1].value);
89 	SetXMMRegister(X86_64_REGISTER_XMM2, extended.fp_ymm[2].value,
90 		extended.fp_fxsave.xmm[2].value);
91 	SetXMMRegister(X86_64_REGISTER_XMM3, extended.fp_ymm[3].value,
92 		extended.fp_fxsave.xmm[3].value);
93 	SetXMMRegister(X86_64_REGISTER_XMM4, extended.fp_ymm[4].value,
94 		extended.fp_fxsave.xmm[4].value);
95 	SetXMMRegister(X86_64_REGISTER_XMM5, extended.fp_ymm[5].value,
96 		extended.fp_fxsave.xmm[5].value);
97 	SetXMMRegister(X86_64_REGISTER_XMM6, extended.fp_ymm[6].value,
98 		extended.fp_fxsave.xmm[6].value);
99 	SetXMMRegister(X86_64_REGISTER_XMM7, extended.fp_ymm[7].value,
100 		extended.fp_fxsave.xmm[7].value);
101 	SetXMMRegister(X86_64_REGISTER_XMM8, extended.fp_ymm[8].value,
102 		extended.fp_fxsave.xmm[8].value);
103 	SetXMMRegister(X86_64_REGISTER_XMM9, extended.fp_ymm[9].value,
104 		extended.fp_fxsave.xmm[9].value);
105 	SetXMMRegister(X86_64_REGISTER_XMM10, extended.fp_ymm[10].value,
106 		extended.fp_fxsave.xmm[10].value);
107 	SetXMMRegister(X86_64_REGISTER_XMM11, extended.fp_ymm[11].value,
108 		extended.fp_fxsave.xmm[11].value);
109 	SetXMMRegister(X86_64_REGISTER_XMM12, extended.fp_ymm[12].value,
110 		extended.fp_fxsave.xmm[12].value);
111 	SetXMMRegister(X86_64_REGISTER_XMM13, extended.fp_ymm[13].value,
112 		extended.fp_fxsave.xmm[13].value);
113 	SetXMMRegister(X86_64_REGISTER_XMM14, extended.fp_ymm[14].value,
114 		extended.fp_fxsave.xmm[14].value);
115 	SetXMMRegister(X86_64_REGISTER_XMM15, extended.fp_ymm[15].value,
116 		extended.fp_fxsave.xmm[15].value);
117 
118 	fInterruptVector = state.vector;
119 }
120 
121 
122 CpuStateX8664::~CpuStateX8664()
123 {
124 }
125 
126 
127 status_t
128 CpuStateX8664::Clone(CpuState*& _clone) const
129 {
130 	CpuStateX8664* newState = new(std::nothrow) CpuStateX8664();
131 	if (newState == NULL)
132 		return B_NO_MEMORY;
133 
134 
135 	memcpy(newState->fIntRegisters, fIntRegisters, sizeof(fIntRegisters));
136 	memcpy(newState->fFloatRegisters, fFloatRegisters,
137 		sizeof(fFloatRegisters));
138 	memcpy(newState->fMMXRegisters, fMMXRegisters, sizeof(fMMXRegisters));
139 	memcpy(newState->fXMMRegisters, fXMMRegisters, sizeof(fXMMRegisters));
140 
141 	newState->fSetRegisters = fSetRegisters;
142 	newState->fInterruptVector = fInterruptVector;
143 
144 	_clone = newState;
145 
146 	return B_OK;
147 }
148 
149 
150 status_t
151 CpuStateX8664::UpdateDebugState(void* state, size_t size) const
152 {
153 	if (size != sizeof(x86_64_debug_cpu_state))
154 		return B_BAD_VALUE;
155 
156 	x86_64_debug_cpu_state* x64State = (x86_64_debug_cpu_state*)state;
157 
158 	x64State->rip = InstructionPointer();
159 	x64State->rsp = StackPointer();
160 	x64State->rbp = StackFramePointer();
161 	x64State->rax = IntRegisterValue(X86_64_REGISTER_RAX);
162 	x64State->rbx = IntRegisterValue(X86_64_REGISTER_RBX);
163 	x64State->rcx = IntRegisterValue(X86_64_REGISTER_RCX);
164 	x64State->rdx = IntRegisterValue(X86_64_REGISTER_RDX);
165 	x64State->rsi = IntRegisterValue(X86_64_REGISTER_RSI);
166 	x64State->rdi = IntRegisterValue(X86_64_REGISTER_RDI);
167 	x64State->r8 = IntRegisterValue(X86_64_REGISTER_R8);
168 	x64State->r9 = IntRegisterValue(X86_64_REGISTER_R9);
169 	x64State->r10 = IntRegisterValue(X86_64_REGISTER_R10);
170 	x64State->r11 = IntRegisterValue(X86_64_REGISTER_R11);
171 	x64State->r12 = IntRegisterValue(X86_64_REGISTER_R12);
172 	x64State->r13 = IntRegisterValue(X86_64_REGISTER_R13);
173 	x64State->r14 = IntRegisterValue(X86_64_REGISTER_R14);
174 	x64State->r15 = IntRegisterValue(X86_64_REGISTER_R15);
175 	x64State->cs = IntRegisterValue(X86_64_REGISTER_CS);
176 	x64State->ds = IntRegisterValue(X86_64_REGISTER_DS);
177 	x64State->es = IntRegisterValue(X86_64_REGISTER_ES);
178 	x64State->fs = IntRegisterValue(X86_64_REGISTER_FS);
179 	x64State->gs = IntRegisterValue(X86_64_REGISTER_GS);
180 	x64State->ss = IntRegisterValue(X86_64_REGISTER_SS);
181 
182 	for (int32 i = 0; i < 8; i++) {
183 		*(long double*)(x64State->extended_registers.fp_fxsave.fp[i].value)
184 			= (long double)FloatRegisterValue(X86_64_REGISTER_ST0 + i);
185 
186 		if (IsRegisterSet(X86_64_REGISTER_MM0 + i)) {
187 			memcpy(&x64State->extended_registers.fp_fxsave.mmx[i],
188 				&fMMXRegisters[i], sizeof(x86_64_fp_register));
189 		}
190 	}
191 
192 	for (int32 i = 0; i < 16; i++) {
193 		if (IsRegisterSet(X86_64_REGISTER_XMM0 + i)) {
194 			memcpy(&x64State->extended_registers.fp_fxsave.xmm[i],
195 				&fXMMRegisters[i], sizeof(x86_64_xmm_register));
196 		} else {
197 			memset(&x64State->extended_registers.fp_fxsave.xmm[i],
198 				0, sizeof(x86_64_xmm_register));
199 		}
200 	}
201 
202 	return B_OK;
203 }
204 
205 
206 target_addr_t
207 CpuStateX8664::InstructionPointer() const
208 {
209 	return IsRegisterSet(X86_64_REGISTER_RIP)
210 		? IntRegisterValue(X86_64_REGISTER_RIP) : 0;
211 }
212 
213 
214 void
215 CpuStateX8664::SetInstructionPointer(target_addr_t address)
216 {
217 	SetIntRegister(X86_64_REGISTER_RIP, address);
218 }
219 
220 
221 target_addr_t
222 CpuStateX8664::StackFramePointer() const
223 {
224 	return IsRegisterSet(X86_64_REGISTER_RBP)
225 		? IntRegisterValue(X86_64_REGISTER_RBP) : 0;
226 }
227 
228 
229 target_addr_t
230 CpuStateX8664::StackPointer() const
231 {
232 	return IsRegisterSet(X86_64_REGISTER_RSP)
233 		? IntRegisterValue(X86_64_REGISTER_RSP) : 0;
234 }
235 
236 
237 bool
238 CpuStateX8664::GetRegisterValue(const Register* reg, BVariant& _value) const
239 {
240 	int32 index = reg->Index();
241 	if (!IsRegisterSet(index))
242 		return false;
243 
244 	if (index >= X86_64_XMM_REGISTER_END)
245 		return false;
246 
247 	if (BVariant::TypeIsInteger(reg->ValueType())) {
248 		if (reg->BitSize() == 16)
249 			_value.SetTo((uint16)fIntRegisters[index]);
250 		else
251 			_value.SetTo(fIntRegisters[index]);
252 	} else if (BVariant::TypeIsFloat(reg->ValueType())) {
253 		index -= X86_64_REGISTER_ST0;
254 		if (reg->ValueType() == B_FLOAT_TYPE)
255 			_value.SetTo((float)fFloatRegisters[index]);
256 		else
257 			_value.SetTo(fFloatRegisters[index]);
258 	} else {
259 		if (index >= X86_64_REGISTER_MM0 && index < X86_64_REGISTER_XMM0) {
260 			index -= X86_64_REGISTER_MM0;
261 			_value.SetTo(fMMXRegisters[index].value);
262 		} else {
263 			index -= X86_64_REGISTER_XMM0;
264 			_value.SetTo(fXMMRegisters[index].value);
265 		}
266 	}
267 
268 	return true;
269 }
270 
271 
272 bool
273 CpuStateX8664::SetRegisterValue(const Register* reg, const BVariant& value)
274 {
275 	int32 index = reg->Index();
276 	if (index >= X86_64_XMM_REGISTER_END)
277 		return false;
278 
279 	if (index < X86_64_INT_REGISTER_END)
280 		fIntRegisters[index] = value.ToUInt64();
281 	else if (index >= X86_64_REGISTER_ST0 && index < X86_64_FP_REGISTER_END)
282 		fFloatRegisters[index - X86_64_REGISTER_ST0] = value.ToDouble();
283 	else if (index >= X86_64_REGISTER_MM0 && index < X86_64_MMX_REGISTER_END) {
284 		if (value.Size() > sizeof(int64))
285 			return false;
286 		memset(&fMMXRegisters[index - X86_64_REGISTER_MM0], 0,
287 			sizeof(x86_64_fp_register));
288 		memcpy(fMMXRegisters[index - X86_64_REGISTER_MM0].value,
289 			value.ToPointer(), value.Size());
290 	} else if (index >= X86_64_REGISTER_XMM0
291 			&& index < X86_64_XMM_REGISTER_END) {
292 		if (value.Size() > sizeof(x86_64_xmm_register))
293 			return false;
294 
295 		memset(&fXMMRegisters[index - X86_64_REGISTER_XMM0], 0,
296 			sizeof(x86_64_xmm_register));
297 		memcpy(fXMMRegisters[index - X86_64_REGISTER_XMM0].value,
298 			value.ToPointer(), value.Size());
299 	} else
300 		return false;
301 
302 	fSetRegisters[index] = 1;
303 	return true;
304 }
305 
306 
307 bool
308 CpuStateX8664::IsRegisterSet(int32 index) const
309 {
310 	return index >= 0 && index < X86_64_REGISTER_COUNT && fSetRegisters[index];
311 }
312 
313 
314 uint64
315 CpuStateX8664::IntRegisterValue(int32 index) const
316 {
317 	if (!IsRegisterSet(index) || index >= X86_64_INT_REGISTER_END)
318 		return 0;
319 
320 	return fIntRegisters[index];
321 }
322 
323 
324 void
325 CpuStateX8664::SetIntRegister(int32 index, uint64 value)
326 {
327 	if (index < 0 || index >= X86_64_INT_REGISTER_END)
328 		return;
329 
330 	fIntRegisters[index] = value;
331 	fSetRegisters[index] = 1;
332 }
333 
334 
335 double
336 CpuStateX8664::FloatRegisterValue(int32 index) const
337 {
338 	if (index < X86_64_REGISTER_ST0 || index >= X86_64_FP_REGISTER_END
339 		|| !IsRegisterSet(index)) {
340 		return 0.0;
341 	}
342 
343 	return fFloatRegisters[index - X86_64_REGISTER_ST0];
344 }
345 
346 
347 void
348 CpuStateX8664::SetFloatRegister(int32 index, double value)
349 {
350 	if (index < X86_64_REGISTER_ST0 || index >= X86_64_FP_REGISTER_END)
351 		return;
352 
353 	fFloatRegisters[index - X86_64_REGISTER_ST0] = value;
354 	fSetRegisters[index] = 1;
355 }
356 
357 
358 const void*
359 CpuStateX8664::MMXRegisterValue(int32 index) const
360 {
361 	if (index < X86_64_REGISTER_MM0 || index >= X86_64_MMX_REGISTER_END
362 		|| !IsRegisterSet(index)) {
363 		return 0;
364 	}
365 
366 	return fMMXRegisters[index - X86_64_REGISTER_MM0].value;
367 }
368 
369 
370 void
371 CpuStateX8664::SetMMXRegister(int32 index, const uint8* value)
372 {
373 	if (index < X86_64_REGISTER_MM0 || index >= X86_64_MMX_REGISTER_END)
374 		return;
375 
376 	memcpy(fMMXRegisters[index - X86_64_REGISTER_MM0].value, value,
377 		sizeof(uint64));
378 	fSetRegisters[index] = 1;
379 }
380 
381 
382 const void*
383 CpuStateX8664::XMMRegisterValue(int32 index) const
384 {
385 	if (index < X86_64_REGISTER_XMM0 || index >= X86_64_XMM_REGISTER_END
386 		|| !IsRegisterSet(index)) {
387 		return NULL;
388 	}
389 
390 	return fXMMRegisters[index - X86_64_REGISTER_XMM0].value;
391 }
392 
393 
394 void
395 CpuStateX8664::SetXMMRegister(int32 index, const uint8* highValue, const uint8* lowValue)
396 {
397 	if (index < X86_64_REGISTER_XMM0 || index >= X86_64_XMM_REGISTER_END)
398 		return;
399 
400 	memcpy(&fXMMRegisters[index - X86_64_REGISTER_XMM0].value[0], lowValue,
401 		sizeof(x86_64_xmm_register));
402 	memcpy(&fXMMRegisters[index - X86_64_REGISTER_XMM0].value[2], highValue,
403 		sizeof(x86_64_xmm_register));
404 	fSetRegisters[index] = 1;
405 }
406 
407 
408 void
409 CpuStateX8664::UnsetRegister(int32 index)
410 {
411 	if (index < 0 || index >= X86_64_REGISTER_COUNT)
412 		return;
413 
414 	fSetRegisters[index] = 0;
415 }
416