Previous 199869 Revisions Next

r18984 Friday 16th November, 2012 at 12:23:38 UTC by Michael Zapf
Fixed overflow detection in INC and DEC opcodes (nw)
[src/emu/cpu/tms9900]tms9900.c tms9995.c

trunk/src/emu/cpu/tms9900/tms9995.c
r18983r18984
9494/* tms9995 ST register bits. */
9595enum
9696{
97   ST_LH = 0x8000,      // Logical higher (unsigned comparison)
98   ST_AGT = 0x4000,   // Arithmetical greater than (signed comparison)
99   ST_EQ = 0x2000,      // Equal
100   ST_C = 0x1000,      // Carry
101   ST_OV = 0x0800,      // Overflow (when using signed operations)
102   ST_OP = 0x0400,      // Odd parity (used with byte operations)
103   ST_X = 0x0200,      // XOP
104   ST_OE = 0x0020,      // Overflow interrupt enabled
105   ST_IM = 0x000f      // Interrupt mask
97   ST_LH = 0x8000,     // Logical higher (unsigned comparison)
98   ST_AGT = 0x4000,    // Arithmetical greater than (signed comparison)
99   ST_EQ = 0x2000,     // Equal
100   ST_C = 0x1000,      // Carry
101   ST_OV = 0x0800,     // Overflow (when using signed operations)
102   ST_OP = 0x0400,     // Odd parity (used with byte operations)
103   ST_X = 0x0200,      // XOP
104   ST_OE = 0x0020,     // Overflow interrupt enabled
105   ST_IM = 0x000f      // Interrupt mask
106106};
107107
108108enum
r18983r18984
124124
125125tms9995_device::tms9995_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
126126   : cpu_device(mconfig, TMS9995, "TMS9995", tag, owner, clock),
127     m_program_config("program", ENDIANNESS_BIG, 8, 16),
128     m_io_config("cru", ENDIANNESS_BIG, 8, 16),
129     m_prgspace(NULL),
130     m_cru(NULL)
127      m_program_config("program", ENDIANNESS_BIG, 8, 16),
128      m_io_config("cru", ENDIANNESS_BIG, 8, 16),
129      m_prgspace(NULL),
130      m_cru(NULL)
131131{
132132}
133133
r18983r18984
148148
149149   // TODO: Restore save state suport
150150
151   m_prgspace = &space(AS_PROGRAM);                  // dimemory.h
151   m_prgspace = &space(AS_PROGRAM);                        // dimemory.h
152152   m_cru = &space(AS_IO);
153153
154154   // Resolve our external connections
r18983r18984
207207*/
208208void tms9995_device::device_reset()
209209{
210   m_reset = true;      // for the main loop
210   m_reset = true;     // for the main loop
211211}
212212
213213const char* tms9995_device::s_statename[20] =
r18983r18984
402402
403403MICROPROGRAM(operand_address_derivation)
404404{
405   RETADDR, 0, 0, 0,                     // Register direct                  0
406   WORD_READ, RETADDR, 0, 0,               // Register indirect                1 (1)
407   WORD_READ, RETADDR, 0, 0,               // Symbolic                         1 (1)
408   WORD_READ, INCREG, WORD_WRITE, RETADDR1,   // Reg indirect auto-increment      3 (1) (1)
409   WORD_READ, INDX, WORD_READ, RETADDR         // Indexed                          3 (1) (1)
405   RETADDR, 0, 0, 0,                           // Register direct                  0
406   WORD_READ, RETADDR, 0, 0,                   // Register indirect                1 (1)
407   WORD_READ, RETADDR, 0, 0,                   // Symbolic                         1 (1)
408   WORD_READ, INCREG, WORD_WRITE, RETADDR1,    // Reg indirect auto-increment      3 (1) (1)
409   WORD_READ, INDX, WORD_READ, RETADDR         // Indexed                          3 (1) (1)
410410};
411411
412412MICROPROGRAM(add_s_sxc_mp)
413413{
414   OPERAND_ADDR,         // x
415   MEMORY_READ,         // 1 (1)
416   OPERAND_ADDR,         // y
417   MEMORY_READ,         // 1 (1)
418   ALU_ADD_S_SXC,         // 0
419   PREFETCH,            // 1 (1)
420   MEMORY_WRITE,         // 1 (1)
414   OPERAND_ADDR,           // x
415   MEMORY_READ,            // 1 (1)
416   OPERAND_ADDR,           // y
417   MEMORY_READ,            // 1 (1)
418   ALU_ADD_S_SXC,          // 0
419   PREFETCH,               // 1 (1)
420   MEMORY_WRITE,           // 1 (1)
421421   END
422422};
423423
424424MICROPROGRAM(b_mp)
425425{
426426   OPERAND_ADDR,
427   ALU_NOP,            // Don't read, just use the address
427   ALU_NOP,                // Don't read, just use the address
428428   ALU_B,
429429   PREFETCH,
430   ALU_NOP,            // Don't save the return address
430   ALU_NOP,                // Don't save the return address
431431   END
432432};
433433
434434MICROPROGRAM(bl_mp)
435435{
436436   OPERAND_ADDR,
437   ALU_NOP,            // Don't read, just use the address
438   ALU_B,               // Re-use the alu operation from B
437   ALU_NOP,                // Don't read, just use the address
438   ALU_B,                  // Re-use the alu operation from B
439439   PREFETCH,
440440   ALU_NOP,
441   MEMORY_WRITE,         // Write R11
441   MEMORY_WRITE,           // Write R11
442442   ALU_NOP,
443443   END
444444};
445445
446446MICROPROGRAM(blwp_mp)
447447{
448   OPERAND_ADDR,         // Determine source address
448   OPERAND_ADDR,           // Determine source address
449449   MEMORY_READ,
450   ALU_BLWP,            // Got new WP, save it; increase address, save
451   MEMORY_WRITE,         // save old ST to new R15
450   ALU_BLWP,               // Got new WP, save it; increase address, save
451   MEMORY_WRITE,           // save old ST to new R15
452452   ALU_BLWP,
453   MEMORY_WRITE,         // save old PC to new R14
453   MEMORY_WRITE,           // save old PC to new R14
454454   ALU_BLWP,
455   MEMORY_WRITE,         // save old WP to new R13
456   ALU_BLWP,            // retrieve address
457   MEMORY_READ,         // Read new PC
458   ALU_BLWP,            // Set new PC
455   MEMORY_WRITE,           // save old WP to new R13
456   ALU_BLWP,               // retrieve address
457   MEMORY_READ,            // Read new PC
458   ALU_BLWP,               // Set new PC
459459   PREFETCH,
460460   ALU_NOP,
461461   END
r18983r18984
463463
464464MICROPROGRAM(c_mp)
465465{
466   OPERAND_ADDR,         // x
467   MEMORY_READ,         // 1 (1)
468   OPERAND_ADDR,         // y
469   MEMORY_READ,         // 1 (1)
470   ALU_C,               // 0
471   PREFETCH,            // 1 (1)
472   ALU_NOP,            // 1
466   OPERAND_ADDR,           // x
467   MEMORY_READ,            // 1 (1)
468   OPERAND_ADDR,           // y
469   MEMORY_READ,            // 1 (1)
470   ALU_C,                  // 0
471   PREFETCH,               // 1 (1)
472   ALU_NOP,                // 1
473473   END
474474};
475475
476476MICROPROGRAM(ci_mp)
477477{
478   MEMORY_READ,         // 1 (reg)
479   SET_IMM,            // 0
480   MEMORY_READ,         // 1 (imm)
481   ALU_CI,               // (1) set status
482   PREFETCH,            // 1
483   ALU_NOP,            // 1
478   MEMORY_READ,            // 1 (reg)
479   SET_IMM,                // 0
480   MEMORY_READ,            // 1 (imm)
481   ALU_CI,                 // (1) set status
482   PREFETCH,               // 1
483   ALU_NOP,                // 1
484484   END
485485};
486486
r18983r18984
500500{
501501   OPERAND_ADDR,
502502   ALU_NOP,
503   ALU_CLR_SETO,         // (1)
504   PREFETCH,            // 1
505   MEMORY_WRITE,         // 1
503   ALU_CLR_SETO,           // (1)
504   PREFETCH,               // 1
505   MEMORY_WRITE,           // 1
506506   END
507507};
508508
509509MICROPROGRAM(divide_mp)
510510{
511   OPERAND_ADDR,         // Address of divisor S in Q=W1W2/S
512   MEMORY_READ,         // Get S
511   OPERAND_ADDR,           // Address of divisor S in Q=W1W2/S
512   MEMORY_READ,            // Get S
513513   ALU_DIV,
514   MEMORY_READ,         // Get W1
515   ALU_DIV,            // Check for overflow; skip next instruction if not
514   MEMORY_READ,            // Get W1
515   ALU_DIV,                // Check for overflow; skip next instruction if not
516516   ABORT,
517   MEMORY_READ,         // Get W2
518   ALU_DIV,            // Calculate quotient
519   MEMORY_WRITE,         // Write quotient to &W1
517   MEMORY_READ,            // Get W2
518   ALU_DIV,                // Calculate quotient
519   MEMORY_WRITE,           // Write quotient to &W1
520520   ALU_DIV,
521521   PREFETCH,
522   MEMORY_WRITE,         // Write remainder to &W2
522   MEMORY_WRITE,           // Write remainder to &W2
523523   END
524524};
525525
526526MICROPROGRAM(divide_signed_mp)
527527{
528   OPERAND_ADDR,         // Address of divisor S in Q=W1W2/S
529   MEMORY_READ,         // Get S
528   OPERAND_ADDR,           // Address of divisor S in Q=W1W2/S
529   MEMORY_READ,            // Get S
530530   ALU_DIV,
531   MEMORY_READ,         // Get W1
532   ALU_DIV,            //
533   MEMORY_READ,         // Get W2
534   ALU_DIV,            // Check for overflow, skip next instruction if not
531   MEMORY_READ,            // Get W1
532   ALU_DIV,                //
533   MEMORY_READ,            // Get W2
534   ALU_DIV,                // Check for overflow, skip next instruction if not
535535   ABORT,
536   ALU_DIV,            // Calculate quotient
537   MEMORY_WRITE,         // Write quotient to &W1
536   ALU_DIV,                // Calculate quotient
537   MEMORY_WRITE,           // Write quotient to &W1
538538   ALU_DIV,
539539   PREFETCH,
540   MEMORY_WRITE,         // Write remainder to &W2
540   MEMORY_WRITE,           // Write remainder to &W2
541541   END
542542};
543543
r18983r18984
557557MICROPROGRAM(imm_arithm_mp)
558558{
559559   MEMORY_READ,
560   SET_IMM,            // 0
561   MEMORY_READ,         // 1 (1)
562   ALU_IMM_ARITHM,         // 0
563   PREFETCH,            // 1 (1)
560   SET_IMM,                // 0
561   MEMORY_READ,            // 1 (1)
562   ALU_IMM_ARITHM,         // 0
563   PREFETCH,               // 1 (1)
564564   MEMORY_WRITE,
565565   END
566566};
r18983r18984
577577{
578578   ALU_LDCR,
579579   OPERAND_ADDR,
580   MEMORY_READ,         // Get source data
581   ALU_LDCR,            // Save it, point to R12
582   WORD_READ,            // Get R12
583   ALU_LDCR,            // Prepare CRU operation
580   MEMORY_READ,            // Get source data
581   ALU_LDCR,               // Save it, point to R12
582   WORD_READ,              // Get R12
583   ALU_LDCR,               // Prepare CRU operation
584584   CRU_OUTPUT,
585585   ALU_NOP,
586586   PREFETCH,
r18983r18984
590590
591591MICROPROGRAM(li_mp)
592592{
593   SET_IMM,            // 0
594   MEMORY_READ,         // 1 (1)
595   ALU_LI,               // 0
596   PREFETCH,            // 1 (1)
593   SET_IMM,                // 0
594   MEMORY_READ,            // 1 (1)
595   ALU_LI,                 // 0
596   PREFETCH,               // 1 (1)
597597   MEMORY_WRITE,
598598   END
599599};
600600
601601MICROPROGRAM(limi_lwpi_mp)
602602{
603   SET_IMM,            // 0
604   MEMORY_READ,         // 1 (1)
605   ALU_NOP,            // 1
606   ALU_LIMIWP,            // (1)
607   PREFETCH,            // 1
608   ALU_NOP,            // 1
603   SET_IMM,                // 0
604   MEMORY_READ,            // 1 (1)
605   ALU_NOP,                // 1
606   ALU_LIMIWP,             // (1)
607   PREFETCH,               // 1
608   ALU_NOP,                // 1
609609   END
610610};
611611
r18983r18984
621621
622622MICROPROGRAM(mov_mp)
623623{
624   OPERAND_ADDR,         // 0
625   MEMORY_READ,         // 1 (1)
626   OPERAND_ADDR,         // 0
627   ALU_MOV,            // 1
624   OPERAND_ADDR,           // 0
625   MEMORY_READ,            // 1 (1)
626   OPERAND_ADDR,           // 0
627   ALU_MOV,                // 1
628628   PREFETCH,
629   MEMORY_WRITE,         // 1 (1)
629   MEMORY_WRITE,           // 1 (1)
630630   END
631631};
632632
r18983r18984
660660
661661MICROPROGRAM(sbo_sbz_mp)
662662{
663   ALU_SBO_SBZ,         // Set address = &R12
664   WORD_READ,            // Read R12
665   ALU_SBO_SBZ,         // Add offset
666   CRU_OUTPUT,            // output via CRU
663   ALU_SBO_SBZ,            // Set address = &R12
664   WORD_READ,              // Read R12
665   ALU_SBO_SBZ,            // Add offset
666   CRU_OUTPUT,             // output via CRU
667667   ALU_NOP,
668668   PREFETCH,
669669   ALU_NOP,
r18983r18984
673673MICROPROGRAM(shift_mp)
674674{
675675   MEMORY_READ,
676   ALU_SHIFT,            // skip next operation if count != 0
677   MEMORY_READ,         // if count=0 we must read R0
678   ALU_SHIFT,            // do the shift
676   ALU_SHIFT,              // skip next operation if count != 0
677   MEMORY_READ,            // if count=0 we must read R0
678   ALU_SHIFT,              // do the shift
679679   PREFETCH,
680680   MEMORY_WRITE,
681681   END
r18983r18984
684684MICROPROGRAM(single_arithm_mp)
685685{
686686   OPERAND_ADDR,
687   MEMORY_READ,         // This one is not done for CLR/SETO
687   MEMORY_READ,            // This one is not done for CLR/SETO
688688   ALU_SINGLE_ARITHM,
689689   PREFETCH,
690690   MEMORY_WRITE,
r18983r18984
693693
694694MICROPROGRAM(stcr_mp)
695695{
696   ALU_STCR,            // Check for byte operation
697   OPERAND_ADDR,         // Source operand
698   ALU_STCR,            // Save, set R12
699   WORD_READ,            // Read R12
696   ALU_STCR,               // Check for byte operation
697   OPERAND_ADDR,           // Source operand
698   ALU_STCR,               // Save, set R12
699   WORD_READ,              // Read R12
700700   ALU_STCR,
701701   CRU_INPUT,
702702   ALU_STCR,
r18983r18984
731731   OPERAND_ADDR,
732732   MEMORY_READ,
733733   ALU_X,
734   END                  // should not be reached
734   END                     // should not be reached
735735};
736736
737737MICROPROGRAM(xop_mp)
738738{
739   OPERAND_ADDR,         // Determine source address
740   ALU_XOP,            // Save it; determine XOP number
741   MEMORY_READ,         // Read new WP
742   ALU_XOP,            //
743   MEMORY_WRITE,         // save source address to new R11
739   OPERAND_ADDR,           // Determine source address
740   ALU_XOP,                // Save it; determine XOP number
741   MEMORY_READ,            // Read new WP
742   ALU_XOP,                //
743   MEMORY_WRITE,           // save source address to new R11
744744   ALU_XOP,
745   MEMORY_WRITE,         // save old ST to new R15
745   MEMORY_WRITE,           // save old ST to new R15
746746   ALU_XOP,
747   MEMORY_WRITE,         // save old PC to new R14
747   MEMORY_WRITE,           // save old PC to new R14
748748   ALU_XOP,
749   MEMORY_WRITE,         // save old WP to new R13
749   MEMORY_WRITE,           // save old WP to new R13
750750   ALU_XOP,
751   MEMORY_READ,         // Read new PC
752   ALU_XOP,            // set new PC, set X flag
751   MEMORY_READ,            // Read new PC
752   ALU_XOP,                // set new PC, set X flag
753753   PREFETCH,
754754   ALU_NOP,
755755   END
r18983r18984
769769
770770MICROPROGRAM(int_mp)
771771{
772   ALU_INT,            // 1
773   MEMORY_READ,         // 1 (1)
774   ALU_INT,            // 2
775   MEMORY_WRITE,         // 1 (1)
776   ALU_INT,            // 1
777   MEMORY_WRITE,         // 1 (1)
778   ALU_INT,            // 1
779   MEMORY_WRITE,         // 1 (1)
780   ALU_INT,            // 1
781   MEMORY_READ,         // 1 (1)
782   ALU_INT,            // 0
783   PREFETCH_NO_INT,      // 1 (1)  (prefetch happens in parallel to the previous operation)
784   ALU_NOP,            // 1 (+decode in parallel; actually performed right after prefetch)
785   ALU_NOP,            // 1
772   ALU_INT,                // 1
773   MEMORY_READ,            // 1 (1)
774   ALU_INT,                // 2
775   MEMORY_WRITE,           // 1 (1)
776   ALU_INT,                // 1
777   MEMORY_WRITE,           // 1 (1)
778   ALU_INT,                // 1
779   MEMORY_WRITE,           // 1 (1)
780   ALU_INT,                // 1
781   MEMORY_READ,            // 1 (1)
782   ALU_INT,                // 0
783   PREFETCH_NO_INT,        // 1 (1)  (prefetch happens in parallel to the previous operation)
784   ALU_NOP,                // 1 (+decode in parallel; actually performed right after prefetch)
785   ALU_NOP,                // 1
786786   END
787787};
788788
r18983r18984
860860
861861static const char opname[][5] =
862862{   "MID ", "A   ", "AB  ", "ABS ", "AI  ", "ANDI", "B   ", "BL  ", "BLWP", "C   ",
863   "CB  ", "CI  ",   "CKOF", "CKON", "CLR ", "COC ", "CZC ", "DEC ", "DECT", "DIV ",
863   "CB  ", "CI  ", "CKOF", "CKON", "CLR ", "COC ", "CZC ", "DEC ", "DECT", "DIV ",
864864   "DIVS", "IDLE", "INC ", "INCT", "INV ", "JEQ ", "JGT ", "JH  ", "JHE ", "JL  ",
865865   "JLE ", "JLT ", "JMP ", "JNC ", "JNE ", "JNO ", "JOC ", "JOP ", "LDCR", "LI  ",
866866   "LIMI", "LREX", "LST ", "LWP ", "LWPI", "MOV ", "MOVB", "MPY ", "MPYS", "NEG ",
867   "ORI ", "RSET",   "RTWP", "S   ", "SB  ", "SBO ", "SBZ ", "SETO", "SLA ", "SOC ",
868   "SOCB", "SRA ", "SRC ", "SRL ",   "STCR", "STST", "STWP", "SWPB", "SZC ", "SZCB",
867   "ORI ", "RSET", "RTWP", "S   ", "SB  ", "SBO ", "SBZ ", "SETO", "SLA ", "SOC ",
868   "SOCB", "SRA ", "SRC ", "SRL ", "STCR", "STST", "STWP", "SWPB", "SZC ", "SZCB",
869869   "TB  ", "X   ", "XOP ", "XOR ", "*int"
870870};
871871
r18983r18984
11871187   {
11881188      m_clock_out_line(ASSERT_LINE);
11891189      m_clock_out_line(CLEAR_LINE);
1190      m_icount--;                     // This is the only location where we count down the cycles.
1190      m_icount--;                         // This is the only location where we count down the cycles.
11911191      if (VERBOSE>7) LOG("tms9995: pulse_clock\n");
11921192      if (m_flag[0] == false && m_flag[1] == true) trigger_decrementer();
11931193   }
r18983r18984
13091309      if (VERBOSE>7) LOG("tms9995: Checking interrupts ... NMI active\n");
13101310      m_int_pending |= PENDING_NMI;
13111311      m_idle_state = false;
1312      PC = (PC + 2) & 0xfffe;      // we have not prefetched the next instruction
1312      PC = (PC + 2) & 0xfffe;     // we have not prefetched the next instruction
13131313   }
13141314   else
13151315   {
r18983r18984
13271327            m_idle_state = false;
13281328            if (VERBOSE>7) LOG("tms9995: Interrupt occured, terminate IDLE state\n");
13291329         }
1330         PC = PC + 2;      // PC must be advanced (see flow chart), but no prefetch
1330         PC = PC + 2;        // PC must be advanced (see flow chart), but no prefetch
13311331         if (VERBOSE>7) LOG("tms9995: Interrupts pending; no prefetch; advance PC to %04x\n", PC);
13321332      }
13331333      else
r18983r18984
13621362      // Second pass for getting the instruction
13631363      if (VERBOSE>6) LOG("tms9995: Prefetch memory access (second pass)\n");
13641364      word_read();
1365      decode(m_current_value);         // This is for free; in reality it is in parallel with the next memory operation
1366      m_address = m_address_copy;      // restore m_address
1367      m_current_value = m_value_copy;   // restore m_current_value
1368      PC = (PC + 2) & 0xfffe;      // advance PC
1365      decode(m_current_value);            // This is for free; in reality it is in parallel with the next memory operation
1366      m_address = m_address_copy;     // restore m_address
1367      m_current_value = m_value_copy; // restore m_current_value
1368      PC = (PC + 2) & 0xfffe;     // advance PC
13691369      m_iaq_line(CLEAR_LINE);
13701370      if (VERBOSE>5) LOG("tms9995: ++++ Prefetch done ++++\n");
13711371      m_lowbyte = false;
r18983r18984
13831383
13841384      if (VERBOSE>5) LOG("tms9995: **** Prefetching new instruction at %04x ****\n", PC);
13851385
1386      m_lowbyte = false;   // for mem_read
1387      word_read();         // this is where the clock pulses occur
1386      m_lowbyte = false;  // for mem_read
1387      word_read();            // this is where the clock pulses occur
13881388
13891389      if (!m_lowbyte)
13901390      {
13911391         // Only if we got the word in one pass
1392         decode(m_current_value);   // This is for free; in reality it is in parallel with the next memory operation
1392         decode(m_current_value);    // This is for free; in reality it is in parallel with the next memory operation
13931393
1394         m_address = m_address_copy;         // restore m_address
1395         m_current_value = m_value_copy;      // restore m_current_value
1396         PC = (PC + 2) & 0xfffe;      // advance PC
1394         m_address = m_address_copy;         // restore m_address
1395         m_current_value = m_value_copy;     // restore m_current_value
1396         PC = (PC + 2) & 0xfffe;     // advance PC
13971397
13981398         m_iaq_line(CLEAR_LINE);
13991399      }
r18983r18984
14701470   if (m_reset)
14711471   {
14721472      vectorpos = 0;
1473      m_intmask = 0;   // clear interrupt mask
1473      m_intmask = 0;  // clear interrupt mask
14741474
14751475      m_nmi_state = false;
14761476      m_hold_state = false;
r18983r18984
15651565   }
15661566   MPC = 0;
15671567   m_first_cycle = m_icount;
1568   m_check_ready = false;      // set to default
1568   m_check_ready = false;      // set to default
15691569}
15701570
15711571/*
r18983r18984
20362036   m_regnumber = (ircopy & 0x000f);
20372037   m_address = (WP + (m_regnumber<<1)) & 0xffff;
20382038
2039   m_source_value = m_current_value;   // will be overwritten when reading the destination
2040   m_current_value = m_address;      // needed for first case
2039   m_source_value = m_current_value;   // will be overwritten when reading the destination
2040   m_current_value = m_address;        // needed for first case
20412041
2042   if (MPC==8)   // Symbolic
2042   if (MPC==8) // Symbolic
20432043   {
20442044      if (m_regnumber != 0)
20452045      {
r18983r18984
20572057   m_get_destination = true;
20582058   m_lowbyte = false;
20592059   m_address_add = 0;
2060   MPC--;      // will be increased in the mail loop
2060   MPC--;      // will be increased in the mail loop
20612061   if (VERBOSE>8) LOG("tms9995: *** Operand address derivation; address=%04x; index=%d\n", m_address, MPC+1);
20622062}
20632063
r18983r18984
20672067*/
20682068void tms9995_device::increment_register()
20692069{
2070   m_address_saved = m_current_value;   // need a special return so we do not lose the value
2070   m_address_saved = m_current_value;  // need a special return so we do not lose the value
20712071   m_current_value += m_instruction->byteop? 1 : 2;
20722072   m_address = (WP + (m_regnumber<<1)) & 0xffff;
20732073   m_lowbyte = false;
r18983r18984
20932093   // Need to determine the register address
20942094   m_address_saved = WP + ((m_instruction->IR & 0x000f)<<1);
20952095   m_address = PC;
2096   m_source_value = m_current_value;      // needed for AI, ANDI, ORI
2096   m_source_value = m_current_value;       // needed for AI, ANDI, ORI
20972097   PC = (PC + 2) & 0xfffe;
20982098   m_lowbyte = false;
20992099}
r18983r18984
22382238      m_address = m_address - 2;
22392239      break;
22402240   case 2:
2241      m_current_value = m_value_copy;      // old WP
2241      m_current_value = m_value_copy;     // old WP
22422242      m_address = m_address - 2;
22432243      break;
22442244   case 3:
r18983r18984
23232323      // or equivalently, dividend / 0x10000 >= divisor
23242324
23252325      // Check overflow for unsigned DIV
2326      if (m_current_value < m_source_value)   // also if source=0
2326      if (m_current_value < m_source_value)   // also if source=0
23272327      {
2328         MPC++;   // skip the abort
2328         MPC++;  // skip the abort
23292329         overflow = false;
23302330      }
23312331      set_status_bit(ST_OV, overflow);
2332      m_value_copy = m_current_value;         // Save the high word
2332      m_value_copy = m_current_value;         // Save the high word
23332333      m_address = m_address + 2;
23342334      break;
23352335   case 2:
r18983r18984
24122412      // requires much less cycles when there is an overflow, so it seems as
24132413      // if this is tested before the algorithm starts.
24142414
2415      if ((w1 & 0x8000)==0)      // positive dividend
2415      if ((w1 & 0x8000)==0)       // positive dividend
24162416      {
2417         if ((d & 0x8000)==0)   // positive divisor
2417         if ((d & 0x8000)==0)    // positive divisor
24182418         {
2419            if ((d & 1)==0)      // even divisor
2419            if ((d & 1)==0)     // even divisor
24202420            {
24212421               if (w1 < d/2) overflow = false;
24222422            }
2423            else            // odd divisor
2423            else                // odd divisor
24242424            {
24252425               if ((w1 < (d-1)/2) || (w1 == (d-1)/2 && w2 < 0x8000)) overflow = false;
24262426            }
24272427         }
2428         else               // negative divisor
2428         else                    // negative divisor
24292429         {
24302430            d = -d;
2431            if ((d & 1)==0)      // even divisor
2431            if ((d & 1)==0)     // even divisor
24322432            {
24332433               if ((w1 < d/2) || (w1 == d/2 && w2 < d)) overflow = false;
24342434            }
2435            else            // odd divisor
2435            else                // odd divisor
24362436            {
24372437               if ((w1 < (d+1)/2) || (w1 == (d+1)/2 && w2 < 0x8000+d)) overflow = false;
24382438            }
24392439         }
24402440      }
2441      else                  // negative dividend
2441      else                        // negative dividend
24422442      {
24432443         w1 = -w1;
2444         if ((d & 0x8000)==0)   // positive divisor
2444         if ((d & 0x8000)==0)    // positive divisor
24452445         {
2446            if ((d & 1)==0)      // even divisor
2446            if ((d & 1)==0)     // even divisor
24472447            {
24482448               if ((w1 < d/2+1) || (w1 == d/2+1 && w2 > (-d))) overflow = false;
24492449            }
2450            else            // odd divisor
2450            else                // odd divisor
24512451            {
24522452               if ((w1 < (d+1)/2) || (w1 == (d+1)/2 && w2 > 0x8000-d)) overflow = false;
24532453            }
24542454         }
2455         else               // negative divisor
2455         else                    // negative divisor
24562456         {
24572457            d = -d;
2458            if ((d & 1)==0)      // even divisor
2458            if ((d & 1)==0)     // even divisor
24592459            {
24602460               if ((w1 < d/2) || (w1 == d/2 && w2 > 0)) overflow = false;
24612461            }
2462            else            // odd divisor
2462            else                // odd divisor
24632463            {
24642464               if ((w1 < (d+1)/2) || (w1 == (d+1)/2 && w2 > 0x8000)) overflow = false;
24652465            }
24662466         }
24672467      }
24682468      set_status_bit(ST_OV, overflow);
2469      if (!overflow) MPC++;      // Skip the next microinstruction when there is no overflow
2469      if (!overflow) MPC++;       // Skip the next microinstruction when there is no overflow
24702470      break;
24712471   case 3:
24722472      // We are here because there was no overflow
2473      w = (m_value_copy << 16) |   m_current_value;
2473      w = (m_value_copy << 16) |  m_current_value;
24742474      // Do the calculation
24752475      m_current_value =  (UINT16)(w / (INT16)m_source_value);
24762476      m_value_copy = (UINT16)(w % (INT16)m_source_value);
r18983r18984
26272627   case JLT:   // LAECOP == x00xxx
26282628      cond = ((ST & (ST_AGT | ST_EQ))==0);
26292629      break;
2630   case JLE:   // LAECOP == 0xxxxx
2630   case JLE:   // LAECOP == 0xxxxx
26312631      cond = ((ST & ST_LH)==0);
26322632      break;
2633   case JEQ:   // LAECOP == xx1xxx
2633   case JEQ:   // LAECOP == xx1xxx
26342634      cond = ((ST & ST_EQ)!=0);
26352635      break;
2636   case JHE:   // LAECOP == 1x0xxx, 0x1xxx
2636   case JHE:   // LAECOP == 1x0xxx, 0x1xxx
26372637      cond = ((ST & (ST_LH | ST_EQ)) != 0);
26382638      break;
2639   case JGT:   // LAECOP == x1xxxx
2639   case JGT:   // LAECOP == x1xxxx
26402640      cond = ((ST & ST_AGT)!=0);
26412641      break;
2642   case JNE:   // LAECOP == xx0xxx
2642   case JNE:   // LAECOP == xx0xxx
26432643      cond = ((ST & ST_EQ)==0);
26442644      break;
2645   case JNC:   // LAECOP == xxx0xx
2645   case JNC:   // LAECOP == xxx0xx
26462646      cond = ((ST & ST_C)==0);
26472647      break;
2648   case JOC:   // LAECOP == xxx1xx
2648   case JOC:   // LAECOP == xxx1xx
26492649      cond = ((ST & ST_C)!=0);
26502650      break;
2651   case JNO:   // LAECOP == xxxx0x
2651   case JNO:   // LAECOP == xxxx0x
26522652      cond = ((ST & ST_OV)==0);
26532653      break;
2654   case JL:   // LAECOP == 0x0xxx
2654   case JL:    // LAECOP == 0x0xxx
26552655      cond = ((ST & (ST_LH | ST_EQ)) == 0);
26562656      break;
2657   case JH:   // LAECOP == 1xxxxx
2657   case JH:    // LAECOP == 1xxxxx
26582658      cond = ((ST & ST_LH)!=0);
26592659      break;
2660   case JOP:   // LAECOP == xxxxx1
2660   case JOP:   // LAECOP == xxxxx1
26612661      cond = ((ST & ST_OP)!=0);
26622662      break;
26632663   }
r18983r18984
27282728   {
27292729      ST = (ST & 0xfff0) | (m_current_value & 0x000f);
27302730      if (VERBOSE>7) LOG("tms9995: ST = %04x\n", ST);
2731      pulse_clock(1);      // needs one more than LWPI
2731      pulse_clock(1);     // needs one more than LWPI
27322732   }
27332733   else
27342734   {
r18983r18984
28472847   switch (m_instruction->state)
28482848   {
28492849   case 0:
2850      m_address = WP + 30;      // R15
2850      m_address = WP + 30;        // R15
28512851      break;
28522852   case 1:
28532853      ST = m_current_value;
2854      m_address -= 2;            // R14
2854      m_address -= 2;             // R14
28552855      break;
28562856   case 2:
28572857      PC = m_current_value;
2858      m_address -= 2;            // R13
2858      m_address -= 2;             // R13
28592859      break;
28602860   case 3:
28612861      WP = m_current_value;
r18983r18984
29562956      set_status_bit(ST_C, carry);
29572957      set_status_bit(ST_OV, overflow);
29582958      compare_and_set_lae(m_current_value, 0);
2959      m_address = m_address_saved;      // Register address
2959      m_address = m_address_saved;        // Register address
29602960      if (VERBOSE>7) LOG("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
29612961      break;
29622962   }
r18983r18984
30493049      return;
30503050   }
30513051
3052   if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)!=sign) && ((dest_new & 0x8000)==sign));
3052   if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)==sign) && ((dest_new & 0x8000)!=sign));
30533053   set_status_bit(ST_C, (dest_new & 0x10000) != 0);
30543054   m_current_value = dest_new & 0xffff;
30553055   compare_and_set_lae(m_current_value, 0);
r18983r18984
31693169      break;
31703170   case 1:
31713171      // m_current_value is new WP
3172      m_value_copy = WP;   // store this for later
3172      m_value_copy = WP;  // store this for later
31733173      WP = m_current_value;
31743174      m_address = WP + 0x0016; // Address of new R11
31753175      m_current_value = m_address_saved;
r18983r18984
32153215      if (VERBOSE>7) LOG("tms9995: interrupt service (0): Prepare to read vector\n");
32163216      break;
32173217   case 1:
3218      pulse = 2;               // two cycles (with the one at the end)
3219      m_source_value = WP;      // old WP
3220      WP = m_current_value;      // new WP
3218      pulse = 2;                  // two cycles (with the one at the end)
3219      m_source_value = WP;        // old WP
3220      WP = m_current_value;       // new WP
32213221      m_current_value = ST;
32223222      m_address = (WP + 30)&0xfffe;
32233223      if (VERBOSE>7) LOG("tms9995: interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address);
r18983r18984
32293229      break;
32303230   case 3:
32313231      m_address = (WP + 26)&0xfffe;
3232      m_current_value = m_source_value;   // old WP
3232      m_current_value = m_source_value;   // old WP
32333233      if (VERBOSE>7) LOG("tms9995: interrupt service (3): Save WP to %04x\n", m_address);
32343234      break;
32353235   case 4:
r18983r18984
32473247         m_int_pending &= ~PENDING_MID;
32483248         m_address = 0xfffc;
32493249         m_intmask = 0;
3250         MPC = 0;   // redo the interrupt service for the NMI
3250         MPC = 0;    // redo the interrupt service for the NMI
32513251      }
32523252      else
32533253      {
trunk/src/emu/cpu/tms9900/tms9900.c
r18983r18984
107107/* tms9900 ST register bits. */
108108enum
109109{
110   ST_LH = 0x8000,      // Logical higher (unsigned comparison)
111   ST_AGT = 0x4000,   // Arithmetical greater than (signed comparison)
112   ST_EQ = 0x2000,      // Equal
113   ST_C = 0x1000,      // Carry
114   ST_OV = 0x0800,      // Overflow (when using signed operations)
115   ST_OP = 0x0400,      // Odd parity (used with byte operations)
116   ST_X = 0x0200,      // XOP
117   ST_IM = 0x000f      // Interrupt mask
110   ST_LH = 0x8000,     // Logical higher (unsigned comparison)
111   ST_AGT = 0x4000,    // Arithmetical greater than (signed comparison)
112   ST_EQ = 0x2000,     // Equal
113   ST_C = 0x1000,      // Carry
114   ST_OV = 0x0800,     // Overflow (when using signed operations)
115   ST_OP = 0x0400,     // Odd parity (used with byte operations)
116   ST_X = 0x0200,      // XOP
117   ST_IM = 0x000f      // Interrupt mask
118118};
119119
120120#define LOG logerror
r18983r18984
128128
129129tms99xx_device::tms99xx_device(const machine_config &mconfig, device_type type,  const char *name, const char *tag, int databus_width, int prg_addr_bits, int cru_addr_bits, device_t *owner, UINT32 clock)
130130   : cpu_device(mconfig, type, name, tag, owner, clock),
131     m_program_config("program", ENDIANNESS_BIG, databus_width, prg_addr_bits),
132     m_io_config("cru", ENDIANNESS_BIG, 8, cru_addr_bits),
133     m_prgspace(NULL),
134     m_cru(NULL),
135     m_prgaddr_mask((1<<prg_addr_bits)-1),
136     m_cruaddr_mask((1<<cru_addr_bits)-1)
131      m_program_config("program", ENDIANNESS_BIG, databus_width, prg_addr_bits),
132      m_io_config("cru", ENDIANNESS_BIG, 8, cru_addr_bits),
133      m_prgspace(NULL),
134      m_cru(NULL),
135      m_prgaddr_mask((1<<prg_addr_bits)-1),
136      m_cruaddr_mask((1<<cru_addr_bits)-1)
137137{
138138}
139139
r18983r18984
167167
168168   // TODO: Restore state save feature
169169
170   m_prgspace = &space(AS_PROGRAM);                  // dimemory.h
170   m_prgspace = &space(AS_PROGRAM);                        // dimemory.h
171171   m_cru = &space(AS_IO);
172172
173173   // Resolve our external connections
r18983r18984
417417*/
418418MICROPROGRAM(data_derivation)
419419{
420   REG_READ, RET, 0, 0, 0, 0, 0, 0,                                    // Rx           (00)
420   REG_READ, RET, 0, 0, 0, 0, 0, 0,                                                // Rx           (00)
421421   0, 0, 0, 0, 0, 0, 0, 0,
422   REG_READ, ALU_SETADDR, MEMORY_READ, RET, 0, 0, 0, 0,                     // *Rx          (01)
422   REG_READ, ALU_SETADDR, MEMORY_READ, RET, 0, 0, 0, 0,                            // *Rx          (01)
423423   0, 0, 0, 0, 0, 0, 0, 0,
424   ALU_CLR, ALU_PCADDR_ADVANCE, MEMORY_READ, ALU_ADDREG, MEMORY_READ, RET, 0, 0,   // @sym         (10)
425   REG_READ, ALU_PCADDR_ADVANCE, MEMORY_READ, ALU_ADDREG, MEMORY_READ, RET, 0, 0,   // @sym(Rx)     (10)
426   REG_READ, ALU_SETADDR_ADDONE, ALU_ADDONE, REG_WRITE, MEMORY_READ, RET, 0, 0,   // *Rx+ (word)  (11)
427   REG_READ, ALU_SETADDR_ADDONE, REG_WRITE, MEMORY_READ, RET, 0, 0, 0            // *Rx+ (byte)  (11)
424   ALU_CLR, ALU_PCADDR_ADVANCE, MEMORY_READ, ALU_ADDREG, MEMORY_READ, RET, 0, 0,   // @sym         (10)
425   REG_READ, ALU_PCADDR_ADVANCE, MEMORY_READ, ALU_ADDREG, MEMORY_READ, RET, 0, 0,  // @sym(Rx)     (10)
426   REG_READ, ALU_SETADDR_ADDONE, ALU_ADDONE, REG_WRITE, MEMORY_READ, RET, 0, 0,    // *Rx+ (word)  (11)
427   REG_READ, ALU_SETADDR_ADDONE, REG_WRITE, MEMORY_READ, RET, 0, 0, 0              // *Rx+ (byte)  (11)
428428};
429429
430430MICROPROGRAM(f1_mp)
431431{
432432   ALU_NOP,
433433   DATA_DERIVE,
434   ALU_SOURCE,         // Store the word
434   ALU_SOURCE,         // Store the word
435435   DATA_DERIVE,
436436   ALU_F1,
437437   MEMORY_WRITE,
r18983r18984
445445   ALU_SOURCE,
446446   DATA_DERIVE,
447447   ALU_COMP,
448   ALU_NOP,      // Compare operations do not write back any data
448   ALU_NOP,        // Compare operations do not write back any data
449449   END
450450};
451451
r18983r18984
454454   ALU_NOP,
455455   DATA_DERIVE,
456456   ALU_F3,
457   MEMORY_READ,   // We have to distinguish this from the C/CB microprogram above
457   MEMORY_READ,    // We have to distinguish this from the C/CB microprogram above
458458   ALU_F3,
459   ALU_NOP,      // Compare operations do not write back any data
459   ALU_NOP,        // Compare operations do not write back any data
460460   END
461461};
462462
r18983r18984
467467   ALU_F3,
468468   MEMORY_READ,
469469   ALU_F3,
470   MEMORY_WRITE,   // XOR again must write back data, cannot reuse f3_mp
470   MEMORY_WRITE,   // XOR again must write back data, cannot reuse f3_mp
471471   END
472472};
473473
r18983r18984
475475{
476476   ALU_NOP,
477477   DATA_DERIVE,
478   ALU_MPY,      // Save the value; put register number in m_regnumber
478   ALU_MPY,        // Save the value; put register number in m_regnumber
479479   MEMORY_READ,
480   ALU_MPY,      // 18 cycles for multiplication
481   MEMORY_WRITE,      // Write the high word
482   ALU_MPY,      // Get low word, increase m_address
480   ALU_MPY,        // 18 cycles for multiplication
481   MEMORY_WRITE,       // Write the high word
482   ALU_MPY,        // Get low word, increase m_address
483483   MEMORY_WRITE,
484484   END
485485};
r18983r18984
487487MICROPROGRAM(div_mp)
488488{
489489   ALU_NOP,
490   DATA_DERIVE,   // Get divisor
491   ALU_DIV,      // 0 Store divisor and get register number
492   MEMORY_READ,   // Read register
493   ALU_DIV,      // 1 Check overflow, increase address (or abort here)
490   DATA_DERIVE,    // Get divisor
491   ALU_DIV,        // 0 Store divisor and get register number
492   MEMORY_READ,    // Read register
493   ALU_DIV,        // 1 Check overflow, increase address (or abort here)
494494   ABORT,
495   MEMORY_READ,   // Read subsequent word (if reg=15 this is behind the workspace)
496   ALU_DIV,      // 2 Calculate quotient (takes variable amount of cycles; at least 32 machine cycles), set register number
497   MEMORY_WRITE,   // Write quotient into register
498   ALU_DIV,      // 3 Get remainder
499   MEMORY_WRITE,   // Write remainder
495   MEMORY_READ,    // Read subsequent word (if reg=15 this is behind the workspace)
496   ALU_DIV,        // 2 Calculate quotient (takes variable amount of cycles; at least 32 machine cycles), set register number
497   MEMORY_WRITE,   // Write quotient into register
498   ALU_DIV,        // 3 Get remainder
499   MEMORY_WRITE,   // Write remainder
500500   END
501501};
502502
503503MICROPROGRAM(xop_mp)
504504{
505505   ALU_NOP,
506   DATA_DERIVE,   // Get argument
507   ALU_XOP,      // 0 Save the address of the source operand, set address = 0x0040 + xopNr*4
508   MEMORY_READ,   // Read the new WP
509   ALU_XOP,      // 1 Save old WP, set new WP, get the source operand address
510   MEMORY_WRITE,   // Write the address of the source operand into the new R11
511   ALU_XOP,      // 2
512   MEMORY_WRITE,   // Write the ST into the new R15
513   ALU_XOP,      // 3
514   MEMORY_WRITE,   // Write the PC into the new R14
515   ALU_XOP,      // 4
516   MEMORY_WRITE,   // Write the WP into the new R13
517   ALU_XOP,      // 5 Set the X bit in the ST
518   MEMORY_READ,   // Read the new PC
519   ALU_XOP,      // 6 Set the new PC
506   DATA_DERIVE,    // Get argument
507   ALU_XOP,        // 0 Save the address of the source operand, set address = 0x0040 + xopNr*4
508   MEMORY_READ,    // Read the new WP
509   ALU_XOP,        // 1 Save old WP, set new WP, get the source operand address
510   MEMORY_WRITE,   // Write the address of the source operand into the new R11
511   ALU_XOP,        // 2
512   MEMORY_WRITE,   // Write the ST into the new R15
513   ALU_XOP,        // 3
514   MEMORY_WRITE,   // Write the PC into the new R14
515   ALU_XOP,        // 4
516   MEMORY_WRITE,   // Write the WP into the new R13
517   ALU_XOP,        // 5 Set the X bit in the ST
518   MEMORY_READ,    // Read the new PC
519   ALU_XOP,        // 6 Set the new PC
520520   ALU_NOP,
521521   END
522522};
r18983r18984
534534{
535535   ALU_NOP,
536536   DATA_DERIVE,
537   ALU_ABS,      // two cycles
538   MEMORY_WRITE,   // skipped when ABS is not performed
537   ALU_ABS,        // two cycles
538   MEMORY_WRITE,   // skipped when ABS is not performed
539539   ALU_NOP,
540540   END
541541};
r18983r18984
548548   END
549549};
550550
551MICROPROGRAM(b_mp)      // Branch
551MICROPROGRAM(b_mp)      // Branch
552552{
553553   ALU_NOP,
554554   DATA_DERIVE,
r18983r18984
556556   END
557557};
558558
559MICROPROGRAM(bl_mp)      // Branch and Link
559MICROPROGRAM(bl_mp)     // Branch and Link
560560{
561561   ALU_NOP,
562562   DATA_DERIVE,
r18983r18984
566566   END
567567};
568568
569MICROPROGRAM(blwp_mp)      // Branch and Load WP
569MICROPROGRAM(blwp_mp)       // Branch and Load WP
570570{
571571   ALU_NOP,
572   DATA_DERIVE,         // Get argument
573   ALU_BLWP,            // 0 Save old WP, set new WP, save position
574   MEMORY_WRITE,         // write ST to R15
575   ALU_BLWP,            // 1
576   MEMORY_WRITE,         // write PC to R14
577   ALU_BLWP,            // 2
578   MEMORY_WRITE,         // write WP to R13
579   ALU_BLWP,            // 3 Get saved position
580   MEMORY_READ,         // Read new PC
581   ALU_BLWP,            // 4 Set new PC
572   DATA_DERIVE,            // Get argument
573   ALU_BLWP,               // 0 Save old WP, set new WP, save position
574   MEMORY_WRITE,           // write ST to R15
575   ALU_BLWP,               // 1
576   MEMORY_WRITE,           // write PC to R14
577   ALU_BLWP,               // 2
578   MEMORY_WRITE,           // write WP to R13
579   ALU_BLWP,               // 3 Get saved position
580   MEMORY_READ,            // Read new PC
581   ALU_BLWP,               // 4 Set new PC
582582   END
583583};
584584
r18983r18984
600600{
601601   ALU_NOP,
602602   DATA_DERIVE,
603   ALU_SOURCE,         // Store address and value
604   ALU_STCR,         // 0 Set register_number = 12
603   ALU_SOURCE,         // Store address and value
604   ALU_STCR,           // 0 Set register_number = 12
605605   MEMORY_READ,
606   ALU_STCR,         // 1 Prepare CRU access
606   ALU_STCR,           // 1 Prepare CRU access
607607   CRU_INPUT,
608   ALU_STCR,         // 2 Create result; Cycles = 5 + (8-#C-1) or + (16-#C)
608   ALU_STCR,           // 2 Create result; Cycles = 5 + (8-#C-1) or + (16-#C)
609609   MEMORY_WRITE,
610610   END
611611};
r18983r18984
675675{
676676   ALU_IMM,
677677   MEMORY_READ,
678   ALU_LI,            // sets status bits
679   ALU_REG,         // set register number
678   ALU_LI,             // sets status bits
679   ALU_REG,            // set register number
680680   MEMORY_WRITE,
681681   END
682682};
r18983r18984
686686   ALU_IMM,
687687   MEMORY_READ,
688688   ALU_NOP,
689   ALU_LWPI,            // sets WP
689   ALU_LWPI,               // sets WP
690690   END
691691};
692692
r18983r18984
695695   ALU_IMM,
696696   MEMORY_READ,
697697   ALU_NOP,
698   ALU_LIMI,            // sets interrupt mask in ST
698   ALU_LIMI,               // sets interrupt mask in ST
699699   ALU_NOP,
700700   ALU_NOP,
701701   END
r18983r18984
715715   END
716716};
717717
718MICROPROGRAM(rtwp_mp)      // Problem: This makes RTWP use 8 instead of 7 machine cycles.
718MICROPROGRAM(rtwp_mp)       // Problem: This makes RTWP use 8 instead of 7 machine cycles.
719719{
720720   ALU_RTWP,
721721   MEMORY_READ,
r18983r18984
730730MICROPROGRAM(int_mp)
731731{
732732   ALU_NOP,
733   ALU_INT,            // 0 Set address = 0
733   ALU_INT,                // 0 Set address = 0
734734   MEMORY_READ,
735   ALU_INT,            // 1 Save old WP, set new WP, save position
736   MEMORY_WRITE,         // write ST to R15
737   ALU_INT,            // 2
738   MEMORY_WRITE,         // write PC to R14
739   ALU_INT,            // 3
740   MEMORY_WRITE,         // write WP to R13
741   ALU_INT,            // 4 Get saved position
742   MEMORY_READ,         // Read new PC
743   ALU_INT,            // 5 Set new PC
735   ALU_INT,                // 1 Save old WP, set new WP, save position
736   MEMORY_WRITE,           // write ST to R15
737   ALU_INT,                // 2
738   MEMORY_WRITE,           // write PC to R14
739   ALU_INT,                // 3
740   MEMORY_WRITE,           // write WP to R13
741   ALU_INT,                // 4 Get saved position
742   MEMORY_READ,            // Read new PC
743   ALU_INT,                // 5 Set new PC
744744   END
745745};
746746
r18983r18984
12461246   {
12471247      m_clock_out_line(ASSERT_LINE);
12481248      m_clock_out_line(CLEAR_LINE);
1249      m_icount--;                     // This is the only location where we count down the cycles.
1249      m_icount--;                         // This is the only location where we count down the cycles.
12501250      if (VERBOSE>7) LOG("tms99xx: pulse_clock\n");
12511251   }
12521252}
r18983r18984
14551455   // Read 8 bits (containing the desired bits)
14561456   value = m_cru->read_byte(location);
14571457
1458   if ((offset + m_count) > 8)   // spans two 8 bit cluster
1458   if ((offset + m_count) > 8) // spans two 8 bit cluster
14591459   {
14601460      // Read next 8 bits
14611461      location = (location + 1) & (m_cruaddr_mask>>3);
14621462      value1 = m_cru->read_byte(location);
14631463      value |= (value1 << 8);
14641464
1465      if ((offset + m_count) > 16)   // spans three 8 bit cluster
1465      if ((offset + m_count) > 16)    // spans three 8 bit cluster
14661466      {
14671467         // Read next 8 bits
14681468         location = (location + 1) & (m_cruaddr_mask>>3);
r18983r18984
15431543   m_program = (UINT8*)data_derivation;
15441544   MPC = ircopy & 0x0030;
15451545
1546   if (((MPC == 0x0020) && (m_regnumber != 0))         // indexed
1547      || ((MPC == 0x0030) && m_byteop))      // byte operation
1546   if (((MPC == 0x0020) && (m_regnumber != 0))         // indexed
1547      || ((MPC == 0x0030) && m_byteop))       // byte operation
15481548   {
1549      MPC += 8;   // the second option
1549      MPC += 8;   // the second option
15501550   }
1551   m_get_destination = true;   // when we call this the second time before END it's the destination
1551   m_get_destination = true;   // when we call this the second time before END it's the destination
15521552   m_pass = 2;
15531553}
15541554
r18983r18984
16681668   // Save the destination value
16691669   UINT16 prev_dest_value = m_current_value;
16701670
1671   m_destination_even = ((m_address & 1)==0);   // this is the destination address; the source address has already been saved
1671   m_destination_even = ((m_address & 1)==0);  // this is the destination address; the source address has already been saved
16721672   bool byteop = byte_operation();
16731673
16741674   if (byteop)
r18983r18984
17751775
17761776void tms99xx_device::alu_comp()
17771777{
1778   m_destination_even = ((m_address & 1)==0);   // this is the destination address; the source address has already been saved
1778   m_destination_even = ((m_address & 1)==0);  // this is the destination address; the source address has already been saved
17791779   if (byte_operation())
17801780   {
17811781      if (!m_destination_even) m_current_value <<= 8;
r18983r18984
18401840      result = (m_source_value & 0x0000ffff) * (m_current_value & 0x0000ffff);
18411841      m_current_value = (result >> 16) & 0xffff;
18421842      m_value_copy = result & 0xffff;
1843      pulse_clock(34);                        // add 36 clock cycles (18 machine cycles); last one in main loop
1843      pulse_clock(34);                                // add 36 clock cycles (18 machine cycles); last one in main loop
18441844      break;
18451845   case 2: // After writing the high word to the destination register
1846      m_current_value = m_value_copy;                  // Prepare to save low word
1846      m_current_value = m_value_copy;                     // Prepare to save low word
18471847      m_address = (m_address + 2) & m_prgaddr_mask;
18481848      break;
18491849   }
r18983r18984
18611861   switch (m_state)
18621862   {
18631863   case 0:
1864      m_source_value = m_current_value;   // store divisor
1864      m_source_value = m_current_value;   // store divisor
18651865      // Set address of register
18661866      m_address = WP + ((IR >> 5) & 0x001e);
18671867      m_address_copy = m_address;
r18983r18984
18711871      // This is the case when the dividend / divisor >= 0x10000,
18721872      // or equivalently, dividend / 0x10000 >= divisor
18731873
1874      if (m_current_value < m_source_value)   // also if source=0
1874      if (m_current_value < m_source_value)   // also if source=0
18751875      {
1876         MPC++;   // skip the abort
1876         MPC++;  // skip the abort
18771877         overflow = false;
18781878      }
18791879      set_status_bit(ST_OV, overflow);
1880      m_value_copy = m_current_value;         // Save the high word
1881      m_address = (m_address + 2) & m_prgaddr_mask;      // Read next word
1880      m_value_copy = m_current_value;         // Save the high word
1881      m_address = (m_address + 2) & m_prgaddr_mask;       // Read next word
18821882      break;
18831883   case 2:
18841884      // W2 is in m_current_value
r18983r18984
19011901      // we need as many cycles as it takes to
19021902      // shift away the dividend. Thus, bigger dividends need more cycles.
19031903
1904      pulse_clock(62);   // one pulse is at the start, one at the end
1904      pulse_clock(62);    // one pulse is at the start, one at the end
19051905      value1 = m_value_copy & 0xffff;
19061906
19071907      while (value1 != 0)
r18983r18984
19351935      m_address = 0x0040 + ((IR >> 4) & 0x003c);
19361936      break;
19371937   case 1:
1938      m_value_copy = WP;                  // save the old WP
1939      WP = m_current_value & m_prgaddr_mask;   // the new WP has been read in the previous microoperation
1940      m_current_value = m_address_saved;      // we saved the address of the source operand; retrieve it
1941      m_address = WP + 0x0016;            // Next register is R11
1938      m_value_copy = WP;                      // save the old WP
1939      WP = m_current_value & m_prgaddr_mask;  // the new WP has been read in the previous microoperation
1940      m_current_value = m_address_saved;      // we saved the address of the source operand; retrieve it
1941      m_address = WP + 0x0016;                // Next register is R11
19421942      break;
19431943   case 2:
19441944      m_address = WP + 0x001e;
r18983r18984
19501950      break;
19511951   case 4:
19521952      m_address = WP + 0x001a;
1953      m_current_value = m_value_copy;         // old WP into new R13
1953      m_current_value = m_value_copy;         // old WP into new R13
19541954      break;
19551955   case 5:
1956      m_address =  0x0042 + ((IR >> 4) & 0x003c);      // location of new PC
1956      m_address =  0x0042 + ((IR >> 4) & 0x003c);     // location of new PC
19571957      set_status_bit(ST_X, true);
19581958      break;
19591959   case 6:
r18983r18984
20302030
20312031   if (setstatus)
20322032   {
2033      if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)!=sign) && ((dest_new & 0x8000)==sign));
2033      if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)==sign) && ((dest_new & 0x8000)!=sign));
20342034      set_status_bit(ST_C, (dest_new & 0x10000) != 0);
20352035      m_current_value = dest_new & 0xffff;
20362036      compare_and_set_lae(m_current_value, 0);
r18983r18984
20522052   if ((m_current_value & 0x8000)!=0)
20532053   {
20542054      m_current_value = (((~m_current_value) & 0x0000ffff) + 1) & 0xffff;
2055      pulse_clock(2);      // If ABS is performed it takes one machine cycle more
2055      pulse_clock(2);     // If ABS is performed it takes one machine cycle more
20562056   }
20572057   else
20582058   {
r18983r18984
20932093   {
20942094   case 0:
20952095      m_value_copy = WP;
2096      WP = m_current_value & m_prgaddr_mask;            // set new WP (*m_destination)
2097      m_address_saved = (m_address + 2) & m_prgaddr_mask;   // Save the location of the WP
2096      WP = m_current_value & m_prgaddr_mask;              // set new WP (*m_destination)
2097      m_address_saved = (m_address + 2) & m_prgaddr_mask; // Save the location of the WP
20982098      m_address = WP + 30;
2099      m_current_value = ST;                     // get status register
2099      m_current_value = ST;                           // get status register
21002100      break;
21012101   case 1:
2102      m_current_value = PC;                     // get program counter
2102      m_current_value = PC;                           // get program counter
21032103      m_address = m_address - 2;
21042104      break;
21052105   case 2:
2106      m_current_value = m_value_copy;               // retrieve the old WP
2106      m_current_value = m_value_copy;                 // retrieve the old WP
21072107      m_address = m_address - 2;
21082108      break;
21092109   case 3:
2110      m_address = m_address_saved;               // point to PC component of branch vector
2110      m_address = m_address_saved;                    // point to PC component of branch vector
21112111      break;
21122112   case 4:
21132113      PC = m_current_value & m_prgaddr_mask;
r18983r18984
21382138   }
21392139   else
21402140   {
2141      value = m_source_value;   // copied by ALU_SOURCE
2141      value = m_source_value; // copied by ALU_SOURCE
21422142      m_count = (IR >> 6) & 0x000f;
21432143      if (m_count == 0) m_count = 16;
21442144      if (m_count <= 8)
r18983r18984
22642264      case JLT:   // LAECOP == x00xxx
22652265         cond = ((ST & (ST_AGT | ST_EQ))==0);
22662266         break;
2267      case JLE:   // LAECOP == 0xxxxx
2267      case JLE:   // LAECOP == 0xxxxx
22682268         cond = ((ST & ST_LH)==0);
22692269         break;
2270      case JEQ:   // LAECOP == xx1xxx
2270      case JEQ:   // LAECOP == xx1xxx
22712271         cond = ((ST & ST_EQ)!=0);
22722272         break;
2273      case JHE:   // LAECOP == 1x0xxx, 0x1xxx
2273      case JHE:   // LAECOP == 1x0xxx, 0x1xxx
22742274         cond = ((ST & (ST_LH | ST_EQ)) != 0);
22752275         break;
2276      case JGT:   // LAECOP == x1xxxx
2276      case JGT:   // LAECOP == x1xxxx
22772277         cond = ((ST & ST_AGT)!=0);
22782278         break;
2279      case JNE:   // LAECOP == xx0xxx
2279      case JNE:   // LAECOP == xx0xxx
22802280         cond = ((ST & ST_EQ)==0);
22812281         break;
2282      case JNC:   // LAECOP == xxx0xx
2282      case JNC:   // LAECOP == xxx0xx
22832283         cond = ((ST & ST_C)==0);
22842284         break;
2285      case JOC:   // LAECOP == xxx1xx
2285      case JOC:   // LAECOP == xxx1xx
22862286         cond = ((ST & ST_C)!=0);
22872287         break;
2288      case JNO:   // LAECOP == xxxx0x
2288      case JNO:   // LAECOP == xxxx0x
22892289         cond = ((ST & ST_OV)==0);
22902290         break;
2291      case JL:   // LAECOP == 0x0xxx
2291      case JL:    // LAECOP == 0x0xxx
22922292         cond = ((ST & (ST_LH | ST_EQ)) == 0);
22932293         break;
2294      case JH:   // LAECOP == 1xxxxx
2294      case JH:    // LAECOP == 1xxxxx
22952295         cond = ((ST & ST_LH)!=0);
22962296         break;
2297      case JOP:   // LAECOP == xxxxx1
2297      case JOP:   // LAECOP == xxxxx1
22982298         cond = ((ST & ST_OP)!=0);
22992299         break;
23002300      }
r18983r18984
23022302      if (!cond)
23032303      {
23042304         if (VERBOSE>7) LOG("tms99xx: Jump condition false\n");
2305         MPC+=1;   // skip next ALU call
2305         MPC+=1; // skip next ALU call
23062306      }
23072307      else
23082308         if (VERBOSE>7) LOG("tms99xx: Jump condition true\n");
r18983r18984
23852385      set_status_bit(ST_C, carry);
23862386      set_status_bit(ST_OV, overflow);
23872387      compare_and_set_lae(m_current_value, 0);
2388      m_address = m_address_saved;      // Register address
2388      m_address = m_address_saved;        // Register address
23892389      if (VERBOSE>7) LOG("tms99xx: ST = %04x (val=%04x)\n", ST, m_current_value);
23902390      break;
23912391   }
r18983r18984
24732473   switch (m_state)
24742474   {
24752475   case 0:
2476      m_address = WP + 30;      // R15
2476      m_address = WP + 30;        // R15
24772477      break;
24782478   case 1:
24792479      ST = m_current_value;
2480      m_address -= 2;            // R14
2480      m_address -= 2;             // R14
24812481      break;
24822482   case 2:
24832483      PC = m_current_value & m_prgaddr_mask;
2484      m_address -= 2;            // R13
2484      m_address -= 2;             // R13
24852485      break;
24862486   case 3:
24872487      WP = m_current_value & m_prgaddr_mask;
r18983r18984
25142514      break;
25152515   case 1:
25162516      m_address_copy = m_address;
2517      m_value_copy = WP;                     // old WP
2518      WP = m_current_value & m_prgaddr_mask;      // new WP
2517      m_value_copy = WP;                          // old WP
2518      WP = m_current_value & m_prgaddr_mask;      // new WP
25192519      m_current_value = ST;
25202520      m_address = (WP + 30) & m_prgaddr_mask;
25212521      break;
r18983r18984
25242524      m_address = (WP + 28) & m_prgaddr_mask;
25252525      break;
25262526   case 3:
2527      m_current_value = m_value_copy;   // old WP
2527      m_current_value = m_value_copy; // old WP
25282528      m_address = (WP + 26) & m_prgaddr_mask;
25292529      break;
25302530   case 4:

Previous 199869 Revisions Next


© 1997-2024 The MAME Team