Viewing File: <root>/src/emu/cpu/upd7810/upd7810.c

    1  /*****************************************************************************
    2   *
    3   *   upd7810.h
    4   *   Portable uPD7810/11, 7810H/11H, 78C10/C11/C14 emulator V0.3
    5   *
    6   *   Copyright Juergen Buchmueller, all rights reserved.
    7   *   You can contact me at juergen@mame.net or pullmoll@stop1984.com
    8   *
    9   *   - This source code is released as freeware for non-commercial purposes
   10   *     as part of the M.A.M.E. (Multiple Arcade Machine Emulator) project.
   11   *     The licensing terms of MAME apply to this piece of code for the MAME
   12   *     project and derviative works, as defined by the MAME license. You
   13   *     may opt to make modifications, improvements or derivative works under
   14   *     that same conditions, and the MAME project may opt to keep
   15   *     modifications, improvements or derivatives under their terms exclusively.
   16   *
   17   *   - Alternatively you can choose to apply the terms of the "GPL" (see
   18   *     below) to this - and only this - piece of code or your derivative works.
   19   *     Note that in no case your choice can have any impact on any other
   20   *     source code of the MAME project, or binary, or executable, be it closely
   21   *     or losely related to this piece of code.
   22   *
   23   *  -  At your choice you are also free to remove either licensing terms from
   24   *     this file and continue to use it under only one of the two licenses. Do this
   25   *     if you think that licenses are not compatible (enough) for you, or if you
   26   *     consider either license 'too restrictive' or 'too free'.
   27   *
   28   *  -  GPL (GNU General Public License)
   29   *     This program is free software; you can redistribute it and/or
   30   *     modify it under the terms of the GNU General Public License
   31   *     as published by the Free Software Foundation; either version 2
   32   *     of the License, or (at your option) any later version.
   33   *
   34   *     This program is distributed in the hope that it will be useful,
   35   *     but WITHOUT ANY WARRANTY; without even the implied warranty of
   36   *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37   *     GNU General Public License for more details.
   38   *
   39   *     You should have received a copy of the GNU General Public License
   40   *     along with this program; if not, write to the Free Software
   41   *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   42   *
   43   *
   44   *  This work is based on the
   45   *  "NEC Electronics User's Manual, April 1987"
   46   *
   47   * NS20030115:
   48   * - fixed INRW_wa(cpustate)
   49   * - TODO: add 7807, differences are listed below.
   50   *       I only added support for these opcodes needed by homedata.c (yes, I am
   51   *       lazy):
   52   *       4C CE (MOV A,PT)
   53   *       48 AC (EXA)
   54   *       48 AD (EXR)
   55   *       48 AE (EXH)
   56   *       48 AF (EXX)
   57   *       50 xx (SKN bit)
   58   *       58 xx (SETB)
   59   *       5B xx (CLR)
   60   *       5D xx (SK bit)
   61   *
   62   * 2008-02-24 (Wilbert Pol):
   63   * - Added preliminary support for uPD7801
   64   *   For the uPD7801 only the basic instruction set was added. The current timer
   65   *   and serial i/o implementations are most likely incorrect.
   66   * - Added basic support for uPD78C05 and uPD78C06
   67   *   Documentation of the actual instruction set layout is missing, so we took
   68   *   the uPD7801 instruction set and only kept the instructions mentioned in
   69   *   the little documentation available on the uPD78c05A/06A. The serial i/o
   70   *   implementation has not been tested and is probably incorrect.
   71   *
   72   *****************************************************************************/
   73  /* Hau around 23 May 2004
   74    gta, gti, dgt fixed
   75    working reg opcodes fixed
   76    sio input fixed
   77  --
   78    PeT around 19 February 2002
   79    type selection/gamemaster support added
   80    gamemaster init hack? added
   81    ORAX added
   82    jre negativ fixed
   83    prefixed opcodes skipping fixed
   84    interrupts fixed and improved
   85    sub(and related)/add/daa flags fixed
   86    mvi ports,... fixed
   87    rll, rlr, drll, drlr fixed
   88    rets fixed
   89    l0, l1 skipping fixed
   90    calt fixed
   91  */
   92  
   93  /*
   94  
   95  7807 DESCRIPTION
   96  
   97  
   98  
   99     PA0  1     64 Vcc
  100     PA1  2     63 Vdd
  101     PA2  3     62 PD7/AD7
  102     PA3  4     61 PD6/AD6
  103     PA4  5     60 PD5/AD5
  104     PA5  6     59 PD4/AD4
  105     PA6  7     58 PD3/AD3
  106     PA7  8     57 PD2/AD2
  107     PB0  9     56 PD1/AD1
  108     PB1 10     55 PD0/AD0
  109     PB2 11     54 PF7/AB15
  110     PB3 12     53 PF6/AB14
  111     PB4 13     52 PF5/AB13
  112     PB5 14     51 PF4/AB12
  113     PB6 15     50 PF3/AB11
  114     PB7 16     49 PF2/AB10
  115     PC0 17     48 PF1/AB9
  116     PC1 18     47 PF0/AB8
  117     PC2 19     46 ALE
  118     PC3 20     45 WR*
  119     PC4 21     44 RD*
  120     PC5 22     43 HLDA
  121     PC6 23     42 HOLD
  122     PC7 24     41 PT7
  123    NMI* 25     40 PT6
  124    INT1 26     39 PT5
  125   MODE1 27     38 PT4
  126  RESET* 28     37 PT3
  127   MODE0 29     36 PT2
  128      X2 30     35 PT1
  129      X1 31     34 PT0
  130     Vss 32     33 Vth
  131  
  132  PA, PB, PC, PD, and PF is bidirectional I/O port
  133  and PT is comparator input port in uPD7808.
  134  uPD7807 uses PD port as data I/O and bottom address output,
  135  and uses PF port as top address output.
  136  
  137  NMI* is non maskable interrupt input signal (negative edge trigger).
  138  
  139  INT1 is interrupt input (positive edge trigger). It can be used as
  140  AC zero-cross input or trigger source of 16bit timer counter.
  141  
  142  MODE0 and MODE1 is input terminal which decides total amount of
  143  external memory of uPD7807 (4KByte, 16KBYte, and 64KByte).
  144  It also decides number of PF ports used as top address output.
  145   4KByte mode: PF0~PF3=address output, PF4~PF7=data I/O port
  146  16KByte mode: PF0~PF5=address output, PF6~PF7=data I/O port
  147  64KByte mode: PF0~PF7=address output
  148  
  149  RESET* is system rest terminal.
  150  
  151  X1 and X2 does clock signal generation (connect OSC and condenser).
  152  
  153  Vth is used to determine threshold voltage for PT port.
  154  PT0~PT7 is connected to + input of each comparator,
  155  and Vth deterimnes voltage connected to - input of PT0~PT7.
  156  But the voltage of Vth is not directly connected to comapators.
  157  It is connected via 16-level programmable voltage separate circuit.
  158  
  159  HOLD and HLDA is terminal for DMA. RD*, WR*, and ALE is bus
  160  interface signal (they are same type of Intel 8085).
  161  Unlike 8085, I/O address space is not available, so IO /M* signal
  162  does not exist. Read/write of external memory can be done
  163  by RD*, WR*, and ALE only.
  164  
  165  Vcc and Vss is main power source. Vdd is backup power source
  166  for internal RWM (32 Byte).
  167  
  168  
  169  PA and PB is I/O port. They have control register MA and MB.
  170  If control register is set to 1, the port is input.
  171  If control register is set to 0, the port is output.
  172  They are set to 1 by reset.
  173  
  174  PT is input-only port. It is consisted of input terminal PT0~PT7
  175  and Vth (set threshold voltage). Each PT input has analog comparator
  176  and latch, and + input of analog comparator is connected to
  177  PT terminal. Every - input of analog comparator is connected
  178  to devided voltage of Vth. Voltage dividing level can be set by
  179  bottom 4bits of MT (mode T) register. The range is 1/16~16/16 of Vth.
  180  
  181  Other internal I/Os are
  182  8bit timer (x2): Upcounter. If the counter matches to specified value,
  183  the timer is reset and counts again from 0.
  184  You can also set it to generate interrupt, or invert output flip-flop
  185  when the counter matches to specified value.
  186  Furthermore, you can output that flip-flop output to PC4/TO output,
  187  connect it to clock input of timer/event counter or watchdog timer.
  188  Or you can use it as bitrate clock of serial interface.
  189  Note: There is only 1 output flip-flop for 2 timers.
  190  If you use it for timer output of 1 timer, another timer cannot be used
  191  for other than interrupt generator.
  192  Clock input for timer can be switched between internal clock (2 type)
  193  or PC3/TI input. You can set 1 timer's match-output as another timer's
  194  clock input, so that you can use them as 1 16bit timer.
  195  
  196  16bit timer/event counter (x1): It can be used as
  197  - Interval timer
  198  - External event counter
  199  - Frequency measurement
  200  - Pulse width measurement
  201  - Programmable rectangle wave output
  202  - One pulse output
  203  Related terminals are PC5/CI input, PC6/CO0 output, and PC7/CO1.
  204  You can measure CI input's H duration, or you can output timing signal
  205  (with phase difference) to CO0 and CO1.
  206  
  207  serial I/F (x1): has 3 modes.
  208  - Asynchronous mode
  209  - Synchronous mode
  210  - I/O interface mode
  211  In all 3 modes, bitrate can be internal fixed clock, or timer output,
  212  or external clock.
  213  In asynchronous mode, you can
  214  - switch 7bit/8bit data
  215  - set parity ON/OFF and EVEN/ODD
  216  - set 1/2 stop bit
  217  
  218  
  219  
  220  
  221  DIFFERENCES BETWEEN 7810 and 7807
  222  
  223  --------------------------
  224  8bit transfer instructions
  225  --------------------------
  226  
  227  7810
  228  inst.     1st byte 2nd byte state   action
  229  EXX       00001001            4     Swap BC DE HL
  230  EXA       00001000            4     Swap VA EA
  231  EXH       01010000            4     Swap HL
  232  BLOCK     00110001          13(C+1)  (DE)+ <- (HL)+, C <- C - 1, until CY
  233  
  234  7807
  235  inst.     1st byte  2nd byte state   action
  236  EXR       01001000  10101101   8     Swap VA BC DE HL EA
  237  EXX       01001000  10101111   8     Swap BC DE HL
  238  EXA       01001000  10101100   8     Swap VA EA
  239  EXH       01001000  10101110   8     Swap HL
  240  BLOCK  D+ 00010000           13(C+1) (DE)+ <- (HL)+, C <- C - 1, until CY
  241  BLOCK  D- 00010001           13(C+1) (DE)- <- (HL)-, C <- C - 1, until CY
  242  
  243  
  244  ---------------------------
  245  16bit transfer instructions
  246  ---------------------------
  247  All instructions are same except operand sr4 of DMOV instruction.
  248  7810
  249  V0-sr4 -function
  250   0-ECNT-timer/event counter upcounter
  251   1-ECPT-timer/event counter capture
  252  
  253  7807
  254  V1-V0- sr4 -function
  255   0- 0-ECNT -timer/event counter upcounter
  256   0- 1-ECPT0-timer/event counter capture 0
  257   1- 0-ECPT1-timer/event counter capture 1
  258  
  259  
  260  -----------------------------------------
  261  8bit operation instructions for registers
  262  -----------------------------------------
  263  All instructions are same.
  264  
  265  
  266  --------------------------------------
  267  8bit operation instructions for memory
  268  --------------------------------------
  269  All instructions are same.
  270  
  271  
  272  -----------------------------------------
  273  Operation instructions for immediate data
  274  -----------------------------------------
  275  uPD7807 has read-only PT port and special register group sr5 for it.
  276  ins.               1st byte  2nd byte 3rd 4th state func
  277  GTI    sr5, byte   01100100  s0101sss  dd      14   !CY  sr5 - byte - 1
  278  LTI    sr5, byte   01100100  s0111sss  dd      14    CY  sr5 - byte
  279  NEI    sr5, byte   01100100  s1101sss  dd      14   !Z   sr5 - byte
  280  EQI    sr5, byte   01100100  s1111sss  dd      14    Z   sr5 - byte
  281  ONI    sr5, byte   01100100  s1001sss  dd      14   !Z   sr5 & byte
  282  OFFI   sr5, byte   01100100  s1011sss  dd      14    Z   sr5 & byte
  283  
  284  S5-S4-S3-S2-S1-S0-sr -sr1-sr2-sr5-register function
  285   0  0  1  1  1  0 --- PT  --- PT  comparator input port T data
  286   1  0  0  1  0  0 WDM WDM --- --- watchdog timer mode register
  287   1  0  0  1  0  1 MT  --- --- --- port T mode
  288  
  289  7807 doesn't have registers below
  290   0  0  1  0  0  0 ANM ANM ANM     A/D channel mode
  291   1  0  0  0  0  0 --- CR0 ---     A/D conversion result 0
  292   1  0  0  0  0  1 --- CR1 ---     A/D conversion result 1
  293   1  0  0  0  1  0 --- CR2 ---     A/D conversion result 2
  294   1  0  0  0  1  1 --- CR3 ---     A/D conversion result 3
  295   1  0  1  0  0  0 ZCM --- ---     zero cross mode
  296  
  297  Special register operand (includes registers for I/O ports) has
  298  6 groups - sr, sr1, sr2, sr3, sr4, and sr5. Among these groups,
  299  sr, sr1, sr2, and sr5 includes registers described in the table
  300  below, and expressed as bit pattern S5-S0.
  301  
  302  S5S4S3S2S1S0 sr  sr1 sr2 sr5 register function
  303  0 0 0 0 0 0  PA  PA  PA  PA  port A
  304  0 0 0 0 0 1  PB  PB  PB  PB  port B
  305  0 0 0 0 1 0  PC  PC  PC  PC  port C
  306  0 0 0 0 1 1  PD  PD  PD  PD  port D
  307  0 0 0 1 0 1  PF  PF  PF  PF  port F
  308  0 0 0 1 1 0  MKH MKH MKH MKH mask high
  309  0 0 0 1 1 1  MKL MKL MKL MKL mask low
  310  0 0 1 0 0 1  SMH SMH SMH SMH serial mode high
  311  0 0 1 0 1 0  SML --- --- --- serial mode low
  312  0 0 1 0 1 1  EOM EOM EOM EOM timer/event counter output mode
  313  0 0 1 1 0 0 ETMM --- --- --- timer/event counter mode
  314  0 0 1 1 0 1  TMM TMM TMM TMM timer mode
  315  0 0 1 1 1 0  --- PT  --- PT  port T
  316  0 1 0 0 0 0  MM  --- --- --- memory mapping
  317  0 1 0 0 0 1  MCC --- --- --- mode control C
  318  0 1 0 0 1 0  MA  --- --- --- mode A
  319  0 1 0 0 1 1  MB  --- --- --- mode B
  320  0 1 0 1 0 0  MC  --- --- --- mode C
  321  0 1 0 1 1 1  MF  --- --- --- mode F
  322  0 1 1 0 0 0  TXB --- --- --- Tx buffer
  323  0 1 1 0 0 1  --- RXB --- --- Rx buffer
  324  0 1 1 0 1 0  TM0 --- --- --- timer register 0
  325  0 1 1 0 1 1  TM1 --- --- --- timer register 1
  326  1 0 0 1 0 0  WDM WDM --- --- watchdog timer mode
  327  1 0 0 1 0 1  MT  --- --- --- mode T
  328  
  329  For sr and sr1, all 6bits (S5, S4, S3, S2, S1, and S0) are used.
  330  For sr2 and sr5, only 4bits (S3, S2, S1, AND S0) are used.
  331  They are expressed as 'ssssss' and 's sss' in operation code.
  332  Note that 's sss' (of sr2 and sr5) is located separately.
  333  S0 is rightmost bit (LSB).
  334  
  335  
  336  --------------------------------------------
  337  Operation instructions for working registers
  338  --------------------------------------------
  339  All instructions are same.
  340  
  341  
  342  --------------------------------------------------------------------------
  343  16bit operation instructions and divider/multiplier operation instructions
  344  --------------------------------------------------------------------------
  345  All instructions are same.
  346  
  347  
  348  ------------------------------------------
  349  Increment/decrement operation instructions
  350  ------------------------------------------
  351  All instructions are same.
  352  
  353  
  354  ----------------------------
  355  Other operation instructions
  356  ----------------------------
  357  7807 has CMC instruction (inverts CY flag).
  358  ins. 1st byte 2nd byte 3rd 4th state func
  359  CMC  01001000 10101010           8   CY <- !CY
  360  
  361  
  362  ---------------------------
  363  Rotation/shift instructions
  364  ---------------------------
  365  All instructions are same.
  366  
  367  
  368  -----------------------------
  369  Jump/call/return instructions
  370  -----------------------------
  371  All instructions are same.
  372  
  373  
  374  -----------------
  375  Skip instructions
  376  -----------------
  377  7807 doesn't have this
  378  ins.            1st byte 2nd byte 3rd 4th state func
  379  BIT bit, wa     01011bbb  wwwwwwww          10*  bit skip if (V.wa).bit = 1
  380  
  381  Instead, 7807 has these bit manipulation instructions.
  382  ins.            1st byte 2nd byte 3rd 4th state func
  383  MOV    CY, bit  01011111  bbbbbbbb          10* CY <- (bit)
  384  MOV    bit, CY  01011010  bbbbbbbb          13* (bit) <- CY
  385  AND    CY, bit  00110001  bbbbbbbb          10* CY <- CY & (bit)
  386  OR     CY, bit  01011100  bbbbbbbb          10* CY <- CY | (bit)
  387  XOR    CY, bit  01011110  bbbbbbbb          10* CY <- CY ^ (bit)
  388  SETB   bit      01011000  bbbbbbbb          13* (bit) <- 1
  389  CLR    bit      01011011  bbbbbbbb          13* (bit) <- 0
  390  NOT    bit      01011001  bbbbbbbb          13* (bit) <- !(bit)
  391  SK     bit      01011101  bbbbbbbb          10*  (b) skip if (bit) = 1
  392  SKN    bit      01010000  bbbbbbbb          10* !(b) skip if (bit) = 0
  393  
  394  
  395  ------------------------
  396  CPU control instructions
  397  ------------------------
  398  ins.            1st byte 2nd byte 3rd 4th state func
  399  HLT             01001000  00111011        11/12 halt
  400  11 state in uPD7807 and uPD7810, 12 state in uPD78C10.
  401  
  402  STOP            01001000  10111011          12  stop
  403  7807 doesn't have STOP instruction.
  404  
  405  */
  406  
  407  #include "emu.h"
  408  #include "debugger.h"
  409  #include "upd7810.h"
  410  
  411  struct upd7810_state
  412  {
  413      PAIR    ppc;    /* previous program counter */
  414      PAIR    pc;     /* program counter */
  415      PAIR    sp;     /* stack pointer */
  416      UINT8   op;     /* opcode */
  417      UINT8   op2;    /* opcode part 2 */
  418      UINT8   iff;    /* interrupt enable flip flop */
  419      UINT8   psw;    /* processor status word */
  420      PAIR    ea;     /* extended accumulator */
  421      PAIR    va;     /* accumulator + vector register */
  422      PAIR    bc;     /* 8bit B and C registers / 16bit BC register */
  423      PAIR    de;     /* 8bit D and E registers / 16bit DE register */
  424      PAIR    hl;     /* 8bit H and L registers / 16bit HL register */
  425      PAIR    ea2;    /* alternate register set */
  426      PAIR    va2;
  427      PAIR    bc2;
  428      PAIR    de2;
  429      PAIR    hl2;
  430      PAIR    cnt;    /* 8 bit timer counter */
  431      PAIR    tm;     /* 8 bit timer 0/1 comparator inputs */
  432      PAIR    ecnt;   /* timer counter register / capture register */
  433      PAIR    etm;    /* timer 0/1 comparator inputs */
  434      UINT8   ma;     /* port A input or output mask */
  435      UINT8   mb;     /* port B input or output mask */
  436      UINT8   mcc;    /* port C control/port select */
  437      UINT8   mc;     /* port C input or output mask */
  438      UINT8   mm;     /* memory mapping */
  439      UINT8   mf;     /* port F input or output mask */
  440      UINT8   tmm;    /* timer 0 and timer 1 operating parameters */
  441      UINT8   etmm;   /* 16-bit multifunction timer/event counter */
  442      UINT8   eom;    /* 16-bit timer/event counter output control */
  443      UINT8   sml;    /* serial interface parameters low */
  444      UINT8   smh;    /* -"- high */
  445      UINT8   anm;    /* analog to digital converter operating parameters */
  446      UINT8   mkl;    /* interrupt mask low */
  447      UINT8   mkh;    /* -"- high */
  448      UINT8   zcm;    /* bias circuitry for ac zero-cross detection */
  449      UINT8   pa_in;  /* port A,B,C,D,F inputs */
  450      UINT8   pb_in;
  451      UINT8   pc_in;
  452      UINT8   pd_in;
  453      UINT8   pf_in;
  454      UINT8   pa_out; /* port A,B,C,D,F outputs */
  455      UINT8   pb_out;
  456      UINT8   pc_out;
  457      UINT8   pd_out;
  458      UINT8   pf_out;
  459      UINT8   cr0;    /* analog digital conversion register 0 */
  460      UINT8   cr1;    /* analog digital conversion register 1 */
  461      UINT8   cr2;    /* analog digital conversion register 2 */
  462      UINT8   cr3;    /* analog digital conversion register 3 */
  463      UINT8   txb;    /* transmitter buffer */
  464      UINT8   rxb;    /* receiver buffer */
  465      UINT8   txd;    /* port C control line states */
  466      UINT8   rxd;
  467      UINT8   sck;
  468      UINT8   ti;
  469      UINT8   to;
  470      UINT8   ci;
  471      UINT8   co0;
  472      UINT8   co1;
  473      UINT16  irr;    /* interrupt request register */
  474      UINT16  itf;    /* interrupt test flag register */
  475      int     int1;   /* keep track of current int1 state. Needed for 7801 irq checking. */
  476      int     int2;   /* keep track to current int2 state. Needed for 7801 irq checking. */
  477  
  478  /* internal helper variables */
  479      UINT16  txs;    /* transmitter shift register */
  480      UINT16  rxs;    /* receiver shift register */
  481      UINT8   txcnt;  /* transmitter shift register bit count */
  482      UINT8   rxcnt;  /* receiver shift register bit count */
  483      UINT8   txbuf;  /* transmitter buffer was written */
  484      INT32   ovc0;   /* overflow counter for timer 0 (for clock div 12/384) */
  485      INT32   ovc1;   /* overflow counter for timer 0 (for clock div 12/384) */
  486      INT32   ovce;   /* overflow counter for ecnt */
  487      INT32   ovcf;   /* overflow counter for fixed clock div 3 mode */
  488      INT32   ovcs;   /* overflow counter for serial I/O */
  489      UINT8   edges;  /* rising/falling edge flag for serial I/O */
  490      const struct opcode_s *opXX;    /* opcode table */
  491      const struct opcode_s *op48;
  492      const struct opcode_s *op4C;
  493      const struct opcode_s *op4D;
  494      const struct opcode_s *op60;
  495      const struct opcode_s *op64;
  496      const struct opcode_s *op70;
  497      const struct opcode_s *op74;
  498      void (*handle_timers)(upd7810_state *cpustate, int cycles);
  499      UPD7810_CONFIG config;
  500      device_irq_acknowledge_callback irq_callback;
  501      legacy_cpu_device *device;
  502      address_space *program;
  503      direct_read_data *direct;
  504      address_space *io;
  505      int icount;
  506  };
  507  
  508  INLINE upd7810_state *get_safe_token(device_t *device)
  509  {
  510      assert(device != NULL);
  511      assert(device->type() == UPD7810 ||
  512              device->type() == UPD7807 ||
  513              device->type() == UPD7801 ||
  514              device->type() == UPD78C05 ||
  515              device->type() == UPD78C06);
  516      return (upd7810_state *)downcast<legacy_cpu_device *>(device)->token();
  517  }
  518  
  519  #define CY  0x01
  520  #define F1  0x02
  521  #define L0  0x04
  522  #define L1  0x08
  523  #define HC  0x10
  524  #define SK  0x20
  525  #define Z   0x40
  526  #define F7  0x80
  527  
  528  /* IRR flags */
  529  #define INTNMI  0x0001
  530  #define INTFT0  0x0002
  531  #define INTFT1  0x0004
  532  #define INTF1   0x0008
  533  #define INTF2   0x0010
  534  #define INTFE0  0x0020
  535  #define INTFE1  0x0040
  536  #define INTFEIN 0x0080
  537  #define INTFAD  0x0100
  538  #define INTFSR  0x0200
  539  #define INTFST  0x0400
  540  #define INTER   0x0800
  541  #define INTOV   0x1000
  542  #define INTF0   0x2000
  543  
  544  /* ITF flags */
  545  #define INTAN4  0x0001
  546  #define INTAN5  0x0002
  547  #define INTAN6  0x0004
  548  #define INTAN7  0x0008
  549  #define INTSB   0x0010
  550  
  551  #define PPC     cpustate->ppc.w.l
  552  #define PC      cpustate->pc.w.l
  553  #define PCL     cpustate->pc.b.l
  554  #define PCH     cpustate->pc.b.h
  555  #define PCD     cpustate->pc.d
  556  #define SP      cpustate->sp.w.l
  557  #define SPL     cpustate->sp.b.l
  558  #define SPH     cpustate->sp.b.h
  559  #define SPD     cpustate->sp.d
  560  #define PSW     cpustate->psw
  561  #define OP      cpustate->op
  562  #define OP2     cpustate->op2
  563  #define IFF     cpustate->iff
  564  #define EA      cpustate->ea.w.l
  565  #define EAL     cpustate->ea.b.l
  566  #define EAH     cpustate->ea.b.h
  567  #define VA      cpustate->va.w.l
  568  #define V       cpustate->va.b.h
  569  #define A       cpustate->va.b.l
  570  #define VAD     cpustate->va.d
  571  #define BC      cpustate->bc.w.l
  572  #define B       cpustate->bc.b.h
  573  #define C       cpustate->bc.b.l
  574  #define DE      cpustate->de.w.l
  575  #define D       cpustate->de.b.h
  576  #define E       cpustate->de.b.l
  577  #define HL      cpustate->hl.w.l
  578  #define H       cpustate->hl.b.h
  579  #define L       cpustate->hl.b.l
  580  #define EA2     cpustate->ea2.w.l
  581  #define VA2     cpustate->va2.w.l
  582  #define BC2     cpustate->bc2.w.l
  583  #define DE2     cpustate->de2.w.l
  584  #define HL2     cpustate->hl2.w.l
  585  
  586  #define OVC0    cpustate->ovc0
  587  #define OVC1    cpustate->ovc1
  588  #define OVCE    cpustate->ovce
  589  #define OVCF    cpustate->ovcf
  590  #define OVCS    cpustate->ovcs
  591  #define EDGES   cpustate->edges
  592  
  593  #define CNT0    cpustate->cnt.b.l
  594  #define CNT1    cpustate->cnt.b.h
  595  #define TM0     cpustate->tm.b.l
  596  #define TM1     cpustate->tm.b.h
  597  #define ECNT    cpustate->ecnt.w.l
  598  #define ECPT    cpustate->ecnt.w.h
  599  #define ETM0    cpustate->etm.w.l
  600  #define ETM1    cpustate->etm.w.h
  601  
  602  #define MA      cpustate->ma
  603  #define MB      cpustate->mb
  604  #define MCC     cpustate->mcc
  605  #define MC      cpustate->mc
  606  #define MM      cpustate->mm
  607  #define MF      cpustate->mf
  608  #define TMM     cpustate->tmm
  609  #define ETMM    cpustate->etmm
  610  #define EOM     cpustate->eom
  611  #define SML     cpustate->sml
  612  #define SMH     cpustate->smh
  613  #define ANM     cpustate->anm
  614  #define MKL     cpustate->mkl
  615  #define MKH     cpustate->mkh
  616  #define ZCM     cpustate->zcm
  617  
  618  #define CR0     cpustate->cr0
  619  #define CR1     cpustate->cr1
  620  #define CR2     cpustate->cr2
  621  #define CR3     cpustate->cr3
  622  #define RXB     cpustate->rxb
  623  #define TXB     cpustate->txb
  624  
  625  #define RXD     cpustate->rxd
  626  #define TXD     cpustate->txd
  627  #define SCK     cpustate->sck
  628  #define TI      cpustate->ti
  629  #define TO      cpustate->to
  630  #define CI      cpustate->ci
  631  #define CO0     cpustate->co0
  632  #define CO1     cpustate->co1
  633  
  634  #define IRR     cpustate->irr
  635  #define ITF     cpustate->itf
  636  
  637  struct opcode_s {
  638      void (*opfunc)(upd7810_state *cpustate);
  639      UINT8 oplen;
  640      UINT8 cycles;
  641      UINT8 cycles_skip;
  642      UINT8 mask_l0_l1;
  643  };
  644  
  645  #define RDOP(O)     O = cpustate->direct->read_decrypted_byte(PCD); PC++
  646  #define RDOPARG(A)  A = cpustate->direct->read_raw_byte(PCD); PC++
  647  #define RM(A)       cpustate->program->read_byte(A)
  648  #define WM(A,V)     cpustate->program->write_byte(A,V)
  649  
  650  #define ZHC_ADD(after,before,carry)     \
  651      if (after == 0) PSW |= Z; else PSW &= ~Z; \
  652      if (after == before) \
  653          PSW = (PSW&~CY) | (carry); \
  654      else if (after < before)            \
  655          PSW |= CY;          \
  656      else                                \
  657          PSW &= ~CY;             \
  658      if ((after & 15) < (before & 15))   \
  659          PSW |= HC;                      \
  660      else                                \
  661          PSW &= ~HC;
  662  #define ZHC_SUB(after,before,carry)     \
  663      if (after == 0) PSW |= Z; else PSW &= ~Z; \
  664      if (before == after)                    \
  665          PSW = (PSW & ~CY) | (carry);    \
  666      else if (after > before)            \
  667          PSW |= CY;          \
  668      else                                \
  669          PSW &= ~CY;             \
  670      if ((after & 15) > (before & 15))   \
  671          PSW |= HC;                      \
  672      else                                \
  673          PSW &= ~HC;
  674  #define SKIP_CY     if (CY == (PSW & CY)) PSW |= SK
  675  #define SKIP_NC     if (0 == (PSW & CY)) PSW |= SK
  676  #define SKIP_Z      if (Z == (PSW & Z)) PSW |= SK
  677  #define SKIP_NZ     if (0 == (PSW & Z)) PSW |= SK
  678  #define SET_Z(n)    if (n) PSW &= ~Z; else PSW |= Z
  679  
  680  static UINT8 RP(upd7810_state *cpustate, offs_t port)
  681  {
  682      UINT8 data = 0xff;
  683      switch (port)
  684      {
  685      case UPD7810_PORTA:
  686          if (cpustate->ma)   // NS20031301 no need to read if the port is set as output
  687              cpustate->pa_in = cpustate->io->read_byte(port);
  688          data = (cpustate->pa_in & cpustate->ma) | (cpustate->pa_out & ~cpustate->ma);
  689          break;
  690      case UPD7810_PORTB:
  691          if (cpustate->mb)   // NS20031301 no need to read if the port is set as output
  692              cpustate->pb_in = cpustate->io->read_byte(port);
  693          data = (cpustate->pb_in & cpustate->mb) | (cpustate->pb_out & ~cpustate->mb);
  694          break;
  695      case UPD7810_PORTC:
  696          if (cpustate->mc)   // NS20031301 no need to read if the port is set as output
  697              cpustate->pc_in = cpustate->io->read_byte(port);
  698          data = (cpustate->pc_in & cpustate->mc) | (cpustate->pc_out & ~cpustate->mc);
  699          if (cpustate->mcc & 0x01)   /* PC0 = TxD output */
  700              data = (data & ~0x01) | (cpustate->txd & 1 ? 0x01 : 0x00);
  701          if (cpustate->mcc & 0x02)   /* PC1 = RxD input */
  702              data = (data & ~0x02) | (cpustate->rxd & 1 ? 0x02 : 0x00);
  703          if (cpustate->mcc & 0x04)   /* PC2 = SCK input/output */
  704              data = (data & ~0x04) | (cpustate->sck & 1 ? 0x04 : 0x00);
  705          if (cpustate->mcc & 0x08)   /* PC3 = TI input */
  706              data = (data & ~0x08) | (cpustate->ti & 1 ? 0x08 : 0x00);
  707          if (cpustate->mcc & 0x10)   /* PC4 = TO output */
  708              data = (data & ~0x10) | (cpustate->to & 1 ? 0x10 : 0x00);
  709          if (cpustate->mcc & 0x20)   /* PC5 = CI input */
  710              data = (data & ~0x20) | (cpustate->ci & 1 ? 0x20 : 0x00);
  711          if (cpustate->mcc & 0x40)   /* PC6 = CO0 output */
  712              data = (data & ~0x40) | (cpustate->co0 & 1 ? 0x40 : 0x00);
  713          if (cpustate->mcc & 0x80)   /* PC7 = CO1 output */
  714              data = (data & ~0x80) | (cpustate->co1 & 1 ? 0x80 : 0x00);
  715          break;
  716      case UPD7810_PORTD:
  717          cpustate->pd_in = cpustate->io->read_byte(port);
  718          switch (cpustate->mm & 0x07)
  719          {
  720          case 0x00:          /* PD input mode, PF port mode */
  721              data = cpustate->pd_in;
  722              break;
  723          case 0x01:          /* PD output mode, PF port mode */
  724              data = cpustate->pd_out;
  725              break;
  726          default:            /* PD extension mode, PF port/extension mode */
  727              data = 0xff;    /* what do we see on the port here? */
  728              break;
  729          }
  730          break;
  731      case UPD7810_PORTF:
  732          cpustate->pf_in = cpustate->io->read_byte(port);
  733          switch (cpustate->mm & 0x06)
  734          {
  735          case 0x00:          /* PD input/output mode, PF port mode */
  736              data = (cpustate->pf_in & cpustate->mf) | (cpustate->pf_out & ~cpustate->mf);
  737              break;
  738          case 0x02:          /* PD extension mode, PF0-3 extension mode, PF4-7 port mode */
  739              data = (cpustate->pf_in & cpustate->mf) | (cpustate->pf_out & ~cpustate->mf);
  740              data |= 0x0f;   /* what would we see on the lower bits here? */
  741              break;
  742          case 0x04:          /* PD extension mode, PF0-5 extension mode, PF6-7 port mode */
  743              data = (cpustate->pf_in & cpustate->mf) | (cpustate->pf_out & ~cpustate->mf);
  744              data |= 0x3f;   /* what would we see on the lower bits here? */
  745              break;
  746          case 0x06:
  747              data = 0xff;    /* what would we see on the lower bits here? */
  748              break;
  749          }
  750          break;
  751      case UPD7807_PORTT: // NS20031301 partial implementation
  752          data = cpustate->io->read_byte(port);
  753          break;
  754      default:
  755          logerror("uPD7810 internal error: RP(cpustate) called with invalid port number\n");
  756      }
  757      return data;
  758  }
  759  
  760  static void WP(upd7810_state *cpustate, offs_t port, UINT8 data)
  761  {
  762      switch (port)
  763      {
  764      case UPD7810_PORTA:
  765          cpustate->pa_out = data;
  766  //      data = (data & ~cpustate->ma) | (cpustate->pa_in & cpustate->ma);
  767          data = (data & ~cpustate->ma) | (cpustate->ma); // NS20031401
  768          cpustate->io->write_byte(port, data);
  769          break;
  770      case UPD7810_PORTB:
  771          cpustate->pb_out = data;
  772  //      data = (data & ~cpustate->mb) | (cpustate->pb_in & cpustate->mb);
  773          data = (data & ~cpustate->mb) | (cpustate->mb); // NS20031401
  774          cpustate->io->write_byte(port, data);
  775          break;
  776      case UPD7810_PORTC:
  777          cpustate->pc_out = data;
  778  //      data = (data & ~cpustate->mc) | (cpustate->pc_in & cpustate->mc);
  779          data = (data & ~cpustate->mc) | (cpustate->mc); // NS20031401
  780          if (cpustate->mcc & 0x01)   /* PC0 = TxD output */
  781              data = (data & ~0x01) | (cpustate->txd & 1 ? 0x01 : 0x00);
  782          if (cpustate->mcc & 0x02)   /* PC1 = RxD input */
  783              data = (data & ~0x02) | (cpustate->rxd & 1 ? 0x02 : 0x00);
  784          if (cpustate->mcc & 0x04)   /* PC2 = SCK input/output */
  785              data = (data & ~0x04) | (cpustate->sck & 1 ? 0x04 : 0x00);
  786          if (cpustate->mcc & 0x08)   /* PC3 = TI input */
  787              data = (data & ~0x08) | (cpustate->ti & 1 ? 0x08 : 0x00);
  788          if (cpustate->mcc & 0x10)   /* PC4 = TO output */
  789              data = (data & ~0x10) | (cpustate->to & 1 ? 0x10 : 0x00);
  790          if (cpustate->mcc & 0x20)   /* PC5 = CI input */
  791              data = (data & ~0x20) | (cpustate->ci & 1 ? 0x20 : 0x00);
  792          if (cpustate->mcc & 0x40)   /* PC6 = CO0 output */
  793              data = (data & ~0x40) | (cpustate->co0 & 1 ? 0x40 : 0x00);
  794          if (cpustate->mcc & 0x80)   /* PC7 = CO1 output */
  795              data = (data & ~0x80) | (cpustate->co1 & 1 ? 0x80 : 0x00);
  796          cpustate->io->write_byte(port, data);
  797          break;
  798      case UPD7810_PORTD:
  799          cpustate->pd_out = data;
  800          switch (cpustate->mm & 0x07)
  801          {
  802          case 0x00:          /* PD input mode, PF port mode */
  803              data = cpustate->pd_in;
  804              break;
  805          case 0x01:          /* PD output mode, PF port mode */
  806              data = cpustate->pd_out;
  807              break;
  808          default:            /* PD extension mode, PF port/extension mode */
  809              return;
  810          }
  811          cpustate->io->write_byte(port, data);
  812          break;
  813      case UPD7810_PORTF:
  814          cpustate->pf_out = data;
  815          data = (data & ~cpustate->mf) | (cpustate->pf_in & cpustate->mf);
  816          switch (cpustate->mm & 0x06)
  817          {
  818          case 0x00:          /* PD input/output mode, PF port mode */
  819              break;
  820          case 0x02:          /* PD extension mode, PF0-3 extension mode, PF4-7 port mode */
  821              data |= 0x0f;   /* what would come out for the lower bits here? */
  822              break;
  823          case 0x04:          /* PD extension mode, PF0-5 extension mode, PF6-7 port mode */
  824              data |= 0x3f;   /* what would come out for the lower bits here? */
  825              break;
  826          case 0x06:
  827              data |= 0xff;   /* what would come out for the lower bits here? */
  828              break;
  829          }
  830          cpustate->io->write_byte(port, data);
  831          break;
  832      default:
  833          logerror("uPD7810 internal error: RP(cpustate) called with invalid port number\n");
  834      }
  835  }
  836  
  837  static void upd7810_take_irq(upd7810_state *cpustate)
  838  {
  839      UINT16 vector = 0;
  840      int irqline = 0;
  841  
  842      /* global interrupt disable? */
  843      if (0 == IFF)
  844          return;
  845  
  846      switch ( cpustate->config.type )
  847      {
  848      case TYPE_7801:
  849          /* 1 - SOFTI - vector at 0x0060 */
  850          /* 2 - INT0 - Masked by MK0 bit */
  851          if ( IRR & INTF0 && 0 == (MKL & 0x01 ) )
  852          {
  853              irqline = UPD7810_INTF0;
  854              vector = 0x0004;
  855              IRR &= ~INTF0;
  856          }
  857          /* 3 - INTT - Masked by MKT bit */
  858          if ( IRR & INTFT0 && 0 == ( MKL & 0x02 ) )
  859          {
  860              vector = 0x0008;
  861              IRR &= ~INTFT0;
  862          }
  863          /* 4 - INT1 - Masked by MK1 bit */
  864          if ( IRR & INTF1 && 0 == ( MKL & 0x04 ) )
  865          {
  866              irqline = UPD7810_INTF1;
  867              vector = 0x0010;
  868              IRR &= ~INTF1;
  869          }
  870          /* 5 - INT2 - Masked by MK2 bit */
  871          if ( IRR & INTF2 && 0 == ( MKL & 0x08 ) )
  872          {
  873              irqline = UPD7810_INTF2;
  874              vector = 0x0020;
  875              IRR &= ~INTF2;
  876          }
  877          /* 6 - INTS - Masked by MKS bit */
  878          if ( IRR & INTFST && 0 == ( MKL & 0x10 ) )
  879          {
  880              vector = 0x0040;
  881              IRR &= ~INTFST;
  882          }
  883          break;
  884  
  885      default:
  886          /* check the interrupts in priority sequence */
  887          if ((IRR & INTFT0)  && 0 == (MKL & 0x02))
  888          {
  889              switch (cpustate->config.type)
  890              {
  891                  case TYPE_7810_GAMEMASTER:
  892                      vector = 0xff2a;
  893                      break;
  894                  default:
  895                      vector = 0x0008;
  896              }
  897              if (!((IRR & INTFT1)    && 0 == (MKL & 0x04)))
  898              IRR&=~INTFT0;
  899          }
  900          else
  901          if ((IRR & INTFT1)  && 0 == (MKL & 0x04))
  902          {
  903              switch (cpustate->config.type)
  904              {
  905                  case TYPE_7810_GAMEMASTER:
  906                      vector = 0xff2a;
  907                      break;
  908                  default:
  909                      vector = 0x0008;
  910              }
  911              IRR&=~INTFT1;
  912          }
  913          else
  914          if ((IRR & INTF1)   && 0 == (MKL & 0x08))
  915          {
  916              irqline = UPD7810_INTF1;
  917              vector = 0x0010;
  918              if (!((IRR & INTF2) && 0 == (MKL & 0x10)))
  919                  IRR&=~INTF1;
  920          }
  921          else
  922          if ((IRR & INTF2)   && 0 == (MKL & 0x10))
  923          {
  924              irqline = UPD7810_INTF2;
  925              vector = 0x0010;
  926              IRR&=~INTF2;
  927          }
  928          else
  929          if ((IRR & INTFE0)  && 0 == (MKL & 0x20))
  930          {
  931              switch (cpustate->config.type)
  932              {
  933                  case TYPE_7810_GAMEMASTER:
  934                      vector = 0xff2d;
  935                      break;
  936                  default:
  937                      vector = 0x0018;
  938              }
  939              if (!((IRR & INTFE1)    && 0 == (MKL & 0x40)))
  940              IRR&=~INTFE0;
  941          }
  942          else
  943          if ((IRR & INTFE1)  && 0 == (MKL & 0x40))
  944          {
  945              switch (cpustate->config.type)
  946              {
  947                  case TYPE_7810_GAMEMASTER:
  948                      vector = 0xff2d;
  949                      break;
  950                  default:
  951                      vector = 0x0018;
  952              }
  953              IRR&=~INTFE1;
  954          }
  955          else
  956          if ((IRR & INTFEIN) && 0 == (MKL & 0x80))
  957          {
  958              vector = 0x0020;
  959          }
  960          else
  961          if ((IRR & INTFAD)  && 0 == (MKH & 0x01))
  962          {
  963              vector = 0x0020;
  964          }
  965          else
  966          if ((IRR & INTFSR)  && 0 == (MKH & 0x02))
  967          {
  968              vector = 0x0028;
  969              IRR&=~INTFSR;
  970          }
  971          else
  972          if ((IRR & INTFST)  && 0 == (MKH & 0x04))
  973          {
  974              vector = 0x0028;
  975              IRR&=~INTFST;
  976          }
  977          break;
  978      }
  979  
  980      if (vector)
  981      {
  982          /* acknowledge external IRQ */
  983          if (irqline)
  984              (*cpustate->irq_callback)(cpustate->device, irqline);
  985          SP--;
  986          WM( SP, PSW );
  987          SP--;
  988          WM( SP, PCH );
  989          SP--;
  990          WM( SP, PCL );
  991          IFF = 0;
  992          PSW &= ~(SK|L0|L1);
  993          PC = vector;
  994      }
  995  }
  996  
  997  static void upd7810_write_EOM(upd7810_state *cpustate)
  998  {
  999      if (EOM & 0x01) /* output LV0 content ? */
 1000      {
 1001          switch (EOM & 0x0e)
 1002          {
 1003          case 0x02:  /* toggle CO0 */
 1004              CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
 1005              break;
 1006          case 0x04:  /* reset CO0 */
 1007              CO0 = 0;
 1008              break;
 1009          case 0x08:  /* set CO0 */
 1010              CO0 = 1;
 1011              break;
 1012          }
 1013      }
 1014      if (EOM & 0x10) /* output LV0 content ? */
 1015      {
 1016          switch (EOM & 0xe0)
 1017          {
 1018          case 0x20:  /* toggle CO1 */
 1019              CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
 1020              break;
 1021          case 0x40:  /* reset CO1 */
 1022              CO1 = 0;
 1023              break;
 1024          case 0x80:  /* set CO1 */
 1025              CO1 = 1;
 1026              break;
 1027          }
 1028      }
 1029  }
 1030  
 1031  static void upd7810_write_TXB(upd7810_state *cpustate)
 1032  {
 1033      cpustate->txbuf = 1;
 1034  }
 1035  
 1036  #define PAR7(n) ((((n)>>6)^((n)>>5)^((n)>>4)^((n)>>3)^((n)>>2)^((n)>>1)^((n)))&1)
 1037  #define PAR8(n) ((((n)>>7)^((n)>>6)^((n)>>5)^((n)>>4)^((n)>>3)^((n)>>2)^((n)>>1)^((n)))&1)
 1038  
 1039  static void upd7810_sio_output(upd7810_state *cpustate)
 1040  {
 1041      /* shift out more bits? */
 1042      if (cpustate->txcnt > 0)
 1043      {
 1044          TXD = cpustate->txs & 1;
 1045          if (cpustate->config.io_callback)
 1046              (*cpustate->config.io_callback)(cpustate->device,UPD7810_TXD,TXD);
 1047          cpustate->txs >>= 1;
 1048          cpustate->txcnt--;
 1049          if (0 == cpustate->txcnt)
 1050              IRR |= INTFST;      /* serial transfer completed */
 1051      }
 1052      else
 1053      if (SMH & 0x04) /* send enable ? */
 1054      {
 1055          /* nothing written into the transmitter buffer ? */
 1056          if (0 == cpustate->txbuf)
 1057              return;
 1058          cpustate->txbuf = 0;
 1059  
 1060          if (SML & 0x03)         /* asynchronous mode ? */
 1061          {
 1062              switch (SML & 0xfc)
 1063              {
 1064              case 0x48:  /* 7bits, no parity, 1 stop bit */
 1065              case 0x68:  /* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
 1066                  /* insert start bit in bit0, stop bit int bit8 */
 1067                  cpustate->txs = (TXB << 1) | (1 << 8);
 1068                  cpustate->txcnt = 9;
 1069                  break;
 1070              case 0x4c:  /* 8bits, no parity, 1 stop bit */
 1071              case 0x6c:  /* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
 1072                  /* insert start bit in bit0, stop bit int bit9 */
 1073                  cpustate->txs = (TXB << 1) | (1 << 9);
 1074                  cpustate->txcnt = 10;
 1075                  break;
 1076              case 0x58:  /* 7bits, odd parity, 1 stop bit */
 1077                  /* insert start bit in bit0, parity in bit 8, stop bit in bit9 */
 1078                  cpustate->txs = (TXB << 1) | (PAR7(TXB) << 8) | (1 << 9);
 1079                  cpustate->txcnt = 10;
 1080                  break;
 1081              case 0x5c:  /* 8bits, odd parity, 1 stop bit */
 1082                  /* insert start bit in bit0, parity in bit 9, stop bit int bit10 */
 1083                  cpustate->txs = (TXB << 1) | (PAR8(TXB) << 9) | (1 << 10);
 1084                  cpustate->txcnt = 11;
 1085                  break;
 1086              case 0x78:  /* 7bits, even parity, 1 stop bit */
 1087                  /* insert start bit in bit0, parity in bit 8, stop bit in bit9 */
 1088                  cpustate->txs = (TXB << 1) | ((PAR7(TXB) ^ 1) << 8) | (1 << 9);
 1089                  cpustate->txcnt = 10;
 1090                  break;
 1091              case 0x7c:  /* 8bits, even parity, 1 stop bit */
 1092                  /* insert start bit in bit0, parity in bit 9, stop bit int bit10 */
 1093                  cpustate->txs = (TXB << 1) | ((PAR8(TXB) ^ 1) << 9) | (1 << 10);
 1094                  cpustate->txcnt = 11;
 1095                  break;
 1096              case 0xc8:  /* 7bits, no parity, 2 stop bits */
 1097              case 0xe8:  /* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
 1098                  /* insert start bit in bit0, stop bits int bit8+9 */
 1099                  cpustate->txs = (TXB << 1) | (3 << 8);
 1100                  cpustate->txcnt = 10;
 1101                  break;
 1102              case 0xcc:  /* 8bits, no parity, 2 stop bits */
 1103              case 0xec:  /* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
 1104                  /* insert start bit in bit0, stop bits in bits9+10 */
 1105                  cpustate->txs = (TXB << 1) | (3 << 9);
 1106                  cpustate->txcnt = 11;
 1107                  break;
 1108              case 0xd8:  /* 7bits, odd parity, 2 stop bits */
 1109                  /* insert start bit in bit0, parity in bit 8, stop bits in bits9+10 */
 1110                  cpustate->txs = (TXB << 1) | (PAR7(TXB) << 8) | (3 << 9);
 1111                  cpustate->txcnt = 11;
 1112                  break;
 1113              case 0xdc:  /* 8bits, odd parity, 2 stop bits */
 1114                  /* insert start bit in bit0, parity in bit 9, stop bits int bit10+11 */
 1115                  cpustate->txs = (TXB << 1) | (PAR8(TXB) << 9) | (3 << 10);
 1116                  cpustate->txcnt = 12;
 1117                  break;
 1118              case 0xf8:  /* 7bits, even parity, 2 stop bits */
 1119                  /* insert start bit in bit0, parity in bit 8, stop bits in bit9+10 */
 1120                  cpustate->txs = (TXB << 1) | ((PAR7(TXB) ^ 1) << 8) | (3 << 9);
 1121                  cpustate->txcnt = 11;
 1122                  break;
 1123              case 0xfc:  /* 8bits, even parity, 2 stop bits */
 1124                  /* insert start bit in bit0, parity in bit 9, stop bits int bits10+10 */
 1125                  cpustate->txs = (TXB << 1) | ((PAR8(TXB) ^ 1) << 9) | (1 << 10);
 1126                  cpustate->txcnt = 12;
 1127                  break;
 1128              }
 1129          }
 1130          else
 1131          {
 1132              /* synchronous mode */
 1133              cpustate->txs = TXB;
 1134              cpustate->txcnt = 8;
 1135          }
 1136      }
 1137  }
 1138  
 1139  static void upd7810_sio_input(upd7810_state *cpustate)
 1140  {
 1141      /* sample next bit? */
 1142      if (cpustate->rxcnt > 0)
 1143      {
 1144          if (cpustate->config.io_callback)
 1145              RXD = (*cpustate->config.io_callback)(cpustate->device,UPD7810_RXD,RXD);
 1146          cpustate->rxs = (cpustate->rxs >> 1) | ((UINT16)RXD << 15);
 1147          cpustate->rxcnt--;
 1148          if (0 == cpustate->rxcnt)
 1149          {
 1150              /* reset the TSK bit */
 1151              SMH &= ~0x40;
 1152              /* serial receive completed interrupt */
 1153              IRR |= INTFSR;
 1154              /* now extract the data from the shift register */
 1155              if (SML & 0x03)     /* asynchronous mode ? */
 1156              {
 1157                  switch (SML & 0xfc)
 1158                  {
 1159                  case 0x48:  /* 7bits, no parity, 1 stop bit */
 1160                  case 0x68:  /* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
 1161                      cpustate->rxs >>= 16 - 9;
 1162                      RXB = (cpustate->rxs >> 1) & 0x7f;
 1163                      if ((1 << 8) != (cpustate->rxs & (1 | (1 << 8))))
 1164                          IRR |= INTER;   /* framing error */
 1165                      break;
 1166                  case 0x4c:  /* 8bits, no parity, 1 stop bit */
 1167                  case 0x6c:  /* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
 1168                      cpustate->rxs >>= 16 - 10;
 1169                      RXB = (cpustate->rxs >> 1) & 0xff;
 1170                      if ((1 << 9) != (cpustate->rxs & (1 | (1 << 9))))
 1171                          IRR |= INTER;   /* framing error */
 1172                      break;
 1173                  case 0x58:  /* 7bits, odd parity, 1 stop bit */
 1174                      cpustate->rxs >>= 16 - 10;
 1175                      RXB = (cpustate->rxs >> 1) & 0x7f;
 1176                      if ((1 << 9) != (cpustate->rxs & (1 | (1 << 9))))
 1177                          IRR |= INTER;   /* framing error */
 1178                      if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
 1179                          IRR |= INTER;   /* parity error */
 1180                      break;
 1181                  case 0x5c:  /* 8bits, odd parity, 1 stop bit */
 1182                      cpustate->rxs >>= 16 - 11;
 1183                      RXB = (cpustate->rxs >> 1) & 0xff;
 1184                      if ((1 << 10) != (cpustate->rxs & (1 | (1 << 10))))
 1185                          IRR |= INTER;   /* framing error */
 1186                      if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
 1187                          IRR |= INTER;   /* parity error */
 1188                      break;
 1189                  case 0x78:  /* 7bits, even parity, 1 stop bit */
 1190                      cpustate->rxs >>= 16 - 10;
 1191                      RXB = (cpustate->rxs >> 1) & 0x7f;
 1192                      if ((1 << 9) != (cpustate->rxs & (1 | (1 << 9))))
 1193                          IRR |= INTER;   /* framing error */
 1194                      if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
 1195                          IRR |= INTER;   /* parity error */
 1196                      break;
 1197                  case 0x7c:  /* 8bits, even parity, 1 stop bit */
 1198                      cpustate->rxs >>= 16 - 11;
 1199                      RXB = (cpustate->rxs >> 1) & 0xff;
 1200                      if ((1 << 10) != (cpustate->rxs & (1 | (1 << 10))))
 1201                          IRR |= INTER;   /* framing error */
 1202                      if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
 1203                          IRR |= INTER;   /* parity error */
 1204                      break;
 1205                  case 0xc8:  /* 7bits, no parity, 2 stop bits */
 1206                  case 0xe8:  /* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
 1207                      cpustate->rxs >>= 16 - 10;
 1208                      RXB = (cpustate->rxs >> 1) & 0x7f;
 1209                      if ((3 << 9) != (cpustate->rxs & (1 | (3 << 9))))
 1210                          IRR |= INTER;   /* framing error */
 1211                      if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
 1212                          IRR |= INTER;   /* parity error */
 1213                      break;
 1214                  case 0xcc:  /* 8bits, no parity, 2 stop bits */
 1215                  case 0xec:  /* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
 1216                      cpustate->rxs >>= 16 - 11;
 1217                      RXB = (cpustate->rxs >> 1) & 0xff;
 1218                      if ((3 << 10) != (cpustate->rxs & (1 | (3 << 10))))
 1219                          IRR |= INTER;   /* framing error */
 1220                      if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
 1221                          IRR |= INTER;   /* parity error */
 1222                      break;
 1223                  case 0xd8:  /* 7bits, odd parity, 2 stop bits */
 1224                      cpustate->rxs >>= 16 - 11;
 1225                      RXB = (cpustate->rxs >> 1) & 0x7f;
 1226                      if ((3 << 10) != (cpustate->rxs & (1 | (3 << 10))))
 1227                          IRR |= INTER;   /* framing error */
 1228                      if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
 1229                          IRR |= INTER;   /* parity error */
 1230                      break;
 1231                  case 0xdc:  /* 8bits, odd parity, 2 stop bits */
 1232                      cpustate->rxs >>= 16 - 12;
 1233                      RXB = (cpustate->rxs >> 1) & 0xff;
 1234                      if ((3 << 11) != (cpustate->rxs & (1 | (3 << 11))))
 1235                          IRR |= INTER;   /* framing error */
 1236                      if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
 1237                          IRR |= INTER;   /* parity error */
 1238                      break;
 1239                  case 0xf8:  /* 7bits, even parity, 2 stop bits */
 1240                      cpustate->rxs >>= 16 - 11;
 1241                      RXB = (cpustate->rxs >> 1) & 0x7f;
 1242                      if ((3 << 10) != (cpustate->rxs & (1 | (3 << 10))))
 1243                          IRR |= INTER;   /* framing error */
 1244                      if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
 1245                          IRR |= INTER;   /* parity error */
 1246                      break;
 1247                  case 0xfc:  /* 8bits, even parity, 2 stop bits */
 1248                      cpustate->rxs >>= 16 - 12;
 1249                      RXB = (cpustate->rxs >> 1) & 0xff;
 1250                      if ((3 << 11) != (cpustate->rxs & (1 | (3 << 11))))
 1251                          IRR |= INTER;   /* framing error */
 1252                      if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
 1253                          IRR |= INTER;   /* parity error */
 1254                      break;
 1255                  }
 1256              }
 1257              else
 1258              {
 1259                  cpustate->rxs >>= 16 - 8;
 1260                  RXB = cpustate->rxs;
 1261  //              cpustate->rxcnt = 8;
 1262              }
 1263          }
 1264      }
 1265      else
 1266      if (SMH & 0x08) /* receive enable ? */
 1267      {
 1268          if (SML & 0x03)     /* asynchronous mode ? */
 1269          {
 1270              switch (SML & 0xfc)
 1271              {
 1272              case 0x48:  /* 7bits, no parity, 1 stop bit */
 1273              case 0x68:  /* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
 1274                  cpustate->rxcnt = 9;
 1275                  break;
 1276              case 0x4c:  /* 8bits, no parity, 1 stop bit */
 1277              case 0x6c:  /* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
 1278                  cpustate->rxcnt = 10;
 1279                  break;
 1280              case 0x58:  /* 7bits, odd parity, 1 stop bit */
 1281                  cpustate->rxcnt = 10;
 1282                  break;
 1283              case 0x5c:  /* 8bits, odd parity, 1 stop bit */
 1284                  cpustate->rxcnt = 11;
 1285                  break;
 1286              case 0x78:  /* 7bits, even parity, 1 stop bit */
 1287                  cpustate->rxcnt = 10;
 1288                  break;
 1289              case 0x7c:  /* 8bits, even parity, 1 stop bit */
 1290                  cpustate->rxcnt = 11;
 1291                  break;
 1292              case 0xc8:  /* 7bits, no parity, 2 stop bits */
 1293              case 0xe8:  /* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
 1294                  cpustate->rxcnt = 10;
 1295                  break;
 1296              case 0xcc:  /* 8bits, no parity, 2 stop bits */
 1297              case 0xec:  /* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
 1298                  cpustate->rxcnt = 11;
 1299                  break;
 1300              case 0xd8:  /* 7bits, odd parity, 2 stop bits */
 1301                  cpustate->rxcnt = 11;
 1302                  break;
 1303              case 0xdc:  /* 8bits, odd parity, 2 stop bits */
 1304                  cpustate->rxcnt = 12;
 1305                  break;
 1306              case 0xf8:  /* 7bits, even parity, 2 stop bits */
 1307                  cpustate->rxcnt = 11;
 1308                  break;
 1309              case 0xfc:  /* 8bits, even parity, 2 stop bits */
 1310                  cpustate->rxcnt = 12;
 1311                  break;
 1312              }
 1313          }
 1314          else
 1315          /* TSK bit set ? */
 1316          if (SMH & 0x40)
 1317          {
 1318              cpustate->rxcnt = 8;
 1319          }
 1320      }
 1321  }
 1322  
 1323  static void upd7810_timers(upd7810_state *cpustate, int cycles)
 1324  {
 1325      /**** TIMER 0 ****/
 1326      if (TMM & 0x10)         /* timer 0 upcounter reset ? */
 1327          CNT0 = 0;
 1328      else
 1329      {
 1330          switch (TMM & 0x0c) /* timer 0 clock source */
 1331          {
 1332          case 0x00:  /* clock divided by 12 */
 1333              OVC0 += cycles;
 1334              while (OVC0 >= 12)
 1335              {
 1336                  OVC0 -= 12;
 1337                  CNT0++;
 1338                  if (CNT0 == TM0)
 1339                  {
 1340                      CNT0 = 0;
 1341                      IRR |= INTFT0;
 1342                      /* timer F/F source is timer 0 ? */
 1343                      if (0x00 == (TMM & 0x03))
 1344                      {
 1345                          TO ^= 1;
 1346                          if (cpustate->config.io_callback)
 1347                              (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1348                      }
 1349                      /* timer 1 chained with timer 0 ? */
 1350                      if ((TMM & 0xe0) == 0x60)
 1351                      {
 1352                          CNT1++;
 1353                          if (CNT1 == TM1)
 1354                          {
 1355                              IRR |= INTFT1;
 1356                              CNT1 = 0;
 1357                              /* timer F/F source is timer 1 ? */
 1358                              if (0x01 == (TMM & 0x03))
 1359                              {
 1360                                  TO ^= 1;
 1361                                  if (cpustate->config.io_callback)
 1362                                      (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1363                              }
 1364                          }
 1365                      }
 1366                  }
 1367              }
 1368              break;
 1369          case 0x04:  /* clock divided by 384 */
 1370              OVC0 += cycles;
 1371              while (OVC0 >= 384)
 1372              {
 1373                  OVC0 -= 384;
 1374                  CNT0++;
 1375                  if (CNT0 == TM0)
 1376                  {
 1377                      CNT0 = 0;
 1378                      IRR |= INTFT0;
 1379                      /* timer F/F source is timer 0 ? */
 1380                      if (0x00 == (TMM & 0x03))
 1381                      {
 1382                          TO ^= 1;
 1383                          if (cpustate->config.io_callback)
 1384                              (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1385                      }
 1386                      /* timer 1 chained with timer 0 ? */
 1387                      if ((TMM & 0xe0) == 0x60)
 1388                      {
 1389                          CNT1++;
 1390                          if (CNT1 == TM1)
 1391                          {
 1392                              CNT1 = 0;
 1393                              IRR |= INTFT1;
 1394                              /* timer F/F source is timer 1 ? */
 1395                              if (0x01 == (TMM & 0x03))
 1396                              {
 1397                                  TO ^= 1;
 1398                                  if (cpustate->config.io_callback)
 1399                                      (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1400                              }
 1401                          }
 1402                      }
 1403                  }
 1404              }
 1405              break;
 1406          case 0x08:  /* external signal at TI */
 1407              break;
 1408          case 0x0c:  /* disabled */
 1409              break;
 1410          }
 1411      }
 1412  
 1413      /**** TIMER 1 ****/
 1414      if (TMM & 0x80)         /* timer 1 upcounter reset ? */
 1415          CNT1 = 0;
 1416      else
 1417      {
 1418          switch (TMM & 0x60) /* timer 1 clock source */
 1419          {
 1420          case 0x00:  /* clock divided by 12 */
 1421              OVC1 += cycles;
 1422              while (OVC1 >= 12)
 1423              {
 1424                  OVC1 -= 12;
 1425                  CNT1++;
 1426                  if (CNT1 == TM1)
 1427                  {
 1428                      CNT1 = 0;
 1429                      IRR |= INTFT1;
 1430                      /* timer F/F source is timer 1 ? */
 1431                      if (0x01 == (TMM & 0x03))
 1432                      {
 1433                          TO ^= 1;
 1434                          if (cpustate->config.io_callback)
 1435                              (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1436                      }
 1437                  }
 1438              }
 1439              break;
 1440          case 0x20:  /* clock divided by 384 */
 1441              OVC1 += cycles;
 1442              while (OVC1 >= 384)
 1443              {
 1444                  OVC1 -= 384;
 1445                  CNT1++;
 1446                  if (CNT1 == TM1)
 1447                  {
 1448                      CNT1 = 0;
 1449                      IRR |= INTFT1;
 1450                      /* timer F/F source is timer 1 ? */
 1451                      if (0x01 == (TMM & 0x03))
 1452                      {
 1453                          TO ^= 1;
 1454                          if (cpustate->config.io_callback)
 1455                              (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1456                      }
 1457                  }
 1458              }
 1459              break;
 1460          case 0x40:  /* external signal at TI */
 1461              break;
 1462          case 0x60:  /* clocked with timer 0 */
 1463              break;
 1464          }
 1465      }
 1466  
 1467      /**** TIMER F/F ****/
 1468      /* timer F/F source is clock divided by 3 ? */
 1469      if (0x02 == (TMM & 0x03))
 1470      {
 1471          OVCF += cycles;
 1472          while (OVCF >= 3)
 1473          {
 1474              TO ^= 1;
 1475              if (cpustate->config.io_callback)
 1476                  (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1477              OVCF -= 3;
 1478          }
 1479      }
 1480  
 1481      /**** ETIMER ****/
 1482      /* ECNT clear */
 1483      if (0x00 == (ETMM & 0x0c))
 1484          ECNT = 0;
 1485      else
 1486      if (0x00 == (ETMM & 0x03) || (0x01 == (ETMM & 0x03) && CI))
 1487      {
 1488          OVCE += cycles;
 1489          /* clock divided by 12 */
 1490          while (OVCE >= 12)
 1491          {
 1492              OVCE -= 12;
 1493              ECNT++;
 1494              switch (ETMM & 0x0c)
 1495              {
 1496              case 0x00:              /* clear ECNT */
 1497                  break;
 1498              case 0x04:              /* free running */
 1499                  if (0 == ECNT)
 1500                      ITF |= INTOV;   /* set overflow flag if counter wrapped */
 1501                  break;
 1502              case 0x08:              /* reset at falling edge of CI or TO */
 1503                  break;
 1504              case 0x0c:              /* reset if ECNT == ETM1 */
 1505                  if (ETM1 == ECNT)
 1506                      ECNT = 0;
 1507                  break;
 1508              }
 1509              switch (ETMM & 0x30)
 1510              {
 1511              case 0x00:  /* set CO0 if ECNT == ETM0 */
 1512                  if (ETM0 == ECNT)
 1513                  {
 1514                      switch (EOM & 0x0e)
 1515                      {
 1516                      case 0x02:  /* toggle CO0 */
 1517                          CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
 1518                          break;
 1519                      case 0x04:  /* reset CO0 */
 1520                          CO0 = 0;
 1521                          break;
 1522                      case 0x08:  /* set CO0 */
 1523                          CO0 = 1;
 1524                          break;
 1525                      }
 1526                  }
 1527                  break;
 1528              case 0x10:  /* prohibited */
 1529                  break;
 1530              case 0x20:  /* set CO0 if ECNT == ETM0 or at falling CI input */
 1531                  if (ETM0 == ECNT)
 1532                  {
 1533                      switch (EOM & 0x0e)
 1534                      {
 1535                      case 0x02:  /* toggle CO0 */
 1536                          CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
 1537                          break;
 1538                      case 0x04:  /* reset CO0 */
 1539                          CO0 = 0;
 1540                          break;
 1541                      case 0x08:  /* set CO0 */
 1542                          CO0 = 1;
 1543                          break;
 1544                      }
 1545                  }
 1546                  break;
 1547              case 0x30:  /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */
 1548                  if (ETM0 == ECNT || ETM1 == ECNT)
 1549                  {
 1550                      switch (EOM & 0x0e)
 1551                      {
 1552                      case 0x02:  /* toggle CO0 */
 1553                          CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
 1554                          break;
 1555                      case 0x04:  /* reset CO0 */
 1556                          CO0 = 0;
 1557                          break;
 1558                      case 0x08:  /* set CO0 */
 1559                          CO0 = 1;
 1560                          break;
 1561                      }
 1562                  }
 1563                  break;
 1564              }
 1565              switch (ETMM & 0xc0)
 1566              {
 1567              case 0x00:  /* lacth CO1 if ECNT == ETM1 */
 1568                  if (ETM1 == ECNT)
 1569                  {
 1570                      switch (EOM & 0xe0)
 1571                      {
 1572                      case 0x20:  /* toggle CO1 */
 1573                          CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
 1574                          break;
 1575                      case 0x40:  /* reset CO1 */
 1576                          CO1 = 0;
 1577                          break;
 1578                      case 0x80:  /* set CO1 */
 1579                          CO1 = 1;
 1580                          break;
 1581                      }
 1582                  }
 1583                  break;
 1584              case 0x40:  /* prohibited */
 1585                  break;
 1586              case 0x80:  /* latch CO1 if ECNT == ETM1 or falling edge of CI input */
 1587                  if (ETM1 == ECNT)
 1588                  {
 1589                      switch (EOM & 0xe0)
 1590                      {
 1591                      case 0x20:  /* toggle CO1 */
 1592                          CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
 1593                          break;
 1594                      case 0x40:  /* reset CO1 */
 1595                          CO1 = 0;
 1596                          break;
 1597                      case 0x80:  /* set CO1 */
 1598                          CO1 = 1;
 1599                          break;
 1600                      }
 1601                  }
 1602                  break;
 1603              case 0xc0:  /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
 1604                  if (ETM0 == ECNT || ETM1 == ECNT)
 1605                  {
 1606                      switch (EOM & 0xe0)
 1607                      {
 1608                      case 0x20:  /* toggle CO1 */
 1609                          CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
 1610                          break;
 1611                      case 0x40:  /* reset CO1 */
 1612                          CO1 = 0;
 1613                          break;
 1614                      case 0x80:  /* set CO1 */
 1615                          CO1 = 1;
 1616                          break;
 1617                      }
 1618                  }
 1619                  break;
 1620              }
 1621          }
 1622      }
 1623  
 1624      /**** SIO ****/
 1625      switch (SMH & 0x03)
 1626      {
 1627      case 0x00:      /* interval timer F/F */
 1628          break;
 1629      case 0x01:      /* internal clock divided by 384 */
 1630          OVCS += cycles;
 1631          while (OVCS >= 384)
 1632          {
 1633              OVCS -= 384;
 1634              if (0 == (EDGES ^= 1))
 1635                  upd7810_sio_input(cpustate);
 1636              else
 1637                  upd7810_sio_output(cpustate);
 1638          }
 1639          break;
 1640      case 0x02:      /* internal clock divided by 24 */
 1641          OVCS += cycles;
 1642          while (OVCS >= 24)
 1643          {
 1644              OVCS -= 24;
 1645              if (0 == (EDGES ^= 1))
 1646                  upd7810_sio_input(cpustate);
 1647              else
 1648                  upd7810_sio_output(cpustate);
 1649          }
 1650          break;
 1651      }
 1652  }
 1653  
 1654  static void upd7801_timers(upd7810_state *cpustate, int cycles)
 1655  {
 1656      if ( cpustate->ovc0 )
 1657      {
 1658          cpustate->ovc0 -= cycles;
 1659  
 1660          /* Check if timer expired */
 1661          if ( cpustate->ovc0 <= 0 )
 1662          {
 1663              IRR |= INTFT0;
 1664  
 1665              /* Reset the timer flip/fliop */
 1666              TO = 0;
 1667              if ( cpustate->config.io_callback)
 1668                  (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1669  
 1670              /* Reload the timer */
 1671              cpustate->ovc0 = 16 * ( TM0 + ( ( TM1 & 0x0f ) << 8 ) );
 1672          }
 1673      }
 1674  }
 1675  
 1676  static void upd78c05_timers(upd7810_state *cpustate, int cycles)
 1677  {
 1678      if ( cpustate->ovc0 ) {
 1679          cpustate->ovc0 -= cycles;
 1680  
 1681          if ( cpustate->ovc0 <= 0 ) {
 1682              IRR |= INTFT0;
 1683              if (0x00 == (TMM & 0x03)) {
 1684                  TO ^= 1;
 1685                  if (cpustate->config.io_callback)
 1686                      (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
 1687              }
 1688  
 1689              while ( cpustate->ovc0 <= 0 ) {
 1690                  cpustate->ovc0 += ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
 1691              }
 1692          }
 1693      }
 1694  }
 1695  
 1696  static CPU_INIT( upd7810 )
 1697  {
 1698      upd7810_state *cpustate = get_safe_token(device);
 1699  
 1700      cpustate->config = *(const UPD7810_CONFIG*) device->static_config();
 1701      cpustate->irq_callback = irqcallback;
 1702      cpustate->device = device;
 1703      cpustate->program = &device->space(AS_PROGRAM);
 1704      cpustate->direct = &cpustate->program->direct();
 1705      cpustate->io = &device->space(AS_IO);
 1706  
 1707      device->save_item(NAME(cpustate->ppc.w.l));
 1708      device->save_item(NAME(cpustate->pc.w.l));
 1709      device->save_item(NAME(cpustate->sp.w.l));
 1710      device->save_item(NAME(cpustate->psw));
 1711      device->save_item(NAME(cpustate->op));
 1712      device->save_item(NAME(cpustate->op2));
 1713      device->save_item(NAME(cpustate->iff));
 1714      device->save_item(NAME(cpustate->ea.w.l));
 1715      device->save_item(NAME(cpustate->va.w.l));
 1716      device->save_item(NAME(cpustate->bc.w.l));
 1717      device->save_item(NAME(cpustate->de.w.l));
 1718      device->save_item(NAME(cpustate->hl.w.l));
 1719      device->save_item(NAME(cpustate->ea2.w.l));
 1720      device->save_item(NAME(cpustate->va2.w.l));
 1721      device->save_item(NAME(cpustate->bc2.w.l));
 1722      device->save_item(NAME(cpustate->de2.w.l));
 1723      device->save_item(NAME(cpustate->hl2.w.l));
 1724      device->save_item(NAME(cpustate->cnt.d));
 1725      device->save_item(NAME(cpustate->tm.d));
 1726      device->save_item(NAME(cpustate->ecnt.d));
 1727      device->save_item(NAME(cpustate->etm.d));
 1728      device->save_item(NAME(cpustate->ma));
 1729      device->save_item(NAME(cpustate->mb));
 1730      device->save_item(NAME(cpustate->mcc));
 1731      device->save_item(NAME(cpustate->mc));
 1732      device->save_item(NAME(cpustate->mm));
 1733      device->save_item(NAME(cpustate->mf));
 1734      device->save_item(NAME(cpustate->tmm));
 1735      device->save_item(NAME(cpustate->etmm));
 1736      device->save_item(NAME(cpustate->eom));
 1737      device->save_item(NAME(cpustate->sml));
 1738      device->save_item(NAME(cpustate->smh));
 1739      device->save_item(NAME(cpustate->anm));
 1740      device->save_item(NAME(cpustate->mkl));
 1741      device->save_item(NAME(cpustate->mkh));
 1742      device->save_item(NAME(cpustate->zcm));
 1743      device->save_item(NAME(cpustate->pa_out));
 1744      device->save_item(NAME(cpustate->pb_out));
 1745      device->save_item(NAME(cpustate->pc_out));
 1746      device->save_item(NAME(cpustate->pd_out));
 1747      device->save_item(NAME(cpustate->pf_out));
 1748      device->save_item(NAME(cpustate->cr0));
 1749      device->save_item(NAME(cpustate->cr1));
 1750      device->save_item(NAME(cpustate->cr2));
 1751      device->save_item(NAME(cpustate->cr3));
 1752      device->save_item(NAME(cpustate->txb));
 1753      device->save_item(NAME(cpustate->rxb));
 1754      device->save_item(NAME(cpustate->txd));
 1755      device->save_item(NAME(cpustate->rxd));
 1756      device->save_item(NAME(cpustate->sck));
 1757      device->save_item(NAME(cpustate->ti));
 1758      device->save_item(NAME(cpustate->to));
 1759      device->save_item(NAME(cpustate->ci));
 1760      device->save_item(NAME(cpustate->co0));
 1761      device->save_item(NAME(cpustate->co1));
 1762      device->save_item(NAME(cpustate->irr));
 1763      device->save_item(NAME(cpustate->itf));
 1764      device->save_item(NAME(cpustate->ovc0));
 1765      device->save_item(NAME(cpustate->ovc1));
 1766      device->save_item(NAME(cpustate->ovcf));
 1767      device->save_item(NAME(cpustate->ovcs));
 1768      device->save_item(NAME(cpustate->edges));
 1769      device->save_item(NAME(cpustate->int1));
 1770      device->save_item(NAME(cpustate->int2));
 1771  }
 1772  
 1773  #include "7810tbl.c"
 1774  #include "7810ops.c"
 1775  
 1776  static CPU_RESET( upd7810 )
 1777  {
 1778      upd7810_state *cpustate = get_safe_token(device);
 1779      UPD7810_CONFIG save_config;
 1780      device_irq_acknowledge_callback save_irqcallback;
 1781  
 1782      save_config = cpustate->config;
 1783      save_irqcallback = cpustate->irq_callback;
 1784      memset(cpustate, 0, sizeof(*cpustate));
 1785      cpustate->config = save_config;
 1786      cpustate->irq_callback = save_irqcallback;
 1787      cpustate->device = device;
 1788      cpustate->program = &device->space(AS_PROGRAM);
 1789      cpustate->direct = &cpustate->program->direct();
 1790      cpustate->io = &device->space(AS_IO);
 1791  
 1792      cpustate->opXX = opXX_7810;
 1793      cpustate->op48 = op48;
 1794      cpustate->op4C = op4C;
 1795      cpustate->op4D = op4D;
 1796      cpustate->op60 = op60;
 1797      cpustate->op64 = op64;
 1798      cpustate->op70 = op70;
 1799      cpustate->op74 = op74;
 1800      ETMM = 0xff;
 1801      TMM = 0xff;
 1802      MA = 0xff;
 1803      MB = 0xff;
 1804      switch (cpustate->config.type)
 1805      {
 1806          case TYPE_7810_GAMEMASTER:
 1807              // needed for lcd screen/ram selection; might be internal in cpu and therefor not needed; 0x10 written in some games
 1808              MC = 0xff&~0x7;
 1809              WP( cpustate, UPD7810_PORTC, 1 ); //hyper space
 1810              PCD=0x8000;
 1811              break;
 1812          default:
 1813              MC = 0xff;
 1814      }
 1815      MF = 0xff;
 1816      // gamemaster falling block "and"s to enable interrupts
 1817      MKL = 0xff;
 1818      MKH = 0xff; //?
 1819      cpustate->handle_timers = upd7810_timers;
 1820  }
 1821  
 1822  static CPU_RESET( upd7807 )
 1823  {
 1824      upd7810_state *cpustate = get_safe_token(device);
 1825      CPU_RESET_CALL(upd7810);
 1826      cpustate->opXX = opXX_7807;
 1827  }
 1828  
 1829  static CPU_RESET( upd7801 )
 1830  {
 1831      upd7810_state *cpustate = get_safe_token(device);
 1832      CPU_RESET_CALL(upd7810);
 1833      cpustate->op48 = op48_7801;
 1834      cpustate->op4C = op4C_7801;
 1835      cpustate->op4D = op4D_7801;
 1836      cpustate->op60 = op60_7801;
 1837      cpustate->op64 = op64_7801;
 1838      cpustate->op70 = op70_7801;
 1839      cpustate->op74 = op74_7801;
 1840      cpustate->opXX = opXX_7801;
 1841      cpustate->handle_timers = upd7801_timers;
 1842      MA = 0;     /* Port A is output port on the uPD7801 */
 1843      cpustate->ovc0 = 0;
 1844  }
 1845  
 1846  static CPU_RESET( upd78c05 )
 1847  {
 1848      upd7810_state *cpustate = get_safe_token(device);
 1849      CPU_RESET_CALL(upd7810);
 1850      cpustate->op48 = op48_78c05;
 1851      cpustate->op4C = op4C_78c05;
 1852      cpustate->op4D = op4D_78c05;
 1853      cpustate->op60 = op60_78c05;
 1854      cpustate->op64 = op64_78c05;
 1855      cpustate->op70 = op70_78c05;
 1856      cpustate->op74 = op74_78c05;
 1857      cpustate->opXX = opXX_78c05;
 1858      MA = 0;     /* All outputs */
 1859      MC = 0xFF;  /* All inputs */
 1860      V = 0xFF;   /* The vector register is always pointing to FF00 */
 1861      cpustate->handle_timers = upd78c05_timers;
 1862      TM0 = 0xFF; /* Timer seems to be running from boot */
 1863      cpustate->ovc0 = ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
 1864  }
 1865  
 1866  static CPU_RESET( upd78c06 )
 1867  {
 1868      upd7810_state *cpustate = get_safe_token(device);
 1869      CPU_RESET_CALL(upd78c05);
 1870      cpustate->op48 = op48_78c06;
 1871      cpustate->op4C = op4C_78c06;
 1872      cpustate->op4D = op4D_78c06;
 1873      cpustate->op60 = op60_78c06;
 1874      cpustate->op64 = op64_78c06;
 1875      cpustate->op70 = op70_78c06;
 1876      cpustate->op74 = op74_78c06;
 1877      cpustate->opXX = opXX_78c06;
 1878  }
 1879  
 1880  static CPU_EXIT( upd7810 )
 1881  {
 1882  }
 1883  
 1884  static CPU_EXECUTE( upd7810 )
 1885  {
 1886      upd7810_state *cpustate = get_safe_token(device);
 1887  
 1888      do
 1889      {
 1890          int cc = 0;
 1891  
 1892          debugger_instruction_hook(device, PC);
 1893  
 1894          PPC = PC;
 1895          RDOP(OP);
 1896  
 1897          /*
 1898           * clear L0 and/or L1 flags for all opcodes except
 1899           * L0   for "MVI L,xx" or "LXI H,xxxx"
 1900           * L1   for "MVI A,xx"
 1901           */
 1902          PSW &= ~cpustate->opXX[OP].mask_l0_l1;
 1903  
 1904          /* skip flag set and not SOFTI opcode? */
 1905          if ((PSW & SK) && (OP != 0x72))
 1906          {
 1907              if (cpustate->opXX[OP].cycles)
 1908              {
 1909                  cc = cpustate->opXX[OP].cycles_skip;
 1910                  PC += cpustate->opXX[OP].oplen - 1;
 1911              }
 1912              else
 1913              {
 1914                  RDOP(OP2);
 1915                  switch (OP)
 1916                  {
 1917                  case 0x48:
 1918                      cc = cpustate->op48[OP2].cycles_skip;
 1919                      PC += cpustate->op48[OP2].oplen - 2;
 1920                      break;
 1921                  case 0x4c:
 1922                      cc = cpustate->op4C[OP2].cycles_skip;
 1923                      PC += cpustate->op4C[OP2].oplen - 2;
 1924                      break;
 1925                  case 0x4d:
 1926                      cc = cpustate->op4D[OP2].cycles_skip;
 1927                      PC += cpustate->op4D[OP2].oplen - 2;
 1928                      break;
 1929                  case 0x60:
 1930                      cc = cpustate->op60[OP2].cycles_skip;
 1931                      PC += cpustate->op60[OP2].oplen - 2;
 1932                      break;
 1933                  case 0x64:
 1934                      cc = cpustate->op64[OP2].cycles_skip;
 1935                      PC += cpustate->op64[OP2].oplen - 2;
 1936                      break;
 1937                  case 0x70:
 1938                      cc = cpustate->op70[OP2].cycles_skip;
 1939                      PC += cpustate->op70[OP2].oplen - 2;
 1940                      break;
 1941                  case 0x74:
 1942                      cc = cpustate->op74[OP2].cycles_skip;
 1943                      PC += cpustate->op74[OP2].oplen - 2;
 1944                      break;
 1945                  default:
 1946                      fatalerror("uPD7810 internal error: check cycle counts for main\n");
 1947                  }
 1948              }
 1949              PSW &= ~SK;
 1950              cpustate->handle_timers( cpustate, cc );
 1951          }
 1952          else
 1953          {
 1954              cc = cpustate->opXX[OP].cycles;
 1955              cpustate->handle_timers( cpustate, cc );
 1956              (*cpustate->opXX[OP].opfunc)(cpustate);
 1957          }
 1958          cpustate->icount -= cc;
 1959          upd7810_take_irq(cpustate);
 1960  
 1961      } while (cpustate->icount > 0);
 1962  }
 1963  
 1964  static void set_irq_line(upd7810_state *cpustate, int irqline, int state)
 1965  {
 1966      /* The uPD7801 can check for falling and rising edges changes on the INT2 input */
 1967      switch ( cpustate->config.type )
 1968      {
 1969      case TYPE_7801:
 1970          switch ( irqline )
 1971          {
 1972          case UPD7810_INTF0:
 1973              /* INT0 is level sensitive */
 1974              if ( state == ASSERT_LINE )
 1975                  IRR |= INTF0;
 1976              else
 1977                  IRR &= INTF0;
 1978              break;
 1979  
 1980          case UPD7810_INTF1:
 1981              /* INT1 is rising edge sensitive */
 1982              if ( cpustate->int1 == CLEAR_LINE && state == ASSERT_LINE )
 1983                  IRR |= INTF1;
 1984  
 1985              cpustate->int1 = state;
 1986              break;
 1987  
 1988          case UPD7810_INTF2:
 1989              /* INT2 is rising or falling edge sensitive */
 1990              /* Check if the ES bit is set then check for rising edge, otherwise falling edge */
 1991              if ( MKL & 0x20 )
 1992              {
 1993                  if ( cpustate->int2 == CLEAR_LINE && state == ASSERT_LINE )
 1994                  {
 1995                      IRR |= INTF2;
 1996                  }
 1997              }
 1998              else
 1999              {
 2000                  if ( cpustate->int2 == ASSERT_LINE && state == CLEAR_LINE )
 2001                  {
 2002                      IRR |= INTF2;
 2003                  }
 2004              }
 2005              cpustate->int2 = state;
 2006              break;
 2007          }
 2008          break;
 2009  
 2010      default:
 2011          if (state != CLEAR_LINE)
 2012          {
 2013              if (irqline == INPUT_LINE_NMI)
 2014              {
 2015                  /* no nested NMIs ? */
 2016  //              if (0 == (IRR & INTNMI))
 2017                  {
 2018                      IRR |= INTNMI;
 2019                      SP--;
 2020                      WM( SP, PSW );
 2021                      SP--;
 2022                      WM( SP, PCH );
 2023                      SP--;
 2024                      WM( SP, PCL );
 2025                      IFF = 0;
 2026                      PSW &= ~(SK|L0|L1);
 2027                      PC = 0x0004;
 2028                  }
 2029              }
 2030              else
 2031              if (irqline == UPD7810_INTF1)
 2032                  IRR |= INTF1;
 2033              else
 2034              if ( irqline == UPD7810_INTF2 && ( MKL & 0x20 ) )
 2035                  IRR |= INTF2;
 2036              // gamemaster hack
 2037              else
 2038              if (irqline == UPD7810_INTFE1)
 2039                  IRR |= INTFE1;
 2040              else
 2041                  logerror("upd7810_set_irq_line invalid irq line #%d\n", irqline);
 2042          }
 2043          /* resetting interrupt requests is done with the SKIT/SKNIT opcodes only! */
 2044      }
 2045  }
 2046  
 2047  
 2048  /**************************************************************************
 2049   * Generic set_info
 2050   **************************************************************************/
 2051  
 2052  static CPU_SET_INFO( upd7810 )
 2053  {
 2054      upd7810_state *cpustate = get_safe_token(device);
 2055      switch (state)
 2056      {
 2057          /* --- the following bits of info are set as 64-bit signed integers --- */
 2058          case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:  set_irq_line(cpustate, INPUT_LINE_NMI, info->i);    break;
 2059          case CPUINFO_INT_INPUT_STATE + UPD7810_INTF1:   set_irq_line(cpustate, UPD7810_INTF1, info->i); break;
 2060          case CPUINFO_INT_INPUT_STATE + UPD7810_INTF2:   set_irq_line(cpustate, UPD7810_INTF2, info->i); break;
 2061          case CPUINFO_INT_INPUT_STATE + UPD7810_INTFE1:  set_irq_line(cpustate, UPD7810_INTFE1, info->i);    break;
 2062  
 2063          case CPUINFO_INT_PC:                            PC = info->i;                           break;
 2064          case CPUINFO_INT_REGISTER + UPD7810_PC:         PC = info->i;                           break;
 2065          case CPUINFO_INT_SP:
 2066          case CPUINFO_INT_REGISTER + UPD7810_SP:         SP = info->i;                           break;
 2067          case CPUINFO_INT_REGISTER + UPD7810_PSW:        PSW = info->i;                          break;
 2068          case CPUINFO_INT_REGISTER + UPD7810_A:          A = info->i;                            break;
 2069          case CPUINFO_INT_REGISTER + UPD7810_V:          V = info->i;                            break;
 2070          case CPUINFO_INT_REGISTER + UPD7810_EA:         EA = info->i;                           break;
 2071          case CPUINFO_INT_REGISTER + UPD7810_VA:         VA = info->i;                           break;
 2072          case CPUINFO_INT_REGISTER + UPD7810_BC:         BC = info->i;                           break;
 2073          case CPUINFO_INT_REGISTER + UPD7810_DE:         DE = info->i;                           break;
 2074          case CPUINFO_INT_REGISTER + UPD7810_HL:         HL = info->i;                           break;
 2075          case CPUINFO_INT_REGISTER + UPD7810_EA2:        EA2 = info->i;                          break;
 2076          case CPUINFO_INT_REGISTER + UPD7810_VA2:        VA2 = info->i;                          break;
 2077          case CPUINFO_INT_REGISTER + UPD7810_BC2:        BC2 = info->i;                          break;
 2078          case CPUINFO_INT_REGISTER + UPD7810_DE2:        DE2 = info->i;                          break;
 2079          case CPUINFO_INT_REGISTER + UPD7810_HL2:        HL2 = info->i;                          break;
 2080          case CPUINFO_INT_REGISTER + UPD7810_CNT0:       CNT0 = info->i;                         break;
 2081          case CPUINFO_INT_REGISTER + UPD7810_CNT1:       CNT1 = info->i;                         break;
 2082          case CPUINFO_INT_REGISTER + UPD7810_TM0:        TM0 = info->i;                          break;
 2083          case CPUINFO_INT_REGISTER + UPD7810_TM1:        TM1 = info->i;                          break;
 2084          case CPUINFO_INT_REGISTER + UPD7810_ECNT:       ECNT = info->i;                         break;
 2085          case CPUINFO_INT_REGISTER + UPD7810_ECPT:       ECPT = info->i;                         break;
 2086          case CPUINFO_INT_REGISTER + UPD7810_ETM0:       ETM0 = info->i;                         break;
 2087          case CPUINFO_INT_REGISTER + UPD7810_ETM1:       ETM1 = info->i;                         break;
 2088          case CPUINFO_INT_REGISTER + UPD7810_MA:         MA = info->i;                           break;
 2089          case CPUINFO_INT_REGISTER + UPD7810_MB:         MB = info->i;                           break;
 2090          case CPUINFO_INT_REGISTER + UPD7810_MCC:        MCC = info->i;                          break;
 2091          case CPUINFO_INT_REGISTER + UPD7810_MC:         MC = info->i;                           break;
 2092          case CPUINFO_INT_REGISTER + UPD7810_MM:         MM = info->i;                           break;
 2093          case CPUINFO_INT_REGISTER + UPD7810_MF:         MF = info->i;                           break;
 2094          case CPUINFO_INT_REGISTER + UPD7810_TMM:        TMM = info->i;                          break;
 2095          case CPUINFO_INT_REGISTER + UPD7810_ETMM:       ETMM = info->i;                         break;
 2096          case CPUINFO_INT_REGISTER + UPD7810_EOM:        EOM = info->i;                          break;
 2097          case CPUINFO_INT_REGISTER + UPD7810_SML:        SML = info->i;                          break;
 2098          case CPUINFO_INT_REGISTER + UPD7810_SMH:        SMH = info->i;                          break;
 2099          case CPUINFO_INT_REGISTER + UPD7810_ANM:        ANM = info->i;                          break;
 2100          case CPUINFO_INT_REGISTER + UPD7810_MKL:        MKL = info->i;                          break;
 2101          case CPUINFO_INT_REGISTER + UPD7810_MKH:        MKH = info->i;                          break;
 2102          case CPUINFO_INT_REGISTER + UPD7810_ZCM:        ZCM = info->i;                          break;
 2103          case CPUINFO_INT_REGISTER + UPD7810_TXB:        TXB = info->i;                          break;
 2104          case CPUINFO_INT_REGISTER + UPD7810_RXB:        RXB = info->i;                          break;
 2105          case CPUINFO_INT_REGISTER + UPD7810_CR0:        CR0 = info->i;                          break;
 2106          case CPUINFO_INT_REGISTER + UPD7810_CR1:        CR1 = info->i;                          break;
 2107          case CPUINFO_INT_REGISTER + UPD7810_CR2:        CR2 = info->i;                          break;
 2108          case CPUINFO_INT_REGISTER + UPD7810_CR3:        CR3 = info->i;                          break;
 2109          case CPUINFO_INT_REGISTER + UPD7810_TXD:        TXD = info->i;                          break;
 2110          case CPUINFO_INT_REGISTER + UPD7810_RXD:        RXD = info->i;                          break;
 2111          case CPUINFO_INT_REGISTER + UPD7810_SCK:        SCK = info->i;                          break;
 2112          case CPUINFO_INT_REGISTER + UPD7810_TI:         TI  = info->i;                          break;
 2113          case CPUINFO_INT_REGISTER + UPD7810_TO:         TO  = info->i;                          break;
 2114          case CPUINFO_INT_REGISTER + UPD7810_CI:         CI  = info->i;                          break;
 2115          case CPUINFO_INT_REGISTER + UPD7810_CO0:        CO0 = info->i;                          break;
 2116          case CPUINFO_INT_REGISTER + UPD7810_CO1:        CO1 = info->i;                          break;
 2117      }
 2118  }
 2119  
 2120  
 2121  
 2122  /**************************************************************************
 2123   * Generic get_info
 2124   **************************************************************************/
 2125  
 2126  CPU_GET_INFO( upd7810 )
 2127  {
 2128      upd7810_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
 2129      switch (state)
 2130      {
 2131          /* --- the following bits of info are returned as 64-bit signed integers --- */
 2132          case CPUINFO_INT_CONTEXT_SIZE:                  info->i = sizeof(upd7810_state);                break;
 2133          case CPUINFO_INT_INPUT_LINES:                   info->i = 2;                            break;
 2134          case CPUINFO_INT_DEFAULT_IRQ_VECTOR:            info->i = 0;                            break;
 2135          case CPUINFO_INT_ENDIANNESS:                    info->i = ENDIANNESS_LITTLE;                    break;
 2136          case CPUINFO_INT_CLOCK_MULTIPLIER:              info->i = 1;                            break;
 2137          case CPUINFO_INT_CLOCK_DIVIDER:                 info->i = 1;                            break;
 2138          case CPUINFO_INT_MIN_INSTRUCTION_BYTES:         info->i = 1;                            break;
 2139          case CPUINFO_INT_MAX_INSTRUCTION_BYTES:         info->i = 4;                            break;
 2140          case CPUINFO_INT_MIN_CYCLES:                    info->i = 1;                            break;
 2141          case CPUINFO_INT_MAX_CYCLES:                    info->i = 40;                           break;
 2142  
 2143          case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM:    info->i = 8;                    break;
 2144          case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16;                  break;
 2145          case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0;                   break;
 2146          case CPUINFO_INT_DATABUS_WIDTH + AS_DATA:   info->i = 0;                    break;
 2147          case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA:   info->i = 0;                    break;
 2148          case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA:   info->i = 0;                    break;
 2149          case CPUINFO_INT_DATABUS_WIDTH + AS_IO:     info->i = 8;                    break;
 2150          case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO:     info->i = 8;                    break;
 2151          case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO:     info->i = 0;                    break;
 2152  
 2153          case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:  info->i = (IRR & INTNMI) ? ASSERT_LINE : CLEAR_LINE; break;
 2154          case CPUINFO_INT_INPUT_STATE + UPD7810_INTF1:   info->i = (IRR & INTF1) ? ASSERT_LINE : CLEAR_LINE; break;
 2155          case CPUINFO_INT_INPUT_STATE + UPD7810_INTF2:   info->i = (IRR & INTF2) ? ASSERT_LINE : CLEAR_LINE; break;
 2156          case CPUINFO_INT_INPUT_STATE + UPD7810_INTFE1:  info->i = (IRR & INTFE1) ? ASSERT_LINE : CLEAR_LINE; break;
 2157  
 2158          case CPUINFO_INT_PREVIOUSPC:                    info->i = PPC;                          break;
 2159  
 2160          case CPUINFO_INT_PC:
 2161          case CPUINFO_INT_REGISTER + UPD7810_PC:         info->i = PC;                           break;
 2162          case CPUINFO_INT_SP:
 2163          case CPUINFO_INT_REGISTER + UPD7810_SP:         info->i = SP;                           break;
 2164          case CPUINFO_INT_REGISTER + UPD7810_PSW:        info->i = PSW;                          break;
 2165          case CPUINFO_INT_REGISTER + UPD7810_EA:         info->i = EA;                           break;
 2166          case CPUINFO_INT_REGISTER + UPD7810_VA:         info->i = VA;                           break;
 2167          case CPUINFO_INT_REGISTER + UPD7810_BC:         info->i = BC;                           break;
 2168          case CPUINFO_INT_REGISTER + UPD7810_DE:         info->i = DE;                           break;
 2169          case CPUINFO_INT_REGISTER + UPD7810_HL:         info->i = HL;                           break;
 2170          case CPUINFO_INT_REGISTER + UPD7810_EA2:        info->i = EA2;                          break;
 2171          case CPUINFO_INT_REGISTER + UPD7810_VA2:        info->i = VA2;                          break;
 2172          case CPUINFO_INT_REGISTER + UPD7810_BC2:        info->i = BC2;                          break;
 2173          case CPUINFO_INT_REGISTER + UPD7810_DE2:        info->i = DE2;                          break;
 2174          case CPUINFO_INT_REGISTER + UPD7810_HL2:        info->i = HL2;                          break;
 2175          case CPUINFO_INT_REGISTER + UPD7810_CNT0:       info->i = CNT0;                         break;
 2176          case CPUINFO_INT_REGISTER + UPD7810_CNT1:       info->i = CNT1;                         break;
 2177          case CPUINFO_INT_REGISTER + UPD7810_TM0:        info->i = TM0;                          break;
 2178          case CPUINFO_INT_REGISTER + UPD7810_TM1:        info->i = TM1;                          break;
 2179          case CPUINFO_INT_REGISTER + UPD7810_ECNT:       info->i = ECNT;                         break;
 2180          case CPUINFO_INT_REGISTER + UPD7810_ECPT:       info->i = ECPT;                         break;
 2181          case CPUINFO_INT_REGISTER + UPD7810_ETM0:       info->i = ETM0;                         break;
 2182          case CPUINFO_INT_REGISTER + UPD7810_ETM1:       info->i = ETM1;                         break;
 2183          case CPUINFO_INT_REGISTER + UPD7810_MA:         info->i = MA;                           break;
 2184          case CPUINFO_INT_REGISTER + UPD7810_MB:         info->i = MB;                           break;
 2185          case CPUINFO_INT_REGISTER + UPD7810_MCC:        info->i = MCC;                          break;
 2186          case CPUINFO_INT_REGISTER + UPD7810_MC:         info->i = MC;                           break;
 2187          case CPUINFO_INT_REGISTER + UPD7810_MM:         info->i = MM;                           break;
 2188          case CPUINFO_INT_REGISTER + UPD7810_MF:         info->i = MF;                           break;
 2189          case CPUINFO_INT_REGISTER + UPD7810_TMM:        info->i = TMM;                          break;
 2190          case CPUINFO_INT_REGISTER + UPD7810_ETMM:       info->i = ETMM;                         break;
 2191          case CPUINFO_INT_REGISTER + UPD7810_EOM:        info->i = EOM;                          break;
 2192          case CPUINFO_INT_REGISTER + UPD7810_SML:        info->i = SML;                          break;
 2193          case CPUINFO_INT_REGISTER + UPD7810_SMH:        info->i = SMH;                          break;
 2194          case CPUINFO_INT_REGISTER + UPD7810_ANM:        info->i = ANM;                          break;
 2195          case CPUINFO_INT_REGISTER + UPD7810_MKL:        info->i = MKL;                          break;
 2196          case CPUINFO_INT_REGISTER + UPD7810_MKH:        info->i = MKH;                          break;
 2197          case CPUINFO_INT_REGISTER + UPD7810_ZCM:        info->i = ZCM;                          break;
 2198          case CPUINFO_INT_REGISTER + UPD7810_TXB:        info->i = TXB;                          break;
 2199          case CPUINFO_INT_REGISTER + UPD7810_RXB:        info->i = RXB;                          break;
 2200          case CPUINFO_INT_REGISTER + UPD7810_CR0:        info->i = CR0;                          break;
 2201          case CPUINFO_INT_REGISTER + UPD7810_CR1:        info->i = CR1;                          break;
 2202          case CPUINFO_INT_REGISTER + UPD7810_CR2:        info->i = CR2;                          break;
 2203          case CPUINFO_INT_REGISTER + UPD7810_CR3:        info->i = CR3;                          break;
 2204          case CPUINFO_INT_REGISTER + UPD7810_TXD:        info->i = TXD;                          break;
 2205          case CPUINFO_INT_REGISTER + UPD7810_RXD:        info->i = RXD;                          break;
 2206          case CPUINFO_INT_REGISTER + UPD7810_SCK:        info->i = SCK;                          break;
 2207          case CPUINFO_INT_REGISTER + UPD7810_TI:         info->i = TI;                           break;
 2208          case CPUINFO_INT_REGISTER + UPD7810_TO:         info->i = TO;                           break;
 2209          case CPUINFO_INT_REGISTER + UPD7810_CI:         info->i = CI;                           break;
 2210          case CPUINFO_INT_REGISTER + UPD7810_CO0:        info->i = CO0;                          break;
 2211          case CPUINFO_INT_REGISTER + UPD7810_CO1:        info->i = CO1;                          break;
 2212  
 2213          /* --- the following bits of info are returned as pointers to data or functions --- */
 2214          case CPUINFO_FCT_SET_INFO:                      info->setinfo = CPU_SET_INFO_NAME(upd7810);     break;
 2215          case CPUINFO_FCT_INIT:                          info->init = CPU_INIT_NAME(upd7810);                break;
 2216          case CPUINFO_FCT_RESET:                         info->reset = CPU_RESET_NAME(upd7810);          break;
 2217          case CPUINFO_FCT_EXIT:                          info->exit = CPU_EXIT_NAME(upd7810);                break;
 2218          case CPUINFO_FCT_EXECUTE:                       info->execute = CPU_EXECUTE_NAME(upd7810);      break;
 2219          case CPUINFO_FCT_BURN:                          info->burn = NULL;                      break;
 2220          case CPUINFO_FCT_DISASSEMBLE:                   info->disassemble = CPU_DISASSEMBLE_NAME(upd7810);      break;
 2221          case CPUINFO_PTR_INSTRUCTION_COUNTER:           info->icount = &cpustate->icount;           break;
 2222  
 2223          /* --- the following bits of info are returned as NULL-terminated strings --- */
 2224          case CPUINFO_STR_NAME:                          strcpy(info->s, "uPD7810");             break;
 2225          case CPUINFO_STR_FAMILY:                    strcpy(info->s, "NEC uPD7810");         break;
 2226          case CPUINFO_STR_VERSION:                   strcpy(info->s, "0.3");                 break;
 2227          case CPUINFO_STR_SOURCE_FILE:                       strcpy(info->s, __FILE__);              break;
 2228          case CPUINFO_STR_CREDITS:                   strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break;
 2229  
 2230          case CPUINFO_STR_FLAGS:
 2231              sprintf(info->s, "%s:%s:%s:%s:%s:%s",
 2232                  cpustate->psw & 0x40 ? "ZF":"--",
 2233                  cpustate->psw & 0x20 ? "SK":"--",
 2234                  cpustate->psw & 0x10 ? "HC":"--",
 2235                  cpustate->psw & 0x08 ? "L1":"--",
 2236                  cpustate->psw & 0x04 ? "L0":"--",
 2237                  cpustate->psw & 0x01 ? "CY":"--");
 2238              break;
 2239  
 2240          case CPUINFO_STR_REGISTER + UPD7810_PC:         sprintf(info->s, "PC  :%04X", cpustate->pc.w.l); break;
 2241          case CPUINFO_STR_REGISTER + UPD7810_SP:         sprintf(info->s, "SP  :%04X", cpustate->sp.w.l); break;
 2242          case CPUINFO_STR_REGISTER + UPD7810_PSW:        sprintf(info->s, "PSW :%02X", cpustate->psw); break;
 2243          case CPUINFO_STR_REGISTER + UPD7810_A:          sprintf(info->s, "A   :%02X", cpustate->va.b.l); break;
 2244          case CPUINFO_STR_REGISTER + UPD7810_V:          sprintf(info->s, "V   :%02X", cpustate->va.b.h); break;
 2245          case CPUINFO_STR_REGISTER + UPD7810_EA:         sprintf(info->s, "EA  :%04X", cpustate->ea.w.l); break;
 2246          case CPUINFO_STR_REGISTER + UPD7810_BC:         sprintf(info->s, "BC  :%04X", cpustate->bc.w.l); break;
 2247          case CPUINFO_STR_REGISTER + UPD7810_DE:         sprintf(info->s, "DE  :%04X", cpustate->de.w.l); break;
 2248          case CPUINFO_STR_REGISTER + UPD7810_HL:         sprintf(info->s, "HL  :%04X", cpustate->hl.w.l); break;
 2249          case CPUINFO_STR_REGISTER + UPD7810_A2:         sprintf(info->s, "A'  :%02X", cpustate->va2.b.l); break;
 2250          case CPUINFO_STR_REGISTER + UPD7810_V2:         sprintf(info->s, "V'  :%02X", cpustate->va2.b.h); break;
 2251          case CPUINFO_STR_REGISTER + UPD7810_EA2:        sprintf(info->s, "EA' :%04X", cpustate->ea2.w.l); break;
 2252          case CPUINFO_STR_REGISTER + UPD7810_BC2:        sprintf(info->s, "BC' :%04X", cpustate->bc2.w.l); break;
 2253          case CPUINFO_STR_REGISTER + UPD7810_DE2:        sprintf(info->s, "DE' :%04X", cpustate->de2.w.l); break;
 2254          case CPUINFO_STR_REGISTER + UPD7810_HL2:        sprintf(info->s, "HL' :%04X", cpustate->hl2.w.l); break;
 2255          case CPUINFO_STR_REGISTER + UPD7810_CNT0:       sprintf(info->s, "CNT0:%02X", cpustate->cnt.b.l); break;
 2256          case CPUINFO_STR_REGISTER + UPD7810_CNT1:       sprintf(info->s, "CNT1:%02X", cpustate->cnt.b.h); break;
 2257          case CPUINFO_STR_REGISTER + UPD7810_TM0:        sprintf(info->s, "TM0 :%02X", cpustate->tm.b.l); break;
 2258          case CPUINFO_STR_REGISTER + UPD7810_TM1:        sprintf(info->s, "TM1 :%02X", cpustate->tm.b.h); break;
 2259          case CPUINFO_STR_REGISTER + UPD7810_ECNT:       sprintf(info->s, "ECNT:%04X", cpustate->ecnt.w.l); break;
 2260          case CPUINFO_STR_REGISTER + UPD7810_ECPT:       sprintf(info->s, "ECPT:%04X", cpustate->ecnt.w.h); break;
 2261          case CPUINFO_STR_REGISTER + UPD7810_ETM0:       sprintf(info->s, "ETM0:%04X", cpustate->etm.w.l); break;
 2262          case CPUINFO_STR_REGISTER + UPD7810_ETM1:       sprintf(info->s, "ETM1:%04X", cpustate->etm.w.h); break;
 2263          case CPUINFO_STR_REGISTER + UPD7810_MA:         sprintf(info->s, "MA  :%02X", cpustate->ma); break;
 2264          case CPUINFO_STR_REGISTER + UPD7810_MB:         sprintf(info->s, "MB  :%02X", cpustate->mb); break;
 2265          case CPUINFO_STR_REGISTER + UPD7810_MCC:        sprintf(info->s, "MCC :%02X", cpustate->mcc); break;
 2266          case CPUINFO_STR_REGISTER + UPD7810_MC:         sprintf(info->s, "MC  :%02X", cpustate->mc); break;
 2267          case CPUINFO_STR_REGISTER + UPD7810_MM:         sprintf(info->s, "MM  :%02X", cpustate->mm); break;
 2268          case CPUINFO_STR_REGISTER + UPD7810_MF:         sprintf(info->s, "MF  :%02X", cpustate->mf); break;
 2269          case CPUINFO_STR_REGISTER + UPD7810_TMM:        sprintf(info->s, "TMM :%02X", cpustate->tmm); break;
 2270          case CPUINFO_STR_REGISTER + UPD7810_ETMM:       sprintf(info->s, "ETMM:%02X", cpustate->etmm); break;
 2271          case CPUINFO_STR_REGISTER + UPD7810_EOM:        sprintf(info->s, "EOM :%02X", cpustate->eom); break;
 2272          case CPUINFO_STR_REGISTER + UPD7810_SML:        sprintf(info->s, "SML :%02X", cpustate->sml); break;
 2273          case CPUINFO_STR_REGISTER + UPD7810_SMH:        sprintf(info->s, "SMH :%02X", cpustate->smh); break;
 2274          case CPUINFO_STR_REGISTER + UPD7810_ANM:        sprintf(info->s, "ANM :%02X", cpustate->anm); break;
 2275          case CPUINFO_STR_REGISTER + UPD7810_MKL:        sprintf(info->s, "MKL :%02X", cpustate->mkl); break;
 2276          case CPUINFO_STR_REGISTER + UPD7810_MKH:        sprintf(info->s, "MKH :%02X", cpustate->mkh); break;
 2277          case CPUINFO_STR_REGISTER + UPD7810_ZCM:        sprintf(info->s, "ZCM :%02X", cpustate->zcm); break;
 2278          case CPUINFO_STR_REGISTER + UPD7810_CR0:        sprintf(info->s, "CR0 :%02X", cpustate->cr0); break;
 2279          case CPUINFO_STR_REGISTER + UPD7810_CR1:        sprintf(info->s, "CR1 :%02X", cpustate->cr1); break;
 2280          case CPUINFO_STR_REGISTER + UPD7810_CR2:        sprintf(info->s, "CR2 :%02X", cpustate->cr2); break;
 2281          case CPUINFO_STR_REGISTER + UPD7810_CR3:        sprintf(info->s, "CR3 :%02X", cpustate->cr3); break;
 2282          case CPUINFO_STR_REGISTER + UPD7810_RXB:        sprintf(info->s, "RXB :%02X", cpustate->rxb); break;
 2283          case CPUINFO_STR_REGISTER + UPD7810_TXB:        sprintf(info->s, "TXB :%02X", cpustate->txb); break;
 2284          case CPUINFO_STR_REGISTER + UPD7810_TXD:        sprintf(info->s, "TXD :%d", cpustate->txd); break;
 2285          case CPUINFO_STR_REGISTER + UPD7810_RXD:        sprintf(info->s, "RXD :%d", cpustate->rxd); break;
 2286          case CPUINFO_STR_REGISTER + UPD7810_SCK:        sprintf(info->s, "SCK :%d", cpustate->sck); break;
 2287          case CPUINFO_STR_REGISTER + UPD7810_TI:         sprintf(info->s, "TI  :%d", cpustate->ti); break;
 2288          case CPUINFO_STR_REGISTER + UPD7810_TO:         sprintf(info->s, "TO  :%d", cpustate->to); break;
 2289          case CPUINFO_STR_REGISTER + UPD7810_CI:         sprintf(info->s, "CI  :%d", cpustate->ci); break;
 2290          case CPUINFO_STR_REGISTER + UPD7810_CO0:        sprintf(info->s, "CO0 :%d", cpustate->co0 & 1); break;
 2291          case CPUINFO_STR_REGISTER + UPD7810_CO1:        sprintf(info->s, "CO1 :%d", cpustate->co1 & 1); break;
 2292      }
 2293  }
 2294  
 2295  
 2296  /**************************************************************************
 2297   * CPU-specific set_info
 2298   **************************************************************************/
 2299  
 2300  CPU_GET_INFO( upd7807 )
 2301  {
 2302      switch (state)
 2303      {
 2304          /* --- the following bits of info are returned as pointers to data or functions --- */
 2305          case CPUINFO_FCT_RESET:                         info->reset = CPU_RESET_NAME(upd7807);          break;
 2306          case CPUINFO_FCT_DISASSEMBLE:                   info->disassemble = CPU_DISASSEMBLE_NAME(upd7807);      break;
 2307  
 2308          /* --- the following bits of info are returned as NULL-terminated strings --- */
 2309          case CPUINFO_STR_NAME:                          strcpy(info->s, "uPD7807");             break;
 2310  
 2311          default:                                        CPU_GET_INFO_CALL(upd7810);             break;
 2312      }
 2313  }
 2314  
 2315  CPU_GET_INFO( upd7801 ) {
 2316      switch( state ) {
 2317          case CPUINFO_FCT_RESET:                         info->reset = CPU_RESET_NAME(upd7801);          break;
 2318          case CPUINFO_FCT_DISASSEMBLE:                   info->disassemble = CPU_DISASSEMBLE_NAME(upd7801);      break;
 2319  
 2320          case CPUINFO_STR_NAME:                          strcpy(info->s, "uPD7801");             break;
 2321  
 2322          default:                                        CPU_GET_INFO_CALL(upd7810);             break;
 2323      }
 2324  }
 2325  
 2326  CPU_GET_INFO( upd78c05 ) {
 2327      switch ( state ) {
 2328          case CPUINFO_INT_CLOCK_DIVIDER:                 info->i = 4;                            break;
 2329  
 2330          case CPUINFO_FCT_RESET:                         info->reset = CPU_RESET_NAME(upd78c05);         break;
 2331          case CPUINFO_FCT_DISASSEMBLE:                   info->disassemble = CPU_DISASSEMBLE_NAME(upd78c05);     break;
 2332  
 2333          case CPUINFO_STR_NAME:                          strcpy(info->s, "uPD78C05");            break;
 2334  
 2335          /* These registers are not present in the uPD78C05 cpu */
 2336          case CPUINFO_STR_REGISTER + UPD7810_A2:
 2337          case CPUINFO_STR_REGISTER + UPD7810_V2:
 2338          case CPUINFO_STR_REGISTER + UPD7810_EA2:
 2339          case CPUINFO_STR_REGISTER + UPD7810_BC2:
 2340          case CPUINFO_STR_REGISTER + UPD7810_DE2:
 2341          case CPUINFO_STR_REGISTER + UPD7810_HL2:
 2342          case CPUINFO_STR_REGISTER + UPD7810_MA:
 2343          case CPUINFO_STR_REGISTER + UPD7810_MCC:
 2344          case CPUINFO_STR_REGISTER + UPD7810_MC:
 2345          case CPUINFO_STR_REGISTER + UPD7810_MM:
 2346          case CPUINFO_STR_REGISTER + UPD7810_MF:
 2347          case CPUINFO_STR_REGISTER + UPD7810_ETMM:
 2348          case CPUINFO_STR_REGISTER + UPD7810_EOM:
 2349          case CPUINFO_STR_REGISTER + UPD7810_SML:
 2350          case CPUINFO_STR_REGISTER + UPD7810_SMH:
 2351          case CPUINFO_STR_REGISTER + UPD7810_ANM:
 2352          case CPUINFO_STR_REGISTER + UPD7810_MKH:
 2353          case CPUINFO_STR_REGISTER + UPD7810_ZCM:
 2354          case CPUINFO_STR_REGISTER + UPD7810_CR0:
 2355          case CPUINFO_STR_REGISTER + UPD7810_CR1:
 2356          case CPUINFO_STR_REGISTER + UPD7810_CR2:
 2357          case CPUINFO_STR_REGISTER + UPD7810_CR3:
 2358          case CPUINFO_STR_REGISTER + UPD7810_RXB:
 2359          case CPUINFO_STR_REGISTER + UPD7810_TXB:
 2360          case CPUINFO_STR_REGISTER + UPD7810_TXD:
 2361          case CPUINFO_STR_REGISTER + UPD7810_RXD:
 2362          case CPUINFO_STR_REGISTER + UPD7810_SCK:
 2363          case CPUINFO_STR_REGISTER + UPD7810_TI:
 2364          case CPUINFO_STR_REGISTER + UPD7810_TO:
 2365          case CPUINFO_STR_REGISTER + UPD7810_CI:
 2366          case CPUINFO_STR_REGISTER + UPD7810_CO0:
 2367          case CPUINFO_STR_REGISTER + UPD7810_CO1:        break;
 2368  
 2369          default:                                        CPU_GET_INFO_CALL(upd7801);             break;
 2370      }
 2371  }
 2372  
 2373  CPU_GET_INFO( upd78c06 ) {
 2374      switch ( state ) {
 2375          case CPUINFO_FCT_RESET:                         info->reset = CPU_RESET_NAME(upd78c06);         break;
 2376  
 2377          case CPUINFO_STR_NAME:                          strcpy(info->s, "uPD78C06");            break;
 2378  
 2379          default:                                        CPU_GET_INFO_CALL(upd78c05);                break;
 2380      }
 2381  }
 2382  
 2383  DEFINE_LEGACY_CPU_DEVICE(UPD7810, upd7810);
 2384  DEFINE_LEGACY_CPU_DEVICE(UPD7807, upd7807);
 2385  DEFINE_LEGACY_CPU_DEVICE(UPD7801, upd7801);
 2386  DEFINE_LEGACY_CPU_DEVICE(UPD78C05, upd78c05);
 2387  DEFINE_LEGACY_CPU_DEVICE(UPD78C06, upd78c06);