1
/*******************************************************************
3
Toshiba TLCS-900/H emulation
5
This code only supports the 900/H mode which is needed for Neogeo
6
Pocket emulation. The 900 and 900/M modes are not supported yet.
11
- implement the remaining internal mcu features
12
- add support for 900 and 900/M modes
14
*******************************************************************/
20
typedef struct _tlcs900_state tlcs900_state;
23
const tlcs900_interface *intf;
25
devcb_resolved_write8 to1;
26
devcb_resolved_write8 to3;
47
/* Internal timers, irqs, etc */
55
/* Current state of input levels */
56
int level[TLCS900_NUM_INPUTS];
61
/* used during execution */
62
PAIR dummy; /* for illegal register references */
67
UINT8 *p1_reg8, *p2_reg8;
68
UINT16 *p1_reg16, *p2_reg16;
69
UINT32 *p1_reg32, *p2_reg32;
74
device_irq_callback irqcallback;
75
legacy_cpu_device *device;
76
address_space *program;
80
/* Internal register defines */
180
#define INTETC10 0x79
181
#define INTETC32 0x7a
198
#define RDMEM(addr) cpustate->program->read_byte( addr )
199
#define WRMEM(addr,data) cpustate->program->write_byte( addr, data )
200
#define RDOP() RDMEM( cpustate->pc.d ); cpustate->pc.d++
201
#define RDMEMW(addr) ( RDMEM(addr) | ( RDMEM(addr+1) << 8 ) )
202
#define RDMEML(addr) ( RDMEMW(addr) | ( RDMEMW(addr+2) << 16 ) )
203
#define WRMEMW(addr,data) { UINT16 dw = data; WRMEM(addr,dw & 0xff); WRMEM(addr+1,(dw >> 8 )); }
204
#define WRMEML(addr,data) { UINT32 dl = data; WRMEMW(addr,dl); WRMEMW(addr+2,(dl >> 16)); }
207
INLINE tlcs900_state *get_safe_token( device_t *device )
209
assert( device != NULL );
210
assert( device->type() == TLCS900H );
212
return (tlcs900_state *) downcast<legacy_cpu_device *>(device)->token();
216
static CPU_INIT( tlcs900 )
218
tlcs900_state *cpustate = get_safe_token(device);
220
cpustate->intf = (const tlcs900_interface *)device->static_config();
221
cpustate->irqcallback = irqcallback;
222
cpustate->device = device;
223
cpustate->program = device->space( AS_PROGRAM );
225
cpustate->to1.resolve(cpustate->intf->to1, *device );
226
cpustate->to3.resolve(cpustate->intf->to3, *device );
228
device->save_item( NAME(cpustate->xwa) );
229
device->save_item( NAME(cpustate->xbc) );
230
device->save_item( NAME(cpustate->xde) );
231
device->save_item( NAME(cpustate->xhl) );
232
device->save_item( NAME(cpustate->xix) );
233
device->save_item( NAME(cpustate->xiy) );
234
device->save_item( NAME(cpustate->xiz) );
235
device->save_item( NAME(cpustate->xssp) );
236
device->save_item( NAME(cpustate->xnsp) );
237
device->save_item( NAME(cpustate->pc) );
238
device->save_item( NAME(cpustate->sr) );
239
device->save_item( NAME(cpustate->f2) );
240
device->save_item( NAME(cpustate->dmas) );
241
device->save_item( NAME(cpustate->dmad) );
242
device->save_item( NAME(cpustate->dmac) );
243
device->save_item( NAME(cpustate->dmam) );
244
device->save_item( NAME(cpustate->reg) );
245
device->save_item( NAME(cpustate->timer_pre) );
246
device->save_item( NAME(cpustate->timer) );
247
device->save_item( NAME(cpustate->tff1) );
248
device->save_item( NAME(cpustate->tff3) );
249
device->save_item( NAME(cpustate->timer_change) );
250
device->save_item( NAME(cpustate->level) );
251
device->save_item( NAME(cpustate->check_irqs) );
252
device->save_item( NAME(cpustate->ad_cycles_left) );
253
device->save_item( NAME(cpustate->nmi_state) );
257
static CPU_RESET( tlcs900 )
259
tlcs900_state *cpustate = get_safe_token(device);
262
cpustate->pc.b.l = RDMEM( 0xFFFF00 );
263
cpustate->pc.b.h = RDMEM( 0xFFFF01 );
264
cpustate->pc.b.h2 = RDMEM( 0xFFFF02 );
265
cpustate->pc.b.h3 = 0;
266
/* system mode, iff set to 111, max mode, register bank 0 */
267
cpustate->sr.d = 0xF800;
268
cpustate->regbank = 0;
269
cpustate->xssp.d = 0x0100;
270
cpustate->halted = 0;
271
cpustate->check_irqs = 0;
272
cpustate->ad_cycles_left = 0;
273
cpustate->nmi_state = CLEAR_LINE;
274
cpustate->timer_pre = 0;
275
cpustate->timer_change[0] = 0;
276
cpustate->timer_change[1] = 0;
277
cpustate->timer_change[2] = 0;
278
cpustate->timer_change[3] = 0;
280
cpustate->reg[P1] = 0x00;
281
cpustate->reg[P1CR] = 0x00;
282
cpustate->reg[P2] = 0xff;
283
cpustate->reg[P2FC] = 0x00;
284
cpustate->reg[P5] = 0x3d;
285
cpustate->reg[P5CR] = 0x00;
286
cpustate->reg[P5FC] = 0x00;
287
cpustate->reg[P6] = 0x3b;
288
cpustate->reg[P6FC] = 0x00;
289
cpustate->reg[P7] = 0xff;
290
cpustate->reg[P7CR] = 0x00;
291
cpustate->reg[P7FC] = 0x00;
292
cpustate->reg[P8] = 0x3f;
293
cpustate->reg[P8CR] = 0x00;
294
cpustate->reg[P8FC] = 0x00;
295
cpustate->reg[PA] = 0x0f;
296
cpustate->reg[PACR] = 0x00;
297
cpustate->reg[PAFC] = 0x00;
298
cpustate->reg[PB] = 0xff;
299
cpustate->reg[PBCR] = 0x00;
300
cpustate->reg[PBFC] = 0x00;
301
cpustate->reg[MSAR0] = 0xff;
302
cpustate->reg[MSAR1] = 0xff;
303
cpustate->reg[MSAR2] = 0xff;
304
cpustate->reg[MSAR3] = 0xff;
305
cpustate->reg[MAMR0] = 0xff;
306
cpustate->reg[MAMR1] = 0xff;
307
cpustate->reg[MAMR2] = 0xff;
308
cpustate->reg[MAMR3] = 0xff;
309
cpustate->reg[DREFCR] = 0x00;
310
cpustate->reg[DMEMCR] = 0x80;
311
cpustate->reg[T01MOD] = 0x00;
312
cpustate->reg[T23MOD] = 0x00;
313
cpustate->reg[TFFCR] = 0x00;
314
cpustate->reg[TRUN] = 0x00;
315
cpustate->reg[TRDC] = 0x00;
316
cpustate->reg[T4MOD] = 0x20;
317
cpustate->reg[T4FFCR] = 0x00;
318
cpustate->reg[T5MOD] = 0x20;
319
cpustate->reg[T5FFCR] = 0x00;
320
cpustate->reg[T45CR] = 0x00;
321
cpustate->reg[PG01CR] = 0x00;
322
cpustate->reg[PG0REG] = 0x00;
323
cpustate->reg[PG1REG] = 0x00;
324
cpustate->reg[SC0MOD] = 0x00;
325
cpustate->reg[SC0CR] = 0x00;
326
cpustate->reg[BR0CR] = 0x00;
327
cpustate->reg[SC1MOD] = 0x00;
328
cpustate->reg[SC1CR] = 0x00;
329
cpustate->reg[BR1CR] = 0x00;
330
cpustate->reg[P8FC] = 0x00;
331
cpustate->reg[ODE] = 0x00;
332
cpustate->reg[ADMOD] = 0x00;
333
cpustate->reg[ADREG0L] = 0x3f;
334
cpustate->reg[ADREG1L] = 0x3f;
335
cpustate->reg[ADREG2L] = 0x3f;
336
cpustate->reg[ADREG3L] = 0x3f;
337
cpustate->reg[WDMOD] = 0x80;
339
for ( i = 0; i < TLCS900_NUM_INPUTS; i++ )
341
cpustate->level[i] = CLEAR_LINE;
346
static CPU_EXIT( tlcs900 )
354
#define NUM_MASKABLE_IRQS 22
355
static const struct {
359
} irq_vector_map[NUM_MASKABLE_IRQS] =
361
{ INTETC32, 0x80, 0x80 }, /* INTTC3 */
362
{ INTETC32, 0x08, 0x7c }, /* INTTC2 */
363
{ INTETC10, 0x80, 0x78 }, /* INTTC1 */
364
{ INTETC10, 0x08, 0x74 }, /* INTTC0 */
365
{ INTE0AD, 0x80, 0x70 }, /* INTAD */
366
{ INTES1, 0x80, 0x6c }, /* INTTX1 */
367
{ INTES1, 0x08, 0x68 }, /* INTRX1 */
368
{ INTES0, 0x80, 0x64 }, /* INTTX0 */
369
{ INTES0, 0x08, 0x60 }, /* INTRX0 */
370
{ INTET76, 0x80, 0x5c }, /* INTTR7 */
371
{ INTET76, 0x08, 0x58 }, /* INTTR6 */
372
{ INTET54, 0x80, 0x54 }, /* INTTR5 */
373
{ INTET54, 0x08, 0x50 }, /* INTTR4 */
374
{ INTET32, 0x80, 0x4c }, /* INTT3 */
375
{ INTET32, 0x08, 0x48 }, /* INTT2 */
376
{ INTET10, 0x80, 0x44 }, /* INTT1 */
377
{ INTET10, 0x08, 0x40 }, /* INTT0 */
378
/* 0x3c - reserved */
379
{ INTE67, 0x80, 0x38 }, /* INT7 */
380
{ INTE67, 0x08, 0x34 }, /* INT6 */
381
{ INTE45, 0x80, 0x30 }, /* INT5 */
382
{ INTE45, 0x08, 0x2c }, /* INT4 */
383
{ INTE0AD, 0x08, 0x28 } /* INT0 */
387
INLINE int tlcs900_process_hdma( tlcs900_state *cpustate, int channel )
389
UINT8 vector = ( cpustate->reg[0x7c + channel] & 0x1f ) << 2;
391
/* Check if any HDMA actions should be performed */
392
if ( vector >= 0x28 && vector != 0x3C && vector < 0x74 )
396
while( irq < NUM_MASKABLE_IRQS && irq_vector_map[irq].vector != vector )
399
/* Check if our interrupt flip-flop is set */
400
if ( irq < NUM_MASKABLE_IRQS && cpustate->reg[irq_vector_map[irq].reg] & irq_vector_map[irq].iff )
402
switch( cpustate->dmam[channel].b.l & 0x1f )
405
WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
406
cpustate->dmad[channel].d += 1;
407
cpustate->cycles += 8;
410
WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
411
cpustate->dmad[channel].d += 2;
412
cpustate->cycles += 8;
415
WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
416
cpustate->dmad[channel].d += 4;
417
cpustate->cycles += 12;
420
WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
421
cpustate->dmad[channel].d -= 1;
422
cpustate->cycles += 8;
425
WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
426
cpustate->dmad[channel].d -= 2;
427
cpustate->cycles += 8;
430
WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
431
cpustate->dmad[channel].d -= 4;
432
cpustate->cycles += 12;
435
WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
436
cpustate->dmas[channel].d += 1;
437
cpustate->cycles += 8;
440
WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
441
cpustate->dmas[channel].d += 2;
442
cpustate->cycles += 8;
445
WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
446
cpustate->dmas[channel].d += 4;
447
cpustate->cycles += 12;
450
WRMEM( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
451
cpustate->dmas[channel].d -= 1;
452
cpustate->cycles += 8;
455
WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
456
cpustate->dmas[channel].d -= 2;
457
cpustate->cycles += 8;
460
WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
461
cpustate->dmas[channel].d -= 4;
462
cpustate->cycles += 12;
465
WRMEM( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
466
cpustate->cycles += 8;
469
WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
470
cpustate->cycles += 8;
473
WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
474
cpustate->cycles += 12;
477
cpustate->dmas[channel].d += 1;
478
cpustate->cycles += 5;
482
cpustate->dmac[channel].w.l -= 1;
484
if ( cpustate->dmac[channel].w.l == 0 )
486
cpustate->reg[0x7c + channel] = 0;
490
cpustate->reg[INTETC10] |= 0x08;
493
cpustate->reg[INTETC10] |= 0x80;
496
cpustate->reg[INTETC32] |= 0x08;
499
cpustate->reg[INTETC32] |= 0x80;
504
/* Clear the interrupt flip-flop */
505
cpustate->reg[irq_vector_map[irq].reg] &= ~irq_vector_map[irq].iff;
514
INLINE void tlcs900_check_hdma( tlcs900_state *cpustate )
516
/* HDMA can only be performed if interrupts are allowed */
517
if ( ( cpustate->sr.b.h & 0x70 ) != 0x70 )
519
if ( ! tlcs900_process_hdma( cpustate, 0 ) )
521
if ( ! tlcs900_process_hdma( cpustate, 1 ) )
523
if ( ! tlcs900_process_hdma( cpustate, 2 ) )
525
tlcs900_process_hdma( cpustate, 3 );
533
INLINE void tlcs900_check_irqs( tlcs900_state *cpustate )
535
int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
541
if ( cpustate->nmi_state == ASSERT_LINE )
543
cpustate->xssp.d -= 4;
544
WRMEML( cpustate->xssp.d, cpustate->pc.d );
545
cpustate->xssp.d -= 2;
546
WRMEMW( cpustate->xssp.d, cpustate->sr.w.l );
547
cpustate->pc.d = RDMEML( 0xffff00 + 0x20 );
548
cpustate->cycles += 18;
550
cpustate->halted = 0;
552
cpustate->nmi_state = CLEAR_LINE;
557
/* Check regular irqs */
558
for( i = 0; i < NUM_MASKABLE_IRQS; i++ )
560
if ( cpustate->reg[irq_vector_map[i].reg] & irq_vector_map[i].iff )
562
switch( irq_vector_map[i].iff )
565
irq_vectors[ ( cpustate->reg[ irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i;
568
irq_vectors[ cpustate->reg[ irq_vector_map[i].reg ] & 0x07 ] = i;
574
/* Check highest allowed priority irq */
575
for ( i = MAX( 1, ( ( cpustate->sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ )
577
if ( irq_vectors[i] >= 0 )
579
irq = irq_vectors[i];
587
UINT8 vector = irq_vector_map[irq].vector;
589
cpustate->xssp.d -= 4;
590
WRMEML( cpustate->xssp.d, cpustate->pc.d );
591
cpustate->xssp.d -= 2;
592
WRMEMW( cpustate->xssp.d, cpustate->sr.w.l );
594
/* Mask off any lower priority interrupts */
595
cpustate->sr.b.h = ( cpustate->sr.b.h & 0x8f ) | ( level << 4 );
597
cpustate->pc.d = RDMEML( 0xffff00 + vector );
598
cpustate->cycles += 18;
600
cpustate->halted = 0;
602
/* Clear taken IRQ */
603
cpustate->reg[ irq_vector_map[irq].reg ] &= ~ irq_vector_map[irq].iff;
608
INLINE void tlcs900_handle_ad( tlcs900_state *cpustate )
610
if ( cpustate->ad_cycles_left > 0 )
612
cpustate->ad_cycles_left -= cpustate->cycles;
613
if ( cpustate->ad_cycles_left <= 0 )
615
/* Store A/D converted value */
616
switch( cpustate->reg[ADMOD] & 0x03 )
619
cpustate->reg[ADREG0L] |= 0xc0;
620
cpustate->reg[ADREG0H] = 0xff;
628
/* Clear BUSY flag, set END flag */
629
cpustate->reg[ADMOD] &= ~ 0x40;
630
cpustate->reg[ADMOD] |= 0x80;
632
cpustate->reg[INTE0AD] |= 0x80;
633
cpustate->check_irqs = 1;
647
INLINE void tlcs900_change_tff( tlcs900_state *cpustate, int which, int change )
664
if ( !cpustate->to1.isnull() )
665
cpustate->to1(0, cpustate->tff1 );
681
if ( !cpustate->to3.isnull() )
682
cpustate->to3(0, cpustate->tff3 );
688
INLINE void tlcs900_handle_timers( tlcs900_state *cpustate )
690
UINT32 old_pre = cpustate->timer_pre;
692
/* Is the pre-scaler active */
693
if ( cpustate->reg[TRUN] & 0x80 )
694
cpustate->timer_pre += cpustate->cycles;
697
if ( cpustate->reg[TRUN] & 0x01 )
699
switch( cpustate->reg[T01MOD] & 0x03 )
704
cpustate->timer_change[0] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
707
cpustate->timer_change[0] += ( cpustate->timer_pre >> 9 ) - ( old_pre >> 9 );
710
cpustate->timer_change[0] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
714
for( ; cpustate->timer_change[0] > 0; cpustate->timer_change[0]-- )
716
//printf("timer0 = %02x, TREG0 = %02x\n", cpustate->timer[0], cpustate->reg[TREG0] );
717
cpustate->timer[0] += 1;
718
if ( cpustate->timer[0] == cpustate->reg[TREG0] )
720
if ( ( cpustate->reg[T01MOD] & 0x0c ) == 0x00 )
722
cpustate->timer_change[1] += 1;
725
/* In 16bit timer mode the timer should not be reset */
726
if ( ( cpustate->reg[T01MOD] & 0xc0 ) != 0x40 )
728
cpustate->timer[0] = 0;
729
cpustate->reg[INTET10] |= 0x08;
736
if ( cpustate->reg[TRUN] & 0x02 )
738
switch( ( cpustate->reg[T01MOD] >> 2 ) & 0x03 )
740
case 0x00: /* TO0TRG */
743
cpustate->timer_change[1] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
746
cpustate->timer_change[1] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
748
case 0x03: /* T256 */
749
cpustate->timer_change[1] += ( cpustate->timer_pre >> 15 ) - ( old_pre >> 15 );
753
for( ; cpustate->timer_change[1] > 0; cpustate->timer_change[1]-- )
755
cpustate->timer[1] += 1;
756
if ( cpustate->timer[1] == cpustate->reg[TREG1] )
758
cpustate->timer[1] = 0;
759
cpustate->reg[INTET10] |= 0x80;
761
if ( cpustate->reg[TFFCR] & 0x02 )
763
tlcs900_change_tff( cpustate, 1, FF_INVERT );
766
/* In 16bit timer mode also reset timer 0 */
767
if ( ( cpustate->reg[T01MOD] & 0xc0 ) == 0x40 )
769
cpustate->timer[0] = 0;
776
if ( cpustate->reg[TRUN] & 0x04 )
778
switch( cpustate->reg[T23MOD] & 0x03 )
780
case 0x00: /* invalid */
782
cpustate->timer_change[2] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
785
cpustate->timer_change[2] += ( cpustate->timer_pre >> 9 ) - ( old_pre >> 9 );
788
cpustate->timer_change[2] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
792
for( ; cpustate->timer_change[2] > 0; cpustate->timer_change[2]-- )
794
cpustate->timer[2] += 1;
795
if ( cpustate->timer[2] == cpustate->reg[TREG2] )
797
if ( ( cpustate->reg[T23MOD] & 0x0c ) == 0x00 )
799
cpustate->timer_change[3] += 1;
802
/* In 16bit timer mode the timer should not be reset */
803
if ( ( cpustate->reg[T23MOD] & 0xc0 ) != 0x40 )
805
cpustate->timer[2] = 0;
806
cpustate->reg[INTET32] |= 0x08;
813
if ( cpustate->reg[TRUN] & 0x08 )
815
switch( ( cpustate->reg[T23MOD] >> 2 ) & 0x03 )
817
case 0x00: /* TO2TRG */
820
cpustate->timer_change[3] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
823
cpustate->timer_change[3] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
825
case 0x03: /* T256 */
826
cpustate->timer_change[3] += ( cpustate->timer_pre >> 15 ) - ( old_pre >> 15 );
830
for( ; cpustate->timer_change[3] > 0; cpustate->timer_change[3]-- )
832
cpustate->timer[3] += 1;
833
if ( cpustate->timer[3] == cpustate->reg[TREG3] )
835
cpustate->timer[3] = 0;
836
cpustate->reg[INTET32] |= 0x80;
838
if ( cpustate->reg[TFFCR] & 0x20 )
840
tlcs900_change_tff( cpustate, 3, FF_INVERT );
843
/* In 16bit timer mode also reset timer 2 */
844
if ( ( cpustate->reg[T23MOD] & 0xc0 ) == 0x40 )
846
cpustate->timer[2] = 0;
852
cpustate->timer_pre &= 0xffffff;
856
static CPU_EXECUTE( tlcs900 )
858
tlcs900_state *cpustate = get_safe_token(device);
862
const tlcs900inst *inst;
864
cpustate->cycles = 0;
866
if ( cpustate->check_irqs )
868
tlcs900_check_irqs( cpustate );
869
cpustate->check_irqs = 0;
872
debugger_instruction_hook( device, cpustate->pc.d );
874
if ( cpustate->halted )
876
cpustate->cycles += 8;
880
cpustate->op = RDOP();
881
inst = &mnemonic[cpustate->op];
882
prepare_operands( cpustate, inst );
884
/* Execute the instruction */
885
inst->opfunc( cpustate );
886
cpustate->cycles += inst->cycles;
889
tlcs900_handle_ad( cpustate );
891
tlcs900_handle_timers( cpustate );
893
tlcs900_check_hdma( cpustate );
895
cpustate->icount -= cpustate->cycles;
896
} while ( cpustate->icount > 0 );
900
static void tlcs900_input_level_change( tlcs900_state *cpustate, int input, int level )
906
if ( cpustate->level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE )
908
cpustate->nmi_state = level;
910
cpustate->level[TLCS900_NMI] = level;
917
/* Is INT0 functionality enabled? */
918
if ( cpustate->reg[IIMC] & 0x04 )
920
if ( cpustate->reg[IIMC] & 0x02 )
922
/* Rising edge detect */
923
if ( cpustate->level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE )
925
/* Leave HALT state */
926
cpustate->halted = 0;
927
cpustate->reg[INTE0AD] |= 0x08;
933
if ( level == ASSERT_LINE )
934
cpustate->reg[INTE0AD] |= 0x08;
936
cpustate->reg[INTE0AD] &= ~ 0x08;
939
cpustate->level[TLCS900_INT0] = level;
943
if ( ! ( cpustate->reg[PBCR] & 0x01 ) )
945
if ( cpustate->level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE )
947
cpustate->reg[INTE45] |= 0x08;
950
cpustate->level[TLCS900_INT4] = level;
954
if ( ! ( cpustate->reg[PBCR] & 0x02 ) )
956
if ( cpustate->level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE )
958
cpustate->reg[INTE45] |= 0x80;
961
cpustate->level[TLCS900_INT5] = level;
964
case TLCS900_TIO: /* External timer input for timer 0 */
965
if ( ( cpustate->reg[TRUN] & 0x01 ) && ( cpustate->reg[T01MOD] & 0x03 ) == 0x00 )
967
if ( cpustate->level[TLCS900_TIO] == CLEAR_LINE && level == ASSERT_LINE )
969
cpustate->timer_change[0] += 1;
972
cpustate->level[TLCS900_TIO] = level;
975
cpustate->check_irqs = 1;
979
static READ8_HANDLER( tlcs900_internal_r )
981
tlcs900_state *cpustate = get_safe_token( &space->device() );
983
return cpustate->reg[ offset ];
987
static WRITE8_HANDLER( tlcs900_internal_w )
989
tlcs900_state *cpustate = get_safe_token( &space->device() );
994
if ( ! ( data & 0x01 ) )
996
cpustate->timer[0] = 0;
997
cpustate->timer_change[0] = 0;
999
if ( ! ( data & 0x02 ) )
1001
cpustate->timer[1] = 0;
1002
cpustate->timer_change[1] = 0;
1004
if ( ! ( data & 0x04 ) )
1006
cpustate->timer[2] = 0;
1007
cpustate->timer_change[2] = 0;
1009
if ( ! ( data & 0x08 ) )
1011
cpustate->timer[3] = 0;
1012
cpustate->timer_change[3] = 0;
1014
if ( ! ( data & 0x10 ) )
1015
cpustate->timer[4] = 0;
1016
if ( ! ( data & 0x20 ) )
1017
cpustate->timer[5] = 0;
1021
switch( data & 0x0c )
1024
tlcs900_change_tff( cpustate, 1, FF_INVERT );
1027
tlcs900_change_tff( cpustate, 1, FF_SET );
1030
tlcs900_change_tff( cpustate, 1, FF_CLEAR );
1033
switch( data & 0xc0 )
1036
tlcs900_change_tff( cpustate, 3, FF_INVERT );
1039
tlcs900_change_tff( cpustate, 3, FF_SET );
1042
tlcs900_change_tff( cpustate, 3, FF_CLEAR );
1053
/* Preserve read-only bits */
1054
data = ( cpustate->reg[ADMOD] & 0xc0 ) | ( data & 0x3f );
1056
/* Check for A/D request start */
1061
cpustate->ad_cycles_left = ( data & 0x08 ) ? 640 : 320;
1081
data = ( data & 0x7f ) | ( cpustate->reg[offset] & 0x80 );
1083
data = ( data & 0xf7 ) | ( cpustate->reg[offset] & 0x08 );
1093
cpustate->check_irqs = 1;
1094
cpustate->reg[ offset ] = data;
1098
static ADDRESS_MAP_START( tlcs900_mem, AS_PROGRAM, 8 )
1099
AM_RANGE( 0x000000, 0x00007f ) AM_READWRITE( tlcs900_internal_r, tlcs900_internal_w )
1103
static CPU_SET_INFO( tlcs900 )
1105
tlcs900_state *cpustate = get_safe_token( device );
1109
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
1110
case CPUINFO_INT_INPUT_STATE + TLCS900_NMI:
1111
case CPUINFO_INT_INPUT_STATE + TLCS900_INTWD:
1112
case CPUINFO_INT_INPUT_STATE + TLCS900_INT0:
1113
case CPUINFO_INT_INPUT_STATE + TLCS900_INT4:
1114
case CPUINFO_INT_INPUT_STATE + TLCS900_INT5:
1115
case CPUINFO_INT_INPUT_STATE + TLCS900_TIO:
1116
tlcs900_input_level_change( cpustate, state - CPUINFO_INT_INPUT_STATE, info->i ); break;
1121
CPU_GET_INFO( tlcs900h )
1123
tlcs900_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL;
1127
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tlcs900_state); break;
1128
case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
1129
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
1130
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
1131
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
1132
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 7; break; /* FIXME */
1133
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; /* FIXME */
1134
case CPUINFO_INT_MAX_CYCLES: info->i = 1; break; /* FIXME */
1135
case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
1137
case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
1138
case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
1139
case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
1141
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
1142
case CPUINFO_INT_INPUT_STATE + TLCS900_NMI: info->i = cpustate->level[TLCS900_NMI]; break;
1143
case CPUINFO_INT_INPUT_STATE + TLCS900_INTWD: info->i = cpustate->level[TLCS900_INTWD]; break;
1144
case CPUINFO_INT_INPUT_STATE + TLCS900_INT0: info->i = cpustate->level[TLCS900_INT0]; break;
1145
case CPUINFO_INT_INPUT_STATE + TLCS900_INT4: info->i = cpustate->level[TLCS900_INT4]; break;
1146
case CPUINFO_INT_INPUT_STATE + TLCS900_INT5: info->i = cpustate->level[TLCS900_INT5]; break;
1147
case CPUINFO_INT_INPUT_STATE + TLCS900_TIO: info->i = cpustate->level[TLCS900_TIO]; break;
1149
case CPUINFO_INT_PC: info->i = cpustate->pc.d; break;
1150
case CPUINFO_INT_REGISTER + TLCS900_PC: info->i = cpustate->pc.d; break;
1151
case CPUINFO_INT_REGISTER + TLCS900_SR: info->i = cpustate->sr.d; break;
1152
case CPUINFO_INT_REGISTER + TLCS900_XWA0: info->i = cpustate->xwa[0].d; break;
1153
case CPUINFO_INT_REGISTER + TLCS900_XBC0: info->i = cpustate->xbc[0].d; break;
1154
case CPUINFO_INT_REGISTER + TLCS900_XDE0: info->i = cpustate->xde[0].d; break;
1155
case CPUINFO_INT_REGISTER + TLCS900_XHL0: info->i = cpustate->xhl[0].d; break;
1156
case CPUINFO_INT_REGISTER + TLCS900_XWA1: info->i = cpustate->xwa[1].d; break;
1157
case CPUINFO_INT_REGISTER + TLCS900_XBC1: info->i = cpustate->xbc[1].d; break;
1158
case CPUINFO_INT_REGISTER + TLCS900_XDE1: info->i = cpustate->xde[1].d; break;
1159
case CPUINFO_INT_REGISTER + TLCS900_XHL1: info->i = cpustate->xhl[1].d; break;
1160
case CPUINFO_INT_REGISTER + TLCS900_XWA2: info->i = cpustate->xwa[2].d; break;
1161
case CPUINFO_INT_REGISTER + TLCS900_XBC2: info->i = cpustate->xbc[2].d; break;
1162
case CPUINFO_INT_REGISTER + TLCS900_XDE2: info->i = cpustate->xde[2].d; break;
1163
case CPUINFO_INT_REGISTER + TLCS900_XHL2: info->i = cpustate->xhl[2].d; break;
1164
case CPUINFO_INT_REGISTER + TLCS900_XWA3: info->i = cpustate->xwa[3].d; break;
1165
case CPUINFO_INT_REGISTER + TLCS900_XBC3: info->i = cpustate->xbc[3].d; break;
1166
case CPUINFO_INT_REGISTER + TLCS900_XDE3: info->i = cpustate->xde[3].d; break;
1167
case CPUINFO_INT_REGISTER + TLCS900_XHL3: info->i = cpustate->xhl[3].d; break;
1168
case CPUINFO_INT_REGISTER + TLCS900_XIX: info->i = cpustate->xix.d; break;
1169
case CPUINFO_INT_REGISTER + TLCS900_XIY: info->i = cpustate->xiy.d; break;
1170
case CPUINFO_INT_REGISTER + TLCS900_XIZ: info->i = cpustate->xiz.d; break;
1171
case CPUINFO_INT_REGISTER + TLCS900_XNSP: info->i = cpustate->xnsp.d; break;
1172
case CPUINFO_INT_REGISTER + TLCS900_XSSP: info->i = cpustate->xssp.d; break;
1174
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tlcs900); break;
1175
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tlcs900); break;
1176
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tlcs900); break;
1177
case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tlcs900); break;
1178
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tlcs900); break;
1179
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tlcs900); break;
1180
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
1181
case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tlcs900_mem); break;
1183
case CPUINFO_STR_REGISTER + TLCS900_PC: sprintf( info->s, "PC:%08x", cpustate->pc.d ); break;
1184
case CPUINFO_STR_REGISTER + TLCS900_SR: sprintf( info->s, "SR:%c%d%c%d%c%c%c%c%c%c%c%c",
1185
cpustate->sr.w.l & 0x8000 ? 'S' : 'U',
1186
( cpustate->sr.w.l & 0x7000 ) >> 12,
1187
cpustate->sr.w.l & 0x0800 ? 'M' : 'N',
1188
( cpustate->sr.w.l & 0x0700 ) >> 8,
1189
cpustate->sr.w.l & 0x0080 ? 'S' : '.',
1190
cpustate->sr.w.l & 0x0040 ? 'Z' : '.',
1191
cpustate->sr.w.l & 0x0020 ? '1' : '.',
1192
cpustate->sr.w.l & 0x0010 ? 'H' : '.',
1193
cpustate->sr.w.l & 0x0008 ? '1' : '.',
1194
cpustate->sr.w.l & 0x0004 ? 'V' : '.',
1195
cpustate->sr.w.l & 0x0002 ? 'N' : '.',
1196
cpustate->sr.w.l & 0x0001 ? 'C' : '.' );
1198
case CPUINFO_STR_REGISTER + TLCS900_XWA0: sprintf( info->s, "XWA0:%08x", cpustate->xwa[0].d ); break;
1199
case CPUINFO_STR_REGISTER + TLCS900_XBC0: sprintf( info->s, "XBC0:%08x", cpustate->xbc[0].d ); break;
1200
case CPUINFO_STR_REGISTER + TLCS900_XDE0: sprintf( info->s, "XDE0:%08x", cpustate->xde[0].d ); break;
1201
case CPUINFO_STR_REGISTER + TLCS900_XHL0: sprintf( info->s, "XHL0:%08x", cpustate->xhl[0].d ); break;
1202
case CPUINFO_STR_REGISTER + TLCS900_XWA1: sprintf( info->s, "XWA1:%08x", cpustate->xwa[1].d ); break;
1203
case CPUINFO_STR_REGISTER + TLCS900_XBC1: sprintf( info->s, "XBC1:%08x", cpustate->xbc[1].d ); break;
1204
case CPUINFO_STR_REGISTER + TLCS900_XDE1: sprintf( info->s, "XDE1:%08x", cpustate->xde[1].d ); break;
1205
case CPUINFO_STR_REGISTER + TLCS900_XHL1: sprintf( info->s, "XHL1:%08x", cpustate->xhl[1].d ); break;
1206
case CPUINFO_STR_REGISTER + TLCS900_XWA2: sprintf( info->s, "XWA2:%08x", cpustate->xwa[2].d ); break;
1207
case CPUINFO_STR_REGISTER + TLCS900_XBC2: sprintf( info->s, "XBC2:%08x", cpustate->xbc[2].d ); break;
1208
case CPUINFO_STR_REGISTER + TLCS900_XDE2: sprintf( info->s, "XDE2:%08x", cpustate->xde[2].d ); break;
1209
case CPUINFO_STR_REGISTER + TLCS900_XHL2: sprintf( info->s, "XHL2:%08x", cpustate->xhl[2].d ); break;
1210
case CPUINFO_STR_REGISTER + TLCS900_XWA3: sprintf( info->s, "XWA3:%08x", cpustate->xwa[3].d ); break;
1211
case CPUINFO_STR_REGISTER + TLCS900_XBC3: sprintf( info->s, "XBC3:%08x", cpustate->xbc[3].d ); break;
1212
case CPUINFO_STR_REGISTER + TLCS900_XDE3: sprintf( info->s, "XDE3:%08x", cpustate->xde[3].d ); break;
1213
case CPUINFO_STR_REGISTER + TLCS900_XHL3: sprintf( info->s, "XHL3:%08x", cpustate->xhl[3].d ); break;
1214
case CPUINFO_STR_REGISTER + TLCS900_XIX: sprintf( info->s, "XIX:%08x", cpustate->xix.d ); break;
1215
case CPUINFO_STR_REGISTER + TLCS900_XIY: sprintf( info->s, "XIY:%08x", cpustate->xiy.d ); break;
1216
case CPUINFO_STR_REGISTER + TLCS900_XIZ: sprintf( info->s, "XIZ:%08x", cpustate->xiz.d ); break;
1217
case CPUINFO_STR_REGISTER + TLCS900_XNSP: sprintf( info->s, "XNSP:%08x", cpustate->xnsp.d ); break;
1218
case CPUINFO_STR_REGISTER + TLCS900_XSSP: sprintf( info->s, "XSSP:%08x", cpustate->xssp.d ); break;
1219
case CPUINFO_STR_REGISTER + TLCS900_DMAS0: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[0].d ); break;
1220
case CPUINFO_STR_REGISTER + TLCS900_DMAD0: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[0].d ); break;
1221
case CPUINFO_STR_REGISTER + TLCS900_DMAC0: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[0].w.l ); break;
1222
case CPUINFO_STR_REGISTER + TLCS900_DMAM0: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[0].b.l ); break;
1223
case CPUINFO_STR_REGISTER + TLCS900_DMAS1: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[1].d ); break;
1224
case CPUINFO_STR_REGISTER + TLCS900_DMAD1: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[1].d ); break;
1225
case CPUINFO_STR_REGISTER + TLCS900_DMAC1: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[1].w.l ); break;
1226
case CPUINFO_STR_REGISTER + TLCS900_DMAM1: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[1].b.l ); break;
1227
case CPUINFO_STR_REGISTER + TLCS900_DMAS2: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[2].d ); break;
1228
case CPUINFO_STR_REGISTER + TLCS900_DMAD2: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[2].d ); break;
1229
case CPUINFO_STR_REGISTER + TLCS900_DMAC2: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[2].w.l ); break;
1230
case CPUINFO_STR_REGISTER + TLCS900_DMAM2: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[2].b.l ); break;
1231
case CPUINFO_STR_REGISTER + TLCS900_DMAS3: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[3].d ); break;
1232
case CPUINFO_STR_REGISTER + TLCS900_DMAD3: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[3].d ); break;
1233
case CPUINFO_STR_REGISTER + TLCS900_DMAC3: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[3].w.l ); break;
1234
case CPUINFO_STR_REGISTER + TLCS900_DMAM3: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[3].b.l ); break;
1236
case DEVINFO_STR_NAME: strcpy( info->s, "TLCS-900/H" ); break;
1237
case DEVINFO_STR_FAMILY: strcpy( info->s, "Toshiba TLCS-900" ); break;
1238
case DEVINFO_STR_VERSION: strcpy( info->s, "0.1" ); break;
1239
case DEVINFO_STR_SOURCE_FILE: strcpy( info->s, __FILE__ ); break;
1240
case DEVINFO_STR_CREDITS: strcpy( info->s, "Copyright Wilbert Pol" ); break;
1244
DEFINE_LEGACY_CPU_DEVICE(TLCS900H, tlcs900h);