Previous 199869 Revisions Next

r19051 Monday 19th November, 2012 at 20:11:19 UTC by Sandro Ronco
(MESS) Added Sanyo LC8670 CPU core. [Sandro Ronco]
[src/emu/cpu]cpu.mak
[src/emu/cpu/lc8670]lc8670.c* lc8670.h* lc8670dsm.c*

trunk/src/emu/cpu/cpu.mak
r19050r19051
20372037
20382038$(CPUOBJ)/hd61700/hd61700.o:   $(CPUSRC)/hd61700/hd61700.c \
20392039                        $(CPUSRC)/hd61700/hd61700.h
2040
2041#-------------------------------------------------
2042# Sanyo LC8670
2043#-------------------------------------------------
2044
2045ifneq ($(filter LC8670,$(CPUS)),)
2046OBJDIRS += $(CPUOBJ)/lc8670
2047CPUOBJS += $(CPUOBJ)/lc8670/lc8670.o
2048DASMOBJS += $(CPUOBJ)/lc8670/lc8670dsm.o
2049endif
2050
2051$(CPUOBJ)/lc8670/lc8670.o:   $(CPUSRC)/lc8670/lc8670.c \
2052                     $(CPUSRC)/lc8670/lc8670.h
trunk/src/emu/cpu/lc8670/lc8670.c
r0r19051
1/******************************************************************************
2
3    Sanyo LC8670 "Potato" CPU core
4    by Sandro Ronco
5
6    Based on:
7    - Sega VMU hardware manual
8    - Sanyo LC86104C datasheet
9
10    TODO:
11    - SIO
12    - HOLD state
13
14******************************************************************************/
15
16#include "emu.h"
17#include "debugger.h"
18#include "lc8670.h"
19
20//***************************************************************************
21//    DEBUGGING
22//***************************************************************************
23
24#define LOG_TIMERS         0
25#define LOG_IRQ            0
26
27
28//**************************************************************************
29//  CONSTANTS
30//**************************************************************************
31
32const device_type LC8670 = &device_creator<lc8670_cpu_device>;
33
34
35//**************************************************************************
36//  MACROS
37//**************************************************************************
38
39// registers
40#define      REG_A      m_sfr[0x00]
41#define      REG_PSW      m_sfr[0x01]
42#define      REG_B      m_sfr[0x02]
43#define      REG_C      m_sfr[0x03]
44#define      REG_TRL      m_sfr[0x04]
45#define      REG_TRH      m_sfr[0x05]
46#define      REG_SP      m_sfr[0x06]
47#define      REG_PCON   m_sfr[0x07]
48#define      REG_IE      m_sfr[0x08]
49#define      REG_IP      m_sfr[0x09]
50#define      REG_EXT      m_sfr[0x0d]
51#define      REG_OCR      m_sfr[0x0e]
52#define      REG_T0CNT   m_sfr[0x10]
53#define      REG_T0PRR   m_sfr[0x11]
54#define      REG_T0LR   m_sfr[0x13]
55#define      REG_T0HR   m_sfr[0x15]
56#define      REG_T1CNT   m_sfr[0x18]
57#define      REG_T1LC   m_sfr[0x1a]
58#define      REG_T1LR   m_sfr[0x1b]
59#define      REG_T1HC   m_sfr[0x1c]
60#define      REG_T1HR   m_sfr[0x1d]
61#define      REG_MCR      m_sfr[0x20]
62#define      REG_STAD   m_sfr[0x22]
63#define      REG_CNR      m_sfr[0x23]
64#define      REG_TDR      m_sfr[0x24]
65#define      REG_XBNK   m_sfr[0x25]
66#define      REG_VCCR   m_sfr[0x27]
67#define      REG_SCON0   m_sfr[0x30]
68#define      REG_SBUF0   m_sfr[0x31]
69#define      REG_SBR      m_sfr[0x32]
70#define      REG_SCON1   m_sfr[0x34]
71#define      REG_SBUF1   m_sfr[0x35]
72#define      REG_P1      m_sfr[0x44]
73#define      REG_P1DDR   m_sfr[0x45]
74#define      REG_P1FCR   m_sfr[0x46]
75#define      REG_P3      m_sfr[0x4c]
76#define      REG_P3DDR   m_sfr[0x4d]
77#define      REG_P3INT   m_sfr[0x4e]
78#define      REG_FPR      m_sfr[0x54]
79#define      REG_I01CR   m_sfr[0x5d]
80#define      REG_I23CR   m_sfr[0x5e]
81#define      REG_ISL      m_sfr[0x5f]
82#define      REG_VSEL   m_sfr[0x63]
83#define      REG_VRMAD1   m_sfr[0x64]
84#define      REG_VRMAD2   m_sfr[0x65]
85#define      REG_BTCR   m_sfr[0x7f]
86
87// addressing modes
88#define      GET_D9      (((m_op & 0x01)<<8) | fetch())
89#define      GET_D9B3   (((m_op & 0x10)<<4) | fetch())
90#define      GET_I8      fetch()
91#define      GET_R8      fetch()
92#define      GET_RI      (m_op & 0x03)
93#define      GET_B3      (m_op & 0x07)
94#define      GET_A12      (((m_op & 0x10)<<7) | ((m_op & 0x07)<<8) | fetch())
95#define      SIGNED(v)   ((v) - (BIT(v,7) ? 0x100 : 0))
96
97// flags
98#define      FLAG_CY      0x80
99#define      FLAG_AC      0x40
100#define      FLAG_OV      0x04
101#define      FLAG_P      0x01
102#define      GET_CY      BIT(REG_PSW,7)
103#define      GET_AC      BIT(REG_PSW,6)
104#define      GET_OV      BIT(REG_PSW,2)
105#define      GET_P      BIT(REG_PSW,0)
106#define      SET_CY(v)   { if (v) REG_PSW |= FLAG_CY; else REG_PSW &= ~FLAG_CY; } while(0)
107#define      SET_AC(v)   { if (v) REG_PSW |= FLAG_AC; else REG_PSW &= ~FLAG_AC; } while(0)
108#define      SET_OV(v)   { if (v) REG_PSW |= FLAG_OV; else REG_PSW &= ~FLAG_OV; } while(0)
109#define      CHECK_P()   check_p_flag()
110
111// CPU state
112#define      HALT_MODE   0x01
113#define      HOLD_MODE   0x02
114
115
116//**************************************************************************
117//  Opcodes Table
118//**************************************************************************
119
120const lc8670_cpu_device::op_handler lc8670_cpu_device::s_opcode_table[] =
121{
122   &lc8670_cpu_device::op_nop  , &lc8670_cpu_device::op_br  , &lc8670_cpu_device::op_ld  , &lc8670_cpu_device::op_ld  , &lc8670_cpu_device::op_call,   // 0x0*
123   &lc8670_cpu_device::op_callr, &lc8670_cpu_device::op_brf , &lc8670_cpu_device::op_st  , &lc8670_cpu_device::op_st  , &lc8670_cpu_device::op_call,   // 0x1*
124   &lc8670_cpu_device::op_callf, &lc8670_cpu_device::op_jmpf, &lc8670_cpu_device::op_mov , &lc8670_cpu_device::op_mov , &lc8670_cpu_device::op_jmp,   // 0x2*
125   &lc8670_cpu_device::op_mul  , &lc8670_cpu_device::op_be  , &lc8670_cpu_device::op_be  , &lc8670_cpu_device::op_be_ri, &lc8670_cpu_device::op_jmp,   // 0x3*
126   &lc8670_cpu_device::op_div  , &lc8670_cpu_device::op_bne , &lc8670_cpu_device::op_bne , &lc8670_cpu_device::op_bne_ri, &lc8670_cpu_device::op_bpc,   // 0x4*
127   &lc8670_cpu_device::op_ldf  , &lc8670_cpu_device::op_stf , &lc8670_cpu_device::op_dbnz, &lc8670_cpu_device::op_dbnz, &lc8670_cpu_device::op_bpc,   // 0x5*
128   &lc8670_cpu_device::op_push , &lc8670_cpu_device::op_push, &lc8670_cpu_device::op_inc , &lc8670_cpu_device::op_inc , &lc8670_cpu_device::op_bp,      // 0x6*
129   &lc8670_cpu_device::op_pop  , &lc8670_cpu_device::op_pop , &lc8670_cpu_device::op_dec , &lc8670_cpu_device::op_dec , &lc8670_cpu_device::op_bp,      // 0x7*
130   &lc8670_cpu_device::op_bz   , &lc8670_cpu_device::op_add , &lc8670_cpu_device::op_add , &lc8670_cpu_device::op_add , &lc8670_cpu_device::op_bn,      // 0x8*
131   &lc8670_cpu_device::op_bnz  , &lc8670_cpu_device::op_addc, &lc8670_cpu_device::op_addc, &lc8670_cpu_device::op_addc, &lc8670_cpu_device::op_bn,      // 0x9*
132   &lc8670_cpu_device::op_ret  , &lc8670_cpu_device::op_sub , &lc8670_cpu_device::op_sub , &lc8670_cpu_device::op_sub , &lc8670_cpu_device::op_not1,   // 0xa*
133   &lc8670_cpu_device::op_reti , &lc8670_cpu_device::op_subc, &lc8670_cpu_device::op_subc, &lc8670_cpu_device::op_subc, &lc8670_cpu_device::op_not1,   // 0xb*
134   &lc8670_cpu_device::op_ror  , &lc8670_cpu_device::op_ldc , &lc8670_cpu_device::op_xch , &lc8670_cpu_device::op_xch , &lc8670_cpu_device::op_clr1,   // 0xc*
135   &lc8670_cpu_device::op_rorc , &lc8670_cpu_device::op_or  , &lc8670_cpu_device::op_or  , &lc8670_cpu_device::op_or  , &lc8670_cpu_device::op_clr1,   // 0xd*
136   &lc8670_cpu_device::op_rol  , &lc8670_cpu_device::op_and , &lc8670_cpu_device::op_and , &lc8670_cpu_device::op_and , &lc8670_cpu_device::op_set1,   // 0xe*
137   &lc8670_cpu_device::op_rolc , &lc8670_cpu_device::op_xor , &lc8670_cpu_device::op_xor , &lc8670_cpu_device::op_xor , &lc8670_cpu_device::op_set1,   // 0xf*
138};
139
140
141//**************************************************************************
142//  IRQ vectors
143//**************************************************************************
144
145const UINT16 lc8670_cpu_device::s_irq_vectors[] =
146{
147   0x0000, 0x0003, 0x000b, 0x0013, 0x001b, 0x0023, 0x002b, 0x0033,
148   0x003b, 0x0043, 0x004b, 0x004f, 0x0052, 0x0055, 0x005a, 0x005d
149};
150
151
152//**************************************************************************
153//  Internal memory map
154//**************************************************************************
155
156static ADDRESS_MAP_START( lc8670_internal_map, AS_DATA, 8, lc8670_cpu_device )
157   AM_RANGE(0x000, 0x0ff) AM_DEVREADWRITE(DEVICE_SELF, lc8670_cpu_device, mram_r, mram_w)
158   AM_RANGE(0x100, 0x17f) AM_DEVREADWRITE(DEVICE_SELF, lc8670_cpu_device, regs_r, regs_w)
159   AM_RANGE(0x180, 0x1ff) AM_DEVREADWRITE(DEVICE_SELF, lc8670_cpu_device, xram_r, xram_w)
160ADDRESS_MAP_END
161
162
163//**************************************************************************
164//  LC8670 DEVICE
165//**************************************************************************
166
167//-------------------------------------------------
168//  lc8670_cpu_device - constructor
169//-------------------------------------------------
170
171lc8670_cpu_device::lc8670_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
172   : cpu_device(mconfig, LC8670, "Sanyo LC8670", tag, owner, clock),
173     m_program_config("program", ENDIANNESS_BIG, 8, 16, 0),
174     m_data_config("data", ENDIANNESS_BIG, 8, 9, 0, ADDRESS_MAP_NAME(lc8670_internal_map)),
175     m_io_config("io", ENDIANNESS_BIG, 8, 8, 0),
176     m_bankswitch_func(*this)
177{
178}
179
180//-------------------------------------------------
181//  device_start - start up the device
182//-------------------------------------------------
183
184void lc8670_cpu_device::device_start()
185{
186   // find address spaces
187   m_program = &space(AS_PROGRAM);
188   m_data = &space(AS_DATA);
189   m_io = &space(AS_IO);
190   m_direct = &m_program->direct();
191
192   // set our instruction counter
193   m_icountptr = &m_icount;
194
195   // resolve callbacks
196   m_bankswitch_func.resolve();
197
198   // setup timers
199   m_basetimer = timer_alloc(BASE_TIMER);
200   m_basetimer->adjust(attotime::from_hz(m_clocks[LC8670_SUB_CLOCK]), 0, attotime::from_hz(m_clocks[LC8670_SUB_CLOCK]));
201   m_clocktimer = timer_alloc(CLOCK_TIMER);
202
203   // alloc internal RAM
204   m_sfr = auto_alloc_array(machine(), UINT8, 0x80);
205   m_mram = auto_alloc_array(machine(), UINT8, 0x200);
206   m_xram = auto_alloc_array(machine(), UINT8, 0xc6);
207   m_vtrbf = auto_alloc_array(machine(), UINT8, 0x200);
208
209   // register state for debugger
210   state_add(LC8670_PC  , "PC"  , m_pc).callimport().callexport().formatstr("%04X");
211   state_add(LC8670_SFR + 0x00, "A"     , REG_A     ).callimport().callexport().formatstr("%02X");
212   state_add(LC8670_SFR + 0x02, "B"     , REG_B     ).callimport().callexport().formatstr("%02X");
213   state_add(LC8670_SFR + 0x03, "C"     , REG_C     ).callimport().callexport().formatstr("%02X");
214   state_add(LC8670_SFR + 0x06, "SP"    , REG_SP    ).callimport().callexport().formatstr("%02X");
215   state_add(LC8670_SFR + 0x01, "PSW"   , REG_PSW   ).callimport().callexport().formatstr("%02X");
216   state_add(LC8670_SFR + 0x04, "TRL"   , REG_TRL   ).callimport().callexport().formatstr("%02X");
217   state_add(LC8670_SFR + 0x05, "TRH"   , REG_TRH   ).callimport().callexport().formatstr("%02X");
218   state_add(LC8670_SFR + 0x07, "PCON"  , REG_PCON  ).callimport().callexport().formatstr("%02X");
219   state_add(LC8670_SFR + 0x08, "IE"    , REG_IE    ).callimport().callexport().formatstr("%02X");
220   state_add(LC8670_SFR + 0x09, "IP"    , REG_IP    ).callimport().callexport().formatstr("%02X");
221   state_add(LC8670_SFR + 0x0d, "EXT"   , REG_EXT   ).callimport().callexport().formatstr("%02X");
222   state_add(LC8670_SFR + 0x0e, "OCR"   , REG_OCR   ).callimport().callexport().formatstr("%02X");
223   state_add(LC8670_SFR + 0x10, "T0CNT" , REG_T0CNT ).callimport().callexport().formatstr("%02X");
224   state_add(LC8670_SFR + 0x11, "T0PRR" , REG_T0PRR ).callimport().callexport().formatstr("%02X");
225   state_add(LC8670_SFR + 0x12, "T0L"   , m_timer0[0]).callimport().callexport().formatstr("%02X");
226   state_add(LC8670_SFR + 0x13, "T0LR"  , REG_T0LR  ).callimport().callexport().formatstr("%02X");
227   state_add(LC8670_SFR + 0x14, "T0H"   , m_timer0[1]).callimport().callexport().formatstr("%02X");
228   state_add(LC8670_SFR + 0x15, "T0HR"  , REG_T0HR  ).callimport().callexport().formatstr("%02X");
229   state_add(LC8670_SFR + 0x18, "T1CNT" , REG_T1CNT ).callimport().callexport().formatstr("%02X");
230   state_add(LC8670_SFR + 0x80, "T1L"   , m_timer1[0]).callimport().callexport().formatstr("%02X");
231   state_add(LC8670_SFR + 0x1a, "T1LC"  , REG_T1LC  ).callimport().callexport().formatstr("%02X");
232   state_add(LC8670_SFR + 0x1b, "T1LR"  , REG_T1LR  ).callimport().callexport().formatstr("%02X");
233   state_add(LC8670_SFR + 0x81, "T1H"   , m_timer1[1]).callimport().callexport().formatstr("%02X");
234   state_add(LC8670_SFR + 0x1c, "T1HC"  , REG_T1HC  ).callimport().callexport().formatstr("%02X");
235   state_add(LC8670_SFR + 0x1d, "T1HR"  , REG_T1HR  ).callimport().callexport().formatstr("%02X");
236   state_add(LC8670_SFR + 0x20, "MCR"   , REG_MCR   ).callimport().callexport().formatstr("%02X");
237   state_add(LC8670_SFR + 0x22, "STAD"  , REG_STAD  ).callimport().callexport().formatstr("%02X");
238   state_add(LC8670_SFR + 0x23, "CNR"   , REG_CNR   ).callimport().callexport().formatstr("%02X");
239   state_add(LC8670_SFR + 0x24, "TDR"   , REG_TDR   ).callimport().callexport().formatstr("%02X");
240   state_add(LC8670_SFR + 0x25, "XBNK"  , REG_XBNK  ).callimport().callexport().formatstr("%02X");
241   state_add(LC8670_SFR + 0x27, "VCCR"  , REG_VCCR  ).callimport().callexport().formatstr("%02X");
242   state_add(LC8670_SFR + 0x30, "SCON0" , REG_SCON0 ).callimport().callexport().formatstr("%02X");
243   state_add(LC8670_SFR + 0x31, "SBUF0" , REG_SBUF0 ).callimport().callexport().formatstr("%02X");
244   state_add(LC8670_SFR + 0x32, "SBR"   , REG_SBR   ).callimport().callexport().formatstr("%02X");
245   state_add(LC8670_SFR + 0x34, "SCON1" , REG_SCON1 ).callimport().callexport().formatstr("%02X");
246   state_add(LC8670_SFR + 0x35, "SBUF1" , REG_SBUF1 ).callimport().callexport().formatstr("%02X");
247   state_add(LC8670_SFR + 0x44, "P1"    , REG_P1    ).callimport().callexport().formatstr("%02X");
248   state_add(LC8670_SFR + 0x45, "P1DDR" , REG_P1DDR ).callimport().callexport().formatstr("%02X");
249   state_add(LC8670_SFR + 0x46, "P1FCR" , REG_P1FCR ).callimport().callexport().formatstr("%02X");
250   state_add(LC8670_SFR + 0x4c, "P3"    , REG_P3    ).callimport().callexport().formatstr("%02X");
251   state_add(LC8670_SFR + 0x4d, "P3DDR" , REG_P3DDR ).callimport().callexport().formatstr("%02X");
252   state_add(LC8670_SFR + 0x4e, "P3INT" , REG_P3INT ).callimport().callexport().formatstr("%02X");
253   state_add(LC8670_SFR + 0x54, "FPR"   , REG_FPR   ).callimport().callexport().formatstr("%02X");
254   state_add(LC8670_SFR + 0x5d, "I01CR" , REG_I01CR ).callimport().callexport().formatstr("%02X");
255   state_add(LC8670_SFR + 0x5e, "I23CR" , REG_I23CR ).callimport().callexport().formatstr("%02X");
256   state_add(LC8670_SFR + 0x5f, "ISL"   , REG_ISL   ).callimport().callexport().formatstr("%02X");
257   state_add(LC8670_SFR + 0x63, "VSEL"  , REG_VSEL  ).callimport().callexport().formatstr("%02X");
258   state_add(LC8670_SFR + 0x64, "VRMAD1", REG_VRMAD1).callimport().callexport().formatstr("%02X");
259   state_add(LC8670_SFR + 0x65, "VRMAD2", REG_VRMAD2).callimport().callexport().formatstr("%02X");
260   state_add(LC8670_SFR + 0x7f, "BTCR"  , REG_BTCR  ).callimport().callexport().formatstr("%02X");
261
262   state_add(STATE_GENPC, "curpc", m_pc).callimport().callexport().formatstr("%04X").noshow();
263   state_add(STATE_GENPCBASE, "curpcbase", m_ppc).callimport().callexport().formatstr("%4X").noshow();
264   state_add(STATE_GENFLAGS, "GENFLAGS",  REG_PSW).mask(0xff).formatstr("%7s").noshow();
265
266   // save state
267   save_pointer(NAME(m_sfr), 0x80);
268   save_pointer(NAME(m_mram), 0x200);
269   save_pointer(NAME(m_xram), 0xc6);
270   save_pointer(NAME(m_vtrbf), 0x200);
271   save_item(NAME(m_pc));
272   save_item(NAME(m_ppc));
273   save_item(NAME(m_op));
274   save_item(NAME(m_irq_flag));
275   save_item(NAME(m_irq_lev));
276   save_item(NAME(m_after_reti));
277   save_item(NAME(m_p1_data));
278   save_item(NAME(m_timer0_prescaler));
279   save_item(NAME(m_timer0));
280   save_item(NAME(m_timer1));
281   save_item(NAME(m_timer1_comparator));
282   save_item(NAME(m_base_timer));
283   save_item(NAME(m_clock_changed));
284   save_item(NAME(m_input_lines));
285}
286
287
288//-------------------------------------------------
289//  device_reset - reset up the device
290//-------------------------------------------------
291
292void lc8670_cpu_device::device_reset()
293{
294   m_pc = s_irq_vectors[0];
295   m_ppc = m_pc;
296   m_op = 0;
297   m_icount = 0;
298   m_irq_flag = 0;
299   m_irq_lev = 0;
300   m_after_reti = false;
301   m_p1_data = 0;
302   m_timer0_prescaler = 0;
303   m_timer0[0] = m_timer0[1] = 0;
304   m_timer1[0] = m_timer1[1] = 0;
305   m_timer1_comparator[0] = m_timer1_comparator[1] = 0;
306   m_base_timer[0] = m_base_timer[1] = 0;
307   m_clock_changed = false;
308   memset(m_sfr, 0, 0x80);
309   memset(m_mram, 0, 0x200);
310   memset(m_xram, 0, 0xc6);
311   memset(m_vtrbf, 0, 0x200);
312
313   // default values from VMU hardware manual
314   REG_P1FCR = 0xbf;
315   REG_P3INT = 0xfd;
316   REG_ISL = 0xc0;
317   REG_VSEL = 0xfc;
318   REG_BTCR = 0x41;
319
320   // reset bankswitch and clock source
321   m_bankswitch_func(0);
322   change_clock_source();
323}
324
325
326//-------------------------------------------------
327//  device_timer - handler timer events
328//-------------------------------------------------
329
330void lc8670_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
331{
332   switch(id)
333   {
334      case BASE_TIMER:
335         if (!(REG_ISL & 0x10))
336            base_timer_tick();
337         break;
338
339      case CLOCK_TIMER:
340         timer0_prescaler_tick();
341         timer1_tick();
342
343         if ((REG_ISL & 0x30) == 0x10)
344            base_timer_tick();
345         break;
346   }
347}
348
349
350//-------------------------------------------------
351//  state_import - import state into the device,
352//  after it has been set
353//-------------------------------------------------
354
355void lc8670_cpu_device::state_import(const device_state_entry &entry)
356{
357   switch (entry.index())
358   {
359      case STATE_GENPC:
360         set_pc(m_pc);
361         break;
362   }
363}
364
365
366//-------------------------------------------------
367//  state_string_export - export state as a string
368//  for the debugger
369//-------------------------------------------------
370
371void lc8670_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
372{
373   switch (entry.index())
374   {
375      case STATE_GENFLAGS:
376         string.printf("%s%s%s%s",
377            GET_CY ? "CY" : "..",
378            GET_AC ? "AC" : "..",
379            GET_OV ? "OV" : "..",
380            GET_P  ? "P"  : "."
381         );
382         break;
383   }
384}
385
386
387//-------------------------------------------------
388//  memory_space_config - return the configuration
389//  of the specified address space, or NULL if
390//  the space doesn't exist
391//-------------------------------------------------
392
393const address_space_config * lc8670_cpu_device::memory_space_config(address_spacenum spacenum) const
394{
395   return   (spacenum == AS_PROGRAM) ? &m_program_config :
396         (spacenum == AS_DATA) ? &m_data_config :
397         (spacenum == AS_IO) ? &m_io_config :
398         NULL;
399}
400
401//-------------------------------------------------
402//  execute - execute for the provided number of
403//  countcles
404//-------------------------------------------------
405
406void lc8670_cpu_device::execute_run()
407{
408   if (m_clock_changed)
409   {
410      change_clock_source();
411      return;
412   }
413
414   do
415   {
416      check_irqs();
417
418      debugger_instruction_hook(this, m_pc);
419
420      int cycles = 0;
421      m_ppc = m_pc;
422
423      if (REG_PCON & HALT_MODE)
424      {
425         // in HALT state the timers are still updated
426         cycles = 1;
427      }
428      else
429      {
430         // instruction fetch
431         m_op = fetch();
432         int op_idx = decode_op(m_op);
433
434         // execute the instruction
435         cycles = (this->*s_opcode_table[op_idx])();
436      }
437
438      // update the instruction counter
439      m_icount -= cycles;
440   }
441   while (m_icount > 0 && !m_clock_changed);
442}
443
444
445//-------------------------------------------------
446//  execute_set_input
447//-------------------------------------------------
448
449void lc8670_cpu_device::execute_set_input(int inputnum, int state)
450{
451   switch(inputnum)
452   {
453      case LC8670_EXT_INT0:
454         if ((REG_I01CR & 0x0c) == 0x00 && m_input_lines[inputnum] && !state)      // falling edge
455         {
456            REG_I01CR |= 0x02;
457            if (REG_I01CR & 0x01)
458               set_irq_flag(1);
459         }
460         else if ((REG_I01CR & 0x0c) == 0x04 && !state)      // low level
461         {
462            REG_I01CR |= 0x02;
463            if (REG_I01CR & 0x01)
464               set_irq_flag(1);
465         }
466         else if ((REG_I01CR & 0x0c) == 0x08 && !m_input_lines[inputnum] && state)      // rising edge
467         {
468            REG_I01CR |= 0x02;
469            if (REG_I01CR & 0x01)
470               set_irq_flag(1);
471         }
472         else if ((REG_I01CR & 0x0c) == 0x0c && state)      // high level
473         {
474            REG_I01CR |= 0x02;
475            if (REG_I01CR & 0x01)
476               set_irq_flag(1);
477         }
478         break;
479      case LC8670_EXT_INT1:
480         if ((REG_I01CR & 0xc0) == 0x00 && m_input_lines[inputnum] && !state)      // falling edge
481         {
482            REG_I01CR |= 0x20;
483            if (REG_I01CR & 0x10)
484               set_irq_flag(2);
485         }
486         else if ((REG_I01CR & 0xc0) == 0x40 && !state)      // low level
487         {
488            REG_I01CR |= 0x20;
489            if (REG_I01CR & 0x10)
490               set_irq_flag(2);
491         }
492         else if ((REG_I01CR & 0xc0) == 0x80 && !m_input_lines[inputnum] && state)      // rising edge
493         {
494            REG_I01CR |= 0x20;
495            if (REG_I01CR & 0x10)
496               set_irq_flag(2);
497         }
498         else if ((REG_I01CR & 0xc0) == 0xc0 && state)      // high level
499         {
500            REG_I01CR |= 0x20;
501            if (REG_I01CR & 0x10)
502               set_irq_flag(2);
503         }
504         break;
505      case LC8670_EXT_INT2:
506         if ((REG_I23CR & 0x04) && m_input_lines[inputnum] && !state)   // falling edge
507         {
508            if (!(REG_ISL & 0x01))
509               timer0_tick(true);
510
511            REG_I23CR |= 0x02;
512            if (REG_I23CR & 0x01)
513               set_irq_flag(3);
514         }
515         if ((REG_I23CR & 0x08) && !m_input_lines[inputnum] && state)   // rising edge
516         {
517            if (!(REG_ISL & 0x01))
518               timer0_tick(true);
519
520            REG_I23CR |= 0x02;
521            if (REG_I23CR & 0x01)
522               set_irq_flag(3);
523         }
524         break;
525      case LC8670_EXT_INT3:
526         if ((REG_I23CR & 0x40) && m_input_lines[inputnum] && !state)   // falling edge
527         {
528            if (REG_ISL & 0x01)
529               timer0_tick(true);
530
531            REG_I23CR |= 0x20;
532            if (REG_I23CR & 0x10)
533               set_irq_flag(4);
534         }
535         if ((REG_I23CR & 0x80) && !m_input_lines[inputnum] && state)   // rising edge
536         {
537            if (REG_ISL & 0x01)
538               timer0_tick(true);
539
540            REG_I23CR |= 0x20;
541            if (REG_I23CR & 0x10)
542               set_irq_flag(4);
543         }
544         break;
545   }
546
547   m_input_lines[inputnum] = state;
548}
549
550
551//-------------------------------------------------
552//  screen_update - handle updating the screen
553//-------------------------------------------------
554
555UINT32 lc8670_cpu_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
556{
557   if (m_lcd_update_func)
558      return m_lcd_update_func(*this, bitmap, cliprect, m_xram, (REG_MCR & 0x08) && (REG_VCCR & 0x80), REG_STAD);
559
560   return 0;
561}
562
563
564//-------------------------------------------------
565//  check_irqs - check for interrupts request
566//-------------------------------------------------
567
568void lc8670_cpu_device::check_irqs()
569{
570   // update P3 interrupt
571   check_p3int();
572
573   if (m_irq_flag && !m_after_reti)
574   {
575      int irq = 0;
576      UINT8 priority = 0;
577
578      // highest priority IRQ
579      if (!(REG_IE & 0x01) && (m_irq_flag & 0x02))
580      {
581         irq = 0x01;
582         priority = 2;
583      }
584      else if (!(REG_IE & 0x02) && (m_irq_flag & 0x04))
585      {
586         irq = 0x02;
587         priority = 2;
588      }
589
590      // high priority IRQ
591      else if ((REG_IE & 0x80) && ((REG_IP<<3) & m_irq_flag))
592      {
593         for(int i=3; i<=10; i++)
594            if ((m_irq_flag & (REG_IP<<3)) & (1<<i))
595            {
596               irq = i;
597               priority = 1;
598               break;
599            }
600      }
601
602      // low priority IRQ
603      else if ((REG_IE & 0x80) && (m_irq_flag & 0x02))
604      {
605         irq = 0x01;
606         priority = 0;
607      }
608      else if ((REG_IE & 0x80) && (m_irq_flag & 0x04))
609      {
610         irq = 0x02;
611         priority = 0;
612      }
613      else if (REG_IE & 0x80)
614      {
615         for(int i=3; i<=10; i++)
616            if (m_irq_flag & (1<<i))
617            {
618               irq = i;
619               priority = 0;
620               break;
621            }
622      }
623
624      // IRQ with less priority of current interrupt are not executed until the end of the current interrupt routine
625      if (irq != 0 && ((m_irq_lev & (1<<priority)) || (priority == 0 && (m_irq_lev & 0x06)) || (priority == 1 && (m_irq_lev & 0x04))))
626      {
627         if (LOG_IRQ)   logerror("%s: interrupt %d (Priority=%d, Level=%d) delayed\n", tag(), irq, priority, m_irq_lev);
628         irq = 0;
629      }
630
631      if (irq != 0)
632      {
633         if (LOG_IRQ)   logerror("%s: interrupt %d (Priority=%d, Level=%d) executed\n", tag(), irq, priority, m_irq_lev);
634
635         m_irq_lev |= (1<<priority);
636
637         push((m_pc>>0) & 0xff);
638         push((m_pc>>8) & 0xff);
639
640         set_pc(s_irq_vectors[irq]);
641
642         REG_PCON &= ~HALT_MODE;      // interrupts resume from HALT state
643
644         // clear the IRQ flag
645         m_irq_flag &= ~(1<<irq);
646
647         standard_irq_callback(irq);
648      }
649   }
650
651   // at least one opcode need to be executed after a RETI before another IRQ can be accepted
652   m_after_reti = false;
653}
654
655
656//-------------------------------------------------
657//  base_timer_tick - update base timer
658//-------------------------------------------------
659
660void lc8670_cpu_device::base_timer_tick()
661{
662   if (REG_BTCR & 0x40)
663   {
664      UINT16 base_counter_l = m_base_timer[0] + 1;
665      UINT16 base_counter_h = m_base_timer[1];
666
667      if (REG_BTCR & 0x80)   // 6-bit mode
668         base_counter_h++;
669      else if (base_counter_l & 0x100)
670         base_counter_h++;
671
672      if (base_counter_h & 0x40)
673      {
674         if (LOG_TIMERS)   logerror("%s: base timer 0 overflow, IRQ: %d\n", tag(), BIT(REG_BTCR,0));
675         REG_BTCR |= 0x02;
676         if (REG_BTCR & 0x01)
677            set_irq_flag(4);
678      }
679
680      bool bt1_req = false;
681      switch(REG_BTCR & 0x30)
682      {
683         case 0x00:
684            if (base_counter_l & 0x20)
685               bt1_req = true;
686            break;
687         case 0x10:
688            if (base_counter_l & 0x80)
689               bt1_req = true;
690            break;
691         case 0x20:
692            if (base_counter_h & 0x01)
693               bt1_req = true;
694            break;
695         case 0x30:
696            if (base_counter_h & 0x04)
697               bt1_req = true;
698            break;
699      }
700
701      if (bt1_req)
702      {
703         if (LOG_TIMERS)   logerror("%s: base timer 1 overflow, IRQ: %d\n", tag(), BIT(REG_BTCR,3));
704         REG_BTCR |= 0x08;
705         if (REG_BTCR & 0x04)
706            set_irq_flag(4);
707      }
708
709      if (((base_counter_l & 0x04) && (REG_ISL & 0x08)) || ((base_counter_l & 0x08) && !(REG_ISL & 0x08)))
710         update_port1(m_p1_data | 0x40);
711      else
712         update_port1(m_p1_data & 0xbf);
713
714      m_base_timer[0] = base_counter_l & 0xff;
715      m_base_timer[1] = base_counter_h & 0x3f;
716   }
717}
718
719//-------------------------------------------------
720//  update_to_prescaler - update timer 0 prescaler
721//-------------------------------------------------
722
723void lc8670_cpu_device::timer0_prescaler_tick()
724{
725   UINT16 prescaler = m_timer0_prescaler + 1;
726   if (prescaler & 0x100)
727   {
728      if (LOG_TIMERS)   logerror("%s: timer0 prescaler overflow\n", tag());
729
730      if ((REG_ISL & 0x30) == 0x30)
731         base_timer_tick();
732
733      timer0_tick();
734
735      m_timer0_prescaler = REG_T0PRR;
736   }
737   else
738   {
739      m_timer0_prescaler = prescaler & 0xff;
740   }
741}
742
743//-------------------------------------------------
744//  timer0_tick - update timer 0
745//-------------------------------------------------
746
747void lc8670_cpu_device::timer0_tick(bool ext_line)
748{
749   if (REG_T0CNT & 0xc0)
750   {
751      if (REG_T0CNT & 0x20)
752      {
753         // 16-bit timer/counter mode
754         if ((REG_T0CNT & 0xc0) == 0xc0 && (((REG_T0CNT & 0x10) && ext_line) || (!(REG_T0CNT & 0x10) && !ext_line)))
755         {
756            UINT32 timer0 = ((m_timer0[1] << 8) | m_timer0[0]) + 1;
757
758            if (timer0 & 0x10000)
759            {
760               if (LOG_TIMERS)   logerror("%s: timer0 long overflow, IRQ: %d\n", tag(), BIT(REG_T0CNT,3));
761               m_timer0[0] = REG_T0LR;
762               m_timer0[1] = REG_T0HR;
763               REG_T0CNT |= 0x0a;
764               if (REG_T0CNT & 0x04)
765                  set_irq_flag(5);
766            }
767            else
768            {
769               m_timer0[0] = (timer0>>0) & 0xff;
770               m_timer0[1] = (timer0>>8) & 0xff;
771            }
772         }
773      }
774      else
775      {
776         // 8-bit timer/counter mode
777         if ((REG_T0CNT & 0x40) && (((REG_T0CNT & 0x10) && ext_line) || (!(REG_T0CNT & 0x10) && !ext_line)))
778         {
779            UINT16 timer0l = m_timer0[0] + 1;
780
781            if (timer0l & 0x100)
782            {
783               if (LOG_TIMERS)   logerror("%s: timer0 low overflow, IRQ: %d\n", tag(), BIT(REG_T0CNT,0));
784               m_timer0[0] = REG_T0LR;
785               REG_T0CNT |= 0x02;
786               if (REG_T0CNT & 0x01)
787                  set_irq_flag(3);
788            }
789            else
790            {
791               m_timer0[0]  = timer0l & 0xff;
792            }
793         }
794         if ((REG_T0CNT & 0x80)  && !ext_line)
795         {
796            UINT16 timer0h = m_timer0[1] + 1;
797            if (timer0h & 0x100)
798            {
799               if (LOG_TIMERS)   logerror("%s: timer0 high overflow, IRQ: %d\n", tag(), BIT(REG_T0CNT,3));
800               m_timer0[1] = REG_T0HR;
801               REG_T0CNT |= 0x08;
802               if (REG_T0CNT & 0x04)
803                  set_irq_flag(5);
804            }
805            else
806            {
807               m_timer0[1]  = timer0h & 0xff;
808            }
809         }
810      }
811   }
812}
813
814//-------------------------------------------------
815//  timer1_tick - update timer 1
816//-------------------------------------------------
817
818void lc8670_cpu_device::timer1_tick()
819{
820   if (REG_T1CNT & 0xc0)
821   {
822      if (REG_T1CNT & 0x20)
823      {
824         if (REG_T1CNT & 0x40)
825         {
826            // 16-bit timer mode
827            UINT16 timer1l = m_timer1[0] + (REG_T1CNT & 0x80 ? 1 : 2);
828            if (timer1l & 0x100)
829            {
830               UINT16 timer1h = m_timer1[1] + 1;
831               m_timer1[0] = REG_T1LR;
832               REG_T1CNT |= 0x04;
833
834               if (timer1h & 0x100)
835               {
836                  if (LOG_TIMERS)   logerror("%s: timer1 long overflow, IRQ: %d\n", tag(), BIT(REG_T1CNT,3));
837                  m_timer1[1] = REG_T1HR;
838                  REG_T1CNT |= 0x08;
839                  if (REG_T1CNT & 0x05)
840                     set_irq_flag(6);
841               }
842               else
843               {
844                  m_timer1[1] = timer1h & 0xff;
845               }
846            }
847            else
848            {
849               m_timer1[0]  = timer1l & 0xff;
850            }
851         }
852      }
853      else
854      {
855         // 8-bit timer/pulse generator mode
856         if (REG_T1CNT & 0x40)
857         {
858            UINT16 timer1l = m_timer1[0] + 1;
859
860            if (timer1l == m_timer1_comparator[0])
861               update_port1(m_p1_data | 0x80);
862
863            if (timer1l & 0x100)
864            {
865               if (LOG_TIMERS)   logerror("%s: timer1 low overflow, IRQ: %d\n", tag(), BIT(REG_T1CNT,0));
866               m_timer1[0] = REG_T1LR;
867               update_port1(m_p1_data & 0x7f);
868               REG_T1CNT |= 0x02;
869               if (REG_T1CNT & 0x01)
870                  set_irq_flag(6);
871            }
872            else
873            {
874               m_timer1[0] = timer1l & 0xff;
875            }
876         }
877         if (REG_T1CNT & 0x80)
878         {
879            UINT16 timer1h = m_timer1[1] + 1;
880
881            if (timer1h & 0x100)
882            {
883               if (LOG_TIMERS)   logerror("%s: timer1 high overflow, IRQ: %d\n", tag(), BIT(REG_T1CNT,3));
884               m_timer1[1] = REG_T1HR;
885               REG_T1CNT |= 0x08;
886               if (REG_T1CNT & 0x04)
887                  set_irq_flag(6);
888            }
889            else
890            {
891               m_timer1[1] = timer1h & 0xff;
892            }
893         }
894      }
895   }
896}
897
898
899//**************************************************************************
900//  internal map handlers
901//**************************************************************************
902
903READ8_MEMBER(lc8670_cpu_device::mram_r)
904{
905   return m_mram[BIT(REG_PSW,1)*0x100 + offset];
906}
907
908WRITE8_MEMBER(lc8670_cpu_device::mram_w)
909{
910   m_mram[BIT(REG_PSW,1)*0x100 + offset] = data;
911}
912
913READ8_MEMBER(lc8670_cpu_device::xram_r)
914{
915   if (!(REG_VCCR & 0x40) || space.debugger_access())   // XRAM access enabled
916   {
917      UINT8 * xram_bank = m_xram + (REG_XBNK & 0x03) * 0x60;
918
919      switch(REG_XBNK & 0x03)
920      {
921         case 0:
922         case 1:
923            if ((offset & 0x0f) < 0x0c)
924               return xram_bank[(offset>>4) * 0x0c + (offset & 0x0f)];
925            break;
926         case 2:
927            if (offset < 0x06)
928               return xram_bank[offset];
929            break;
930      }
931   }
932
933   return 0xff;
934}
935
936WRITE8_MEMBER(lc8670_cpu_device::xram_w)
937{
938   if (!(REG_VCCR & 0x40) || space.debugger_access())   // XRAM access enabled
939   {
940      UINT8 * xram_bank = m_xram + (REG_XBNK & 0x03) * 0x60;
941
942      switch(REG_XBNK & 0x03)
943      {
944         case 0:
945         case 1:
946            if ((offset & 0x0f) < 0x0c)
947               xram_bank[(offset>>4) * 0x0c + (offset & 0x0f)] = data;
948            break;
949         case 2:
950            if (offset < 0x06)
951               xram_bank[offset] = data;
952            break;
953      }
954   }
955}
956
957READ8_MEMBER(lc8670_cpu_device::regs_r)
958{
959   switch(offset)
960   {
961      case 0x12:
962         return m_timer0[0];
963      case 0x14:
964         return m_timer0[1];
965      case 0x1b:
966         return m_timer1[0];
967      case 0x1d:
968         return m_timer1[1];
969      case 0x44:
970         return (REG_P1 & REG_P1DDR) | (m_io->read_byte(LC8670_PORT1) & (REG_P1DDR ^ 0xff));
971      case 0x4c:
972         return (REG_P3 & REG_P3DDR) | (m_io->read_byte(LC8670_PORT3) & (REG_P3DDR ^ 0xff));
973      case 0x5c:
974         return m_io->read_byte(LC8670_PORT7) | 0xf0;   // 4-bit read-only port
975      case 0x66:
976      {
977         UINT8 data = m_vtrbf[((REG_VRMAD2<<8) | REG_VRMAD1) & 0x1ff];
978         if (!space.debugger_access() && (REG_VSEL & 0x10))
979         {
980            UINT16 vrmad = (REG_VRMAD1 | (REG_VRMAD2<<8)) + 1;
981            REG_VRMAD1 = vrmad & 0xff;
982            REG_VRMAD2 = (vrmad >> 8) & 0x01;
983         }
984         return data;
985      }
986
987      // write-only registers
988      case 0x20: case 0x23: case 0x24: case 0x27:
989      case 0x45: case 0x46: case 0x4d:
990         if(!space.debugger_access())   logerror("%s: read write-only SFR %04x\n", machine().describe_context(), offset);
991         return 0xff;
992   }
993   return m_sfr[offset];
994}
995
996WRITE8_MEMBER(lc8670_cpu_device::regs_w)
997{
998   switch(offset)
999   {
1000      case 0x00:
1001         REG_A = data;
1002         CHECK_P();
1003         break;
1004      case 0x07:
1005         if (data & HOLD_MODE)
1006            fatalerror("%s: unemulated HOLD mode\n", machine().describe_context());
1007         break;
1008      case 0x10:
1009         if (!(data & 0x80))
1010            m_timer0[1] = REG_T0HR;
1011         if (!(data & 0x40))
1012            m_timer0[0] = REG_T0LR;
1013         break;
1014      case 0x18:
1015         if ((data & 0x10) && !(REG_T1CNT & 0x10))
1016         {
1017            m_timer1_comparator[0] = REG_T1LC;
1018            m_timer1_comparator[1] = REG_T1HC;
1019         }
1020         if (!(data & 0x80))
1021            m_timer1[1] = REG_T1HR;
1022         if (!(data & 0x40))
1023            m_timer1[0] = REG_T1LR;
1024         break;
1025      case 0x1a:
1026         if ((REG_T1CNT & 0x10) || !(REG_T1CNT & 0x40))
1027            m_timer1_comparator[0] = data;
1028         break;
1029      case 0x1c:
1030         if ((REG_T1CNT & 0x10) || !(REG_T1CNT & 0x80))
1031            m_timer1_comparator[1] = data;
1032         break;
1033      case 0x0e:
1034         if ((data ^ REG_OCR) & 0xb0)
1035            m_clock_changed = true;
1036         break;
1037      case 0x44:
1038         m_io->write_byte(LC8670_PORT1, ((data | (m_p1_data & REG_P1FCR)) & REG_P1DDR) | (m_io->read_byte(LC8670_PORT1) & (REG_P1DDR ^ 0xff)));
1039         break;
1040      case 0x4c:
1041         m_io->write_byte(LC8670_PORT3, (data & REG_P3DDR) | (m_io->read_byte(LC8670_PORT3) & (REG_P3DDR ^ 0xff)));
1042         break;
1043      case 0x66:
1044         m_vtrbf[((REG_VRMAD2<<8) | REG_VRMAD1) & 0x1ff] = data;
1045         if (!space.debugger_access() && (REG_VSEL & 0x10))
1046         {
1047            UINT16 vrmad = (REG_VRMAD1 | (REG_VRMAD2<<8)) + 1;
1048            REG_VRMAD1 = vrmad & 0xff;
1049            REG_VRMAD2 = (vrmad >> 8) & 0x01;
1050         }
1051         break;
1052      case 0x7f:
1053         if (!(data & 0x40))
1054            m_base_timer[0] = m_base_timer[1] = 0;   // stop the timer clear the counter
1055         break;
1056
1057      // read-only registers
1058      case 0x12: case 0x14: case 0x5c:
1059         if(!space.debugger_access())   logerror("%s: write read-only SFR %04x = %02x\n", machine().describe_context(), offset, data);
1060         return;
1061   }
1062
1063   m_sfr[offset] = data;
1064}
1065
1066
1067//**************************************************************************
1068//  HELPERS
1069//**************************************************************************
1070
1071inline UINT8 lc8670_cpu_device::fetch()
1072{
1073   UINT8 data = m_direct->read_decrypted_byte(m_pc);
1074
1075   set_pc(m_pc + 1);
1076
1077   return data;
1078}
1079
1080inline UINT8 lc8670_cpu_device::read_data(UINT16 offset)
1081{
1082   return m_data->read_byte(offset);
1083}
1084
1085inline void lc8670_cpu_device::write_data(UINT16 offset, UINT8 data)
1086{
1087   m_data->write_byte(offset, data);
1088}
1089
1090inline UINT8 lc8670_cpu_device::read_data_latch(UINT16 offset)
1091{
1092   if (offset == 0x144)
1093      return REG_P1;
1094   else if (offset == 0x14c)
1095      return REG_P3;
1096   else
1097      return read_data(offset);
1098}
1099
1100inline void lc8670_cpu_device::write_data_latch(UINT16 offset, UINT8 data)
1101{
1102   if (offset == 0x144)
1103      REG_P1 = data;
1104   else if (offset == 0x14c)
1105      REG_P3 = data;
1106   else
1107      write_data(offset, data);
1108}
1109
1110inline void lc8670_cpu_device::update_port1(UINT8 data)
1111{
1112   m_p1_data = data;
1113   m_io->write_byte(LC8670_PORT1, ((REG_P1 | (m_p1_data & REG_P1FCR)) & REG_P1DDR) | (m_io->read_byte(LC8670_PORT1) & (REG_P1DDR ^ 0xff)));
1114}
1115
1116inline void lc8670_cpu_device::set_pc(UINT16 new_pc)
1117{
1118   m_pc = new_pc;
1119}
1120
1121inline void lc8670_cpu_device::push(UINT8 data)
1122{
1123   REG_SP++;
1124   m_mram[REG_SP] = data;
1125}
1126
1127inline UINT8 lc8670_cpu_device::pop()
1128{
1129   UINT8 data =  m_mram[REG_SP];
1130   REG_SP--;
1131   return data;
1132}
1133
1134inline UINT16 lc8670_cpu_device::get_addr()
1135{
1136   int mode = m_op & 0x0f;
1137   UINT16 addr = 0;
1138
1139   if (mode > 0x01 && mode <= 0x03)
1140      addr = GET_D9;
1141   else if (mode > 0x03 && mode <= 0x07)
1142      addr = read_data(GET_RI | ((REG_PSW>>1) & 0x0c)) | ((GET_RI & 0x02) ? 0x100 : 0x00);
1143   else
1144      fatalerror("%s: invalid get_addr in mode %x\n", machine().describe_context(), mode);
1145
1146   return addr;
1147}
1148
1149inline UINT8 lc8670_cpu_device::get_data()
1150{
1151   int mode = m_op & 0x0f;
1152   UINT8 data = 0;
1153
1154   if (mode == 0x01)
1155      data = GET_I8;
1156   else
1157      data = read_data(get_addr());
1158
1159   return data;
1160}
1161
1162inline void lc8670_cpu_device::change_clock_source()
1163{
1164   UINT32 new_clock = 0;
1165
1166   switch(REG_OCR & 0x30)
1167   {
1168      case 0x00:
1169         new_clock = m_clocks[LC8670_RC_CLOCK];
1170         break;
1171      case 0x20:
1172         new_clock = m_clocks[LC8670_SUB_CLOCK];
1173         break;
1174      case 0x10:
1175      case 0x30:
1176         new_clock = m_clocks[LC8670_CF_CLOCK];
1177         break;
1178   }
1179
1180   set_unscaled_clock(new_clock);
1181   set_clock_scale(1.0 / (REG_OCR & 0x80 ? 6.0 : 12.0));
1182   m_clocktimer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
1183   m_clock_changed = false;
1184}
1185
1186inline void lc8670_cpu_device::check_p_flag()
1187{
1188   UINT8 p_plag = 0;
1189   for(int i=0; i<8; i++)
1190      p_plag ^= BIT(REG_A, i);
1191
1192   if (p_plag)
1193      REG_PSW |= FLAG_P;
1194   else
1195      REG_PSW &= ~FLAG_P;
1196}
1197
1198inline void lc8670_cpu_device::check_p3int()
1199{
1200   if (REG_P3INT & 0x04)
1201   {
1202      if ((m_io->read_byte(LC8670_PORT3) ^ 0xff) & (REG_P3DDR ^ 0xff) & REG_P3)
1203      {
1204         REG_P3INT |= 0x02;
1205         if (REG_P3INT & 0x01)
1206            set_irq_flag(10);
1207      }
1208   }
1209}
1210
1211inline void lc8670_cpu_device::set_irq_flag(int source)
1212{
1213   if (LOG_IRQ)   logerror("%s: set interrupt flag: %d\n", tag(), source);
1214   m_irq_flag |= 1<<source;
1215}
1216
1217int lc8670_cpu_device::decode_op(UINT8 op)
1218{
1219   int idx = 0;
1220   switch (op & 0x0f)
1221   {
1222      case 0: case 1:
1223         idx =  op & 0x0f;
1224         break;
1225      case 2: case 3:
1226         idx = 2;
1227         break;
1228      case 4: case 5: case 6: case 7:
1229         idx = 3;
1230         break;
1231      default:
1232         idx = 4;
1233         break;
1234   }
1235
1236   return ((op>>4) & 0x0f) * 5 + idx;
1237}
1238
1239//**************************************************************************
1240//  Opcodes
1241//**************************************************************************
1242
1243int lc8670_cpu_device::op_nop()
1244{
1245   return 1;
1246}
1247
1248int lc8670_cpu_device::op_br()
1249{
1250   UINT8 r8 = GET_R8;
1251   set_pc(m_pc + SIGNED(r8));
1252
1253   return 2;
1254}
1255
1256int lc8670_cpu_device::op_ld()
1257{
1258   REG_A = get_data();
1259   CHECK_P();
1260
1261   return 1;
1262}
1263
1264int lc8670_cpu_device::op_call()
1265{
1266   UINT16 new_pc = GET_A12;
1267
1268   push((m_pc>>0) & 0xff);
1269   push((m_pc>>8) & 0xff);
1270
1271   set_pc((m_pc & 0xf000) | new_pc);
1272
1273   return 2;
1274}
1275
1276
1277int lc8670_cpu_device::op_callr()
1278{
1279   UINT16 r16 = fetch();
1280   r16 |= fetch()<<8;
1281
1282   push((m_pc>>0) & 0xff);
1283   push((m_pc>>8) & 0xff);
1284   set_pc(m_pc - 1 + r16);
1285
1286   return 4;
1287}
1288
1289int lc8670_cpu_device::op_brf()
1290{
1291   UINT16 r16 = fetch();
1292   r16 |= fetch()<<8;
1293   set_pc(m_pc - 1 + r16);
1294
1295   return 4;
1296}
1297
1298int lc8670_cpu_device::op_st()
1299{
1300   write_data(get_addr(), REG_A);
1301
1302   return 1;
1303}
1304
1305int lc8670_cpu_device::op_callf()
1306{
1307   UINT16 a16 = fetch()<<8;
1308   a16 |= fetch();
1309
1310   push((m_pc>>0) & 0xff);
1311   push((m_pc>>8) & 0xff);
1312   set_pc(a16);
1313
1314   return 2;
1315}
1316
1317int lc8670_cpu_device::op_jmpf()
1318{
1319   UINT16 a16 = fetch()<<8;
1320   a16 |= fetch();
1321   set_pc(a16);
1322
1323   m_bankswitch_func(((REG_EXT & 0x01) ? 1 : (REG_EXT & 0x08) ? 0 : 2));
1324
1325   return 2;
1326}
1327
1328int lc8670_cpu_device::op_mov()
1329{
1330   UINT16 addr = get_addr();
1331   UINT8 i8 = GET_I8;
1332   write_data(addr, i8);
1333
1334   return 1;
1335}
1336
1337int lc8670_cpu_device::op_jmp()
1338{
1339   UINT16 new_pc = GET_A12;
1340   set_pc((m_pc & 0xf000) | new_pc);
1341
1342   return 2;
1343}
1344
1345int lc8670_cpu_device::op_mul()
1346{
1347   UINT32 res = REG_B * ((REG_A<<8) | REG_C);
1348
1349   REG_A = (res>>8) & 0xff;
1350   REG_B = (res>>16) & 0xff;
1351   REG_C = (res>>0) & 0xff;
1352
1353   SET_OV(REG_B != 0 ? 1 : 0);
1354   SET_CY(0);
1355   CHECK_P();
1356
1357   return 7;
1358}
1359
1360int lc8670_cpu_device::op_be()
1361{
1362   UINT8 data = get_data();
1363   UINT8 r8 = GET_R8;
1364
1365   if (REG_A == data)
1366      set_pc(m_pc + SIGNED(r8));
1367
1368   SET_CY((REG_A < data) ? 1 : 0);
1369
1370   return 2;
1371}
1372
1373int lc8670_cpu_device::op_be_ri()
1374{
1375   UINT8 data = get_data();
1376   UINT8 i8 = GET_I8;
1377   UINT8 r8 = GET_R8;
1378
1379   if (i8 == data)
1380      set_pc(m_pc + SIGNED(r8));
1381
1382   SET_CY((data < i8) ? 1 : 0);
1383
1384   return 2;
1385}
1386
1387
1388int lc8670_cpu_device::op_div()
1389{
1390   UINT32 res, mod;
1391
1392   if (REG_B != 0)
1393   {
1394      UINT16 v = ((REG_A<<8) | REG_C);
1395      res = v / REG_B;
1396      mod = v % REG_B;
1397
1398      REG_A = (res>>8) & 0xff;
1399      REG_C = (res>>0) & 0xff;
1400      REG_B = mod & 0xff;
1401      SET_OV(0);
1402   }
1403   else
1404   {
1405      REG_A = 0xff;
1406      SET_OV(1);
1407   }
1408
1409   SET_CY(0);
1410   CHECK_P();
1411
1412   return 7;
1413}
1414
1415int lc8670_cpu_device::op_bne()
1416{
1417   UINT8 data = get_data();
1418   UINT8 r8 = GET_R8;
1419
1420   if (REG_A != data)
1421      set_pc(m_pc + SIGNED(r8));
1422
1423   SET_CY((REG_A < data) ? 1 : 0);
1424
1425   return 2;
1426}
1427
1428int lc8670_cpu_device::op_bne_ri()
1429{
1430   UINT8 data = get_data();
1431   UINT8 i8 = GET_I8;
1432   UINT8 r8 = GET_R8;
1433
1434   if (i8 != data)
1435      set_pc(m_pc + SIGNED(r8));
1436
1437   SET_CY((data < i8) ? 1 : 0);
1438
1439   return 2;
1440}
1441
1442int lc8670_cpu_device::op_ldf()
1443{
1444   UINT16 addr = REG_TRL | (REG_TRH<<8);
1445
1446   m_bankswitch_func(REG_FPR & 0x01 ? 2 : 1);
1447   REG_A = m_program->read_byte(addr);
1448   CHECK_P();
1449   m_bankswitch_func(((REG_EXT & 0x01) ? 1 : (REG_EXT & 0x08) ? 0 : 2));
1450
1451   return 2;
1452}
1453
1454int lc8670_cpu_device::op_stf()
1455{
1456   UINT16 addr = REG_TRL | (REG_TRH<<8);
1457
1458   m_bankswitch_func(REG_FPR & 0x01 ? 2 : 1);
1459   m_program->write_byte(addr, REG_A);
1460   m_bankswitch_func(((REG_EXT & 0x01) ? 1 : (REG_EXT & 0x08) ? 0 : 2));
1461
1462   return 2;
1463}
1464
1465int lc8670_cpu_device::op_dbnz()
1466{
1467   UINT16 addr = get_addr();
1468   UINT8 r8 = GET_R8;
1469   UINT8 data = read_data_latch(addr) - 1;
1470
1471   write_data_latch(addr, data);
1472
1473   if (data != 0)
1474      set_pc(m_pc + SIGNED(r8));
1475
1476   return 2;
1477}
1478
1479int lc8670_cpu_device::op_bpc()
1480{
1481   UINT8 b3 = GET_B3;
1482   UINT16 d9 = GET_D9B3;
1483   UINT8 r8 = GET_R8;
1484   UINT8 data = read_data_latch(d9);
1485
1486   if (data & (1<<b3))
1487   {
1488      write_data_latch(d9, data & ~(1<<b3));
1489      set_pc(m_pc + SIGNED(r8));
1490   }
1491
1492   return 2;
1493}
1494
1495int lc8670_cpu_device::op_push()
1496{
1497   UINT16 d9 = GET_D9;
1498   push(read_data(d9));
1499
1500   return 2;
1501}
1502
1503int lc8670_cpu_device::op_inc()
1504{
1505   UINT16 addr = get_addr();
1506   UINT8 data = read_data_latch(addr);
1507
1508   write_data_latch(addr, data + 1);
1509
1510   return 1;
1511}
1512
1513int lc8670_cpu_device::op_bp()
1514{
1515   UINT8 b3 = GET_B3;
1516   UINT16 d9 = GET_D9B3;
1517   UINT8 r8 = GET_R8;
1518
1519   if (read_data(d9) & (1<<b3))
1520      set_pc(m_pc + SIGNED(r8));
1521
1522   return 2;
1523}
1524
1525int lc8670_cpu_device::op_pop()
1526{
1527   UINT16 d9 = GET_D9;
1528   write_data(d9, pop());
1529
1530   return 2;
1531}
1532
1533int lc8670_cpu_device::op_dec()
1534{
1535   UINT16 addr = get_addr();
1536   UINT8 data = read_data_latch(addr);
1537
1538   write_data_latch(addr, data - 1);
1539
1540   return 1;
1541}
1542
1543int lc8670_cpu_device::op_bz()
1544{
1545   UINT8 r8 = GET_R8;
1546
1547   if (REG_A == 0)
1548      set_pc(m_pc + SIGNED(r8));
1549
1550   return 2;
1551}
1552
1553int lc8670_cpu_device::op_add()
1554{
1555   UINT8 data = get_data();
1556   INT32 res = (REG_A + data);
1557
1558   SET_CY(res > 0xff ? 1 : 0);
1559   SET_AC(((REG_A & 0x0f) + (data & 0x0f)) > 0x0f ? 1 : 0);
1560   SET_OV((REG_A & data) & (data ^ res) & 0x80 ? 1 : 0);
1561
1562   REG_A = res & 0xff;
1563   CHECK_P();
1564
1565   return 1;
1566}
1567
1568int lc8670_cpu_device::op_bn()
1569{
1570   UINT8 b3 = GET_B3;
1571   UINT16 d9 = GET_D9B3;
1572   UINT8 r8 = GET_R8;
1573
1574   if (!(read_data(d9) & (1<<b3)))
1575      set_pc(m_pc + SIGNED(r8));
1576
1577   return 2;
1578}
1579
1580int lc8670_cpu_device::op_bnz()
1581{
1582   UINT8 r8 = GET_R8;
1583
1584   if (REG_A != 0)
1585      set_pc(m_pc + SIGNED(r8));
1586
1587   return 2;
1588}
1589
1590int lc8670_cpu_device::op_addc()
1591{
1592   UINT8 data = get_data();
1593   INT32 res = (REG_A + data + GET_CY);
1594
1595   SET_CY(res > 0xff ? 1 : 0);
1596   SET_AC(((REG_A & 0x0f) + (data & 0x0f) + GET_CY) > 0x0f ? 1 : 0);
1597   SET_OV(((REG_A+GET_CY) & data) & (data ^ res) & 0x80 ? 1 : 0);
1598
1599   REG_A = res & 0xff;
1600   CHECK_P();
1601
1602   return 1;
1603}
1604
1605int lc8670_cpu_device::op_ret()
1606{
1607   UINT16 new_pc = pop()<<8;
1608   new_pc |= pop();
1609   set_pc(new_pc);
1610
1611   return 2;
1612}
1613
1614int lc8670_cpu_device::op_sub()
1615{
1616   UINT8 data = get_data();
1617   INT32 res = (REG_A - data);
1618
1619   SET_CY(res < 0x00 ? 1 : 0);
1620   SET_AC(((REG_A & 0x0f) - (data & 0x0f)) < 0x00 ? 1 : 0);
1621   SET_OV((REG_A ^ data) & (data & res) & 0x80 ? 1 : 0);
1622
1623   REG_A = res & 0xff;
1624   CHECK_P();
1625
1626   return 1;
1627}
1628
1629int lc8670_cpu_device::op_not1()
1630{
1631   UINT16 d9 = GET_D9B3;
1632   UINT8 data = read_data_latch(d9);
1633
1634   data ^= (1<<GET_B3);
1635   write_data_latch(d9, data);
1636
1637   return 1;
1638}
1639
1640int lc8670_cpu_device::op_reti()
1641{
1642   UINT16 new_pc = pop()<<8;
1643   new_pc |= pop();
1644   set_pc(new_pc);
1645
1646   if (LOG_IRQ)   logerror("%s: RETI from level %d\n", machine().describe_context(), m_irq_lev);
1647   for(int i=2; i>=0; i--)
1648      if (m_irq_lev & (1<<i))
1649      {
1650         m_irq_lev &= ~(1<<i);
1651         break;
1652      }
1653
1654   m_after_reti = true;
1655
1656   return 2;
1657}
1658
1659int lc8670_cpu_device::op_subc()
1660{
1661   UINT8 data = get_data();
1662   INT32 res = (REG_A - data - GET_CY);
1663
1664   SET_CY(res < 0x00 ? 1 : 0);
1665   SET_AC(((REG_A & 0x0f) - (data & 0x0f) - GET_CY) < 0x00 ? 1 : 0);
1666   SET_OV((REG_A ^ (data + GET_CY)) & (data & res) & 0x80 ? 1 : 0);
1667
1668   REG_A = res & 0xff;
1669   CHECK_P();
1670
1671   return 1;
1672}
1673
1674int lc8670_cpu_device::op_ror()
1675{
1676   REG_A = ((REG_A & 0x01) << 7) | (REG_A>>1);
1677   CHECK_P();
1678
1679   return 1;
1680}
1681
1682int lc8670_cpu_device::op_ldc()
1683{
1684   REG_A = m_program->read_byte(((REG_TRH<<8) | REG_TRL) + REG_A);
1685   CHECK_P();
1686
1687   return 2;
1688}
1689
1690int lc8670_cpu_device::op_xch()
1691{
1692   UINT16 addr = get_addr();
1693   UINT8 data = read_data(addr);
1694
1695   write_data(addr, REG_A);
1696   REG_A = data;
1697   CHECK_P();
1698
1699   return 1;
1700}
1701
1702int lc8670_cpu_device::op_clr1()
1703{
1704   UINT16 d9 = GET_D9B3;
1705   UINT8 data = read_data_latch(d9);
1706
1707   data &= ~(1<<GET_B3);
1708   write_data_latch(d9, data);
1709
1710   return 1;
1711}
1712
1713int lc8670_cpu_device::op_rorc()
1714{
1715   UINT8 a = (REG_A>>1) | (GET_CY ? 0x80 : 0x00);
1716
1717   SET_CY(BIT(REG_A,0));
1718   REG_A = a;
1719   CHECK_P();
1720
1721   return 1;
1722}
1723
1724int lc8670_cpu_device::op_or()
1725{
1726   REG_A = REG_A | get_data();
1727   CHECK_P();
1728
1729   return 1;
1730}
1731
1732int lc8670_cpu_device::op_rol()
1733{
1734   REG_A = ((REG_A & 0x80) >> 7) | (REG_A<<1);
1735   CHECK_P();
1736
1737   return 1;
1738}
1739
1740int lc8670_cpu_device::op_and()
1741{
1742   REG_A = REG_A & get_data();
1743   CHECK_P();
1744
1745   return 1;
1746}
1747
1748int lc8670_cpu_device::op_set1()
1749{
1750   UINT16 d9 = GET_D9B3;
1751   UINT8 data = read_data_latch(d9);
1752
1753   data |= (1<<GET_B3);
1754   write_data_latch(d9, data);
1755
1756   return 1;
1757}
1758
1759int lc8670_cpu_device::op_rolc()
1760{
1761   UINT8 a = (REG_A<<1) | (GET_CY ? 0x01 : 0x00);
1762
1763   SET_CY(BIT(REG_A,7));
1764   REG_A = a;
1765   CHECK_P();
1766
1767   return 1;
1768}
1769
1770int lc8670_cpu_device::op_xor()
1771{
1772   REG_A = REG_A ^ get_data();
1773   CHECK_P();
1774
1775   return 1;
1776}
trunk/src/emu/cpu/lc8670/lc8670dsm.c
r0r19051
1/******************************************************************************
2
3    Sanyo LC8670 disassembler
4
5******************************************************************************/
6
7#include "emu.h"
8#include "debugger.h"
9#include "lc8670.h"
10
11const lc8670_cpu_device::dasm_entry lc8670_cpu_device::s_dasm_table[] =
12{
13   { "NOP" ,   OP_NULL,   OP_NULL, 0 },      // 0x0*
14   { "BR"  ,   OP_R8  ,   OP_NULL, 0 },
15   { "LD"  ,   OP_D9  ,   OP_NULL, 0 },
16   { "LD"  ,   OP_RI  ,   OP_NULL, 0 },
17   { "CALL",   OP_A12 ,   OP_NULL, 0 },
18   { "CALLR",  OP_R16 ,   OP_NULL, 0 },      // 0x1*
19   { "BRF" ,   OP_R16 ,   OP_NULL, 0 },
20   { "ST"  ,   OP_D9  ,   OP_NULL, 0 },
21   { "ST"  ,   OP_RI  ,   OP_NULL, 0 },
22   { "CALL",   OP_A12 ,   OP_NULL, 0 },
23   { "CALLF",  OP_A16 ,   OP_NULL, 0 },      // 0x2*
24   { "JMPF",   OP_A16 ,   OP_NULL, 0 },
25   { "MOV" ,   OP_D9  ,   OP_I8  , 1 },
26   { "MOV" ,   OP_RI  ,   OP_I8  , 1 },
27   { "JMP" ,   OP_A12 ,   OP_NULL, 0 },
28   { "MUL" ,   OP_NULL,   OP_NULL, 0 },      // 0x3*
29   { "BE"  ,   OP_I8  ,   OP_R8  , 0 },
30   { "BE"  ,   OP_D9  ,   OP_R8  , 0 },
31   { "BE"  ,   OP_RII8,   OP_R8  , 0 },
32   { "JMP" ,   OP_A12 ,   OP_NULL, 0 },
33   { "DIV" ,   OP_NULL,   OP_NULL, 0 },      // 0x4*
34   { "BNE" ,   OP_I8  ,   OP_R8  , 0 },
35   { "BNE" ,   OP_D9  ,   OP_R8  , 0 },
36   { "BNE" ,   OP_RII8,   OP_R8  , 0 },
37   { "BPC" ,   OP_D9B3,   OP_R8  , 0 },
38   { "LDF" ,   OP_NULL,   OP_NULL, 0 },      // 0x5*
39   { "STF" ,   OP_NULL,   OP_NULL, 0 },
40   { "DBNZ",   OP_D9  ,   OP_R8  , 0 },
41   { "DBNZ",   OP_RI  ,   OP_R8RI, 0 },
42   { "BPC" ,   OP_D9B3,   OP_R8  , 0 },
43   { "PUSH",   OP_D9  ,   OP_NULL, 0 },      // 0x6*
44   { "PUSH",   OP_D9  ,   OP_NULL, 0 },
45   { "INC" ,   OP_D9  ,   OP_NULL, 0 },
46   { "INC" ,   OP_RI  ,   OP_NULL, 0 },
47   { "BP"  ,   OP_D9B3,   OP_R8  , 0 },
48   { "POP" ,   OP_D9  ,   OP_NULL, 0 },      // 0x7*
49   { "POP" ,   OP_D9  ,   OP_NULL, 0 },
50   { "DEC" ,   OP_D9  ,   OP_NULL, 0 },
51   { "DEC" ,   OP_RI  ,   OP_NULL, 0 },
52   { "BP"  ,   OP_D9B3,   OP_R8  , 0 },
53   { "BZ"  ,   OP_R8  ,   OP_NULL, 0 },      // 0x8*
54   { "ADD" ,   OP_I8  ,   OP_NULL, 0 },
55   { "ADD" ,   OP_D9  ,   OP_NULL, 0 },
56   { "ADD" ,   OP_RI  ,   OP_NULL, 0 },
57   { "BN"  ,   OP_D9B3,   OP_R8  , 0 },
58   { "BNZ" ,   OP_R8  ,   OP_NULL, 0 },      // 0x9*
59   { "ADDC",   OP_I8  ,   OP_NULL, 0 },
60   { "ADDC",   OP_D9  ,   OP_NULL, 0 },
61   { "ADDC",   OP_RI  ,   OP_NULL, 0 },
62   { "BN"  ,   OP_D9B3,   OP_R8  , 0 },
63   { "RET" ,   OP_NULL,   OP_NULL, 0 },      // 0xa*
64   { "SUB" ,   OP_I8  ,   OP_NULL, 0 },
65   { "SUB" ,   OP_D9  ,   OP_NULL, 0 },
66   { "SUB" ,   OP_RI  ,   OP_NULL, 0 },
67   { "NOT1",   OP_D9B3,   OP_NULL, 0 },
68   { "RETI",   OP_NULL,   OP_NULL, 0 },      // 0xb*
69   { "SUBC",   OP_I8  ,   OP_NULL, 0 },
70   { "SUBC",   OP_D9  ,   OP_NULL, 0 },
71   { "SUBC",   OP_RI  ,   OP_NULL, 0 },
72   { "NOT1",   OP_D9B3,   OP_NULL, 0 },
73   { "ROR" ,   OP_NULL,   OP_NULL, 0 },      // 0xc*
74   { "LDC" ,   OP_NULL,   OP_NULL, 0 },
75   { "XCH" ,   OP_D9  ,   OP_NULL, 0 },
76   { "XCH" ,   OP_RI  ,   OP_NULL, 0 },
77   { "CLR1",   OP_D9B3,   OP_NULL, 0 },
78   { "RORC",   OP_NULL,   OP_NULL, 0 },      // 0xd*
79   { "OR"  ,   OP_I8  ,   OP_NULL, 0 },
80   { "OR"  ,   OP_D9  ,   OP_NULL, 0 },
81   { "OR"  ,   OP_RI  ,   OP_NULL, 0 },
82   { "CLR1",   OP_D9B3,   OP_NULL, 0 },
83   { "ROL" ,   OP_NULL,   OP_NULL, 0 },      // 0xe*
84   { "AND" ,   OP_I8  ,   OP_NULL, 0 },
85   { "AND" ,   OP_D9  ,   OP_NULL, 0 },
86   { "AND" ,   OP_RI  ,   OP_NULL, 0 },
87   { "SET1",   OP_D9B3,   OP_NULL, 0 },
88   { "ROLC",   OP_NULL,   OP_NULL, 0 },      // 0xf*
89   { "XOR" ,   OP_I8  ,   OP_NULL, 0 },
90   { "XOR" ,   OP_D9  ,   OP_NULL, 0 },
91   { "XOR" ,   OP_RI  ,   OP_NULL, 0 },
92   { "SET1",   OP_D9B3,   OP_NULL, 0 },
93};
94
95void lc8670_cpu_device::dasm_arg(UINT8 op, char *buffer, offs_t pc, int arg, const UINT8 *oprom, int &pos)
96{
97   switch( arg )
98   {
99      case OP_NULL:
100         buffer[0] = '\0';
101         break;
102      case OP_R8:
103         pc++;
104         // fall through
105      case OP_R8RI:
106         buffer += sprintf(buffer, "%04x", (pc + 1 + oprom[pos] - (oprom[pos]&0x80 ? 0x100 : 0)) & 0xffff);
107         pos++;
108         break;
109      case OP_R16:
110         buffer += sprintf(buffer, "%04x", (pc + 2 + ((oprom[pos+1]<<8) | oprom[pos])) & 0xffff);
111         pos += 2;
112         break;
113      case OP_RI:
114         buffer += sprintf(buffer, "@%x", op & 0x03);
115         break;
116      case OP_A12:
117         buffer += sprintf(buffer, "%04x", ((pc + 2) & 0xf000) | ((op & 0x10)<<7) | ((op & 0x07)<<8) | oprom[pos]);
118         pos++;
119         break;
120      case OP_A16:
121         buffer += sprintf(buffer, "%04x", (oprom[pos]<<8) | oprom[pos+1]);
122         pos += 2;
123         break;
124      case OP_I8:
125         buffer += sprintf(buffer, "#$%02x", oprom[pos++]);
126         break;
127      case OP_B3:
128         buffer += sprintf(buffer, "%x", op & 0x07);
129         break;
130      case OP_D9:
131         buffer += sprintf(buffer, "($%03x)", ((op & 0x01)<<8) | oprom[pos]);
132         pos++;
133         break;
134      case OP_D9B3:
135         buffer += sprintf(buffer, "($%03x)", ((op & 0x10)<<4) | oprom[pos]);
136         buffer += sprintf(buffer, ",%x", op & 0x07);
137         pos++;
138         break;
139      case OP_RII8:
140         buffer += sprintf(buffer, "@%x", op & 0x03);
141         buffer += sprintf(buffer, ",#$%02x", oprom[pos]);
142         pos++;
143         break;
144   }
145}
146
147//-------------------------------------------------
148//  disasm_disassemble - call the disassembly
149//  helper function
150//-------------------------------------------------
151
152offs_t lc8670_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
153{
154   int pos = 0;
155   char arg1[16], arg2[16];
156
157   UINT8 op = oprom[pos++];
158
159   int op_idx = decode_op(op);
160   const dasm_entry *inst = &s_dasm_table[op_idx];
161
162   buffer += sprintf(buffer,"%-8s", inst->str);
163
164   dasm_arg(op, inst->inv ? arg2 : arg1, pc+0, inst->arg1, oprom, pos);
165   dasm_arg(op, inst->inv ? arg1 : arg2, pc+1, inst->arg2, oprom, pos);
166
167   strcat(buffer, arg1);
168
169   if (inst->arg2 != OP_NULL)
170   {
171      strcat(buffer, ",");
172      strcat(buffer, arg2);
173   }
174
175   return pos;
176}
trunk/src/emu/cpu/lc8670/lc8670.h
r0r19051
1/**********************************************************************
2
3    Sanyo LC8670
4
5**********************************************************************/
6
7#pragma once
8
9#ifndef __LC8670_H__
10#define __LC8670_H__
11
12
13//**************************************************************************
14//  DEFINITION
15//**************************************************************************
16
17enum
18{
19   LC8670_PC = 1,
20   LC8670_SFR
21};
22
23// input ports
24enum
25{
26   LC8670_PORT1,      // 8-bit I/O port
27   LC8670_PORT3,      // 8-bit I/O port
28   LC8670_PORT7      // 4-bit I port
29};
30
31// external input lines
32enum
33{
34   LC8670_EXT_INT0 = 0,   // P70
35   LC8670_EXT_INT1,      // P71
36   LC8670_EXT_INT2,      // P72
37   LC8670_EXT_INT3         // P73
38};
39
40// clock sources
41enum
42{
43   LC8670_SUB_CLOCK = 0,
44   LC8670_RC_CLOCK,
45   LC8670_CF_CLOCK
46};
47
48
49//**************************************************************************
50//  TYPE DEFINITIONS
51//**************************************************************************
52
53typedef UINT32 (*lc8670_lcd_update)(device_t &device, bitmap_ind16 &bitmap, const rectangle &cliprect, UINT8* vram, bool lcd_enabled, UINT8 stad);
54#define LC8670_LCD_UPDATE(name) UINT32 name(device_t &device, bitmap_ind16 &bitmap, const rectangle &cliprect, UINT8* vram, bool lcd_enabled, UINT8 stad)
55
56
57//**************************************************************************
58//  INTERFACE CONFIGURATION MACROS
59//**************************************************************************
60
61#define MCFG_LC8670_SET_CLOCK_SOURCES(_sub_clock, _rc_clock, _cf_clock) \
62   lc8670_cpu_device::static_set_cpu_clock(*device, LC8670_SUB_CLOCK, _sub_clock); \
63   lc8670_cpu_device::static_set_cpu_clock(*device, LC8670_RC_CLOCK, _rc_clock); \
64   lc8670_cpu_device::static_set_cpu_clock(*device, LC8670_CF_CLOCK, _cf_clock); \
65
66#define MCFG_LC8670_BANKSWITCH_CB(_devcb) \
67   devcb = &lc8670_cpu_device::static_set_bankswitch_cb(*device, DEVCB2_##_devcb);
68
69#define MCFG_LC8670_LCD_UPDATE_CB(_cb) \
70   lc8670_cpu_device::static_set_lcd_update_cb(*device, _cb);
71
72
73// ======================> lc8670_cpu_device
74
75class lc8670_cpu_device : public cpu_device
76{
77public:
78   // construction/destruction
79   lc8670_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);
80
81   // public interfaces
82   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
83
84   // internal map handlers
85   DECLARE_READ8_MEMBER(regs_r);
86   DECLARE_WRITE8_MEMBER(regs_w);
87   DECLARE_READ8_MEMBER(mram_r);
88   DECLARE_WRITE8_MEMBER(mram_w);
89   DECLARE_READ8_MEMBER(xram_r);
90   DECLARE_WRITE8_MEMBER(xram_w);
91
92   // static configuration helpers
93   static void static_set_cpu_clock(device_t &device, int _source, UINT32 _clock) { downcast<lc8670_cpu_device &>(device).m_clocks[_source] = _clock; }
94   static void static_set_lcd_update_cb(device_t &device, lc8670_lcd_update _cb) { downcast<lc8670_cpu_device &>(device).m_lcd_update_func = _cb; }
95   template<class _Object> static devcb2_base & static_set_bankswitch_cb(device_t &device, _Object object) { return downcast<lc8670_cpu_device &>(device).m_bankswitch_func.set_callback(object); }
96
97protected:
98   // device-level overrides
99   virtual void device_start();
100   virtual void device_reset();
101   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
102
103   // device_execute_interface overrides
104   virtual UINT32 execute_min_cycles() const { return 1; }
105   virtual UINT32 execute_max_cycles() const { return 7; }
106   virtual UINT32 execute_input_lines() const { return 4; }
107   virtual void execute_run();
108   virtual void execute_set_input(int inputnum, int state);
109
110   // device_state_interface overrides
111   virtual void state_import(const device_state_entry &entry);
112   void state_string_export(const device_state_entry &entry, astring &string);
113
114   // device_memory_interface overrides
115   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
116
117   // device_disasm_interface overrides
118   virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
119   virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
120   virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
121
122private:
123   // helpers
124   inline UINT8 fetch();
125   inline void  push(UINT8 data);
126   inline UINT8 pop();
127   inline UINT8 read_data(UINT16 offset);
128   inline void write_data(UINT16 offset, UINT8 data);
129   inline UINT8 read_data_latch(UINT16 offset);
130   inline void write_data_latch(UINT16 offset, UINT8 data);
131   inline void update_port1(UINT8 data);
132   inline void set_pc(UINT16 new_pc);
133   inline UINT8 get_data();
134   inline UINT16 get_addr();
135   inline void change_clock_source();
136   inline void check_p_flag();
137   inline void check_p3int();
138   inline void set_irq_flag(int source);
139   int decode_op(UINT8 op);
140   void check_irqs();
141   void timer0_prescaler_tick();
142   void timer0_tick(bool ext_line = false);
143   void timer1_tick();
144   void base_timer_tick();
145   void dasm_arg(UINT8 op, char *buffer, offs_t pc, int arg, const UINT8 *oprom, int &pos);
146
147   // opcodes handlers
148   int op_nop();
149   int op_br();
150   int op_ld();
151   int op_call();
152   int op_callr();
153   int op_brf();
154   int op_st();
155   int op_callf();
156   int op_jmpf();
157   int op_mov();
158   int op_jmp();
159   int op_mul();
160   int op_be();
161   int op_be_ri();
162   int op_div();
163   int op_bne();
164   int op_bne_ri();
165   int op_ldf();
166   int op_stf();
167   int op_dbnz();
168   int op_bpc();
169   int op_push();
170   int op_inc();
171   int op_bp();
172   int op_pop();
173   int op_dec();
174   int op_bz();
175   int op_add();
176   int op_bn();
177   int op_bnz();
178   int op_addc();
179   int op_ret();
180   int op_sub();
181   int op_not1();
182   int op_reti();
183   int op_subc();
184   int op_ror();
185   int op_ldc();
186   int op_xch();
187   int op_clr1();
188   int op_rorc();
189   int op_or();
190   int op_rol();
191   int op_and();
192   int op_set1();
193   int op_rolc();
194   int op_xor();
195
196private:
197   address_space_config m_program_config;
198   address_space_config m_data_config;
199   address_space_config m_io_config;
200
201   address_space *      m_program;            // program space (ROM or flash)
202   address_space *      m_data;               // internal RAM/register
203   address_space *      m_io;               // I/O ports
204   direct_read_data *   m_direct;
205
206   // timers
207   static const device_timer_id BASE_TIMER = 1;
208   static const device_timer_id CLOCK_TIMER = 2;
209   emu_timer *         m_basetimer;
210   emu_timer *         m_clocktimer;
211
212   // internal state
213   int               m_icount;
214   UINT16            m_pc;
215   UINT16            m_ppc;
216   UINT8            m_op;
217   UINT8 *            m_sfr;               // special function registers
218   UINT8 *            m_mram;               // main RAM
219   UINT8 *            m_xram;               // XRAM
220   UINT8 *            m_vtrbf;            // work RAM
221   UINT16            m_irq_flag;
222   UINT8            m_irq_lev;
223   bool            m_after_reti;
224   UINT8            m_p1_data;
225   UINT8            m_timer0_prescaler;
226   UINT8            m_timer0[2];
227   UINT8            m_timer1[2];
228   UINT8            m_timer1_comparator[2];
229   UINT8            m_base_timer[2];
230   bool            m_clock_changed;
231   int               m_input_lines[4];
232
233   // configuration
234   UINT32            m_clocks[3];         // clock sources
235   devcb2_write8      m_bankswitch_func;      // bankswitch CB
236   lc8670_lcd_update   m_lcd_update_func;      // LCD update CB
237
238   // interrupts vectors
239   static const UINT16   s_irq_vectors[16];
240
241   // opcodes table
242   typedef int (lc8670_cpu_device::*op_handler)();
243   static const op_handler s_opcode_table[80];
244
245   // disassembler
246   enum
247   {
248      OP_NULL,
249      OP_R8,
250      OP_R8RI,
251      OP_R16,
252      OP_RI,
253      OP_A12,
254      OP_A16,
255      OP_I8,
256      OP_B3,
257      OP_D9,
258      OP_D9B3,
259      OP_RII8
260   };
261
262   // disasm table
263   struct dasm_entry
264   {
265      const char *str;
266      UINT8      arg1;
267      UINT8      arg2;
268      bool      inv;
269   };
270   static const dasm_entry s_dasm_table[80];
271};
272
273extern const device_type LC8670;
274
275#endif /* __LC8670_H__ */

Previous 199869 Revisions Next


© 1997-2024 The MAME Team