3 #include <aros/i386/cpucontext.h>
5 /* This was taken from Mingw32's w32api/winnt.h */
8 #define CONTEXT_i386 0x10000
9 #define CONTEXT_i486 0x10000
10 #define CONTEXT_CONTROL (CONTEXT_i386|0x00000001L)
11 #define CONTEXT_INTEGER (CONTEXT_i386|0x00000002L)
12 #define CONTEXT_SEGMENTS (CONTEXT_i386|0x00000004L)
13 #define CONTEXT_FLOATING_POINT (CONTEXT_i386|0x00000008L)
14 #define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386|0x00000010L)
15 #define CONTEXT_EXTENDED_REGISTERS (CONTEXT_i386|0x00000020L)
16 #define CONTEXT_FULL (CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS)
19 #define MAXIMUM_SUPPORTED_EXTENSION 512
21 typedef struct _FLOATING_SAVE_AREA
30 UBYTE RegisterArea
[80];
34 typedef struct _CONTEXT
43 FLOATING_SAVE_AREA FloatSave
;
60 BYTE ExtendedRegisters
[MAXIMUM_SUPPORTED_EXTENSION
];
63 /* On AROS side we save also LastError code */
66 struct ExceptionContext regs
; /* Public portion */
67 ULONG LastError
; /* LastError code */
71 * Common part of SAVEREGS and TRAP_SAVEREGS.
72 * Saves CPU registers from CONTEXT in struct ExceptionContext.
74 #define SAVE_CPU(regs, ctx) \
76 ctx.eax = regs->Eax; \
77 ctx.ebx = regs->Ebx; \
78 ctx.ecx = regs->Ecx; \
79 ctx.edx = regs->Edx; \
80 ctx.esi = regs->Esi; \
81 ctx.edi = regs->Edi; \
82 ctx.ebp = regs->Ebp; \
83 ctx.eip = regs->Eip; \
84 ctx.eflags = regs->EFlags; \
85 ctx.esp = regs->Esp; \
86 if (regs->ContextFlags & CONTEXT_SEGMENTS) \
88 ctx.Flags |= ECF_SEGMENTS; \
89 ctx.ds = regs->SegDs; \
90 ctx.es = regs->SegEs; \
91 ctx.fs = regs->SegFs; \
92 ctx.gs = regs->SegGs; \
93 ctx.cs = regs->SegCs; \
94 ctx.ss = regs->SegSs; \
98 * Restore CPU registers.
99 * Does not restore segment registers because they are of private use
100 * by Windows. We can't modify them.
102 #define RESTORE_CPU(regs, ctx) \
103 regs->ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER; \
104 regs->Eax = ctx.eax; \
105 regs->Ebx = ctx.ebx; \
106 regs->Ecx = ctx.ecx; \
107 regs->Edx = ctx.edx; \
108 regs->Esi = ctx.esi; \
109 regs->Edi = ctx.edi; \
110 regs->Ebp = ctx.ebp; \
111 regs->Eip = ctx.eip; \
112 regs->EFlags = ctx.eflags; \
115 /* Provide legacy 8087 context together with SSE one */
116 #define USE_LEGACY_8087
118 /* 8087 frame contains private portion (Cr0NpxState) */
119 #define SIZEOF_8087_FRAME sizeof(FLOATING_SAVE_AREA)
122 * Save the whole set of registers in the allocated context space.
123 * Also saves FPU and SSE, if available.
125 #define SAVEREGS(regs, ctx) \
126 SAVE_CPU(regs, ctx->regs); \
127 if (regs->ContextFlags & CONTEXT_FLOATING_POINT) \
129 ctx->regs.Flags |= ECF_FPU; \
130 CopyMemQuick(®s->FloatSave, ctx->regs.FPData, sizeof(FLOATING_SAVE_AREA)); \
132 if (regs->ContextFlags & CONTEXT_EXTENDED_REGISTERS) \
134 ctx->regs.Flags |= ECF_FPX; \
135 CopyMemQuick(regs->ExtendedRegisters, ctx->regs.FXData, MAXIMUM_SUPPORTED_EXTENSION); \
139 * Restore complete set of registers.
140 * Restores FPU and SSE only if they present both in CONTEXT and in struct ExceptionContext.
141 * This is done because a debugger may want to modify one of frames. In this case it will
142 * reset flag of the second frame (which is still unmodified).
144 #define RESTOREREGS(regs, ctx) \
146 ULONG orig = regs->ContextFlags; \
147 RESTORE_CPU(regs, ctx->regs); \
148 if (ctx->regs.Flags & ECF_FPU) \
150 regs->ContextFlags |= CONTEXT_FLOATING_POINT; \
151 CopyMemQuick(ctx->regs.FPData, ®s->FloatSave, sizeof(FLOATING_SAVE_AREA)); \
153 if ((ctx->regs.Flags & ECF_FPX) && (orig & CONTEXT_EXTENDED_REGISTERS)) \
155 regs->ContextFlags |= CONTEXT_EXTENDED_REGISTERS; \
156 CopyMemQuick(ctx->regs.FXData, regs->ExtendedRegisters, MAXIMUM_SUPPORTED_EXTENSION); \
161 * Similar to SAVEREGS and RESTOREREGS, but actually copies only CPU part.
162 * FPU and SSE are specified by references (frames format in host and AROS match).
163 * This is for use within trap handling code.
165 #define TRAP_SAVEREGS(src, dest) \
166 SAVE_CPU(src, dest) \
167 if (src->ContextFlags & CONTEXT_FLOATING_POINT) \
169 dest.Flags |= ECF_FPU; \
170 dest.FPData = (struct FPUContext *)&src->FloatSave; \
172 if (src->ContextFlags & CONTEXT_EXTENDED_REGISTERS) \
174 dest.Flags |= ECF_FPX; \
175 dest.FXData = (struct FPXContext *)src->ExtendedRegisters; \
178 #define TRAP_RESTOREREGS(dest, src) \
179 RESTORE_CPU(dest, src); \
180 if (src.Flags & ECF_FPU) \
181 dest->ContextFlags |= CONTEXT_FLOATING_POINT; \
182 if (src.Flags & ECF_FPX) \
183 dest->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
186 * Realign and copy FPU portion from src to dest. It is supposed
187 * that common part is already copied.
189 #define COPY_FPU(src, dest) \
191 IPTR fpdata = (IPTR)(dest) + sizeof(struct AROSCPUContext); \
192 if ((src)->Flags & ECF_FPU) \
194 (dest)->FPData = (struct FPUContext *)fpdata; \
195 fpdata += sizeof(FLOATING_SAVE_AREA); \
196 CopyMemQuick((src)->FPData, (dest)->FPData, sizeof(FLOATING_SAVE_AREA)); \
199 (dest)->FPData = NULL; \
200 if ((src)->Flags & ECF_FPX) \
202 fpdata = (fpdata + 15) & ~15; \
203 (dest)->FXData = (struct FPXContext *)fpdata; \
204 CopyMemQuick((src)->FXData, (dest)->FXData, MAXIMUM_SUPPORTED_EXTENSION); \
207 (dest)->FXData = NULL; \
210 #define GET_SP(ctx) (void *)ctx->regs.esp
212 #define EXCEPTIONS_COUNT 18
214 #endif /* __AROS__ */
216 /* The following macros need to be visible on both Windows and AROS side */
218 #define PRINT_CPUCONTEXT(ctx) \
219 bug (" ContextFlags: 0x%08lX\n" \
220 " ESP=%08lx EBP=%08lx EIP=%08lx\n" \
221 " EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n" \
222 " EDI=%08lx ESI=%08lx EFLAGS=%08lx\n" \
223 , (ctx)->ContextFlags \
236 #define CONTEXT_INIT_FLAGS(ctx) (ctx)->ContextFlags = CONTEXT_FULL|CONTEXT_FLOATING_POINT|CONTEXT_DEBUG_REGISTERS|CONTEXT_EXTENDED_REGISTERS
238 #define PC(regs) regs->Eip
239 #define R0(regs) regs->Eax