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
17CpuStateX8664::CpuStateX8664()
18	:
19	fSetRegisters()
20{
21}
22
23
24CpuStateX8664::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
122CpuStateX8664::~CpuStateX8664()
123{
124}
125
126
127status_t
128CpuStateX8664::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
150status_t
151CpuStateX8664::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
206target_addr_t
207CpuStateX8664::InstructionPointer() const
208{
209	return IsRegisterSet(X86_64_REGISTER_RIP)
210		? IntRegisterValue(X86_64_REGISTER_RIP) : 0;
211}
212
213
214void
215CpuStateX8664::SetInstructionPointer(target_addr_t address)
216{
217	SetIntRegister(X86_64_REGISTER_RIP, address);
218}
219
220
221target_addr_t
222CpuStateX8664::StackFramePointer() const
223{
224	return IsRegisterSet(X86_64_REGISTER_RBP)
225		? IntRegisterValue(X86_64_REGISTER_RBP) : 0;
226}
227
228
229target_addr_t
230CpuStateX8664::StackPointer() const
231{
232	return IsRegisterSet(X86_64_REGISTER_RSP)
233		? IntRegisterValue(X86_64_REGISTER_RSP) : 0;
234}
235
236
237bool
238CpuStateX8664::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
272bool
273CpuStateX8664::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
307bool
308CpuStateX8664::IsRegisterSet(int32 index) const
309{
310	return index >= 0 && index < X86_64_REGISTER_COUNT && fSetRegisters[index];
311}
312
313
314uint64
315CpuStateX8664::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
324void
325CpuStateX8664::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
335double
336CpuStateX8664::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
347void
348CpuStateX8664::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
358const void*
359CpuStateX8664::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
370void
371CpuStateX8664::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
382const void*
383CpuStateX8664::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
394void
395CpuStateX8664::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
408void
409CpuStateX8664::UnsetRegister(int32 index)
410{
411	if (index < 0 || index >= X86_64_REGISTER_COUNT)
412		return;
413
414	fSetRegisters[index] = 0;
415}
416