OSDN Git Service

[VM][UPD7810] Fix FTBFS.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mcs48.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME 0.148
5         Author : Takeda.Toshiya
6         Date   : 2013.05.01-
7
8         [ MCS48 ]
9 */
10 #include "vm.h"
11 #include "../emu.h"
12
13 #include "mcs48_flags.h"
14 #include "mcs48.h"
15 #ifdef USE_DEBUGGER
16 #include "debugger.h"
17 #endif
18
19 /***************************************************************************
20
21     mcs48.c
22
23     Intel MCS-48/UPI-41 Portable Emulator
24
25     Copyright Mirko Buffoni
26     Based on the original work Copyright Dan Boris, an 8048 emulator
27     You are not allowed to distribute this software commercially
28
29 ****************************************************************************
30
31     Note that the default internal divisor for this chip is by 3 and
32     then again by 5, or by 15 total.
33
34 ***************************************************************************/
35
36 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
37 #pragma warning( disable : 4244 )
38 #endif
39
40 /***************************************************************************
41     INITIALIZATION/RESET
42 ***************************************************************************/
43
44 void MCS48::initialize()
45 {
46         DEVICE::initialize();
47         opaque = calloc(1, sizeof(mcs48_state));
48         
49         mcs48_state *cpustate = (mcs48_state *)opaque;
50         
51         cpustate->mem = d_mem;
52         cpustate->io = d_io;
53         cpustate->intr = d_intr;
54 #ifdef USE_DEBUGGER
55         d_mem_stored = d_mem;
56         d_io_stored = d_io;
57         d_debugger->set_context_mem(d_mem);
58         d_debugger->set_context_io(d_io);
59 #endif
60 }
61
62 void MCS48::release()
63 {
64         free(opaque);
65 }
66
67 /***************************************************************************
68     EXECUTION
69 ***************************************************************************/
70
71
72 /*-------------------------------------------------
73     burn_cycles - burn cycles, processing timers
74     and counters
75 -------------------------------------------------*/
76
77 void MCS48::burn_cycles(mcs48_state *cpustate, int count)
78 {
79         int timerover = FALSE;
80
81         /* output (clock*15/3) hz to t0 */
82         if (cpustate->t0_clk_enabled)
83         {
84                 for(int i = 0; i < count * 5; i++)
85                 {
86                         __mcs48_test_w(0, 1);
87                         __mcs48_test_w(0, 0);
88                 }
89         }
90
91         /* if the timer is enabled, accumulate prescaler cycles */
92         if (cpustate->timecount_enabled & __MCS48_TIMER_ENABLED)
93         {
94                 UINT8 oldtimer = cpustate->timer;
95                 cpustate->prescaler += count;
96                 cpustate->timer += cpustate->prescaler >> 5;
97                 cpustate->prescaler &= 0x1f;
98                 timerover = (oldtimer != 0 && cpustate->timer == 0);
99         }
100
101         /* if the counter is enabled, poll the T1 test input once for each cycle */
102         else if (cpustate->timecount_enabled & __MCS48_COUNTER_ENABLED)
103                 for ( ; count > 0; count--)
104                 {
105                         cpustate->t1_history = (cpustate->t1_history << 1) | (__mcs48_test_r(1) & 1);
106                         if ((cpustate->t1_history & 3) == 2)
107                                 timerover = (++cpustate->timer == 0);
108                 }
109
110         /* if either source caused a timer overflow, set the flags and check IRQs */
111         if (timerover)
112         {
113                 cpustate->timer_flag = TRUE;
114
115                 /* according to the docs, if an overflow occurs with interrupts disabled, the overflow is not stored */
116                 if (cpustate->tirq_enabled)
117                 {
118                         cpustate->timer_overflow = TRUE;
119                         check_irqs(cpustate);
120                 }
121         }
122 }
123
124 int MCS48::run(int icount)
125 {
126         mcs48_state *cpustate = (mcs48_state *)opaque;
127         int curcycles;
128         
129         if (icount == -1) {
130                 cpustate->icount = 1;
131         } else {
132                 cpustate->icount += icount;
133                 if (cpustate->icount < 0) {
134                         return 0;
135                 }
136         }
137         
138         int base_icount = cpustate->icount;
139         
140         update_regptr(cpustate);
141         
142         /* external interrupts may have been set since we last checked */
143         curcycles = check_irqs(cpustate);
144         cpustate->icount -= curcycles * 15;
145         if (cpustate->timecount_enabled != 0)
146                 burn_cycles(cpustate, curcycles);
147 #ifdef USE_DEBUGGER
148         total_icount += curcycles * 15;
149 #endif
150
151         /* iterate over remaining cycles, guaranteeing at least one instruction */
152         do
153         {
154 #ifdef USE_DEBUGGER
155                 bool now_debugging = d_debugger->now_debugging;
156                 if(now_debugging) {
157                         d_debugger->check_break_points(cpustate->pc);
158                         if(d_debugger->now_suspended) {
159                                 emu->mute_sound();
160                                 d_debugger->now_waiting = true;
161                                 while(d_debugger->now_debugging && d_debugger->now_suspended) {
162                                         emu->sleep(10);
163                                 }
164                                 d_debugger->now_waiting = false;
165                         }
166                         if(d_debugger->now_debugging) {
167                                 d_mem = d_io = d_debugger;
168                         } else {
169                                 now_debugging = false;
170                         }
171                         
172                         /* fetch next opcode */
173                         cpustate->prevpc = cpustate->pc;
174                         curcycles = op_call(cpustate);
175
176                         /* burn the cycles */
177                         cpustate->icount -= curcycles * 15;
178                         if (cpustate->timecount_enabled != 0)
179                                 burn_cycles(cpustate, curcycles);
180                         
181                         total_icount += curcycles * 15;
182                         if(now_debugging) {
183                                 if(!d_debugger->now_going) {
184                                         d_debugger->now_suspended = true;
185                                 }
186                                 d_mem = d_mem_stored;
187                                 d_io = d_io_stored;
188                         }
189                 } else {
190 #endif
191                         /* fetch next opcode */
192                         d_debugger->add_cpu_trace(cpustate->pc);
193                         cpustate->prevpc = cpustate->pc;
194                         curcycles = op_call(cpustate);
195
196                         /* burn the cycles */
197                         cpustate->icount -= curcycles * 15;
198                         if (cpustate->timecount_enabled != 0)
199                                 burn_cycles(cpustate, curcycles);
200 #ifdef USE_DEBUGGER
201                         total_icount += curcycles * 15;
202                 }
203 #endif
204         } while (cpustate->icount > 0);
205         
206         return base_icount - cpustate->icount;
207 }
208
209
210 #define STATE_VERSION   3
211
212 bool MCS48::process_state(FILEIO* state_fio, bool loading)
213 {
214         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
215                 return false;
216         }
217         if(!state_fio->StateCheckInt32(this_device_id)) {
218                 return false;
219         }
220 #ifdef USE_DEBUGGER
221         state_fio->StateUint64(total_icount);
222 #endif
223         //state_fio->StateBuffer(opaque, sizeof(mcs48_state), 1);
224
225         // BEGIN CPUREGS
226         mcs48_state *cpustate = (mcs48_state *)opaque;
227         state_fio->StateUint16(cpustate->prevpc);
228         state_fio->StateUint16(cpustate->pc);
229         state_fio->StateUint8(cpustate->a);
230         state_fio->StateInt32(cpustate->regptr);
231         state_fio->StateUint8(cpustate->psw);
232         state_fio->StateUint8(cpustate->p1);
233         state_fio->StateUint8(cpustate->p2);
234         state_fio->StateUint8(cpustate->timer);
235         state_fio->StateUint8(cpustate->prescaler);
236         state_fio->StateUint8(cpustate->t1_history);
237         state_fio->StateUint8(cpustate->sts);
238         state_fio->StateUint8(cpustate->int_state);
239         state_fio->StateUint8(cpustate->irq_state);
240         state_fio->StateUint8(cpustate->irq_in_progress);
241         state_fio->StateUint8(cpustate->timer_overflow);
242         state_fio->StateUint8(cpustate->timer_flag);
243         state_fio->StateUint8(cpustate->tirq_enabled);
244         state_fio->StateUint8(cpustate->xirq_enabled);
245         state_fio->StateUint8(cpustate->t0_clk_enabled);
246         state_fio->StateUint8(cpustate->timecount_enabled);
247         state_fio->StateUint16(cpustate->a11);
248         state_fio->StateInt32(cpustate->icount);
249         state_fio->StateBuffer(cpustate->rom, 0x1000, 1); // 0x100 ?
250         // END CPUREGS
251
252         if(loading) {
253                 mcs48_state *cpustate = (mcs48_state *)opaque;
254                 cpustate->mem = d_mem;
255                 cpustate->io = d_io;
256                 cpustate->intr = d_intr;
257 #ifdef USE_DEBUGGER
258                 prev_total_icount = total_icount;
259 #endif
260         }
261         return true;
262 }