/* id16_cpu.c: Interdata 16b CPU simulator

   Copyright (c) 2000-2008, Robert M. Supnik

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

   Except as contained in this notice, the name of Robert M Supnik shall not be
   used in advertising or otherwise to promote the sale, use or other dealings
   in this Software without prior written authorization from Robert M Supnik.

   cpu                  Interdata 16b CPU

   28-Apr-07    RMS     Removed clock initialization
   27-Oct-06    RMS     Added idle support
                        Removed separate PASLA clock
   06-Feb-06    RMS     Fixed bug in DH (Mark Hittinger)
   22-Sep-05    RMS     Fixed declarations (Sterling Garwood)
   25-Aug-05    RMS     Fixed DH integer overflow cases
   16-Aug-05    RMS     Fixed C++ declaration and cast problems
   10-Mar-05    RMS     Fixed bug in show history routine (Mark Hittinger)
                        Revised examine/deposit to do words rather than bytes
   07-Nov-04    RMS     Added instruction history
   22-Sep-03    RMS     Added additional instruction decode types
   07-Feb-03    RMS     Fixed bug in SETM, SETMR (Mark Pizzolato)

   The register state for the Interdata 16b CPU is:

   R[0:F]<0:15>         general registers
   F[0:7]<0:31>         single precision floating point registers
   D[0:7]<0:63>         double precision floating point registers
   PSW<0:31>            processor status word, including
    STAT<0:11>          status flags
    CC<0:3>             condition codes
    PC<0:15>            program counter
   int_req[8]<0:31>     interrupt requests
   int_enb[8]<0:31>     interrupt enables
   
   The Interdata 16b systems have four instruction formats: register to
   register, short format, register to memory, and register to storage.
   The formats are:

     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |           op          |     R1    |     R2    |    register-register
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |           op          |     R1    |     N     |    short format
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |           op          |     R1    |     RX    |    register-memory
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                    address                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |           op          |     R1    |     RX    |    register-storage
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   |                    address                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

   For register-memory and register-storage instructions, an effective
   address is calculated as follows:

        effective addr = address + RX (if RX > 0)

   Register-memory instructions can access an address space of 64K bytes.

   The Interdata 16b product line had many different models, with varying
   instruction sets:

   instruction group    model = 3    4    5   70   80  716  816  816E
   base group (61)              y    y    y    y    y    y    y    y
   AL, LM, STM (3)              -    y    y    y    y    y    y    y
   single prec fp (13)          -    y    y    y    y    y    y    y
   model 5 group (36)           -    -    y    y    y    y    y    y
   double prec fp (17)          -    -    -    -    -    -    y    y
   memory extension (4)         -    -    -    -    -    -    -    y

   This allows the most common CPU options to be covered by just five
   model selections: I3, I4, I5/70/80/716, I816, and I816E.  Variations
   within a model (e.g., 816 with no floating point or just single
   precision floating point) are not implemented.

   The I3 kept its general registers in memory; this is not simulated.
   Single precision (only) floating point was implemented in microcode,
   did not have a guard digit, and kept the floating point registers in
   memory.  Double precision floating point was implemented in hardware,
   provided a guard digit for single precision (but not double), and
   kept the floating point registers in hardware.

   This routine is the instruction decode routine for the Interdata CPU.
   It is called from the simulator control program to execute
   instructions in simulated memory, starting at the simulated PC.
   It runs until 'reason' is set non-zero.

   General notes:

   1. Reasons to stop.  The simulator can be stopped by:

        HALT instruction
        breakpoint encountered
        wait state and no I/O outstanding
        invalid instruction
        I/O error in I/O simulator

   2. Interrupts.  Each device has an interrupt armed flag, an interrupt
      request flag, and an interrupt enabled flag.  To facilitate evaluation,
      all interrupt requests are kept in int_req, and all enables in int_enb.
      Interrupt armed flags are local to devices.  If external interrupts are
      enabled in the PSW, and a request is pending, an interrupt occurs.

   3. Non-existent memory.  On the Interdata 16b, reads to non-existent
      memory return zero, and writes are ignored.  In the simulator, the
      largest possible memory is instantiated and initialized to zero.
      Thus, only writes need be checked against actual memory size.

   4. Adding I/O devices.  These modules must be modified:

        id_defs.h       add device interrupt definitions
        id16_sys.c      add sim_devices table entry
*/

#include "id_defs.h"

#define PCQ_SIZE        64                              /* must be 2**n */
#define PCQ_MASK        (PCQ_SIZE - 1)
#define PCQ_ENTRY       pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC
#define VAMASK          VAMASK16
#define VA_S1           0x8000                          /* S0/S1 flag */

#define UNIT_V_MSIZE    (UNIT_V_UF + 0)                 /* dummy mask */
#define UNIT_V_ID4      (UNIT_V_UF + 1)
#define UNIT_V_716      (UNIT_V_UF + 2)
#define UNIT_V_816      (UNIT_V_UF + 3)
#define UNIT_V_816E     (UNIT_V_UF + 4)
#define UNIT_MSIZE      (1 << UNIT_V_MSIZE)
#define UNIT_ID4        (1 << UNIT_V_ID4)
#define UNIT_716        (1 << UNIT_V_716)
#define UNIT_816        (1 << UNIT_V_816)
#define UNIT_816E       (1 << UNIT_V_816E)
#define UNIT_TYPE       (UNIT_ID4 | UNIT_716 | UNIT_816 | UNIT_816E)

#define HIST_MIN        64
#define HIST_MAX        65536

typedef struct {
    uint16              vld;
    uint16              pc;
    uint16              ir1;
    uint16              ir2