OSDN Git Service

[General] Convert sourcecode's CRLF format: DOS(WINDOWS) to Unix, to apply patches...
[csp-qt/common_source_project-fm7.git] / source / src / vm / i286.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date  : 2012.10.18-
6
7         [ i286 ]
8 */
9
10 #include "i286.h"
11 #ifdef USE_DEBUGGER
12 #include "debugger.h"
13 #endif
14 #include "../fileio.h"
15
16 /* ----------------------------------------------------------------------------
17         MAME i286
18 ---------------------------------------------------------------------------- */
19
20 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
21 #pragma warning( disable : 4018 )
22 #pragma warning( disable : 4146 )
23 #pragma warning( disable : 4244 )
24 #pragma warning( disable : 4996 )
25 #endif
26
27 #if defined(HAS_I86)
28         #define CPU_MODEL i8086
29 #elif defined(HAS_I88)
30         #define CPU_MODEL i8088
31 #elif defined(HAS_I186)
32         #define CPU_MODEL i80186
33 #elif defined(HAS_I286)
34         #define CPU_MODEL i80286
35 #endif
36
37 #ifndef __BIG_ENDIAN__
38 #define LSB_FIRST
39 #endif
40
41 #ifndef INLINE
42 #define INLINE inline
43 #endif
44
45 #define logerror(...)
46
47 /*****************************************************************************/
48 /* src/emu/devcpu.h */
49
50 // CPU interface functions
51 #define CPU_INIT_NAME(name)                     cpu_init_##name
52 #define CPU_INIT(name)                          void* CPU_INIT_NAME(name)()
53 #define CPU_INIT_CALL(name)                     CPU_INIT_NAME(name)()
54
55 #define CPU_RESET_NAME(name)                    cpu_reset_##name
56 #define CPU_RESET(name)                         void CPU_RESET_NAME(name)(cpu_state *cpustate)
57 #define CPU_RESET_CALL(name)                    CPU_RESET_NAME(name)(cpustate)
58
59 #define CPU_EXECUTE_NAME(name)                  cpu_execute_##name
60 #define CPU_EXECUTE(name)                       int CPU_EXECUTE_NAME(name)(cpu_state *cpustate, int icount)
61 #define CPU_EXECUTE_CALL(name)                  CPU_EXECUTE_NAME(name)(cpustate, icount)
62
63 #define CPU_DISASSEMBLE_NAME(name)              cpu_disassemble_##name
64 #define CPU_DISASSEMBLE(name)                   int CPU_DISASSEMBLE_NAME(name)(char *buffer, offs_t eip, const UINT8 *oprom)
65 #define CPU_DISASSEMBLE_CALL(name)              CPU_DISASSEMBLE_NAME(name)(buffer, eip, oprom)
66
67 /*****************************************************************************/
68 /* src/emu/didisasm.h */
69
70 // Disassembler constants
71 const UINT32 DASMFLAG_SUPPORTED     = 0x80000000;   // are disassembly flags supported?
72 const UINT32 DASMFLAG_STEP_OUT      = 0x40000000;   // this instruction should be the end of a step out sequence
73 const UINT32 DASMFLAG_STEP_OVER     = 0x20000000;   // this instruction should be stepped over by setting a breakpoint afterwards
74 const UINT32 DASMFLAG_OVERINSTMASK  = 0x18000000;   // number of extra instructions to skip when stepping over
75 const UINT32 DASMFLAG_OVERINSTSHIFT = 27;           // bits to shift after masking to get the value
76 const UINT32 DASMFLAG_LENGTHMASK    = 0x0000ffff;   // the low 16-bits contain the actual length
77
78 /*****************************************************************************/
79 /* src/emu/diexec.h */
80
81 // I/O line states
82 enum line_state
83 {
84         CLEAR_LINE = 0,                         // clear (a fired or held) line
85         ASSERT_LINE,                            // assert an interrupt immediately
86         HOLD_LINE,                              // hold interrupt line until acknowledged
87         PULSE_LINE                              // pulse interrupt line instantaneously (only for NMI, RESET)
88 };
89
90 enum
91 {
92         INPUT_LINE_IRQ = 0,
93         INPUT_LINE_NMI
94 };
95
96 /*****************************************************************************/
97 /* src/emu/emucore.h */
98
99 // constants for expression endianness
100 enum endianness_t
101 {
102         ENDIANNESS_LITTLE,
103         ENDIANNESS_BIG
104 };
105
106 // declare native endianness to be one or the other
107 #ifdef LSB_FIRST
108 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
109 #else
110 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
111 #endif
112 // endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
113 #define ENDIAN_VALUE_LE_BE(endian,leval,beval)  (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
114 // endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
115 #define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval)  ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
116 // endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
117 #define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
118
119 /*****************************************************************************/
120 /* src/emu/memory.h */
121
122 // offsets and addresses are 32-bit (for now...)
123 typedef UINT32  offs_t;
124
125 /*****************************************************************************/
126 /* src/osd/osdcomm.h */
127
128 /* Highly useful macro for compile-time knowledge of an array size */
129 #define ARRAY_LENGTH(x)     (sizeof(x) / sizeof(x[0]))
130
131 #if defined(HAS_I86) || defined(HAS_I88) || defined(HAS_I186)
132 #define cpu_state i8086_state
133 #include "mame/emu/cpu/i86/i86.c"
134 #elif defined(HAS_I286)
135 #define cpu_state i80286_state
136 #include "mame/emu/cpu/i86/i286.c"
137 #endif
138 #ifdef USE_DEBUGGER
139 #include "mame/emu/cpu/i386/i386dasm.c"
140 #endif
141
142 void I286::initialize()
143 {
144         opaque = CPU_INIT_CALL(CPU_MODEL);
145         
146         cpu_state *cpustate = (cpu_state *)opaque;
147         cpustate->pic = d_pic;
148         cpustate->program = d_mem;
149         cpustate->io = d_io;
150 #ifdef I86_BIOS_CALL
151         cpustate->bios = d_bios;
152 #endif
153 #ifdef SINGLE_MODE_DMA
154         cpustate->dma = d_dma;
155 #endif
156 #ifdef USE_DEBUGGER
157         cpustate->emu = emu;
158         cpustate->debugger = d_debugger;
159         cpustate->program_stored = d_mem;
160         cpustate->io_stored = d_io;
161         
162         d_debugger->set_context_mem(d_mem);
163         d_debugger->set_context_io(d_io);
164 #endif
165 }
166
167 void I286::release()
168 {
169         free(opaque);
170 }
171
172 void I286::reset()
173 {
174         cpu_state *cpustate = (cpu_state *)opaque;
175         int busreq = cpustate->busreq;
176         
177         CPU_RESET_CALL(CPU_MODEL);
178         
179         cpustate->pic = d_pic;
180         cpustate->program = d_mem;
181         cpustate->io = d_io;
182 #ifdef I86_BIOS_CALL
183         cpustate->bios = d_bios;
184 #endif
185 #ifdef SINGLE_MODE_DMA
186         cpustate->dma = d_dma;
187 #endif
188 #ifdef USE_DEBUGGER
189         cpustate->emu = emu;
190         cpustate->debugger = d_debugger;
191         cpustate->program_stored = d_mem;
192         cpustate->io_stored = d_io;
193 #endif
194         cpustate->busreq = busreq;
195 }
196
197 int I286::run(int icount)
198 {
199         cpu_state *cpustate = (cpu_state *)opaque;
200         return CPU_EXECUTE_CALL(CPU_MODEL);
201 }
202
203 void I286::write_signal(int id, uint32 data, uint32 mask)
204 {
205         cpu_state *cpustate = (cpu_state *)opaque;
206         
207         if(id == SIG_CPU_NMI) {
208                 set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
209         } else if(id == SIG_CPU_IRQ) {
210                 set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
211         } else if(id == SIG_CPU_BUSREQ) {
212                 cpustate->busreq = (data & mask) ? 1 : 0;
213         } else if(id == SIG_I86_TEST) {
214                 cpustate->test_state = (data & mask) ? 1 : 0;
215 #ifdef HAS_I286
216         } else if(id == SIG_I86_A20) {
217                 i80286_set_a20_line(cpustate, data & mask);
218 #endif
219         }
220 }
221
222 void I286::set_intr_line(bool line, bool pending, uint32 bit)
223 {
224         cpu_state *cpustate = (cpu_state *)opaque;
225         set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
226 }
227
228 void I286::set_extra_clock(int icount)
229 {
230         cpu_state *cpustate = (cpu_state *)opaque;
231         cpustate->extra_cycles += icount;
232 }
233
234 int I286::get_extra_clock()
235 {
236         cpu_state *cpustate = (cpu_state *)opaque;
237         return cpustate->extra_cycles;
238 }
239
240 uint32 I286::get_pc()
241 {
242         cpu_state *cpustate = (cpu_state *)opaque;
243         return cpustate->prevpc;
244 }
245
246 uint32 I286::get_next_pc()
247 {
248         cpu_state *cpustate = (cpu_state *)opaque;
249         return cpustate->pc;
250 }
251
252 #ifdef USE_DEBUGGER
253 void I286::debug_write_data8(uint32 addr, uint32 data)
254 {
255         int wait;
256         d_mem->write_data8w(addr, data, &wait);
257 }
258
259 uint32 I286::debug_read_data8(uint32 addr)
260 {
261         int wait;
262         return d_mem->read_data8w(addr, &wait);
263 }
264
265 void I286::debug_write_data16(uint32 addr, uint32 data)
266 {
267         int wait;
268         d_mem->write_data16w(addr, data, &wait);
269 }
270
271 uint32 I286::debug_read_data16(uint32 addr)
272 {
273         int wait;
274         return d_mem->read_data16w(addr, &wait);
275 }
276
277 void I286::debug_write_io8(uint32 addr, uint32 data)
278 {
279         int wait;
280         d_io->write_io8w(addr, data, &wait);
281 }
282
283 uint32 I286::debug_read_io8(uint32 addr) {
284         int wait;
285         return d_io->read_io8w(addr, &wait);
286 }
287
288 void I286::debug_write_io16(uint32 addr, uint32 data)
289 {
290         int wait;
291         d_io->write_io16w(addr, data, &wait);
292 }
293
294 uint32 I286::debug_read_io16(uint32 addr) {
295         int wait;
296         return d_io->read_io16w(addr, &wait);
297 }
298
299 bool I286::debug_write_reg(_TCHAR *reg, uint32 data)
300 {
301         cpu_state *cpustate = (cpu_state *)opaque;
302         if(_tcsicmp(reg, _T("IP")) == 0) {
303                 cpustate->pc = ((data & 0xffff) + cpustate->base[CS]) & AMASK;
304                 CHANGE_PC(cpustate->pc);
305         } else if(_tcsicmp(reg, _T("AX")) == 0) {
306                 cpustate->regs.w[AX] = data;
307         } else if(_tcsicmp(reg, _T("BX")) == 0) {
308                 cpustate->regs.w[BX] = data;
309         } else if(_tcsicmp(reg, _T("CX")) == 0) {
310                 cpustate->regs.w[CX] = data;
311         } else if(_tcsicmp(reg, _T("DX")) == 0) {
312                 cpustate->regs.w[DX] = data;
313         } else if(_tcsicmp(reg, _T("SP")) == 0) {
314                 cpustate->regs.w[SP] = data;
315         } else if(_tcsicmp(reg, _T("BP")) == 0) {
316                 cpustate->regs.w[BP] = data;
317         } else if(_tcsicmp(reg, _T("SI")) == 0) {
318                 cpustate->regs.w[SI] = data;
319         } else if(_tcsicmp(reg, _T("DI")) == 0) {
320                 cpustate->regs.w[DI] = data;
321         } else if(_tcsicmp(reg, _T("AL")) == 0) {
322                 cpustate->regs.b[AL] = data;
323         } else if(_tcsicmp(reg, _T("AH")) == 0) {
324                 cpustate->regs.b[AH] = data;
325         } else if(_tcsicmp(reg, _T("BL")) == 0) {
326                 cpustate->regs.b[BL] = data;
327         } else if(_tcsicmp(reg, _T("BH")) == 0) {
328                 cpustate->regs.b[BH] = data;
329         } else if(_tcsicmp(reg, _T("CL")) == 0) {
330                 cpustate->regs.b[CL] = data;
331         } else if(_tcsicmp(reg, _T("CH")) == 0) {
332                 cpustate->regs.b[CH] = data;
333         } else if(_tcsicmp(reg, _T("DL")) == 0) {
334                 cpustate->regs.b[DL] = data;
335         } else if(_tcsicmp(reg, _T("DH")) == 0) {
336                 cpustate->regs.b[DH] = data;
337         } else {
338                 return false;
339         }
340         return true;
341 }
342
343 void I286::debug_regs_info(_TCHAR *buffer, size_t buffer_len)
344 {
345         cpu_state *cpustate = (cpu_state *)opaque;
346         _stprintf_s(buffer, buffer_len,
347         _T("AX=%04X  BX=%04X CX=%04X DX=%04X SP=%04X  BP=%04X  SI=%04X  DI=%04X\nDS=%04X  ES=%04X SS=%04X CS=%04X IP=%04X  FLAG=[%c%c%c%c%c%c%c%c%c]"),
348         cpustate->regs.w[AX], cpustate->regs.w[BX], cpustate->regs.w[CX], cpustate->regs.w[DX], cpustate->regs.w[SP], cpustate->regs.w[BP], cpustate->regs.w[SI], cpustate->regs.w[DI],
349         cpustate->sregs[DS], cpustate->sregs[ES], cpustate->sregs[SS], cpustate->sregs[CS], cpustate->pc - cpustate->base[CS],
350         OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
351         SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'));
352 }
353
354 int I286::debug_dasm(uint32 pc, _TCHAR *buffer, size_t buffer_len)
355 {
356         cpu_state *cpustate = (cpu_state *)opaque;
357         UINT64 eip = pc - cpustate->base[CS];
358         UINT8 ops[16];
359         for(int i = 0; i < 16; i++) {
360                 int wait;
361                 ops[i] = d_mem->read_data8w(pc + i, &wait);
362         }
363         UINT8 *oprom = ops;
364         
365         return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
366 }
367 #endif
368
369 #ifdef HAS_I286
370 void I286::set_address_mask(uint32 mask)
371 {
372         cpu_state *cpustate = (cpu_state *)opaque;
373         cpustate->amask = mask;
374 }
375
376 uint32 I286::get_address_mask()
377 {
378         cpu_state *cpustate = (cpu_state *)opaque;
379         return cpustate->amask;
380 }
381
382 void I286::set_shutdown_flag(int shutdown)
383 {
384         cpu_state *cpustate = (cpu_state *)opaque;
385         cpustate->shutdown = shutdown;
386 }
387
388 int I286::get_shutdown_flag()
389 {
390         cpu_state *cpustate = (cpu_state *)opaque;
391         return cpustate->shutdown;
392 }
393 #endif
394
395 #define STATE_VERSION   1
396
397 void I286::save_state(FILEIO* state_fio)
398 {
399         state_fio->FputUint32(STATE_VERSION);
400         state_fio->FputInt32(this_device_id);
401         
402         state_fio->Fwrite(opaque, sizeof(cpu_state), 1);
403 }
404
405 bool I286::load_state(FILEIO* state_fio)
406 {
407         if(state_fio->FgetUint32() != STATE_VERSION) {
408                 return false;
409         }
410         if(state_fio->FgetInt32() != this_device_id) {
411                 return false;
412         }
413         state_fio->Fread(opaque, sizeof(cpu_state), 1);
414         
415         // post process
416         cpu_state *cpustate = (cpu_state *)opaque;
417         cpustate->pic = d_pic;
418         cpustate->program = d_mem;
419         cpustate->io = d_io;
420 #ifdef I86_BIOS_CALL
421         cpustate->bios = d_bios;
422 #endif
423 #ifdef SINGLE_MODE_DMA
424         cpustate->dma = d_dma;
425 #endif
426 #ifdef USE_DEBUGGER
427         cpustate->emu = emu;
428         cpustate->debugger = d_debugger;
429         cpustate->program_stored = d_mem;
430         cpustate->io_stored = d_io;
431 #endif
432         return true;
433 }
434