Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/wonderswan/v30mz.cpp
2 views
1
/****************************************************************************
2
3
NEC V30MZ emulator
4
5
Stripped out non-V30MZ clock counts and code.
6
7
Small changes made by [email protected] (Corrected bug in NEG instruction , different AUX flag handling in some opcodes)
8
9
(Re)Written June-September 2000 by Bryan McPhail ([email protected]) based
10
on code by Oliver Bergmann ([email protected]) who based code
11
on the i286 emulator by Fabrice Frances which had initial work based on
12
David Hedley's pcemu(!).
13
14
****************************************************************************/
15
16
/* This NEC V30MZ emulator may be used for purposes both commercial and noncommercial if you give the author, Bryan McPhail,
17
a small credit somewhere(such as in the documentation for an executable package).
18
*/
19
20
/*
21
TODO:
22
Implement bus lock fully(prevent interrupts from occuring during a REP sequence, I think...), taking into account
23
HLT emulation to prevent deadlocks!
24
25
Implement better prefix emulation. It's extremely kludgey right now.
26
27
Implement prefetch/pipeline emulation.
28
*/
29
30
#include "system.h"
31
#include <cstring>
32
#include "v30mz-private.h"
33
34
using namespace MDFN_IEN_WSWAN::V30MZEnum;
35
36
namespace MDFN_IEN_WSWAN
37
{
38
#define ADDBRANCHTRACE(x,y) { }
39
#define ADDBRANCHTRACE_INT(x,y) { }
40
#define SETOLDCSIP() { }
41
42
#include "v30mz-modrm.inc"
43
44
unsigned V30MZ::EA_000() { EO=I.regs.w[BW]+I.regs.w[IX]; EA=DefaultBase(DS0)+EO; return EA; }
45
unsigned V30MZ::EA_001() { EO=I.regs.w[BW]+I.regs.w[IY]; EA=DefaultBase(DS0)+EO; return EA; }
46
unsigned V30MZ::EA_002() { EO=I.regs.w[BP]+I.regs.w[IX]; EA=DefaultBase(SS)+EO; return EA; }
47
unsigned V30MZ::EA_003() { EO=I.regs.w[BP]+I.regs.w[IY]; EA=DefaultBase(SS)+EO; return EA; }
48
unsigned V30MZ::EA_004() { EO=I.regs.w[IX]; EA=DefaultBase(DS0)+EO; return EA; }
49
unsigned V30MZ::EA_005() { EO=I.regs.w[IY]; EA=DefaultBase(DS0)+EO; return EA; }
50
unsigned V30MZ::EA_006() { EO=FETCH; EO+=FETCH<<8; EA=DefaultBase(DS0)+EO; return EA; }
51
unsigned V30MZ::EA_007() { EO=I.regs.w[BW]; EA=DefaultBase(DS0)+EO; return EA; }
52
53
unsigned V30MZ::EA_100() { EO=(I.regs.w[BW]+I.regs.w[IX]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
54
unsigned V30MZ::EA_101() { EO=(I.regs.w[BW]+I.regs.w[IY]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
55
unsigned V30MZ::EA_102() { EO=(I.regs.w[BP]+I.regs.w[IX]+(int8)FETCH); EA=DefaultBase(SS)+EO; return EA; }
56
unsigned V30MZ::EA_103() { EO=(I.regs.w[BP]+I.regs.w[IY]+(int8)FETCH); EA=DefaultBase(SS)+EO; return EA; }
57
unsigned V30MZ::EA_104() { EO=(I.regs.w[IX]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
58
unsigned V30MZ::EA_105() { EO=(I.regs.w[IY]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
59
unsigned V30MZ::EA_106() { EO=(I.regs.w[BP]+(int8)FETCH); EA=DefaultBase(SS)+EO; return EA; }
60
unsigned V30MZ::EA_107() { EO=(I.regs.w[BW]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
61
62
unsigned V30MZ::EA_200() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BW]+I.regs.w[IX]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
63
unsigned V30MZ::EA_201() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BW]+I.regs.w[IY]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
64
unsigned V30MZ::EA_202() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BP]+I.regs.w[IX]+(int16)E16; EA=DefaultBase(SS)+EO; return EA; }
65
unsigned V30MZ::EA_203() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BP]+I.regs.w[IY]+(int16)E16; EA=DefaultBase(SS)+EO; return EA; }
66
unsigned V30MZ::EA_204() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[IX]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
67
unsigned V30MZ::EA_205() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[IY]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
68
unsigned V30MZ::EA_206() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BP]+(int16)E16; EA=DefaultBase(SS)+EO; return EA; }
69
unsigned V30MZ::EA_207() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BW]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
70
71
void V30MZ::SetupEA()
72
{
73
for (int i = 0; i < 64; i += 8)
74
{
75
GetEA[i + 0] = &V30MZ::EA_000;
76
GetEA[i + 1] = &V30MZ::EA_001;
77
GetEA[i + 2] = &V30MZ::EA_002;
78
GetEA[i + 3] = &V30MZ::EA_003;
79
GetEA[i + 4] = &V30MZ::EA_004;
80
GetEA[i + 5] = &V30MZ::EA_005;
81
GetEA[i + 6] = &V30MZ::EA_006;
82
GetEA[i + 7] = &V30MZ::EA_007;
83
}
84
for (int i = 64; i < 128; i += 8)
85
{
86
GetEA[i + 0] = &V30MZ::EA_100;
87
GetEA[i + 1] = &V30MZ::EA_101;
88
GetEA[i + 2] = &V30MZ::EA_102;
89
GetEA[i + 3] = &V30MZ::EA_103;
90
GetEA[i + 4] = &V30MZ::EA_104;
91
GetEA[i + 5] = &V30MZ::EA_105;
92
GetEA[i + 6] = &V30MZ::EA_106;
93
GetEA[i + 7] = &V30MZ::EA_107;
94
}
95
for (int i = 128; i < 192; i += 8)
96
{
97
GetEA[i + 0] = &V30MZ::EA_200;
98
GetEA[i + 1] = &V30MZ::EA_201;
99
GetEA[i + 2] = &V30MZ::EA_202;
100
GetEA[i + 3] = &V30MZ::EA_203;
101
GetEA[i + 4] = &V30MZ::EA_204;
102
GetEA[i + 5] = &V30MZ::EA_205;
103
GetEA[i + 6] = &V30MZ::EA_206;
104
GetEA[i + 7] = &V30MZ::EA_207;
105
}
106
}
107
108
inline void V30MZ::i_real_pushf()
109
{
110
PUSH( CompressFlags() );
111
CLK(2);
112
}
113
114
inline void V30MZ::i_real_popf()
115
{
116
uint32 tmp;
117
POP(tmp);
118
ExpandFlags(tmp);
119
CLK(3);
120
}
121
122
/***************************************************************************/
123
124
V30MZ::V30MZ()
125
{
126
SetupEA();
127
}
128
129
void V30MZ::reset()
130
{
131
const BREGS reg_name[8] = { AL, CL, DL, BL, AH, CH, DH, BH };
132
133
ICount = 0;
134
timestamp = 0;
135
136
std::memset(&I, 0, sizeof(I));
137
138
I.sregs[PS] = 0xffff;
139
140
141
for(unsigned int i = 0; i < 256; i++)
142
{
143
unsigned int c = 0;
144
145
for (unsigned int j = i; j > 0; j >>= 1)
146
if (j & 1) c++;
147
148
parity_table[i] = !(c & 1);
149
}
150
151
I.ZeroVal = I.ParityVal = 1;
152
153
for(unsigned int i = 0; i < 256; i++)
154
{
155
Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
156
Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ;
157
}
158
159
for(unsigned int i = 0xc0; i < 0x100; i++)
160
{
161
Mod_RM.RM.w[i] = (WREGS)( i & 7 );
162
Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
163
}
164
165
prefix_base = 0;
166
seg_prefix = 0;
167
InHLT = 0;
168
}
169
170
void V30MZ::interrupt(uint32 vector, bool IgnoreIF)
171
{
172
InHLT = FALSE; // This is correct! Standby mode is always exited when there is an INT signal, regardless of whether interrupt are disabled.
173
if(I.IF || IgnoreIF)
174
{
175
uint32 dest_seg, dest_off;
176
177
PUSH( CompressFlags() );
178
I.TF = I.IF = 0;
179
dest_off = ReadWord(vector);
180
dest_seg = ReadWord(vector+2);
181
PUSH(I.sregs[PS]);
182
PUSH(I.pc);
183
I.pc = (uint16)dest_off;
184
I.sregs[PS] = (uint16)dest_seg;
185
ADDBRANCHTRACE_INT(I.sregs[PS], I.pc);
186
CLK(32);
187
}
188
}
189
190
void V30MZ::nec_interrupt(unsigned int_num)
191
{
192
uint32 dest_seg, dest_off;
193
194
if (int_num == -1)
195
return;
196
197
i_real_pushf();
198
I.TF = I.IF = 0;
199
200
201
dest_off = ReadWord((int_num)*4);
202
dest_seg = ReadWord((int_num)*4+2);
203
204
PUSH(I.sregs[PS]);
205
PUSH(I.pc);
206
I.pc = (uint16)dest_off;
207
I.sregs[PS] = (uint16)dest_seg;
208
ADDBRANCHTRACE(I.sregs[PS], I.pc);
209
}
210
211
bool V30MZ::CheckInHLT()
212
{
213
if(InHLT)
214
{
215
sys->interrupt.Check();
216
if(InHLT)
217
{
218
int32 tmp = ICount;
219
220
if(tmp > 0)
221
CLK(tmp);
222
return(1);
223
}
224
}
225
return(0);
226
}
227
228
229
/****************************************************************************/
230
/* OPCODES */
231
/****************************************************************************/
232
233
inline void V30MZ::i_real_insb()
234
{
235
PutMemB(DS1,I.regs.w[IY], read_port(I.regs.w[DW]));
236
I.regs.w[IY]+= -2 * I.DF + 1;
237
CLK(6);
238
}
239
240
inline void V30MZ::i_real_insw()
241
{
242
PutMemB(DS1,I.regs.w[IY],read_port(I.regs.w[DW]));
243
PutMemB(DS1,(I.regs.w[IY]+1)&0xffff,read_port((I.regs.w[DW]+1)&0xffff));
244
I.regs.w[IY]+= -4 * I.DF + 2;
245
CLK(6);
246
}
247
248
inline void V30MZ::i_real_outsb()
249
{
250
write_port(I.regs.w[DW],GetMemB(DS0,I.regs.w[IX]));
251
I.regs.w[IX]+= -2 * I.DF + 1;
252
CLK(7);
253
}
254
255
inline void V30MZ::i_real_outsw()
256
{
257
write_port(I.regs.w[DW],GetMemB(DS0,I.regs.w[IX]));
258
write_port((I.regs.w[DW]+1)&0xffff,GetMemB(DS0,(I.regs.w[IX]+1)&0xffff));
259
I.regs.w[IX]+= -4 * I.DF + 2;
260
CLK(7);
261
}
262
263
inline void V30MZ::i_real_movsb()
264
{
265
uint32 tmp = GetMemB(DS0,I.regs.w[IX]);
266
PutMemB(DS1,I.regs.w[IY], tmp);
267
I.regs.w[IY] += -2 * I.DF + 1;
268
I.regs.w[IX] += -2 * I.DF + 1;
269
CLK(5);
270
}
271
272
inline void V30MZ::i_real_movsw()
273
{
274
uint32 tmp = GetMemW(DS0,I.regs.w[IX]); PutMemW(DS1,I.regs.w[IY], tmp); I.regs.w[IY] += -4 * I.DF + 2;
275
I.regs.w[IX] += -4 * I.DF + 2; CLK(5);
276
}
277
278
inline void V30MZ::i_real_cmpsb()
279
{
280
uint32 src = GetMemB(DS1, I.regs.w[IY]); uint32 dst = GetMemB(DS0, I.regs.w[IX]); SUBB; I.regs.w[IY] += -2 * I.DF + 1;
281
I.regs.w[IX] += -2 * I.DF + 1; CLK(6);
282
}
283
284
inline void V30MZ::i_real_cmpsw()
285
{
286
uint32 src = GetMemW(DS1, I.regs.w[IY]); uint32 dst = GetMemW(DS0, I.regs.w[IX]); SUBW; I.regs.w[IY] += -4 * I.DF + 2;
287
I.regs.w[IX] += -4 * I.DF + 2; CLK(6);
288
}
289
290
inline void V30MZ::i_real_stosb()
291
{
292
PutMemB(DS1,I.regs.w[IY],I.regs.b[AL]); I.regs.w[IY] += -2 * I.DF + 1; CLK(3);
293
}
294
295
inline void V30MZ::i_real_stosw()
296
{
297
PutMemW(DS1,I.regs.w[IY],I.regs.w[AW]); I.regs.w[IY] += -4 * I.DF + 2; CLK(3);
298
}
299
300
inline void V30MZ::i_real_lodsb()
301
{
302
I.regs.b[AL] = GetMemB(DS0,I.regs.w[IX]); I.regs.w[IX] += -2 * I.DF + 1; CLK(3);
303
}
304
305
inline void V30MZ::i_real_lodsw()
306
{
307
I.regs.w[AW] = GetMemW(DS0,I.regs.w[IX]); I.regs.w[IX] += -4 * I.DF + 2; CLK(3);
308
}
309
310
inline void V30MZ::i_real_scasb()
311
{
312
uint32 src = GetMemB(DS1, I.regs.w[IY]); uint32 dst = I.regs.b[AL]; SUBB;
313
I.regs.w[IY] += -2 * I.DF + 1; CLK(4);
314
}
315
316
inline void V30MZ::i_real_scasw()
317
{
318
uint32 src = GetMemW(DS1, I.regs.w[IY]); uint32 dst = I.regs.w[AW]; SUBW;
319
I.regs.w[IY] += -4 * I.DF + 2; CLK(4);
320
}
321
322
void V30MZ::DoOP(uint8 opcode)
323
{
324
//#define OP(num,func_name) static void func_name()
325
#define OP(num, func_name) case num:
326
//#define OP_RANGE(num1, num2, func_name) case num1 ... num2:
327
328
#define OP_EPILOGUE break
329
330
switch(opcode)
331
{
332
default:
333
Debug::printf("Invalid op: %02x\n", opcode);
334
CLK(10);
335
break;
336
337
OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
338
OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
339
OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
340
OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
341
OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
342
OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
343
OP( 0x06, i_push_ds1 ) { PUSH(I.sregs[DS1]); CLK(2); } OP_EPILOGUE;
344
OP( 0x07, i_pop_ds1 ) { POP(I.sregs[DS1]); CLK(3); } OP_EPILOGUE;
345
346
OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
347
OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
348
OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
349
OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
350
OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
351
OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
352
OP( 0x0e, i_push_cs ) { PUSH(I.sregs[PS]); CLK(2); } OP_EPILOGUE;
353
354
OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
355
OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
356
OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2, 1); } OP_EPILOGUE;
357
OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKM(2, 1); } OP_EPILOGUE;
358
OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
359
OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
360
OP( 0x16, i_push_ss ) { PUSH(I.sregs[SS]); CLK(2); } OP_EPILOGUE;
361
OP( 0x17, i_pop_ss ) { POP(I.sregs[SS]); CLK(3); } OP_EPILOGUE;
362
363
OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
364
OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
365
OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
366
OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
367
OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
368
OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
369
OP( 0x1e, i_push_ds ) { PUSH(I.sregs[DS0]); CLK(2); } OP_EPILOGUE;
370
OP( 0x1f, i_pop_ds ) { POP(I.sregs[DS0]); CLK(3); } OP_EPILOGUE;
371
372
OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
373
OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
374
OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
375
OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
376
OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
377
OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
378
OP( 0x26, i_ds1 ) { seg_prefix=TRUE; prefix_base=I.sregs[DS1]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
379
OP( 0x27, i_daa ) { ADJ4(6,0x60); CLK(10); } OP_EPILOGUE;
380
381
OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
382
OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
383
OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
384
OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
385
OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
386
OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
387
OP( 0x2e, i_ps ) { seg_prefix=TRUE; prefix_base=I.sregs[PS]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
388
OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLK(10); } OP_EPILOGUE;
389
390
OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
391
OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
392
OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
393
OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
394
OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
395
OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
396
OP( 0x36, i_ss ) { seg_prefix=TRUE; prefix_base=I.sregs[SS]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
397
OP( 0x37, i_aaa ) { ADJB(6,1); CLK(9); } OP_EPILOGUE;
398
399
OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,1); } OP_EPILOGUE;
400
OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKM(2,1); } OP_EPILOGUE;
401
OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,1); } OP_EPILOGUE;
402
OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKM(2,1); } OP_EPILOGUE;
403
OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLK(1); } OP_EPILOGUE;
404
OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLK(1); } OP_EPILOGUE;
405
OP( 0x3e, i_ds0 ) { seg_prefix=TRUE; prefix_base=I.sregs[DS0]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
406
OP( 0x3f, i_aas ) { ADJB(-6,-1); CLK(9); } OP_EPILOGUE;
407
408
OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(1); } OP_EPILOGUE;
409
OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(1); } OP_EPILOGUE;
410
OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(1); } OP_EPILOGUE;
411
OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(1); } OP_EPILOGUE;
412
OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(1); } OP_EPILOGUE;
413
OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(1); } OP_EPILOGUE;
414
OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(1); } OP_EPILOGUE;
415
OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(1); } OP_EPILOGUE;
416
417
OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(1); } OP_EPILOGUE;
418
OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(1); } OP_EPILOGUE;
419
OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(1); } OP_EPILOGUE;
420
OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(1); } OP_EPILOGUE;
421
OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(1); } OP_EPILOGUE;
422
OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(1); } OP_EPILOGUE;
423
OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(1); } OP_EPILOGUE;
424
OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(1); } OP_EPILOGUE;
425
426
OP( 0x50, i_push_ax ) { PUSH(I.regs.w[AW]); CLK(1); } OP_EPILOGUE;
427
OP( 0x51, i_push_cx ) { PUSH(I.regs.w[CW]); CLK(1); } OP_EPILOGUE;
428
OP( 0x52, i_push_dx ) { PUSH(I.regs.w[DW]); CLK(1); } OP_EPILOGUE;
429
OP( 0x53, i_push_bx ) { PUSH(I.regs.w[BW]); CLK(1); } OP_EPILOGUE;
430
OP( 0x54, i_push_sp ) { PUSH(I.regs.w[SP]); CLK(1); } OP_EPILOGUE;
431
OP( 0x55, i_push_bp ) { PUSH(I.regs.w[BP]); CLK(1); } OP_EPILOGUE;
432
OP( 0x56, i_push_si ) { PUSH(I.regs.w[IX]); CLK(1); } OP_EPILOGUE;
433
OP( 0x57, i_push_di ) { PUSH(I.regs.w[IY]); CLK(1); } OP_EPILOGUE;
434
435
OP( 0x58, i_pop_ax ) { POP(I.regs.w[AW]); CLK(1); } OP_EPILOGUE;
436
OP( 0x59, i_pop_cx ) { POP(I.regs.w[CW]); CLK(1); } OP_EPILOGUE;
437
OP( 0x5a, i_pop_dx ) { POP(I.regs.w[DW]); CLK(1); } OP_EPILOGUE;
438
OP( 0x5b, i_pop_bx ) { POP(I.regs.w[BW]); CLK(1); } OP_EPILOGUE;
439
OP( 0x5c, i_pop_sp ) { POP(I.regs.w[SP]); CLK(1); } OP_EPILOGUE;
440
OP( 0x5d, i_pop_bp ) { POP(I.regs.w[BP]); CLK(1); } OP_EPILOGUE;
441
OP( 0x5e, i_pop_si ) { POP(I.regs.w[IX]); CLK(1); } OP_EPILOGUE;
442
OP( 0x5f, i_pop_di ) { POP(I.regs.w[IY]); CLK(1); } OP_EPILOGUE;
443
444
OP( 0x60, i_pusha ) {
445
unsigned tmp=I.regs.w[SP];
446
PUSH(I.regs.w[AW]);
447
PUSH(I.regs.w[CW]);
448
PUSH(I.regs.w[DW]);
449
PUSH(I.regs.w[BW]);
450
PUSH(tmp);
451
PUSH(I.regs.w[BP]);
452
PUSH(I.regs.w[IX]);
453
PUSH(I.regs.w[IY]);
454
CLK(9);
455
} OP_EPILOGUE;
456
457
OP( 0x61, i_popa ) {
458
unsigned tmp;
459
POP(I.regs.w[IY]);
460
POP(I.regs.w[IX]);
461
POP(I.regs.w[BP]);
462
POP(tmp);
463
POP(I.regs.w[BW]);
464
POP(I.regs.w[DW]);
465
POP(I.regs.w[CW]);
466
POP(I.regs.w[AW]);
467
CLK(8);
468
(void)tmp;
469
} OP_EPILOGUE;
470
471
OP( 0x62, i_chkind )
472
{
473
uint32 low,high,tmp;
474
475
GetModRM;
476
477
low = GetRMWord(ModRM);
478
high = GetnextRMWord;
479
tmp = RegWord(ModRM);
480
481
CLK(13);
482
if (tmp<low || tmp>high)
483
{
484
nec_interrupt(5);
485
}
486
} OP_EPILOGUE;
487
488
OP( 0x68, i_push_d16 ) { uint32 tmp; FETCHuint16(tmp); PUSH(tmp); CLK(1); } OP_EPILOGUE;
489
OP( 0x69, i_imul_d16 ) { uint32 tmp; DEF_r16w; FETCHuint16(tmp); dst = (int32)((int16)src)*(int32)((int16)tmp); I.CarryVal = I.OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1); RegWord(ModRM)=(uint16)dst; CLKM(4,3);} OP_EPILOGUE;
490
OP( 0x6a, i_push_d8 ) { uint32 tmp = (uint16)((int16)((int8)FETCH)); PUSH(tmp); CLK(1); } OP_EPILOGUE;
491
OP( 0x6b, i_imul_d8 ) { uint32 src2; DEF_r16w; src2= (uint16)((int16)((int8)FETCH)); dst = (int32)((int16)src)*(int32)((int16)src2); I.CarryVal = I.OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1); RegWord(ModRM)=(uint16)dst; CLKM(4,3); } OP_EPILOGUE;
492
OP( 0x6c, i_insb ) { i_real_insb(); } OP_EPILOGUE;
493
OP( 0x6d, i_insw ) { i_real_insw(); } OP_EPILOGUE;
494
OP( 0x6e, i_outsb ) { i_real_outsb(); } OP_EPILOGUE;
495
OP( 0x6f, i_outsw ) { i_real_outsw(); } OP_EPILOGUE;
496
497
OP( 0x70, i_jo ) { JMP( FLAG_O); CLK(1); } OP_EPILOGUE;
498
OP( 0x71, i_jno ) { JMP(!FLAG_O); CLK(1); } OP_EPILOGUE;
499
OP( 0x72, i_jc ) { JMP( CF); CLK(1); } OP_EPILOGUE;
500
OP( 0x73, i_jnc ) { JMP(!CF); CLK(1); } OP_EPILOGUE;
501
OP( 0x74, i_jz ) { JMP( ZF); CLK(1); } OP_EPILOGUE;
502
OP( 0x75, i_jnz ) { JMP(!ZF); CLK(1); } OP_EPILOGUE;
503
OP( 0x76, i_jce ) { JMP(CF || ZF); CLK(1); } OP_EPILOGUE;
504
OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLK(1); } OP_EPILOGUE;
505
OP( 0x78, i_js ) { JMP( SF); CLK(1); } OP_EPILOGUE;
506
OP( 0x79, i_jns ) { JMP(!SF); CLK(1); } OP_EPILOGUE;
507
OP( 0x7a, i_jp ) { JMP( PF); CLK(1); } OP_EPILOGUE;
508
OP( 0x7b, i_jnp ) { JMP(!PF); CLK(1); } OP_EPILOGUE;
509
OP( 0x7c, i_jl ) { JMP((SF!=FLAG_O)&&(!ZF)); CLK(1); } OP_EPILOGUE;
510
OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==FLAG_O)); CLK(1); } OP_EPILOGUE;
511
OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=FLAG_O)); CLK(1); } OP_EPILOGUE;
512
OP( 0x7f, i_jnle ) { JMP((SF==FLAG_O)&&(!ZF)); CLK(1); } OP_EPILOGUE;
513
514
OP( 0x80, i_80pre ) { uint32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH;
515
CLKM(3, 1);
516
switch (ModRM & 0x38) {
517
case 0x00: ADDB; PutbackRMByte(ModRM,dst); break;
518
case 0x08: ORB; PutbackRMByte(ModRM,dst); break;
519
case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break;
520
case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break;
521
case 0x20: ANDB; PutbackRMByte(ModRM,dst); break;
522
case 0x28: SUBB; PutbackRMByte(ModRM,dst); break;
523
case 0x30: XORB; PutbackRMByte(ModRM,dst); break;
524
case 0x38: SUBB; break; /* CMP */
525
}
526
} OP_EPILOGUE;
527
528
OP( 0x81, i_81pre ) { uint32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH; src+= (FETCH << 8);
529
CLKM(3, 1);
530
switch (ModRM & 0x38) {
531
case 0x00: ADDW; PutbackRMWord(ModRM,dst); break;
532
case 0x08: ORW; PutbackRMWord(ModRM,dst); break;
533
case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break;
534
case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break;
535
case 0x20: ANDW; PutbackRMWord(ModRM,dst); break;
536
case 0x28: SUBW; PutbackRMWord(ModRM,dst); break;
537
case 0x30: XORW; PutbackRMWord(ModRM,dst); break;
538
case 0x38: SUBW; break; /* CMP */
539
}
540
} OP_EPILOGUE;
541
542
OP( 0x82, i_82pre ) { uint32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (uint8)((int8)FETCH);
543
CLKM(3,1);
544
switch (ModRM & 0x38) {
545
case 0x00: ADDB; PutbackRMByte(ModRM,dst); break;
546
case 0x08: ORB; PutbackRMByte(ModRM,dst); break;
547
case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break;
548
case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break;
549
case 0x20: ANDB; PutbackRMByte(ModRM,dst); break;
550
case 0x28: SUBB; PutbackRMByte(ModRM,dst); break;
551
case 0x30: XORB; PutbackRMByte(ModRM,dst); break;
552
case 0x38: SUBB; break; /* CMP */
553
}
554
} OP_EPILOGUE;
555
556
OP( 0x83, i_83pre ) { uint32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (uint16)((int16)((int8)FETCH));
557
CLKM(3,1);
558
switch (ModRM & 0x38) {
559
case 0x00: ADDW; PutbackRMWord(ModRM,dst); break;
560
case 0x08: ORW; PutbackRMWord(ModRM,dst); break;
561
case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break;
562
case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break;
563
case 0x20: ANDW; PutbackRMWord(ModRM,dst); break;
564
case 0x28: SUBW; PutbackRMWord(ModRM,dst); break;
565
case 0x30: XORW; PutbackRMWord(ModRM,dst); break;
566
case 0x38: SUBW; break; /* CMP */
567
}
568
} OP_EPILOGUE;
569
570
OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,1); } OP_EPILOGUE;
571
OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKM(2,1); } OP_EPILOGUE;
572
OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(5,3); } OP_EPILOGUE;
573
OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKM(5,3); } OP_EPILOGUE;
574
575
OP( 0x88, i_mov_br8 ) { uint8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLK(1); } OP_EPILOGUE;
576
OP( 0x89, i_mov_wr16 ) { uint16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLK(1); } OP_EPILOGUE;
577
OP( 0x8a, i_mov_r8b ) { uint8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLK(1); } OP_EPILOGUE;
578
OP( 0x8b, i_mov_r16w ) { uint16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLK(1); } OP_EPILOGUE;
579
OP( 0x8c, i_mov_wsreg ) { GetModRM; PutRMWord(ModRM,I.sregs[(ModRM & 0x38) >> 3]); CLK(1); } OP_EPILOGUE;
580
OP( 0x8d, i_lea ) { uint16 ModRM = FETCH; if(ModRM >= 192) { Debug::printf("LEA Error: %02x\n", ModRM);} else { (void)(this->*GetEA[ModRM])(); } RegWord(ModRM)=EO; CLK(1); } OP_EPILOGUE;
581
OP( 0x8e, i_mov_sregw ) { uint16 src; GetModRM; src = GetRMWord(ModRM); CLKM(3,2);
582
switch (ModRM & 0x38) {
583
case 0x00: I.sregs[DS1] = src; break; /* mov ds1,ew */
584
case 0x08: I.sregs[PS] = src; break; /* mov cs,ew */
585
case 0x10: I.sregs[SS] = src; break; /* mov ss,ew */
586
case 0x18: I.sregs[DS0] = src; break; /* mov ds0,ew */
587
}
588
} OP_EPILOGUE;
589
590
OP( 0x8f, i_popw ) { uint16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); CLKM(3,1); } OP_EPILOGUE;
591
OP( 0x90, i_nop ) { CLK(3); } OP_EPILOGUE;
592
593
OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } OP_EPILOGUE;
594
OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } OP_EPILOGUE;
595
OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } OP_EPILOGUE;
596
OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } OP_EPILOGUE;
597
OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } OP_EPILOGUE;
598
OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } OP_EPILOGUE;
599
OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } OP_EPILOGUE;
600
601
// AKA CVTBW
602
OP( 0x98, i_cbw ) { I.regs.b[AH] = (I.regs.b[AL] & 0x80) ? 0xff : 0; CLK(1); } OP_EPILOGUE;
603
604
// AKA CVTWL
605
OP( 0x99, i_cwd ) { I.regs.w[DW] = (I.regs.b[AH] & 0x80) ? 0xffff : 0; CLK(1); } OP_EPILOGUE;
606
607
OP( 0x9a, i_call_far ) { uint32 tmp, tmp2; FETCHuint16(tmp); FETCHuint16(tmp2); PUSH(I.sregs[PS]); PUSH(I.pc); I.pc = (uint16)tmp; I.sregs[PS] = (uint16)tmp2; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(10); } OP_EPILOGUE;
608
OP( 0x9b, i_poll ) { Debug::puts("POLL"); } OP_EPILOGUE;
609
OP( 0x9c, i_pushf ) { i_real_pushf(); } OP_EPILOGUE;
610
OP( 0x9d, i_popf ) { i_real_popf(); } OP_EPILOGUE;
611
OP( 0x9e, i_sahf ) { uint32 tmp = (CompressFlags() & 0xff00) | (I.regs.b[AH] & 0xd5); ExpandFlags(tmp); CLK(4); } OP_EPILOGUE;
612
OP( 0x9f, i_lahf ) { I.regs.b[AH] = CompressFlags() & 0xff; CLK(2); } OP_EPILOGUE;
613
614
OP( 0xa0, i_mov_aldisp ) { uint32 addr; FETCHuint16(addr); I.regs.b[AL] = GetMemB(DS0, addr); CLK(1); } OP_EPILOGUE;
615
OP( 0xa1, i_mov_axdisp ) { uint32 addr; FETCHuint16(addr); I.regs.b[AL] = GetMemB(DS0, addr); I.regs.b[AH] = GetMemB(DS0, (addr+1)&0xffff); CLK(1); } OP_EPILOGUE;
616
OP( 0xa2, i_mov_dispal ) { uint32 addr; FETCHuint16(addr); PutMemB(DS0, addr, I.regs.b[AL]); CLK(1); } OP_EPILOGUE;
617
OP( 0xa3, i_mov_dispax ) { uint32 addr; FETCHuint16(addr); PutMemB(DS0, addr, I.regs.b[AL]); PutMemB(DS0, (addr+1)&0xffff, I.regs.b[AH]); CLK(1); } OP_EPILOGUE;
618
619
OP( 0xa4, i_movsb ) { i_real_movsb(); } OP_EPILOGUE;
620
OP( 0xa5, i_movsw ) { i_real_movsw(); } OP_EPILOGUE;
621
OP( 0xa6, i_cmpsb ) { i_real_cmpsb(); } OP_EPILOGUE;
622
OP( 0xa7, i_cmpsw ) { i_real_cmpsw(); } OP_EPILOGUE;
623
624
OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLK(1); } OP_EPILOGUE;
625
OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLK(1); } OP_EPILOGUE;
626
627
OP( 0xaa, i_stosb ) { i_real_stosb(); } OP_EPILOGUE;
628
OP( 0xab, i_stosw ) { i_real_stosw(); } OP_EPILOGUE;
629
OP( 0xac, i_lodsb ) { i_real_lodsb(); } OP_EPILOGUE;
630
OP( 0xad, i_lodsw ) { i_real_lodsw(); } OP_EPILOGUE;
631
OP( 0xae, i_scasb ) { i_real_scasb(); } OP_EPILOGUE;
632
OP( 0xaf, i_scasw ) { i_real_scasw(); } OP_EPILOGUE;
633
634
OP( 0xb0, i_mov_ald8 ) { I.regs.b[AL] = FETCH; CLK(1); } OP_EPILOGUE;
635
OP( 0xb1, i_mov_cld8 ) { I.regs.b[CL] = FETCH; CLK(1); } OP_EPILOGUE;
636
OP( 0xb2, i_mov_dld8 ) { I.regs.b[DL] = FETCH; CLK(1); } OP_EPILOGUE;
637
OP( 0xb3, i_mov_bld8 ) { I.regs.b[BL] = FETCH; CLK(1); } OP_EPILOGUE;
638
OP( 0xb4, i_mov_ahd8 ) { I.regs.b[AH] = FETCH; CLK(1); } OP_EPILOGUE;
639
OP( 0xb5, i_mov_chd8 ) { I.regs.b[CH] = FETCH; CLK(1); } OP_EPILOGUE;
640
OP( 0xb6, i_mov_dhd8 ) { I.regs.b[DH] = FETCH; CLK(1); } OP_EPILOGUE;
641
OP( 0xb7, i_mov_bhd8 ) { I.regs.b[BH] = FETCH; CLK(1); } OP_EPILOGUE;
642
643
OP( 0xb8, i_mov_axd16 ) { I.regs.b[AL] = FETCH; I.regs.b[AH] = FETCH; CLK(1); } OP_EPILOGUE;
644
OP( 0xb9, i_mov_cxd16 ) { I.regs.b[CL] = FETCH; I.regs.b[CH] = FETCH; CLK(1); } OP_EPILOGUE;
645
OP( 0xba, i_mov_dxd16 ) { I.regs.b[DL] = FETCH; I.regs.b[DH] = FETCH; CLK(1); } OP_EPILOGUE;
646
OP( 0xbb, i_mov_bxd16 ) { I.regs.b[BL] = FETCH; I.regs.b[BH] = FETCH; CLK(1); } OP_EPILOGUE;
647
OP( 0xbc, i_mov_spd16 ) { I.regs.b[SPL] = FETCH; I.regs.b[SPH] = FETCH; CLK(1); } OP_EPILOGUE;
648
OP( 0xbd, i_mov_bpd16 ) { I.regs.b[BPL] = FETCH; I.regs.b[BPH] = FETCH; CLK(1); } OP_EPILOGUE;
649
OP( 0xbe, i_mov_sid16 ) { I.regs.b[IXL] = FETCH; I.regs.b[IXH] = FETCH; CLK(1); } OP_EPILOGUE;
650
OP( 0xbf, i_mov_did16 ) { I.regs.b[IYL] = FETCH; I.regs.b[IYH] = FETCH; CLK(1); } OP_EPILOGUE;
651
652
OP( 0xc0, i_rotshft_bd8 ) {
653
uint32 src, dst; uint8 c;
654
GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src;
655
c=FETCH;
656
c&=0x1f;
657
CLKM(5,3);
658
if (c) switch (ModRM & 0x38) {
659
case 0x00: do { ROL_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
660
case 0x08: do { ROR_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
661
case 0x10: do { ROLC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
662
case 0x18: do { RORC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
663
case 0x20: SHL_uint8(c); I.AuxVal = 1; break;//
664
case 0x28: SHR_uint8(c); I.AuxVal = 1; break;//
665
case 0x30: break;
666
case 0x38: SHRA_uint8(c); break;
667
}
668
} OP_EPILOGUE;
669
670
OP( 0xc1, i_rotshft_wd8 ) {
671
uint32 src, dst; uint8 c;
672
GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src;
673
c=FETCH;
674
c&=0x1f;
675
CLKM(5,3);
676
if (c) switch (ModRM & 0x38) {
677
case 0x00: do { ROL_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
678
case 0x08: do { ROR_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
679
case 0x10: do { ROLC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
680
case 0x18: do { RORC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
681
case 0x20: SHL_uint16(c); I.AuxVal = 1; break;
682
case 0x28: SHR_uint16(c); I.AuxVal = 1; break;
683
case 0x30: break;
684
case 0x38: SHRA_uint16(c); break;
685
}
686
} OP_EPILOGUE;
687
688
OP( 0xc2, i_ret_d16 ) { uint32 count = FETCH; count += FETCH << 8; POP(I.pc); I.regs.w[SP]+=count; CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
689
OP( 0xc3, i_ret ) { POP(I.pc); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
690
OP( 0xc4, i_les_dw ) { GetModRM; uint16 tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; I.sregs[DS1] = GetnextRMWord; CLK(6); } OP_EPILOGUE;
691
OP( 0xc5, i_lds_dw ) { GetModRM; uint16 tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; I.sregs[DS0] = GetnextRMWord; CLK(6); } OP_EPILOGUE;
692
OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); CLK(1); } OP_EPILOGUE;
693
OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); CLK(1); } OP_EPILOGUE;
694
695
// NEC calls it "PREPARE"
696
OP( 0xc8, i_enter ) {
697
uint32 nb = FETCH;
698
uint32 i,level;
699
700
CLK(19);
701
nb += FETCH << 8;
702
703
level = FETCH;
704
level &= 0x1F; // Only lower 5 bits are valid on V30MZ
705
706
PUSH(I.regs.w[BP]);
707
I.regs.w[BP]=I.regs.w[SP];
708
I.regs.w[SP] -= nb;
709
for (i=1;i<level;i++) {
710
PUSH(GetMemW(SS,I.regs.w[BP]-i*2));
711
CLK(4);
712
}
713
if (level) PUSH(I.regs.w[BP]);
714
} OP_EPILOGUE;
715
716
OP( 0xc9, i_leave ) {
717
I.regs.w[SP]=I.regs.w[BP];
718
POP(I.regs.w[BP]);
719
CLK(2);
720
} OP_EPILOGUE;
721
722
OP( 0xca, i_retf_d16 ) { uint32 count = FETCH; count += FETCH << 8; POP(I.pc); POP(I.sregs[PS]); I.regs.w[SP]+=count; CLK(9); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
723
OP( 0xcb, i_retf ) { POP(I.pc); POP(I.sregs[PS]); CLK(8); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
724
OP( 0xcc, i_int3 ) { nec_interrupt(3); CLK(9); } OP_EPILOGUE;
725
OP( 0xcd, i_int ) { nec_interrupt(FETCH); CLK(10); } OP_EPILOGUE;
726
OP( 0xce, i_into ) { if (FLAG_O) { nec_interrupt(4); CLK(13); } else CLK(6); } OP_EPILOGUE;
727
OP( 0xcf, i_iret ) { POP(I.pc); POP(I.sregs[PS]); i_real_popf(); CLK(10); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
728
729
OP( 0xd0, i_rotshft_b ) {
730
uint32 src, dst; GetModRM; src = (uint32)GetRMByte(ModRM); dst=src;
731
CLKM(3,1);
732
switch (ModRM & 0x38) {
733
case 0x00: ROL_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
734
case 0x08: ROR_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
735
case 0x10: ROLC_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
736
case 0x18: RORC_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
737
case 0x20: SHL_uint8(1); I.OverVal = (src^dst)&0x80;I.AuxVal = 1; break;
738
case 0x28: SHR_uint8(1); I.OverVal = (src^dst)&0x80;I.AuxVal = 1; break;
739
case 0x30: break;
740
case 0x38: SHRA_uint8(1); I.OverVal = 0; break;
741
}
742
} OP_EPILOGUE;
743
744
OP( 0xd1, i_rotshft_w ) {
745
uint32 src, dst; GetModRM; src = (uint32)GetRMWord(ModRM); dst=src;
746
CLKM(3,1);
747
switch (ModRM & 0x38) {
748
case 0x00: ROL_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
749
case 0x08: ROR_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
750
case 0x10: ROLC_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
751
case 0x18: RORC_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
752
case 0x20: SHL_uint16(1); I.AuxVal = 1;I.OverVal = (src^dst)&0x8000; break;
753
case 0x28: SHR_uint16(1); I.AuxVal = 1;I.OverVal = (src^dst)&0x8000; break;
754
case 0x30: break;
755
case 0x38: SHRA_uint16(1); I.AuxVal = 1;I.OverVal = 0; break;
756
}
757
} OP_EPILOGUE;
758
759
OP( 0xd2, i_rotshft_bcl ) {
760
uint32 src, dst; uint8 c; GetModRM; src = (uint32)GetRMByte(ModRM); dst=src;
761
c=I.regs.b[CL];
762
CLKM(5,3);
763
c&=0x1f;
764
if (c) switch (ModRM & 0x38) {
765
case 0x00: do { ROL_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
766
case 0x08: do { ROR_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
767
case 0x10: do { ROLC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
768
case 0x18: do { RORC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
769
case 0x20: SHL_uint8(c); I.AuxVal = 1; break;
770
case 0x28: SHR_uint8(c); I.AuxVal = 1;break;
771
case 0x30: break;
772
case 0x38: SHRA_uint8(c); break;
773
}
774
} OP_EPILOGUE;
775
776
OP( 0xd3, i_rotshft_wcl ) {
777
uint32 src, dst; uint8 c; GetModRM; src = (uint32)GetRMWord(ModRM); dst=src;
778
c=I.regs.b[CL];
779
c&=0x1f;
780
CLKM(5,3);
781
if (c) switch (ModRM & 0x38) {
782
case 0x00: do { ROL_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
783
case 0x08: do { ROR_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
784
case 0x10: do { ROLC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
785
case 0x18: do { RORC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
786
case 0x20: SHL_uint16(c); I.AuxVal = 1; break;
787
case 0x28: SHR_uint16(c); I.AuxVal = 1; break;
788
case 0x30: break;
789
case 0x38: SHRA_uint16(c); break;
790
}
791
} OP_EPILOGUE;
792
793
OP( 0xd4, i_aam ) { uint32 mult=FETCH; mult=0; I.regs.b[AH] = I.regs.b[AL] / 10; I.regs.b[AL] %= 10; SetSZPF_Word(I.regs.w[AW]); CLK(17); } OP_EPILOGUE;
794
OP( 0xd5, i_aad ) { uint32 mult=FETCH; mult=0; I.regs.b[AL] = I.regs.b[AH] * 10 + I.regs.b[AL]; I.regs.b[AH] = 0; SetSZPF_Byte(I.regs.b[AL]); CLK(6); } OP_EPILOGUE;
795
OP( 0xd6, i_setalc ) { I.regs.b[AL] = (CF)?0xff:0x00; CLK(3); } OP_EPILOGUE;
796
OP( 0xd7, i_trans ) { uint32 dest = (I.regs.w[BW]+I.regs.b[AL])&0xffff; I.regs.b[AL] = GetMemB(DS0, dest); CLK(5); } OP_EPILOGUE;
797
798
//
799
OP( 0xd8, i_fpo)
800
OP( 0xd9, i_fpo)
801
OP( 0xda, i_fpo)
802
OP( 0xdb, i_fpo)
803
OP( 0xdc, i_fpo)
804
OP( 0xdd, i_fpo)
805
OP( 0xde, i_fpo)
806
OP( 0xdf, i_fpo)
807
/*OP_RANGE(0xd8, 0xdf, i_fpo)*/ { /*printf("FPO1, Op:%02x\n", opcode);*/ GetModRM; CLK(1); } OP_EPILOGUE;
808
809
OP( 0xe0, i_loopne ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if (!ZF && I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(3); } OP_EPILOGUE;
810
OP( 0xe1, i_loope ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if ( ZF && I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(3); } OP_EPILOGUE;
811
OP( 0xe2, i_loop ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if (I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(5); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(2); } OP_EPILOGUE;
812
OP( 0xe3, i_jcxz ) { int8 disp = (int8)FETCH; if (I.regs.w[CW] == 0) { I.pc = (uint16)(I.pc+disp); CLK(4); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(1); } OP_EPILOGUE;
813
OP( 0xe4, i_inal ) { uint8 port = FETCH; I.regs.b[AL] = read_port(port); CLK(6); } OP_EPILOGUE;
814
OP( 0xe5, i_inax ) { uint8 port = FETCH; I.regs.b[AL] = read_port(port); I.regs.b[AH] = read_port(port+1); CLK(6); } OP_EPILOGUE;
815
OP( 0xe6, i_outal ) { uint8 port = FETCH; write_port(port, I.regs.b[AL]); CLK(6); } OP_EPILOGUE;
816
OP( 0xe7, i_outax ) { uint8 port = FETCH; write_port(port, I.regs.b[AL]); write_port(port+1, I.regs.b[AH]); CLK(6); } OP_EPILOGUE;
817
818
OP( 0xe8, i_call_d16 ) { uint32 tmp; FETCHuint16(tmp); PUSH(I.pc); I.pc = (uint16)(I.pc+(int16)tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(5); } OP_EPILOGUE;
819
OP( 0xe9, i_jmp_d16 ) { uint32 tmp; FETCHuint16(tmp); I.pc = (uint16)(I.pc+(int16)tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(4); } OP_EPILOGUE;
820
OP( 0xea, i_jmp_far ) { uint32 tmp,tmp1; FETCHuint16(tmp); FETCHuint16(tmp1); I.sregs[PS] = (uint16)tmp1; I.pc = (uint16)tmp; ; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(7); } OP_EPILOGUE;
821
OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((int8)FETCH); CLK(4);I.pc = (uint16)(I.pc+tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
822
823
OP( 0xec, i_inaldx ) { I.regs.b[AL] = read_port(I.regs.w[DW]); CLK(6);} OP_EPILOGUE;
824
OP( 0xed, i_inaxdx ) { uint32 port = I.regs.w[DW]; I.regs.b[AL] = read_port(port); I.regs.b[AH] = read_port(port+1); CLK(6); } OP_EPILOGUE;
825
826
OP( 0xee, i_outdxal ) { write_port(I.regs.w[DW], I.regs.b[AL]); CLK(6); } OP_EPILOGUE;
827
OP( 0xef, i_outdxax ) { uint32 port = I.regs.w[DW]; write_port(port, I.regs.b[AL]); write_port(port+1, I.regs.b[AH]); CLK(6); } OP_EPILOGUE;
828
829
// NEC calls it "BUSLOCK"
830
OP( 0xf0, i_lock ) { CLK(1); DoOP(FETCHOP); } OP_EPILOGUE;
831
832
// We put CHK_ICOUNT *after* the first iteration has completed, to match real behavior.
833
#define CHK_ICOUNT(cond) if(ICount < 0 && (cond)) { I.pc -= seg_prefix ? 3 : 2; break; }
834
835
OP( 0xf2, i_repne )
836
{
837
uint32 next = FETCHOP;
838
839
switch(next) { /* Segments */
840
case 0x26: seg_prefix=TRUE; prefix_base=I.sregs[DS1]<<4; next = FETCHOP; CLK(2); break;
841
case 0x2e: seg_prefix=TRUE; prefix_base=I.sregs[PS]<<4; next = FETCHOP; CLK(2); break;
842
case 0x36: seg_prefix=TRUE; prefix_base=I.sregs[SS]<<4; next = FETCHOP; CLK(2); break;
843
case 0x3e: seg_prefix=TRUE; prefix_base=I.sregs[DS0]<<4; next = FETCHOP; CLK(2); break;
844
}
845
846
switch(next) {
847
case 0x6c: CLK(5); if (I.regs.w[CW]) do { i_real_insb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
848
case 0x6d: CLK(5); if (I.regs.w[CW]) do { i_real_insw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
849
case 0x6e: CLK(5); if (I.regs.w[CW]) do { i_real_outsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
850
case 0x6f: CLK(5); if (I.regs.w[CW]) do { i_real_outsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
851
case 0xa4: CLK(5); if (I.regs.w[CW]) do { i_real_movsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
852
case 0xa5: CLK(5); if (I.regs.w[CW]) do { i_real_movsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
853
case 0xa6: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsb(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 0); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==0); break;
854
case 0xa7: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsw(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 0); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==0); break;
855
case 0xaa: CLK(5); if (I.regs.w[CW]) do { i_real_stosb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
856
case 0xab: CLK(5); if (I.regs.w[CW]) do { i_real_stosw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
857
case 0xac: CLK(5); if (I.regs.w[CW]) do { i_real_lodsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
858
case 0xad: CLK(5); if (I.regs.w[CW]) do { i_real_lodsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
859
case 0xae: CLK(5); if (I.regs.w[CW]) do { i_real_scasb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 0); } while (I.regs.w[CW]>0 && ZF==0); break;
860
case 0xaf: CLK(5); if (I.regs.w[CW]) do { i_real_scasw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 0); } while (I.regs.w[CW]>0 && ZF==0); break;
861
default: DoOP(next); break;
862
}
863
seg_prefix=FALSE;
864
} OP_EPILOGUE;
865
866
OP( 0xf3, i_repe)
867
{
868
uint32 next = FETCHOP;
869
870
switch(next) { /* Segments */
871
case 0x26: seg_prefix=TRUE; prefix_base=I.sregs[DS1]<<4; next = FETCHOP; CLK(2); break;
872
case 0x2e: seg_prefix=TRUE; prefix_base=I.sregs[PS]<<4; next = FETCHOP; CLK(2); break;
873
case 0x36: seg_prefix=TRUE; prefix_base=I.sregs[SS]<<4; next = FETCHOP; CLK(2); break;
874
case 0x3e: seg_prefix=TRUE; prefix_base=I.sregs[DS0]<<4; next = FETCHOP; CLK(2); break;
875
}
876
switch(next) {
877
case 0x6c: CLK(5); if (I.regs.w[CW]) do { i_real_insb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
878
case 0x6d: CLK(5); if (I.regs.w[CW]) do { i_real_insw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
879
case 0x6e: CLK(5); if (I.regs.w[CW]) do { i_real_outsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
880
case 0x6f: CLK(5); if (I.regs.w[CW]) do { i_real_outsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
881
case 0xa4: CLK(5); if (I.regs.w[CW]) do { i_real_movsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
882
case 0xa5: CLK(5); if (I.regs.w[CW]) do { i_real_movsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
883
case 0xa6: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsb(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 1); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==1); break;
884
case 0xa7: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsw(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 1);/* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==1); break;
885
case 0xaa: CLK(5); if (I.regs.w[CW]) do { i_real_stosb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
886
case 0xab: CLK(5); if (I.regs.w[CW]) do { i_real_stosw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
887
case 0xac: CLK(5); if (I.regs.w[CW]) do { i_real_lodsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
888
case 0xad: CLK(5); if (I.regs.w[CW]) do { i_real_lodsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
889
case 0xae: CLK(5); if (I.regs.w[CW]) do { i_real_scasb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 1); } while (I.regs.w[CW]>0 && ZF==1); break;
890
case 0xaf: CLK(5); if (I.regs.w[CW]) do { i_real_scasw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 1); } while (I.regs.w[CW]>0 && ZF==1); break;
891
default: DoOP(next); break;
892
}
893
seg_prefix=FALSE;
894
} OP_EPILOGUE;
895
896
OP( 0xf4, i_hlt ) { InHLT = TRUE; CheckInHLT(); } OP_EPILOGUE;
897
898
OP( 0xf5, i_cmc ) { I.CarryVal = !CF; CLK(4); } OP_EPILOGUE;
899
OP( 0xf6, i_f6pre ) { uint32 tmp; uint32 uresult,uresult2; int32 result,result2;
900
GetModRM; tmp = GetRMByte(ModRM);
901
switch (ModRM & 0x38) {
902
case 0x00: tmp &= FETCH; I.CarryVal = I.OverVal = I.AuxVal=0; SetSZPF_Byte(tmp); CLKM(2,1); break; /* TEST */
903
case 0x08: break;
904
case 0x10: PutbackRMByte(ModRM,~tmp); CLKM(3,1); break; /* NOT */
905
906
case 0x18: I.CarryVal=(tmp!=0);tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); CLKM(3,1); break; /* NEG */
907
case 0x20: uresult = I.regs.b[AL]*tmp; I.regs.w[AW]=(uint16)uresult; I.CarryVal=I.OverVal=(I.regs.b[AH]!=0); CLKM(4,3); break; /* MULU */
908
case 0x28: result = (int16)((int8)I.regs.b[AL])*(int16)((int8)tmp); I.regs.w[AW]=(uint16)result; I.CarryVal=I.OverVal=(I.regs.b[AH]!=0); CLKM(4,3); break; /* MUL */
909
case 0x30: if (tmp) { DIVUB; } else nec_interrupt(0); CLKM(16,15); break;
910
case 0x38: if (tmp) { DIVB; } else nec_interrupt(0); CLKM(18,17); break;
911
}
912
} OP_EPILOGUE;
913
914
OP( 0xf7, i_f7pre ) { uint32 tmp,tmp2; uint32 uresult,uresult2; int32 result,result2;
915
GetModRM; tmp = GetRMWord(ModRM);
916
switch (ModRM & 0x38) {
917
case 0x00: FETCHuint16(tmp2); tmp &= tmp2; I.CarryVal = I.OverVal = I.AuxVal=0; SetSZPF_Word(tmp); CLKM(2,1); break; /* TEST */
918
case 0x08: break;
919
case 0x10: PutbackRMWord(ModRM,~tmp); CLKM(3,1); break; /* NOT */
920
case 0x18: I.CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); CLKM(3,1); break; /* NEG */
921
case 0x20: uresult = I.regs.w[AW]*tmp; I.regs.w[AW]=uresult&0xffff; I.regs.w[DW]=((uint32)uresult)>>16; I.CarryVal=I.OverVal=(I.regs.w[DW]!=0); CLKM(4,3); break; /* MULU */
922
case 0x28: result = (int32)((int16)I.regs.w[AW])*(int32)((int16)tmp); I.regs.w[AW]=result&0xffff; I.regs.w[DW]=result>>16; I.CarryVal=I.OverVal=(I.regs.w[DW]!=0); CLKM(4,3); break; /* MUL */
923
case 0x30: if (tmp) { DIVUW; } else nec_interrupt(0); CLKM(24,23); break;
924
case 0x38: if (tmp) { DIVW; } else nec_interrupt(0); CLKM(25,24); break;
925
}
926
} OP_EPILOGUE;
927
928
OP( 0xf8, i_clc ) { I.CarryVal = 0; CLK(4); } OP_EPILOGUE;
929
OP( 0xf9, i_stc ) { I.CarryVal = 1; CLK(4); } OP_EPILOGUE;
930
OP( 0xfa, i_di ) { SetIF(0); CLK(4); } OP_EPILOGUE;
931
OP( 0xfb, i_ei ) { SetIF(1); CLK(4); } OP_EPILOGUE;
932
OP( 0xfc, i_cld ) { SetDF(0); CLK(4); } OP_EPILOGUE;
933
OP( 0xfd, i_std ) { SetDF(1); CLK(4); } OP_EPILOGUE;
934
OP( 0xfe, i_fepre ) { uint32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM);
935
switch(ModRM & 0x38) {
936
case 0x00: tmp1 = tmp+1; I.OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(uint8)tmp1); CLKM(3,1); break; /* INC */
937
case 0x08: tmp1 = tmp-1; I.OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(uint8)tmp1); CLKM(3,1); break; /* DEC */
938
}
939
} OP_EPILOGUE;
940
941
OP( 0xff, i_ffpre ) { uint32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM);
942
switch(ModRM & 0x38) {
943
case 0x00: tmp1 = tmp+1; I.OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(uint16)tmp1); CLKM(3,1); break; /* INC */
944
case 0x08: tmp1 = tmp-1; I.OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(uint16)tmp1); CLKM(3,1); break; /* DEC */
945
case 0x10: PUSH(I.pc); I.pc = (uint16)tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(6,5); break; /* CALL */
946
case 0x18: tmp1 = I.sregs[PS]; I.sregs[PS] = GetnextRMWord; PUSH(tmp1); PUSH(I.pc); I.pc = tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(12,1); break; /* CALL FAR */
947
case 0x20: I.pc = tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(5,4); break; /* JMP */
948
case 0x28: I.pc = tmp; I.sregs[PS] = GetnextRMWord; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(10,1); break; /* JMP FAR */
949
case 0x30: PUSH(tmp); CLKM(2,1); break;
950
}
951
} OP_EPILOGUE;
952
} // End switch statement
953
954
955
} // End func
956
957
958
/*****************************************************************************/
959
960
961
unsigned V30MZ::get_reg(int regnum) const
962
{
963
switch( regnum )
964
{
965
case NEC_PC: return I.pc;
966
case NEC_SP: return I.regs.w[SP];
967
case NEC_FLAGS: return CompressFlags();
968
case NEC_AW: return I.regs.w[AW];
969
case NEC_CW: return I.regs.w[CW];
970
case NEC_DW: return I.regs.w[DW];
971
case NEC_BW: return I.regs.w[BW];
972
case NEC_BP: return I.regs.w[BP];
973
case NEC_IX: return I.regs.w[IX];
974
case NEC_IY: return I.regs.w[IY];
975
case NEC_DS1: return I.sregs[DS1];
976
case NEC_PS: return I.sregs[PS];
977
case NEC_SS: return I.sregs[SS];
978
case NEC_DS0: return I.sregs[DS0];
979
}
980
return 0;
981
}
982
983
void nec_set_irq_line(int irqline, int state);
984
985
void V30MZ::set_reg(int regnum, unsigned val)
986
{
987
switch( regnum )
988
{
989
case NEC_PC: I.pc = val; break;
990
case NEC_SP: I.regs.w[SP] = val; break;
991
case NEC_FLAGS: ExpandFlags(val); break;
992
case NEC_AW: I.regs.w[AW] = val; break;
993
case NEC_CW: I.regs.w[CW] = val; break;
994
case NEC_DW: I.regs.w[DW] = val; break;
995
case NEC_BW: I.regs.w[BW] = val; break;
996
case NEC_BP: I.regs.w[BP] = val; break;
997
case NEC_IX: I.regs.w[IX] = val; break;
998
case NEC_IY: I.regs.w[IY] = val; break;
999
case NEC_DS1: I.sregs[DS1] = val; break;
1000
case NEC_PS: I.sregs[PS] = val; break;
1001
case NEC_SS: I.sregs[SS] = val; break;
1002
case NEC_DS0: I.sregs[DS0] = val; break;
1003
}
1004
}
1005
1006
void V30MZ::execute(int cycles)
1007
{
1008
ICount += cycles;
1009
if(InHLT)
1010
{
1011
SETOLDCSIP();
1012
sys->interrupt.Check();
1013
if(InHLT)
1014
{
1015
int32 tmp = ICount;
1016
if(tmp > 0)
1017
CLK(tmp);
1018
return;
1019
}
1020
}
1021
1022
while(ICount > 0)
1023
{
1024
SETOLDCSIP();
1025
sys->interrupt.Check();
1026
DoOP(FETCHOP);
1027
}
1028
1029
}
1030
1031
uint8 V30MZ::cpu_readop(uint32 addr)
1032
{
1033
if (ExecHook)
1034
ExecHook(addr);
1035
return sys->memory.Read20(addr);
1036
}
1037
uint8 V30MZ::cpu_readop_arg(uint32 addr)
1038
{
1039
// only forward the first opcode byte to callback
1040
return sys->memory.Read20(addr);
1041
}
1042
uint8 V30MZ::cpu_readmem20(uint32 addr)
1043
{
1044
if (ReadHook)
1045
ReadHook(addr);
1046
return sys->memory.Read20(addr);
1047
}
1048
void V30MZ::cpu_writemem20(uint32 addr, uint8 val)
1049
{
1050
sys->memory.Write20(addr, val);
1051
if (WriteHook)
1052
WriteHook(addr);
1053
}
1054
1055
1056
1057
1058
SYNCFUNC(V30MZ)
1059
{
1060
NSS(old_CS);
1061
NSS(old_IP);
1062
NSS(timestamp);
1063
NSS(ICount);
1064
1065
NSS(I);
1066
NSS(InHLT);
1067
1068
NSS(prefix_base);
1069
NSS(seg_prefix);
1070
1071
NSS(parity_table);
1072
1073
NSS(EA);
1074
NSS(EO);
1075
NSS(E16);
1076
1077
NSS(Mod_RM);
1078
}
1079
}
1080
1081