1/*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2011-2014, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7#include "CpuStateX86.h"
8
9#include <new>
10
11#include <string.h>
12
13#include "Register.h"
14
15
16CpuStateX86::CpuStateX86()
17	:
18	fSetRegisters(),
19	fInterruptVector(0)
20{
21}
22
23
24CpuStateX86::CpuStateX86(const x86_debug_cpu_state& state)
25	:
26	fSetRegisters(),
27	fInterruptVector(0)
28{
29	SetIntRegister(X86_REGISTER_EIP, state.eip);
30	SetIntRegister(X86_REGISTER_ESP, state.user_esp);
31	SetIntRegister(X86_REGISTER_EBP, state.ebp);
32	SetIntRegister(X86_REGISTER_EAX, state.eax);
33	SetIntRegister(X86_REGISTER_EBX, state.ebx);
34	SetIntRegister(X86_REGISTER_ECX, state.ecx);
35	SetIntRegister(X86_REGISTER_EDX, state.edx);
36	SetIntRegister(X86_REGISTER_ESI, state.esi);
37	SetIntRegister(X86_REGISTER_EDI, state.edi);
38	SetIntRegister(X86_REGISTER_CS, state.cs);
39	SetIntRegister(X86_REGISTER_DS, state.ds);
40	SetIntRegister(X86_REGISTER_ES, state.es);
41	SetIntRegister(X86_REGISTER_FS, state.fs);
42	SetIntRegister(X86_REGISTER_GS, state.gs);
43	SetIntRegister(X86_REGISTER_SS, state.user_ss);
44
45	const x86_extended_registers& extended = state.extended_registers;
46	SetFloatRegister(X86_REGISTER_ST0,
47		(double)(*(long double*)(extended.fp_registers[0].value)));
48	SetFloatRegister(X86_REGISTER_ST1,
49		(double)(*(long double*)(extended.fp_registers[1].value)));
50	SetFloatRegister(X86_REGISTER_ST2,
51		(double)(*(long double*)(extended.fp_registers[2].value)));
52	SetFloatRegister(X86_REGISTER_ST3,
53		(double)(*(long double*)(extended.fp_registers[3].value)));
54	SetFloatRegister(X86_REGISTER_ST4,
55		(double)(*(long double*)(extended.fp_registers[4].value)));
56	SetFloatRegister(X86_REGISTER_ST5,
57		(double)(*(long double*)(extended.fp_registers[5].value)));
58	SetFloatRegister(X86_REGISTER_ST6,
59		(double)(*(long double*)(extended.fp_registers[6].value)));
60	SetFloatRegister(X86_REGISTER_ST7,
61		(double)(*(long double*)(extended.fp_registers[7].value)));
62
63	SetMMXRegister(X86_REGISTER_MM0, extended.mmx_registers[0].value);
64	SetMMXRegister(X86_REGISTER_MM1, extended.mmx_registers[1].value);
65	SetMMXRegister(X86_REGISTER_MM2, extended.mmx_registers[2].value);
66	SetMMXRegister(X86_REGISTER_MM3, extended.mmx_registers[3].value);
67	SetMMXRegister(X86_REGISTER_MM4, extended.mmx_registers[4].value);
68	SetMMXRegister(X86_REGISTER_MM5, extended.mmx_registers[5].value);
69	SetMMXRegister(X86_REGISTER_MM6, extended.mmx_registers[6].value);
70	SetMMXRegister(X86_REGISTER_MM7, extended.mmx_registers[7].value);
71
72	SetXMMRegister(X86_REGISTER_XMM0, extended.xmm_registers[0].value);
73	SetXMMRegister(X86_REGISTER_XMM1, extended.xmm_registers[1].value);
74	SetXMMRegister(X86_REGISTER_XMM2, extended.xmm_registers[2].value);
75	SetXMMRegister(X86_REGISTER_XMM3, extended.xmm_registers[3].value);
76	SetXMMRegister(X86_REGISTER_XMM4, extended.xmm_registers[4].value);
77	SetXMMRegister(X86_REGISTER_XMM5, extended.xmm_registers[5].value);
78	SetXMMRegister(X86_REGISTER_XMM6, extended.xmm_registers[6].value);
79	SetXMMRegister(X86_REGISTER_XMM7, extended.xmm_registers[7].value);
80
81	fInterruptVector = state.vector;
82}
83
84
85CpuStateX86::~CpuStateX86()
86{
87}
88
89
90status_t
91CpuStateX86::Clone(CpuState*& _clone) const
92{
93	CpuStateX86* newState = new(std::nothrow) CpuStateX86();
94	if (newState == NULL)
95		return B_NO_MEMORY;
96
97
98	memcpy(newState->fIntRegisters, fIntRegisters, sizeof(fIntRegisters));
99	memcpy(newState->fFloatRegisters, fFloatRegisters,
100		sizeof(fFloatRegisters));
101	memcpy(newState->fMMXRegisters, fMMXRegisters, sizeof(fMMXRegisters));
102	memcpy(newState->fXMMRegisters, fXMMRegisters, sizeof(fXMMRegisters));
103
104	newState->fSetRegisters = fSetRegisters;
105	newState->fInterruptVector = fInterruptVector;
106
107	_clone = newState;
108
109	return B_OK;
110}
111
112
113status_t
114CpuStateX86::UpdateDebugState(void* state, size_t size) const
115{
116	if (size != sizeof(x86_debug_cpu_state))
117		return B_BAD_VALUE;
118
119	x86_debug_cpu_state* x86State = (x86_debug_cpu_state*)state;
120
121	x86State->eip = InstructionPointer();
122	x86State->user_esp = StackPointer();
123	x86State->ebp = StackFramePointer();
124	x86State->eax = IntRegisterValue(X86_REGISTER_EAX);
125	x86State->ebx = IntRegisterValue(X86_REGISTER_EBX);
126	x86State->ecx = IntRegisterValue(X86_REGISTER_ECX);
127	x86State->edx = IntRegisterValue(X86_REGISTER_EDX);
128	x86State->esi = IntRegisterValue(X86_REGISTER_ESI);
129	x86State->edi = IntRegisterValue(X86_REGISTER_EDI);
130	x86State->cs = IntRegisterValue(X86_REGISTER_CS);
131	x86State->ds = IntRegisterValue(X86_REGISTER_DS);
132	x86State->es = IntRegisterValue(X86_REGISTER_ES);
133	x86State->fs = IntRegisterValue(X86_REGISTER_FS);
134	x86State->gs = IntRegisterValue(X86_REGISTER_GS);
135	x86State->user_ss = IntRegisterValue(X86_REGISTER_SS);
136	x86State->vector = fInterruptVector;
137
138	for (int32 i = 0; i < 8; i++) {
139		*(long double*)(x86State->extended_registers.fp_registers[i].value)
140			= (long double)FloatRegisterValue(X86_REGISTER_ST0 + i);
141
142		if (IsRegisterSet(X86_REGISTER_MM0 + i)) {
143			memcpy(&x86State->extended_registers.mmx_registers[i],
144				&fMMXRegisters[i], sizeof(x86_fp_register));
145		}
146
147		if (IsRegisterSet(X86_REGISTER_XMM0 + i)) {
148			memcpy(&x86State->extended_registers.xmm_registers[i],
149				&fXMMRegisters[i], sizeof(x86_xmm_register));
150		} else {
151			memset(&x86State->extended_registers.xmm_registers[i],
152				0, sizeof(x86_xmm_register));
153		}
154	}
155
156	return B_OK;
157}
158
159
160target_addr_t
161CpuStateX86::InstructionPointer() const
162{
163	return IsRegisterSet(X86_REGISTER_EIP)
164		? IntRegisterValue(X86_REGISTER_EIP) : 0;
165}
166
167
168void
169CpuStateX86::SetInstructionPointer(target_addr_t address)
170{
171	SetIntRegister(X86_REGISTER_EIP, (uint32)address);
172}
173
174
175target_addr_t
176CpuStateX86::StackFramePointer() const
177{
178	return IsRegisterSet(X86_REGISTER_EBP)
179		? IntRegisterValue(X86_REGISTER_EBP) : 0;
180}
181
182
183target_addr_t
184CpuStateX86::StackPointer() const
185{
186	return IsRegisterSet(X86_REGISTER_ESP)
187		? IntRegisterValue(X86_REGISTER_ESP) : 0;
188}
189
190
191bool
192CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value) const
193{
194	int32 index = reg->Index();
195	if (!IsRegisterSet(index))
196		return false;
197
198	if (index >= X86_XMM_REGISTER_END)
199		return false;
200
201	if (BVariant::TypeIsInteger(reg->ValueType())) {
202		if (reg->BitSize() == 16)
203			_value.SetTo((uint16)fIntRegisters[index]);
204		else
205			_value.SetTo(fIntRegisters[index]);
206	} else if (BVariant::TypeIsFloat(reg->ValueType())) {
207		index -= X86_REGISTER_ST0;
208		if (reg->ValueType() == B_FLOAT_TYPE)
209			_value.SetTo((float)fFloatRegisters[index]);
210		else
211			_value.SetTo(fFloatRegisters[index]);
212	} else {
213		if (index >= X86_REGISTER_MM0 && index < X86_REGISTER_XMM0) {
214			index -= X86_REGISTER_MM0;
215			_value.SetTo(fMMXRegisters[index].value);
216		} else {
217			index -= X86_REGISTER_XMM0;
218			_value.SetTo(fXMMRegisters[index].value);
219		}
220	}
221
222	return true;
223}
224
225
226bool
227CpuStateX86::SetRegisterValue(const Register* reg, const BVariant& value)
228{
229	int32 index = reg->Index();
230	if (index >= X86_XMM_REGISTER_END)
231		return false;
232
233	if (index < X86_INT_REGISTER_END)
234		fIntRegisters[index] = value.ToUInt32();
235	else if (index >= X86_REGISTER_ST0 && index < X86_FP_REGISTER_END)
236		fFloatRegisters[index - X86_REGISTER_ST0] = value.ToDouble();
237	else if (index >= X86_REGISTER_MM0 && index < X86_MMX_REGISTER_END) {
238		if (value.Size() > sizeof(int64))
239			return false;
240		memset(&fMMXRegisters[index - X86_REGISTER_MM0], 0,
241			sizeof(x86_fp_register));
242		memcpy(fMMXRegisters[index - X86_REGISTER_MM0].value,
243			value.ToPointer(), value.Size());
244	} else if (index >= X86_REGISTER_XMM0 && index < X86_XMM_REGISTER_END) {
245		if (value.Size() > sizeof(x86_xmm_register))
246			return false;
247
248		memset(&fXMMRegisters[index - X86_REGISTER_XMM0], 0,
249			sizeof(x86_xmm_register));
250		memcpy(fXMMRegisters[index - X86_REGISTER_XMM0].value,
251			value.ToPointer(), value.Size());
252	} else
253		return false;
254
255	fSetRegisters[index] = 1;
256	return true;
257}
258
259
260bool
261CpuStateX86::IsRegisterSet(int32 index) const
262{
263	return index >= 0 && index < X86_REGISTER_COUNT && fSetRegisters[index];
264}
265
266
267uint32
268CpuStateX86::IntRegisterValue(int32 index) const
269{
270	if (!IsRegisterSet(index) || index >= X86_INT_REGISTER_END)
271		return 0;
272
273	return fIntRegisters[index];
274}
275
276
277void
278CpuStateX86::SetIntRegister(int32 index, uint32 value)
279{
280	if (index < 0 || index >= X86_INT_REGISTER_END)
281		return;
282
283	fIntRegisters[index] = value;
284	fSetRegisters[index] = 1;
285}
286
287
288double
289CpuStateX86::FloatRegisterValue(int32 index) const
290{
291	if (index < X86_REGISTER_ST0 || index >= X86_FP_REGISTER_END
292		|| !IsRegisterSet(index)) {
293		return 0.0;
294	}
295
296	return fFloatRegisters[index - X86_REGISTER_ST0];
297}
298
299
300void
301CpuStateX86::SetFloatRegister(int32 index, double value)
302{
303	if (index < X86_REGISTER_ST0 || index >= X86_FP_REGISTER_END)
304		return;
305
306	fFloatRegisters[index - X86_REGISTER_ST0] = value;
307	fSetRegisters[index] = 1;
308}
309
310
311const void*
312CpuStateX86::MMXRegisterValue(int32 index) const
313{
314	if (index < X86_REGISTER_MM0 || index >= X86_MMX_REGISTER_END
315		|| !IsRegisterSet(index)) {
316		return 0;
317	}
318
319	return fMMXRegisters[index - X86_REGISTER_MM0].value;
320}
321
322
323void
324CpuStateX86::SetMMXRegister(int32 index, const uint8* value)
325{
326	if (index < X86_REGISTER_MM0 || index >= X86_MMX_REGISTER_END)
327		return;
328
329	memcpy(fMMXRegisters[index - X86_REGISTER_MM0].value, value,
330		sizeof(uint64));
331	fSetRegisters[index] = 1;
332}
333
334
335const void*
336CpuStateX86::XMMRegisterValue(int32 index) const
337{
338	if (index < X86_REGISTER_XMM0 || index >= X86_XMM_REGISTER_END
339		|| !IsRegisterSet(index)) {
340		return NULL;
341	}
342
343	return fXMMRegisters[index - X86_REGISTER_XMM0].value;
344}
345
346
347void
348CpuStateX86::SetXMMRegister(int32 index, const uint8* value)
349{
350	if (index < X86_REGISTER_XMM0 || index >= X86_XMM_REGISTER_END)
351		return;
352
353	memcpy(fXMMRegisters[index - X86_REGISTER_XMM0].value, value,
354		sizeof(x86_xmm_register));
355	fSetRegisters[index] = 1;
356}
357
358
359void
360CpuStateX86::UnsetRegister(int32 index)
361{
362	if (index < 0 || index >= X86_REGISTER_COUNT)
363		return;
364
365	fSetRegisters[index] = 0;
366}
367