2 Skelton for retropc emulator
5 Author : Takeda.Toshiya
13 #include "mcs48_flags.h"
19 /***************************************************************************
23 Intel MCS-48/UPI-41 Portable Emulator
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
29 ****************************************************************************
31 Note that the default internal divisor for this chip is by 3 and
32 then again by 5, or by 15 total.
34 ***************************************************************************/
36 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
37 #pragma warning( disable : 4244 )
40 /***************************************************************************
42 ***************************************************************************/
44 void MCS48::initialize()
47 opaque = calloc(1, sizeof(mcs48_state));
49 mcs48_state *cpustate = (mcs48_state *)opaque;
51 cpustate->mem = d_mem;
53 cpustate->intr = d_intr;
57 d_debugger->set_context_mem(d_mem);
58 d_debugger->set_context_io(d_io);
67 /***************************************************************************
69 ***************************************************************************/
72 /*-------------------------------------------------
73 burn_cycles - burn cycles, processing timers
75 -------------------------------------------------*/
77 void MCS48::burn_cycles(mcs48_state *cpustate, int count)
79 int timerover = FALSE;
81 /* output (clock*15/3) hz to t0 */
82 if (cpustate->t0_clk_enabled)
84 for(int i = 0; i < count * 5; i++)
91 /* if the timer is enabled, accumulate prescaler cycles */
92 if (cpustate->timecount_enabled & __MCS48_TIMER_ENABLED)
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);
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--)
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);
110 /* if either source caused a timer overflow, set the flags and check IRQs */
113 cpustate->timer_flag = TRUE;
115 /* according to the docs, if an overflow occurs with interrupts disabled, the overflow is not stored */
116 if (cpustate->tirq_enabled)
118 cpustate->timer_overflow = TRUE;
119 check_irqs(cpustate);
124 int MCS48::run(int icount)
126 mcs48_state *cpustate = (mcs48_state *)opaque;
130 cpustate->icount = 1;
132 cpustate->icount += icount;
133 if (cpustate->icount < 0) {
138 int base_icount = cpustate->icount;
140 update_regptr(cpustate);
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);
148 total_icount += curcycles * 15;
151 /* iterate over remaining cycles, guaranteeing at least one instruction */
155 bool now_debugging = d_debugger->now_debugging;
157 d_debugger->check_break_points(cpustate->pc);
158 if(d_debugger->now_suspended) {
160 d_debugger->now_waiting = true;
161 while(d_debugger->now_debugging && d_debugger->now_suspended) {
164 d_debugger->now_waiting = false;
166 if(d_debugger->now_debugging) {
167 d_mem = d_io = d_debugger;
169 now_debugging = false;
172 /* fetch next opcode */
173 cpustate->prevpc = cpustate->pc;
174 curcycles = op_call(cpustate);
176 /* burn the cycles */
177 cpustate->icount -= curcycles * 15;
178 if (cpustate->timecount_enabled != 0)
179 burn_cycles(cpustate, curcycles);
181 total_icount += curcycles * 15;
183 if(!d_debugger->now_going) {
184 d_debugger->now_suspended = true;
186 d_mem = d_mem_stored;
191 /* fetch next opcode */
192 d_debugger->add_cpu_trace(cpustate->pc);
193 cpustate->prevpc = cpustate->pc;
194 curcycles = op_call(cpustate);
196 /* burn the cycles */
197 cpustate->icount -= curcycles * 15;
198 if (cpustate->timecount_enabled != 0)
199 burn_cycles(cpustate, curcycles);
201 total_icount += curcycles * 15;
204 } while (cpustate->icount > 0);
206 return base_icount - cpustate->icount;
210 #define STATE_VERSION 3
212 bool MCS48::process_state(FILEIO* state_fio, bool loading)
214 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
217 if(!state_fio->StateCheckInt32(this_device_id)) {
221 state_fio->StateUint64(total_icount);
223 //state_fio->StateBuffer(opaque, sizeof(mcs48_state), 1);
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 ?
253 mcs48_state *cpustate = (mcs48_state *)opaque;
254 cpustate->mem = d_mem;
256 cpustate->intr = d_intr;
258 prev_total_icount = total_icount;