mirror of
https://github.com/simh/simh.git
synced 2026-04-30 05:25:05 +00:00
Notes For V3.3-2
1. New Features in 3.3-2 1.1 SCP and Libraries - Added ASSERT command (from Dave Bryan) 1.2 PDP-11, VAX - Added RA60, RA71, RA81 disks 2. Bugs Fixed in 3.3-2 2.1 H316 - Fixed IORETURN macro - PT: fixed bug in OCP '0001 (found by Philipp Hachtmann) - MT: fixed error reporting from OCP (found by Philipp Hachtmann) 2.2 Interdata 32b - Fixed branches to mask new PC (from Greg Johnson) 2.3 PDP-11 - Fixed bugs in RESET for 11/70 (reported by Tim Chapman) - Fixed bug in SHOW MODEL (from Sergey Okhapkin) - Made SYSID variable for 11/70 (from Tim Chapman) - Fixed MBRK write case for 11/70 (from Tim Chapman) - RY: fixed bug in boot code (reported by Graham Toal) 2.4 VAX - Fixed initial state of cpu_extmem 2.5 HP2100 (from Dave Bryan) - Fixed missing MPCK on JRS target - Removed EXECUTE instruction (is NOP in actual microcode) - Fixed missing negative overflow renorm in StoreFP 2.6 I1401 - Fixed bug in line printer write line (reported by Van Snyder)
This commit is contained in:
committed by
Mark Pizzolato
parent
9b5c8c9711
commit
098200a126
1031
HP2100/hp2100_cpu.c
1031
HP2100/hp2100_cpu.c
File diff suppressed because it is too large
Load Diff
73
HP2100/hp2100_cpu.h
Normal file
73
HP2100/hp2100_cpu.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* hp2100_cpu.h: HP 2100 CPU definitions
|
||||
|
||||
Copyright (c) 2005, 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.
|
||||
|
||||
14-Jan-05 RMS Cloned from hp2100_cpu.c
|
||||
*/
|
||||
|
||||
#ifndef _HP2100_CPU_H_
|
||||
#define _HP2100_CPU_H_ 0
|
||||
|
||||
#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] = err_PC
|
||||
|
||||
#define UNIT_V_2100 (UNIT_V_UF + 0) /* 2100 */
|
||||
#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX-E or 21MX-M */
|
||||
#define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */
|
||||
#define UNIT_V_FP (UNIT_V_UF + 3) /* FP */
|
||||
#define UNIT_V_DMS (UNIT_V_UF + 4) /* DMS */
|
||||
#define UNIT_V_IOP (UNIT_V_UF + 5) /* 2100 IOP */
|
||||
#define UNIT_V_IOPX (UNIT_V_UF + 6) /* 21MX IOP */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 7) /* dummy mask */
|
||||
#define UNIT_V_MXM (UNIT_V_UF + 8) /* 21MX is M-series */
|
||||
#define UNIT_2116 (0)
|
||||
#define UNIT_2100 (1 << UNIT_V_2100)
|
||||
#define UNIT_21MX (1 << UNIT_V_21MX)
|
||||
#define UNIT_EAU (1 << UNIT_V_EAU)
|
||||
#define UNIT_FP (1 << UNIT_V_FP)
|
||||
#define UNIT_DMS (1 << UNIT_V_DMS)
|
||||
#define UNIT_IOP (1 << UNIT_V_IOP)
|
||||
#define UNIT_IOPX (1 << UNIT_V_IOPX)
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define UNIT_MXM (1 << UNIT_V_MXM)
|
||||
|
||||
t_stat Ea (uint32 IR, uint32 *addr, uint32 irq);
|
||||
uint8 ReadB (uint32 addr);
|
||||
uint8 ReadBA (uint32 addr);
|
||||
uint16 ReadW (uint32 addr);
|
||||
uint16 ReadWA (uint32 addr);
|
||||
uint32 ReadF (uint32 addr);
|
||||
void WriteB (uint32 addr, uint32 dat);
|
||||
void WriteBA (uint32 addr, uint32 dat);
|
||||
void WriteW (uint32 addr, uint32 dat);
|
||||
void WriteWA (uint32 addr, uint32 dat);
|
||||
t_stat iogrp (uint32 ir, uint32 iotrap);
|
||||
void mp_dms_jmp (uint32 va);
|
||||
uint16 dms_rmap (uint32 mapi);
|
||||
void dms_wmap (uint32 mapi, uint32 dat);
|
||||
void dms_viol (uint32 va, uint32 st);
|
||||
uint32 dms_upd_sr (void);
|
||||
|
||||
#endif
|
||||
982
HP2100/hp2100_cpu1.c
Normal file
982
HP2100/hp2100_cpu1.c
Normal file
@@ -0,0 +1,982 @@
|
||||
/* hp2100_cpu.c: HP 2100 EAU and MAC simulator
|
||||
|
||||
Copyright (c) 2005, 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 extended arithmetic and microcode instructions
|
||||
|
||||
22-Feb-05 JDB Fixed missing MPCK on JRS target
|
||||
Removed EXECUTE instruction (is NOP in actual microcode)
|
||||
15-Jan-05 RMS Cloned from hp2100_cpu.c
|
||||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include <setjmp.h>
|
||||
#include "hp2100_cpu.h"
|
||||
|
||||
extern uint16 ABREG[2];
|
||||
extern uint32 PC;
|
||||
extern uint32 err_PC;
|
||||
extern uint32 XR;
|
||||
extern uint32 YR;
|
||||
extern uint32 E;
|
||||
extern uint32 O;
|
||||
extern uint32 dms_enb;
|
||||
extern uint32 dms_ump;
|
||||
extern uint32 dms_sr;
|
||||
extern uint32 dms_vr;
|
||||
extern uint32 mp_fence;
|
||||
extern uint32 iop_sp;
|
||||
extern uint32 ion_defer;
|
||||
extern uint16 pcq[PCQ_SIZE];
|
||||
extern uint32 pcq_p;
|
||||
extern uint32 stop_inst;
|
||||
extern jmp_buf save_env;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
extern t_stat Ea1 (uint32 *addr, uint32 irq);
|
||||
extern uint32 f_as (uint32 op, t_bool sub);
|
||||
extern uint32 f_mul (uint32 op);
|
||||
extern uint32 f_div (uint32 op);
|
||||
extern uint32 f_fix (void);
|
||||
extern uint32 f_flt (void);
|
||||
|
||||
/* Extended instruction decode tables */
|
||||
|
||||
#define E_V_FL 0 /* flags */
|
||||
#define E_M_FL 0xFF
|
||||
#define E_FP (UNIT_FP >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_21MX (UNIT_21MX >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_DMS (UNIT_DMS >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_IOP (UNIT_IOP >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_IOPX (UNIT_IOPX >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_V_TY 8 /* type */
|
||||
#define E_M_TY 0xF
|
||||
#define E_NO 0 /* no operands */
|
||||
#define E_CN 1 /* PC+1: count */
|
||||
#define E_AD 2 /* PC+1: addr */
|
||||
#define E_AA 3 /* PC+1,2: addr */
|
||||
#define E_AC 4 /* PC+1: addr, +2: count */
|
||||
#define E_AZ 5 /* PC+1: addr, +2: zero */
|
||||
#define ET_NO (E_NO << E_V_TY)
|
||||
#define ET_AD (E_AD << E_V_TY)
|
||||
#define ET_AA (E_AA << E_V_TY)
|
||||
#define ET_CN (E_CN << E_V_TY)
|
||||
#define ET_AC (E_AC << E_V_TY)
|
||||
#define ET_AZ (E_AZ << E_V_TY)
|
||||
#define E_V_TYI 12 /* type if 2100 IOP */
|
||||
#define E_GETFL(x) (((x) >> E_V_FL) & E_M_FL)
|
||||
#define E_GETTY(f,x) (((x) >> \
|
||||
((((f) & E_IOP) && (cpu_unit.flags & UNIT_IOP))? \
|
||||
E_V_TYI: E_V_TY)) & E_M_TY)
|
||||
#define F_NO E_FP | ET_NO
|
||||
#define F_MR E_FP | ET_AD
|
||||
#define X_NO E_21MX | ET_NO
|
||||
#define X_MR E_21MX | ET_AD
|
||||
#define X_AA E_21MX | ET_AA
|
||||
#define X_AZ E_21MX | ET_AZ
|
||||
#define D_NO E_DMS | ET_NO
|
||||
#define D_MR E_DMS | ET_AD
|
||||
#define D_AA E_DMS | ET_AA
|
||||
#define M_NO E_IOPX | ET_NO
|
||||
#define M_CN E_IOPX | ET_CN
|
||||
#define M_AC E_IOPX | ET_AC
|
||||
#define I_NO E_IOP | (ET_NO << (E_V_TYI - E_V_TY))
|
||||
#define I_CN E_IOP | (ET_CN << (E_V_TYI - E_V_TY))
|
||||
#define I_AC E_IOP | (ET_AC << (E_V_TYI - E_V_TY))
|
||||
#define I_AZ E_IOP | (ET_AZ << (E_V_TYI - E_V_TY))
|
||||
|
||||
static const uint32 e_inst[512] = {
|
||||
F_MR | I_AC,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* FAD/ILIST */
|
||||
F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FSB/LAI- */
|
||||
I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,
|
||||
F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FMP/LAI+ */
|
||||
I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,
|
||||
F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FDV/SAI- */
|
||||
I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,
|
||||
F_NO | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FIX/SAI+ */
|
||||
I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,
|
||||
F_NO | I_AZ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* FLT/MBYTE */
|
||||
0,0,0,0,0,0,0,0,I_CN,0,0,0,0,0,0,0, /* CRC */
|
||||
I_CN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* TRSLT */
|
||||
I_AZ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* WMOVE */
|
||||
I_NO,I_NO,I_NO,I_NO,0,0,0,0,0,0,0,0,0,0,0,0, /* READF,PFRIO,PFREI,PFREX */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,I_NO, /* ENQ,PENQ */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DEQ */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SBYTE */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* LBYTE */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* REST */
|
||||
0,0,I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SAVE */
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI-/SAI- */
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI+/SAI+ */
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0440 */
|
||||
M_CN,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_CN, /* CRC,REST,READF,INS,ENQ,PENQ,DEQ,TR */
|
||||
M_AC,M_NO,M_NO,M_NO,M_NO,0,0,0, /* ILIST,PFREI,PFREX,PFRIO,SAVE */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0500 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0520 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0540 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0560 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0600 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0620 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0640 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0660 */
|
||||
D_NO,D_NO,D_NO,D_NO,D_NO,D_NO,D_NO,D_NO, /* XMM,test,MBI,MBF,MBW,MWI,MWF,MWW */
|
||||
D_NO,D_NO,D_NO,D_NO,D_MR,D_AA,D_NO,D_NO, /* SY*,US*,PA*,PB*,SSM,JRS,nop,nop */
|
||||
D_NO,D_NO,D_NO,D_NO,D_MR,D_MR,D_MR,D_NO, /* XMM,XMS,XM*,nop,XL*,XS*,XC*,LF* */
|
||||
D_NO,D_NO,D_MR,D_MR,D_MR,D_MR,D_MR,D_MR, /* RS*,RV*,DJP,DJS,SJP,SJS,UJP,UJS */
|
||||
X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*X,C*X,L*X,STX,CX*,LDX,ADX,X*X */
|
||||
X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*Y,C*Y,L*Y,STY,CY*,LDY,ADY,X*Y */
|
||||
X_NO,X_NO,X_MR,X_NO,X_NO,X_AZ,X_AZ,X_NO, /* ISX,DSX,JLY,LBT,SBT,MBT,CBT,SFB */
|
||||
X_NO,X_NO,X_NO,X_AA,X_AA,X_AA,X_AZ,X_AZ }; /* ISY,DSY,JPY,SBS,CBS,TBS,CMW,MVW */
|
||||
|
||||
/* Extended arithmetic
|
||||
|
||||
The 21MX-E adds three "special instructions" that do not exist in earlier
|
||||
CPUs, including the 21MX-M. They are: TIMER (100060), EXECUTE (100120), and
|
||||
DIAG (100000). On the 21MX-M, these instruction codes map to the
|
||||
microroutines for MPY, ASL, and RRL, respectively.
|
||||
|
||||
Under simulation, these cause undefined instruction stops if the CPU is set
|
||||
to 2100 or 2116. They do not cause stops on the 21MX-M, as TIMER in
|
||||
particular is used by several HP programs to differentiate between M- and
|
||||
E-series machines. */
|
||||
|
||||
t_stat cpu_eau (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
uint32 MA, v1, v2, t;
|
||||
uint32 rs, qs, sc;
|
||||
int32 sop1, sop2;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_EAU) == 0) return stop_inst; /* implemented? */
|
||||
|
||||
switch ((IR >> 8) & 017) { /* case on IR<11:8> */
|
||||
|
||||
case 000: /* EAU group 0 */
|
||||
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
|
||||
case 001: /* ASL */
|
||||
sc = (IR & 017)? (IR & 017): 16; /* get sc */
|
||||
O = 0; /* clear ovflo */
|
||||
while (sc-- != 0) { /* bit by bit */
|
||||
t = BR << 1; /* shift B */
|
||||
BR = (BR & SIGN) | (t & 077777) | (AR >> 15);
|
||||
AR = (AR << 1) & DMASK;
|
||||
if ((BR ^ t) & SIGN) O = 1; }
|
||||
break;
|
||||
case 002: /* LSL */
|
||||
sc = (IR & 017)? (IR & 017): 16; /* get sc */
|
||||
BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
|
||||
AR = (AR << sc) & DMASK; /* BR'AR lsh left */
|
||||
break;
|
||||
case 000: /* DIAG */
|
||||
if (!(cpu_unit.flags & UNIT_21MX)) /* must be 21MX */
|
||||
return stop_inst; /* trap if not */
|
||||
if (!(cpu_unit.flags & UNIT_MXM)) /* E-series? */
|
||||
break; /* is NOP unless halted */
|
||||
case 004: /* RRL (+ DIAG on 21MX-M) */
|
||||
sc = (IR & 017)? (IR & 017): 16; /* get sc */
|
||||
t = BR; /* BR'AR rot left */
|
||||
BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
|
||||
AR = ((AR << sc) | (t >> (16 - sc))) & DMASK;
|
||||
break;
|
||||
case 003: /* TIMER */
|
||||
if (!(cpu_unit.flags & UNIT_21MX)) /* must be 21MX */
|
||||
return stop_inst; /* trap if not */
|
||||
else if (!(cpu_unit.flags & UNIT_MXM)) { /* E-series? */
|
||||
BR = (BR + 1) & DMASK; /* increment B */
|
||||
if (BR) PC = err_PC; /* if !=0, repeat */
|
||||
break; }
|
||||
case 010: /* MPY (+ TIMER on 21MX-M) */
|
||||
if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */
|
||||
sop1 = SEXT (AR); /* sext AR */
|
||||
sop2 = SEXT (ReadW (MA)); /* sext mem */
|
||||
sop1 = sop1 * sop2; /* signed mpy */
|
||||
BR = (sop1 >> 16) & DMASK; /* to BR'AR */
|
||||
AR = sop1 & DMASK;
|
||||
O = 0; /* no overflow */
|
||||
break;
|
||||
default:
|
||||
return stop_inst;
|
||||
}
|
||||
break;
|
||||
|
||||
case 001: /* divide */
|
||||
if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */
|
||||
if (rs = qs = BR & SIGN) { /* save divd sign, neg? */
|
||||
AR = (~AR + 1) & DMASK; /* make B'A pos */
|
||||
BR = (~BR + (AR == 0)) & DMASK; } /* make divd pos */
|
||||
v2 = ReadW (MA); /* divr = mem */
|
||||
if (v2 & SIGN) { /* neg? */
|
||||
v2 = (~v2 + 1) & DMASK; /* make divr pos */
|
||||
qs = qs ^ SIGN; } /* sign of quotient */
|
||||
if (BR >= v2) O = 1; /* divide work? */
|
||||
else { /* maybe... */
|
||||
O = 0; /* assume ok */
|
||||
v1 = (BR << 16) | AR; /* 32b divd */
|
||||
AR = (v1 / v2) & DMASK; /* quotient */
|
||||
BR = (v1 % v2) & DMASK; /* remainder */
|
||||
if (AR) { /* quotient > 0? */
|
||||
if (qs) AR = (~AR + 1) & DMASK; /* apply quo sign */
|
||||
if ((AR ^ qs) & SIGN) O = 1; } /* still wrong? ovflo */
|
||||
if (rs) BR = (~BR + 1) & DMASK; } /* apply rem sign */
|
||||
break;
|
||||
|
||||
case 002: /* EAU group 2 */
|
||||
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
|
||||
case 001: /* ASR */
|
||||
sc = (IR & 017)? (IR & 017): 16; /* get sc */
|
||||
AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK;
|
||||
BR = (SEXT (BR) >> sc) & DMASK; /* BR'AR ash right */
|
||||
O = 0;
|
||||
break;
|
||||
case 002: /* LSR */
|
||||
sc = (IR & 017)? (IR & 017): 16; /* get sc */
|
||||
AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK;
|
||||
BR = BR >> sc; /* BR'AR log right */
|
||||
break;
|
||||
case 004: /* RRR */
|
||||
sc = (IR & 017)? (IR & 017): 16; /* get sc */
|
||||
t = AR; /* BR'AR rot right */
|
||||
AR = ((AR >> sc) | (BR << (16 - sc))) & DMASK;
|
||||
BR = ((BR >> sc) | (t << (16 - sc))) & DMASK;
|
||||
break;
|
||||
default:
|
||||
return stop_inst;
|
||||
}
|
||||
break;
|
||||
|
||||
case 010: /* DLD */
|
||||
if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */
|
||||
AR = ReadW (MA); /* load AR */
|
||||
MA = (MA + 1) & VAMASK;
|
||||
BR = ReadW (MA); /* load BR */
|
||||
break;
|
||||
|
||||
case 011: /* DST */
|
||||
if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */
|
||||
WriteW (MA, AR); /* store AR */
|
||||
MA = (MA + 1) & VAMASK;
|
||||
WriteW (MA, BR); /* store BR */
|
||||
break;
|
||||
|
||||
default: /* should never get here */
|
||||
return SCPE_IERR;
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
|
||||
t_stat cpu_mac (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason;
|
||||
uint32 MA, M1, absel, v1, v2, t;
|
||||
uint32 fop, eop, etype, eflag;
|
||||
uint32 mapi, mapj;
|
||||
uint32 awc, wc, hp, tp;
|
||||
int32 i, sop1, sop2;
|
||||
|
||||
absel = (IR & I_AB)? 1: 0; /* get A/B select */
|
||||
eop = IR & 0777; /* extended opcode */
|
||||
eflag = E_GETFL (e_inst[eop]); /* get flags */
|
||||
if ((eflag & (cpu_unit.flags >> UNIT_V_UF)) == 0) /* invalid? error */
|
||||
return stop_inst;
|
||||
etype = E_GETTY (eflag, e_inst[eop]); /* get format */
|
||||
if (etype > E_CN) { /* at least 1 addr? */
|
||||
if (reason = Ea1 (&MA, intrq)) /* get first address */
|
||||
return reason; }
|
||||
if ((etype == E_AC) || (etype == E_CN)) { /* addr + cnt, cnt */
|
||||
wc = ReadW (PC); /* get count */
|
||||
awc = PC; /* addr of count */
|
||||
PC = (PC + 1) & VAMASK; }
|
||||
else if (etype == E_AZ) { /* addr + zero */
|
||||
wc = ReadW (MA); /* get wc */
|
||||
awc = PC; /* addr of interim */
|
||||
if (wc) { /* wc > 0? */
|
||||
if (t = ReadW (PC)) wc = t; } /* use interim if nz */
|
||||
WriteW (awc, 0); /* clear interim */
|
||||
PC = (PC + 1) & VAMASK; }
|
||||
else if (etype == E_AA) { /* second addr */
|
||||
if (reason = Ea1 (&M1, intrq)) /* get second address */
|
||||
return reason; }
|
||||
|
||||
switch (eop) { /* decode IR<8:0> */
|
||||
|
||||
/* Floating point instructions */
|
||||
|
||||
case 0000: /* IOP ILIST/FAD */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* ILIST (E_AC) */
|
||||
goto IOP_ILIST;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_as (fop, 0); /* add, upd ovflo */
|
||||
break;
|
||||
case 0020: /* IOP LAI-/FSB */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* LAI -20 (I_NO) */
|
||||
goto IOP_LAIM;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_as (fop, 1); /* sub, upd ovflo */
|
||||
break;
|
||||
case 0040: /* IOP LAI+/FMP */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* LAI 0 (I_NO) */
|
||||
goto IOP_LAIP;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_mul (fop); /* mul, upd ovflo */
|
||||
break;
|
||||
case 0060: /* IOP SAI-/FDV */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* SAI -20 (I_NO) */
|
||||
goto IOP_SAIM;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_div (fop); /* div, upd ovflo */
|
||||
break;
|
||||
case 0100: /* IOP SAI+/FIX */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* SAI 0 (I_NO) */
|
||||
goto IOP_SAIP;
|
||||
O = f_fix (); /* FIX (E_NO) */
|
||||
break;
|
||||
case 0120: /* IOP MBYTE/FLT */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* MBYTE (I_AZ) */
|
||||
goto IOP_MBYTE;
|
||||
O = f_flt (); /* FLT (E_NO) */
|
||||
break;
|
||||
|
||||
/* 2100 (and 21MX) IOP instructions */
|
||||
|
||||
IOP_LAIM: case 0021: case 0022: case 0023: /* IOP LAI- (I_NO) */
|
||||
case 0024: case 0025: case 0026: case 0027:
|
||||
case 0030: case 0031: case 0032: case 0033:
|
||||
case 0034: case 0035: case 0036: case 0037:
|
||||
MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */
|
||||
AR = ReadW (MA); /* load AR */
|
||||
break;
|
||||
IOP_LAIP: case 0041: case 0042: case 0043: /* IOP LAI+ (I_NO) */
|
||||
case 0044: case 0045: case 0046: case 0047:
|
||||
case 0050: case 0051: case 0052: case 0053:
|
||||
case 0054: case 0055: case 0056: case 0057:
|
||||
MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */
|
||||
AR = ReadW (MA); /* load AR */
|
||||
break;
|
||||
IOP_SAIM: case 0061: case 0062: case 0063: /* IOP SAI- (I_NO) */
|
||||
case 0064: case 0065: case 0066: case 0067:
|
||||
case 0070: case 0071: case 0072: case 0073:
|
||||
case 0074: case 0075: case 0076: case 0077:
|
||||
MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */
|
||||
WriteW (MA, AR); /* store AR */
|
||||
break;
|
||||
IOP_SAIP: case 0101: case 0102: case 0103: /* IOP SAI+ (I_NO) */
|
||||
case 0104: case 0105: case 0106: case 0107:
|
||||
case 0110: case 0111: case 0112: case 0113:
|
||||
case 0114: case 0115: case 0116: case 0117:
|
||||
MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */
|
||||
WriteW (MA, AR); /* store AR */
|
||||
break;
|
||||
case 0150: /* IOP CRC (I_CN) */
|
||||
case 0460: /* IOPX CRC (I_CN) */
|
||||
t = (AR & 0xFF) ^ wc; /* start CRC */
|
||||
for (i = 0; i < 8; i++) { /* apply polynomial */
|
||||
t = (t >> 1) | ((t & 1) << 15); /* rotate right */
|
||||
if (t & SIGN) t = t ^ 020001; } /* old t<0>? xor */
|
||||
WriteW (awc, t); /* rewrite CRC */
|
||||
break;
|
||||
case 0160: /* IOP TRSLT (I_CN) */
|
||||
case 0467: /* IOPX TRSLT (I_CN) */
|
||||
if (wc & SIGN) break; /* cnt < 0? */
|
||||
while (wc != 0) { /* loop */
|
||||
MA = (AR + AR + ReadB (BR)) & VAMASK;
|
||||
t = ReadB (MA); /* xlate */
|
||||
WriteB (BR, t); /* store char */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
if (wc && intrq) { /* more and intr? */
|
||||
WriteW (awc, wc); /* rewrite wc */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0220: /* IOP READF (I_NO) */
|
||||
case 0462: /* IOPX READF (I_NO) */
|
||||
AR = iop_sp; /* copy stk ptr */
|
||||
break;
|
||||
case 0221: /* IOP PRFIO (I_NO) */
|
||||
case 0473: /* IOPX PFRIO (I_NO) */
|
||||
t = ReadW (PC); /* get IO instr */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
WriteW (PC, 1); /* set flag */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
reason = iogrp (t, 0); /* execute instr */
|
||||
break;
|
||||
case 0222: /* IOP PRFEI (I_NO) */
|
||||
case 0471: /* IOPX PFREI (I_NO) */
|
||||
t = ReadW (PC); /* get IO instr */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
WriteW (PC, 1); /* set flag */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
reason = iogrp (t, 0); /* execute instr */
|
||||
/* fall through */
|
||||
case 0223: /* IOP PRFEX (I_NO) */
|
||||
case 0472: /* IOPX PFREX (I_NO) */
|
||||
MA = ReadW (PC); /* exit addr */
|
||||
PCQ_ENTRY;
|
||||
PC = ReadW (MA) & VAMASK; /* jump indirect */
|
||||
WriteW (MA, 0); /* clear exit */
|
||||
break;
|
||||
case 0240: /* IOP ENQ (I_NO) */
|
||||
case 0464: /* IOPX ENQ (I_NO) */
|
||||
hp = ReadW (AR & VAMASK); /* addr of head */
|
||||
tp = ReadW ((AR + 1) & VAMASK); /* addr of tail */
|
||||
WriteW ((BR - 1) & VAMASK, 0); /* entry link */
|
||||
WriteW ((tp - 1) & VAMASK, BR); /* tail link */
|
||||
WriteW ((AR + 1) & VAMASK, BR); /* queue tail */
|
||||
if (hp != 0) PC = (PC + 1) & VAMASK; /* q not empty? skip */
|
||||
break;
|
||||
case 0257: /* IOP PENQ (I_NO) */
|
||||
case 0465: /* IOPX PENQ (I_NO) */
|
||||
hp = ReadW (AR & VAMASK); /* addr of head */
|
||||
WriteW ((BR - 1) & VAMASK, hp); /* becomes entry link */
|
||||
WriteW (AR & VAMASK, BR); /* queue head */
|
||||
if (hp == 0) /* q empty? */
|
||||
WriteW ((AR + 1) & VAMASK, BR); /* queue tail */
|
||||
else PC = (PC + 1) & VAMASK; /* skip */
|
||||
break;
|
||||
case 0260: /* IOP DEQ (I_NO) */
|
||||
case 0466: /* IOPX DEQ (I_NO) */
|
||||
BR = ReadW (AR & VAMASK); /* addr of head */
|
||||
if (BR) { /* queue not empty? */
|
||||
hp = ReadW ((BR - 1) & VAMASK); /* read hd entry link */
|
||||
WriteW (AR & VAMASK, hp); /* becomes queue head */
|
||||
if (hp == 0) /* q now empty? */
|
||||
WriteW ((AR + 1) & VAMASK, (AR + 1) & DMASK);
|
||||
PC = (PC + 1) & VAMASK; } /* skip */
|
||||
break;
|
||||
case 0300: /* IOP SBYTE (I_NO) */
|
||||
WriteB (BR, AR); /* store byte */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
break;
|
||||
case 0320: /* IOP LBYTE (I_NO) */
|
||||
AR = ReadB (BR); /* load byte */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
break;
|
||||
case 0340: /* IOP REST (I_NO) */
|
||||
case 0461: /* IOPX REST (I_NO) */
|
||||
iop_sp = (iop_sp - 1) & VAMASK; /* pop E/~O,BR,AR */
|
||||
t = ReadW (iop_sp);
|
||||
O = ((t >> 1) ^ 1) & 1;
|
||||
E = t & 1;
|
||||
iop_sp = (iop_sp - 1) & VAMASK;
|
||||
BR = ReadW (iop_sp);
|
||||
iop_sp = (iop_sp - 1) & VAMASK;
|
||||
AR = ReadW (iop_sp);
|
||||
if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp;
|
||||
break;
|
||||
case 0362: /* IOP SAVE (I_NO) */
|
||||
case 0474: /* IOPX SAVE (I_NO) */
|
||||
WriteW (iop_sp, AR); /* push AR,BR,E/~O */
|
||||
iop_sp = (iop_sp + 1) & VAMASK;
|
||||
WriteW (iop_sp, BR);
|
||||
iop_sp = (iop_sp + 1) & VAMASK;
|
||||
t = ((O ^ 1) << 1) | E;
|
||||
WriteW (iop_sp, t);
|
||||
iop_sp = (iop_sp + 1) & VAMASK;
|
||||
if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp;
|
||||
break;
|
||||
|
||||
case 0400: case 0401: case 0402: case 0403: /* IOPX LAI-/SAI- (I_NO) */
|
||||
case 0404: case 0405: case 0406: case 0407:
|
||||
case 0410: case 0411: case 0412: case 0413:
|
||||
case 0414: case 0415: case 0416: case 0417:
|
||||
MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */
|
||||
if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */
|
||||
else WriteW (MA, AR); /* AB = 0? SAI */
|
||||
break;
|
||||
case 0420: case 0421: case 0422: case 0423: /* IOPX LAI+/SAI+ (I_NO) */
|
||||
case 0424: case 0425: case 0426: case 0427:
|
||||
case 0430: case 0431: case 0432: case 0433:
|
||||
case 0434: case 0435: case 0436: case 0437:
|
||||
MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */
|
||||
if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */
|
||||
else WriteW (MA, AR); /* AB = 0? SAI */
|
||||
break;
|
||||
case 0463: /* IOPX INS (I_NO) */
|
||||
iop_sp = AR; /* init stk ptr */
|
||||
break;
|
||||
case 0470: /* IOPX ILIST (I_CN) */
|
||||
IOP_ILIST:
|
||||
do { /* for count */
|
||||
WriteW (MA, AR); /* write AR to mem */
|
||||
AR = (AR + 1) & DMASK; /* incr AR */
|
||||
MA = (MA + 1) & VAMASK; /* incr MA */
|
||||
wc = (wc - 1) & DMASK; } /* decr count */
|
||||
while (wc != 0);
|
||||
break;
|
||||
|
||||
/* DMS instructions, move alternate - interruptible
|
||||
|
||||
DMS privilege violation rules are
|
||||
- load map and CTL set (XMM, XMS, XM*, SY*, US*, PA*, PB*)
|
||||
- load state or fence and UMAP set (JRS, DJP, DJS, SJP, SJS, UJP, UJS, LF*)
|
||||
|
||||
The 21MX manual is incorrect in stating that M*I, M*W, XS* are privileged */
|
||||
|
||||
case 0701: /* self test */
|
||||
ABREG[absel] = ABREG[absel] ^ DMASK; /* CMA or CMB */
|
||||
break;
|
||||
case 0702: /* MBI (E_NO) */
|
||||
AR = AR & ~1; /* force A, B even */
|
||||
BR = BR & ~1;
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadB (AR); /* read curr */
|
||||
WriteBA (BR, t); /* write alt */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
if (XR && intrq && !(AR & 1)) { /* more, int, even? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0703: /* MBF (E_NO) */
|
||||
AR = AR & ~1; /* force A, B even */
|
||||
BR = BR & ~1;
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadBA (AR); /* read alt */
|
||||
WriteB (BR, t); /* write curr */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
if (XR && intrq && !(AR & 1)) { /* more, int, even? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0704: /* MBW (E_NO) */
|
||||
AR = AR & ~1; /* force A, B even */
|
||||
BR = BR & ~1;
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadBA (AR); /* read alt */
|
||||
WriteBA (BR, t); /* write alt */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
if (XR && intrq && !(AR & 1)) { /* more, int, even? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0705: /* MWI (E_NO) */
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadW (AR & VAMASK); /* read curr */
|
||||
WriteWA (BR & VAMASK, t); /* write alt */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
if (XR && intrq) { /* more and intr? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0706: /* MWF (E_NO) */
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadWA (AR & VAMASK); /* read alt */
|
||||
WriteW (BR & VAMASK, t); /* write curr */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
if (XR && intrq) { /* more and intr? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0707: /* MWW (E_NO) */
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadWA (AR & VAMASK); /* read alt */
|
||||
WriteWA (BR & VAMASK, t); /* write alt */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
if (XR && intrq) { /* more and intr? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
|
||||
/* DMS, continued */
|
||||
|
||||
case 0710: /* SYA, SYB (E_NO) */
|
||||
case 0711: /* USA, USB (E_NO) */
|
||||
case 0712: /* PAA, PAB (E_NO) */
|
||||
case 0713: /* PBA, PBB (E_NO) */
|
||||
mapi = (IR & 03) << VA_N_PAG; /* map base */
|
||||
if (ABREG[absel] & SIGN) { /* store? */
|
||||
for (i = 0; i < MAP_LNT; i++) {
|
||||
t = dms_rmap (mapi + i); /* map to memory */
|
||||
WriteW ((ABREG[absel] + i) & VAMASK, t); } }
|
||||
else { /* load */
|
||||
dms_viol (err_PC, MVI_PRV); /* priv if PRO */
|
||||
for (i = 0; i < MAP_LNT; i++) {
|
||||
t = ReadW ((ABREG[absel] + i) & VAMASK);
|
||||
dms_wmap (mapi + i, t); } } /* mem to map */
|
||||
ABREG[absel] = (ABREG[absel] + MAP_LNT) & DMASK;
|
||||
break;
|
||||
case 0714: /* SSM (E_AD) */
|
||||
WriteW (MA, dms_upd_sr ()); /* store stat */
|
||||
break;
|
||||
case 0715: /* JRS (E_AA) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
t = ReadW (MA); /* get status */
|
||||
dms_enb = 0; /* assume off */
|
||||
dms_ump = SMAP;
|
||||
if (t & 0100000) { /* set enable? */
|
||||
dms_enb = 1;
|
||||
if (t & 0040000) dms_ump = UMAP; } /* set/clr usr */
|
||||
mp_dms_jmp (M1); /* mpck jmp target */
|
||||
PCQ_ENTRY; /* save old PC */
|
||||
PC = M1; /* jump */
|
||||
ion_defer = 1; /* defer intr */
|
||||
break;
|
||||
|
||||
/* DMS, continued */
|
||||
|
||||
case 0700: case 0720: /* XMM (E_NO) */
|
||||
if (XR == 0) break; /* nop? */
|
||||
while (XR != 0) { /* loop */
|
||||
if (XR & SIGN) { /* store? */
|
||||
t = dms_rmap (AR); /* map to mem */
|
||||
WriteW (BR & VAMASK, t);
|
||||
XR = (XR + 1) & DMASK; }
|
||||
else { /* load */
|
||||
dms_viol (err_PC, MVI_PRV); /* priv if PRO */
|
||||
t = ReadW (BR & VAMASK); /* mem to map */
|
||||
dms_wmap (AR, t);
|
||||
XR = (XR - 1) & DMASK; }
|
||||
AR = (AR + 1) & DMASK;
|
||||
BR = (BR + 1) & DMASK;
|
||||
if (intrq && ((XR & 0xF) == 0xF)) { /* intr, cnt4 = F? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0721: /* XMS (E_NO) */
|
||||
if ((XR & SIGN) || (XR == 0)) break; /* nop? */
|
||||
dms_viol (err_PC, MVI_PRV); /* priv if PRO */
|
||||
while (XR != 0) {
|
||||
dms_wmap (AR, BR); /* AR to map */
|
||||
XR = (XR - 1) & DMASK;
|
||||
AR = (AR + 1) & DMASK;
|
||||
BR = (BR + 1) & DMASK;
|
||||
if (intrq && ((XR & 0xF) == 0xF)) { /* intr, cnt4 = F? */
|
||||
PC = err_PC;
|
||||
break; } }
|
||||
break;
|
||||
case 0722: /* XMA, XMB (E_NO) */
|
||||
dms_viol (err_PC, MVI_PRV); /* priv if PRO */
|
||||
if (ABREG[absel] & 0100000) mapi = UMAP;
|
||||
else mapi = SMAP;
|
||||
if (ABREG[absel] & 0000001) mapj = PBMAP;
|
||||
else mapj = PAMAP;
|
||||
for (i = 0; i < MAP_LNT; i++) {
|
||||
t = dms_rmap (mapi + i); /* read map */
|
||||
dms_wmap (mapj + i, t); } /* write map */
|
||||
break;
|
||||
case 0724: /* XLA, XLB (E_AD) */
|
||||
ABREG[absel] = ReadWA (MA); /* load alt */
|
||||
break;
|
||||
case 0725: /* XSA, XSB (E_AD) */
|
||||
WriteWA (MA, ABREG[absel]); /* store alt */
|
||||
break;
|
||||
case 0726: /* XCA, XCB (E_AD) */
|
||||
if (ABREG[absel] != ReadWA (MA)) /* compare alt */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
break;
|
||||
case 0727: /* LFA, LFB (E_NO) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
dms_sr = (dms_sr & ~(MST_FLT | MST_FENCE)) |
|
||||
(ABREG[absel] & (MST_FLT | MST_FENCE));
|
||||
break;
|
||||
|
||||
/* DMS, continued */
|
||||
|
||||
case 0730: /* RSA, RSB (E_NO) */
|
||||
ABREG[absel] = dms_upd_sr (); /* save stat */
|
||||
break;
|
||||
case 0731: /* RVA, RVB (E_NO) */
|
||||
ABREG[absel] = dms_vr; /* save viol */
|
||||
break;
|
||||
case 0732: /* DJP (E_AD) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
mp_dms_jmp (MA); /* validate jump addr */
|
||||
PCQ_ENTRY; /* save curr PC */
|
||||
PC = MA; /* new PC */
|
||||
dms_enb = 0; /* disable map */
|
||||
dms_ump = SMAP;
|
||||
ion_defer = 1;
|
||||
break;
|
||||
case 0733: /* DJS (E_AD) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
WriteW (MA, PC); /* store ret addr */
|
||||
PCQ_ENTRY; /* save curr PC */
|
||||
PC = (MA + 1) & VAMASK; /* new PC */
|
||||
dms_enb = 0; /* disable map */
|
||||
dms_ump = SMAP;
|
||||
ion_defer = 1; /* defer intr */
|
||||
break;
|
||||
case 0734: /* SJP (E_AD) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
mp_dms_jmp (MA); /* validate jump addr */
|
||||
PCQ_ENTRY; /* save curr PC */
|
||||
PC = MA; /* jump */
|
||||
dms_enb = 1; /* enable system */
|
||||
dms_ump = SMAP;
|
||||
ion_defer = 1; /* defer intr */
|
||||
break;
|
||||
case 0735: /* SJS (E_AD) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
t = PC; /* save retn addr */
|
||||
PCQ_ENTRY; /* save curr PC */
|
||||
PC = (MA + 1) & VAMASK; /* new PC */
|
||||
dms_enb = 1; /* enable system */
|
||||
dms_ump = SMAP;
|
||||
WriteW (MA, t); /* store ret addr */
|
||||
ion_defer = 1; /* defer intr */
|
||||
break;
|
||||
case 0736: /* UJP (E_AD) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
mp_dms_jmp (MA); /* validate jump addr */
|
||||
PCQ_ENTRY; /* save curr PC */
|
||||
PC = MA; /* jump */
|
||||
dms_enb = 1; /* enable user */
|
||||
dms_ump = UMAP;
|
||||
ion_defer = 1; /* defer intr */
|
||||
break;
|
||||
case 0737: /* UJS (E_AD) */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV);
|
||||
t = PC; /* save retn addr */
|
||||
PCQ_ENTRY; /* save curr PC */
|
||||
PC = (MA + 1) & VAMASK; /* new PC */
|
||||
dms_enb = 1; /* enable user */
|
||||
dms_ump = UMAP;
|
||||
WriteW (MA, t); /* store ret addr */
|
||||
ion_defer = 1; /* defer intr */
|
||||
break;
|
||||
|
||||
/* Index register instructions */
|
||||
|
||||
case 0740: /* SAX, SBX (E_AD) */
|
||||
MA = (MA + XR) & VAMASK; /* indexed addr */
|
||||
WriteW (MA, ABREG[absel]); /* store */
|
||||
break;
|
||||
case 0741: /* CAX, CBX (E_NO) */
|
||||
XR = ABREG[absel]; /* copy to XR */
|
||||
break;
|
||||
case 0742: /* LAX, LBX (E_AD) */
|
||||
MA = (MA + XR) & VAMASK; /* indexed addr */
|
||||
ABREG[absel] = ReadW (MA); /* load */
|
||||
break;
|
||||
case 0743: /* STX (E_AD) */
|
||||
WriteW (MA, XR); /* store XR */
|
||||
break;
|
||||
case 0744: /* CXA, CXB (E_NO) */
|
||||
ABREG[absel] = XR; /* copy from XR */
|
||||
break;
|
||||
case 0745: /* LDX (E_AD)*/
|
||||
XR = ReadW (MA); /* load XR */
|
||||
break;
|
||||
case 0746: /* ADX (E_AD) */
|
||||
v1 = ReadW (MA); /* add to XR */
|
||||
t = XR + v1;
|
||||
if (t > DMASK) E = 1; /* set E, O */
|
||||
if (((~XR ^ v1) & (XR ^ t)) & SIGN) O = 1;
|
||||
XR = t & DMASK;
|
||||
break;
|
||||
case 0747: /* XAX, XBX (E_NO) */
|
||||
t = XR; /* exchange XR */
|
||||
XR = ABREG[absel];
|
||||
ABREG[absel] = t;
|
||||
break;
|
||||
case 0750: /* SAY, SBY (E_AD) */
|
||||
MA = (MA + YR) & VAMASK; /* indexed addr */
|
||||
WriteW (MA, ABREG[absel]); /* store */
|
||||
break;
|
||||
case 0751: /* CAY, CBY (E_NO) */
|
||||
YR = ABREG[absel]; /* copy to YR */
|
||||
break;
|
||||
case 0752: /* LAY, LBY (E_AD) */
|
||||
MA = (MA + YR) & VAMASK; /* indexed addr */
|
||||
ABREG[absel] = ReadW (MA); /* load */
|
||||
break;
|
||||
case 0753: /* STY (E_AD) */
|
||||
WriteW (MA, YR); /* store YR */
|
||||
break;
|
||||
case 0754: /* CYA, CYB (E_NO) */
|
||||
ABREG[absel] = YR; /* copy from YR */
|
||||
break;
|
||||
case 0755: /* LDY (E_AD) */
|
||||
YR = ReadW (MA); /* load YR */
|
||||
break;
|
||||
case 0756: /* ADY (E_AD) */
|
||||
v1 = ReadW (MA); /* add to YR */
|
||||
t = YR + v1;
|
||||
if (t > DMASK) E = 1; /* set E, O */
|
||||
if (((~YR ^ v1) & (YR ^ t)) & SIGN) O = 1;
|
||||
YR = t & DMASK;
|
||||
break;
|
||||
case 0757: /* XAY, XBY (E_NO) */
|
||||
t = YR; /* exchange YR */
|
||||
YR = ABREG[absel];
|
||||
ABREG[absel] = t;
|
||||
break;
|
||||
case 0760: /* ISX (E_NO) */
|
||||
XR = (XR + 1) & DMASK; /* incr XR */
|
||||
if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */
|
||||
break;
|
||||
case 0761: /* DSX (E_NO) */
|
||||
XR = (XR - 1) & DMASK; /* decr XR */
|
||||
if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */
|
||||
break;
|
||||
case 0762: /* JLY (E_AD) */
|
||||
mp_dms_jmp (MA); /* validate jump addr */
|
||||
PCQ_ENTRY;
|
||||
YR = PC; /* ret addr to YR */
|
||||
PC = MA; /* jump */
|
||||
break;
|
||||
case 0770: /* ISY (E_NO) */
|
||||
YR = (YR + 1) & DMASK; /* incr YR */
|
||||
if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */
|
||||
break;
|
||||
case 0771: /* DSY (E_NO) */
|
||||
YR = (YR - 1) & DMASK; /* decr YR */
|
||||
if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */
|
||||
break;
|
||||
case 0772: /* JPY (E_NO) */
|
||||
MA = (ReadW (PC) + YR) & VAMASK; /* index, no indir */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
mp_dms_jmp (MA); /* validate jump addr */
|
||||
PCQ_ENTRY;
|
||||
PC = MA; /* jump */
|
||||
break;
|
||||
|
||||
/* Byte instructions */
|
||||
|
||||
case 0763: /* LBT (E_NO) */
|
||||
AR = ReadB (BR); /* load byte */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
break;
|
||||
case 0764: /* SBT (E_NO) */
|
||||
WriteB (BR, AR); /* store byte */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
break;
|
||||
IOP_MBYTE: /* IOP MBYTE (I_AZ) */
|
||||
if (wc & SIGN) break; /* must be positive */
|
||||
case 0765: /* MBT (E_AZ) */
|
||||
while (wc != 0) { /* while count */
|
||||
WriteW (awc, wc); /* for abort */
|
||||
t = ReadB (AR); /* move byte */
|
||||
WriteB (BR, t);
|
||||
AR = (AR + 1) & DMASK; /* incr src */
|
||||
BR = (BR + 1) & DMASK; /* incr dst */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
if (intrq && wc) { /* intr, more to do? */
|
||||
PC = err_PC; /* back up PC */
|
||||
break; } } /* take intr */
|
||||
WriteW (awc, wc); /* clean up inline */
|
||||
break;
|
||||
case 0766: /* CBT (E_AZ) */
|
||||
while (wc != 0) { /* while count */
|
||||
WriteW (awc, wc); /* for abort */
|
||||
v1 = ReadB (AR); /* get src1 */
|
||||
v2 = ReadB (BR); /* get src2 */
|
||||
if (v1 != v2) { /* compare */
|
||||
PC = (PC + 1 + (v1 > v2)) & VAMASK;
|
||||
BR = (BR + wc) & DMASK; /* update BR */
|
||||
wc = 0; /* clr interim */
|
||||
break; }
|
||||
AR = (AR + 1) & DMASK; /* incr src1 */
|
||||
BR = (BR + 1) & DMASK; /* incr src2 */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
if (intrq && wc) { /* intr, more to do? */
|
||||
PC = err_PC; /* back up PC */
|
||||
break; } } /* take intr */
|
||||
WriteW (awc, wc); /* clean up inline */
|
||||
break;
|
||||
case 0767: /* SFB (E_NO) */
|
||||
v1 = AR & 0377; /* test byte */
|
||||
v2 = (AR >> 8) & 0377; /* term byte */
|
||||
for (;;) { /* scan */
|
||||
t = ReadB (BR); /* read byte */
|
||||
if (t == v1) break; /* test match? */
|
||||
BR = (BR + 1) & DMASK;
|
||||
if (t == v2) { /* term match? */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
break; }
|
||||
if (intrq) { /* int pending? */
|
||||
PC = err_PC; /* back up PC */
|
||||
break; } } /* take intr */
|
||||
break;
|
||||
|
||||
/* Bit, word instructions */
|
||||
|
||||
case 0773: /* SBS (E_AA) */
|
||||
v1 = ReadW (MA);
|
||||
v2 = ReadW (M1);
|
||||
WriteW (M1, v2 | v1); /* set bit */
|
||||
break;
|
||||
case 0774: /* CBS (E_AA) */
|
||||
v1 = ReadW (MA);
|
||||
v2 = ReadW (M1);
|
||||
WriteW (M1, v2 & ~v1); /* clear bit */
|
||||
break;
|
||||
case 0775: /* TBS (E_AA) */
|
||||
v1 = ReadW (MA);
|
||||
v2 = ReadW (M1);
|
||||
if ((v2 & v1) != v1) /* test bits */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
break;
|
||||
case 0776: /* CMW (E_AZ) */
|
||||
while (wc != 0) { /* while count */
|
||||
WriteW (awc, wc); /* for abort */
|
||||
v1 = ReadW (AR & VAMASK); /* first op */
|
||||
v2 = ReadW (BR & VAMASK); /* second op */
|
||||
sop1 = (int32) SEXT (v1); /* signed */
|
||||
sop2 = (int32) SEXT (v2);
|
||||
if (sop1 != sop2) { /* compare */
|
||||
PC = (PC + 1 + (sop1 > sop2)) & VAMASK;
|
||||
BR = (BR + wc) & DMASK; /* update BR */
|
||||
wc = 0; /* clr interim */
|
||||
break; }
|
||||
AR = (AR + 1) & DMASK; /* incr src1 */
|
||||
BR = (BR + 1) & DMASK; /* incr src2 */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
if (intrq && wc) { /* intr, more to do? */
|
||||
PC = err_PC; /* back up PC */
|
||||
break; } } /* take intr */
|
||||
WriteW (awc, wc); /* clean up inline */
|
||||
break;
|
||||
case 0200: /* IOP WMOVE (I_AZ) */
|
||||
if (wc & SIGN) break; /* must be positive */
|
||||
case 0777: /* MVW (E_AZ) */
|
||||
while (wc != 0) { /* while count */
|
||||
WriteW (awc, wc); /* for abort */
|
||||
t = ReadW (AR & VAMASK); /* move word */
|
||||
WriteW (BR & VAMASK, t);
|
||||
AR = (AR + 1) & DMASK; /* incr src */
|
||||
BR = (BR + 1) & DMASK; /* incr dst */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
if (intrq && wc) { /* intr, more to do? */
|
||||
PC = err_PC; /* back up PC */
|
||||
break; } } /* take intr */
|
||||
WriteW (awc, wc); /* clean up inline */
|
||||
break;
|
||||
default: /* all others NOP */
|
||||
break; } /* end case ext */
|
||||
return reason;
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: HP2100 Simulator Usage
|
||||
Date: 22-Dec-2004
|
||||
Date: 20-Jan-2005
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2004, written by Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Original code published in 1993-2005, written by Robert M Supnik
|
||||
Copyright (c) 1993-2005, 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"),
|
||||
@@ -53,8 +53,10 @@ sim/ scp.h
|
||||
sim_timer.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/hp2100/ hp2100_defs.h
|
||||
sim/hp2100/ hp2100_cpu.h
|
||||
hp2100_defs.h
|
||||
hp2100_cpu.c
|
||||
hp2100_cpu1.c
|
||||
hp2100_fp.c
|
||||
hp2100_dp.c
|
||||
hp2100_dq.c
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_fp.c: HP 2100 floating point instructions
|
||||
|
||||
Copyright (c) 2002-2004, Robert M. Supnik
|
||||
Copyright (c) 2002-2005, 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"),
|
||||
@@ -23,6 +23,7 @@
|
||||
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.
|
||||
|
||||
11-Feb-05 JDB Fixed missing negative overflow renorm in StoreFP
|
||||
26-Dec-04 RMS Separated A/B from M[0/1] for DMA IO (from Dave Bryan)
|
||||
15-Jul-03 RMS Fixed signed/unsigned warning
|
||||
21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms
|
||||
@@ -295,8 +296,9 @@ svfr = fop->fr; /* save fraction */
|
||||
sign = FP_GETSIGN (fop->fr); /* save sign */
|
||||
fop->fr = (fop->fr + (sign? FP_RNDM: FP_RNDP)) & FP_FR; /* round */
|
||||
if ((fop->fr ^ svfr) & FP_SIGN) { /* sign change? */
|
||||
fop->fr = (fop->fr >> 1) | (sign? FP_SIGN: 0); /* renormalize */
|
||||
fop->fr = fop->fr >> 1; /* renormalize */
|
||||
fop->exp = fop->exp + 1; }
|
||||
else NormFP (fop); /* check for norm */
|
||||
if (fop->fr == 0) hi = 0; /* result 0? */
|
||||
else if (fop->exp < -(FP_M_EXP + 1)) { /* underflow? */
|
||||
hi = 0; /* store clean 0 */
|
||||
|
||||
Reference in New Issue
Block a user