[SOFT386]
[reactos.git] / lib / soft386 / opgroups.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
4 * FILE: opgroups.c
5 * PURPOSE: Opcode group handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
13 #include <windef.h>
14
15 // #define NDEBUG
16 #include <debug.h>
17
18 #include <soft386.h>
19 #include "opcodes.h"
20 #include "common.h"
21
22 /* PUBLIC FUNCTIONS ***********************************************************/
23
24 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8082)
25 {
26 UCHAR Immediate, Result, Dummy, Value;
27 SOFT386_MOD_REG_RM ModRegRm;
28 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
29
30 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
31 {
32 /* The ADSIZE prefix toggles the size */
33 AddressSize = !AddressSize;
34 }
35
36 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
37 {
38 /* Exception occurred */
39 return FALSE;
40 }
41
42 /* Fetch the immediate operand */
43 if (!Soft386FetchByte(State, &Immediate))
44 {
45 /* Exception occurred */
46 return FALSE;
47 }
48
49 /* Read the operands */
50 if (!Soft386ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
51 {
52 /* Exception occurred */
53 return FALSE;
54 }
55
56 /* Check which operation is this */
57 switch (ModRegRm.Register)
58 {
59 /* ADD */
60 case 0:
61 {
62 Result = Value + Immediate;
63
64 /* Update CF, OF and AF */
65 State->Flags.Cf = (Result < Value) && (Result < Immediate);
66 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) == (Immediate & SIGN_FLAG_BYTE))
67 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
68 State->Flags.Af = (((Value & 0x0F) + (Immediate & 0x0F)) & 0x10) ? TRUE : FALSE;
69
70 break;
71 }
72
73 /* OR */
74 case 1:
75 {
76 Result = Value | Immediate;
77 break;
78 }
79
80 /* ADC */
81 case 2:
82 {
83 INT Carry = State->Flags.Cf ? 1 : 0;
84
85 Result = Value + Immediate + Carry;
86
87 /* Update CF, OF and AF */
88 State->Flags.Cf = ((Immediate == 0xFF) && (Carry == 1))
89 || ((Result < Value) && (Result < (Immediate + Carry)));
90 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) == (Immediate & SIGN_FLAG_BYTE))
91 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
92 State->Flags.Af = (((Value & 0x0F) + ((Immediate + Carry) & 0x0F)) & 0x10)
93 ? TRUE : FALSE;
94
95 break;
96 }
97
98 /* SBB */
99 case 3:
100 {
101 INT Carry = State->Flags.Cf ? 1 : 0;
102
103 Result = Value - Immediate - Carry;
104
105 /* Update CF, OF and AF */
106 State->Flags.Cf = Value < (Immediate + Carry);
107 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) != (Immediate & SIGN_FLAG_BYTE))
108 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
109 State->Flags.Af = (Value & 0x0F) < ((Immediate + Carry) & 0x0F);
110
111 break;
112 }
113
114 /* AND */
115 case 4:
116 {
117 Result = Value & Immediate;
118 break;
119 }
120
121 /* SUB or CMP */
122 case 5:
123 case 7:
124 {
125 Result = Value - Immediate;
126
127 /* Update CF, OF and AF */
128 State->Flags.Cf = Value < Immediate;
129 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) != (Immediate & SIGN_FLAG_BYTE))
130 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
131 State->Flags.Af = (Value & 0x0F) < (Immediate & 0x0F);
132
133 break;
134 }
135
136 /* XOR */
137 case 6:
138 {
139 Value ^= Immediate;
140 break;
141 }
142
143 default:
144 {
145 /* Shouldn't happen */
146 ASSERT(FALSE);
147 }
148 }
149
150 /* Update ZF, SF and PF */
151 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
152 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
153 State->Flags.Pf = Soft386CalculateParity(Result);
154
155 /* Unless this is CMP, write back the result */
156 if (ModRegRm.Register != 7)
157 {
158 return Soft386WriteModrmByteOperands(State, &ModRegRm, FALSE, Result);
159 }
160
161 return TRUE;
162 }
163
164 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup81)
165 {
166 UNIMPLEMENTED;
167 return FALSE; // TODO: NOT IMPLEMENTED
168 }
169
170 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup83)
171 {
172 UNIMPLEMENTED;
173 return FALSE; // TODO: NOT IMPLEMENTED
174 }
175
176 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8F)
177 {
178 ULONG Value;
179 SOFT386_MOD_REG_RM ModRegRm;
180 BOOLEAN OperandSize, AddressSize;
181
182 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
183
184 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
185 {
186 /* The OPSIZE prefix toggles the size */
187 OperandSize = !OperandSize;
188 }
189
190 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
191 {
192 /* The ADSIZE prefix toggles the size */
193 AddressSize = !AddressSize;
194 }
195
196 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
197 {
198 /* Exception occurred */
199 return FALSE;
200 }
201
202 if (ModRegRm.Register != 0)
203 {
204 /* Invalid */
205 Soft386Exception(State, SOFT386_EXCEPTION_UD);
206 return FALSE;
207 }
208
209 /* Pop a value from the stack */
210 if (!Soft386StackPop(State, &Value))
211 {
212 /* Exception occurred */
213 return FALSE;
214 }
215
216 if (OperandSize)
217 {
218 return Soft386WriteModrmDwordOperands(State,
219 &ModRegRm,
220 FALSE,
221 Value);
222 }
223 else
224 {
225 return Soft386WriteModrmWordOperands(State,
226 &ModRegRm,
227 FALSE,
228 LOWORD(Value));
229 }
230 }
231
232 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC0)
233 {
234 UNIMPLEMENTED;
235 return FALSE; // TODO: NOT IMPLEMENTED
236 }
237
238 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC1)
239 {
240 UNIMPLEMENTED;
241 return FALSE; // TODO: NOT IMPLEMENTED
242 }
243
244 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC6)
245 {
246 UCHAR Immediate;
247 SOFT386_MOD_REG_RM ModRegRm;
248 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
249
250 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
251 {
252 /* The ADSIZE prefix toggles the size */
253 AddressSize = !AddressSize;
254 }
255
256 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
257 {
258 /* Exception occurred */
259 return FALSE;
260 }
261
262 if (ModRegRm.Register != 0)
263 {
264 /* Invalid */
265 Soft386Exception(State, SOFT386_EXCEPTION_UD);
266 return FALSE;
267 }
268
269 /* Get the immediate operand */
270 if (!Soft386FetchByte(State, &Immediate))
271 {
272 /* Exception occurred */
273 return FALSE;
274 }
275
276 return Soft386WriteModrmByteOperands(State,
277 &ModRegRm,
278 FALSE,
279 Immediate);
280 }
281
282 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC7)
283 {
284 SOFT386_MOD_REG_RM ModRegRm;
285 BOOLEAN OperandSize, AddressSize;
286
287 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
288
289 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
290 {
291 /* The OPSIZE prefix toggles the size */
292 OperandSize = !OperandSize;
293 }
294
295 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
296 {
297 /* The ADSIZE prefix toggles the size */
298 AddressSize = !AddressSize;
299 }
300
301 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
302 {
303 /* Exception occurred */
304 return FALSE;
305 }
306
307 if (ModRegRm.Register != 0)
308 {
309 /* Invalid */
310 Soft386Exception(State, SOFT386_EXCEPTION_UD);
311 return FALSE;
312 }
313
314 if (OperandSize)
315 {
316 ULONG Immediate;
317
318 /* Get the immediate operand */
319 if (!Soft386FetchDword(State, &Immediate))
320 {
321 /* Exception occurred */
322 return FALSE;
323 }
324
325 return Soft386WriteModrmDwordOperands(State,
326 &ModRegRm,
327 FALSE,
328 Immediate);
329 }
330 else
331 {
332 USHORT Immediate;
333
334 /* Get the immediate operand */
335 if (!Soft386FetchWord(State, &Immediate))
336 {
337 /* Exception occurred */
338 return FALSE;
339 }
340
341 return Soft386WriteModrmWordOperands(State,
342 &ModRegRm,
343 FALSE,
344 Immediate);
345 }
346 }
347
348 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD0)
349 {
350 UNIMPLEMENTED;
351 return FALSE; // TODO: NOT IMPLEMENTED
352 }
353
354 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD1)
355 {
356 UNIMPLEMENTED;
357 return FALSE; // TODO: NOT IMPLEMENTED
358 }
359
360 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD2)
361 {
362 UNIMPLEMENTED;
363 return FALSE; // TODO: NOT IMPLEMENTED
364 }
365
366 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD3)
367 {
368 UNIMPLEMENTED;
369 return FALSE; // TODO: NOT IMPLEMENTED
370 }
371
372 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF6)
373 {
374 UNIMPLEMENTED;
375 return FALSE; // TODO: NOT IMPLEMENTED
376 }
377
378 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF7)
379 {
380 UNIMPLEMENTED;
381 return FALSE; // TODO: NOT IMPLEMENTED
382 }
383
384 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFE)
385 {
386 UNIMPLEMENTED;
387 return FALSE; // TODO: NOT IMPLEMENTED
388 }
389
390 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF)
391 {
392 UNIMPLEMENTED;
393 return FALSE; // TODO: NOT IMPLEMENTED
394 }
395
396 /* EOF */
397