mirror of
https://github.com/simh/simh.git
synced 2026-01-11 23:52:58 +00:00
HP3000: Fourth HP 3000 release
See HP3000/hp3000_release.txt for details of the release
This commit is contained in:
parent
bdb0597411
commit
629f0f0c07
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,15 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
07-Nov-16 JDB Added SETR and SETR_X for SETR executor use;
|
||||
renamed cpu_byte_to_word_ea to cpu_byte_ea
|
||||
03-Nov-16 JDB Added LABEL_LOCAL for PARC/XBR/ENDP executor use
|
||||
01-Nov-16 JDB Added debug flag for per-instruction trace capability
|
||||
22-Oct-16 JDB Added "cpu_interrupt_pending" global from cpu_base.c
|
||||
07-Oct-16 JDB Added "cpu_dev" external so executors can trace instructions
|
||||
28-Sep-16 JDB Added CIS definitions
|
||||
22-Sep-16 JDB Added cpu_byte_to_word_ea, STATUS_CS macro
|
||||
21-Sep-16 JDB Added STATUS_CCI, UNIT_CIS, and the CIS dispatcher
|
||||
12-Sep-16 JDB Added the PCN_SERIES_II and PCN_SERIES_III constants
|
||||
02-Sep-16 JDB Added the POWER_STATE enumeration type, the UNIT_PFARS
|
||||
flag, and the "cpu_power_state" external declaration
|
||||
@ -46,28 +55,6 @@
|
||||
|
||||
|
||||
|
||||
/* Architectural constants.
|
||||
|
||||
The type used to represent a main memory word value is defined. An array of
|
||||
this type is used to simulate the CPU main memory.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The MEMORY_WORD type is a 16-bit unsigned type, corresponding with the
|
||||
16-bit main memory in the HP 3000. Unlike the general data type, which
|
||||
is a 32-bit type for speed, main memory does not benefit from the faster
|
||||
32-bit execution on IA-32 processors, as only one instruction in the
|
||||
cpu_read_memory and cpu_write_memory routines has an operand override
|
||||
that invokes the slower instruction fetch path. There is a negligible
|
||||
difference in the Memory Pattern Test diagnostic execution speeds for the
|
||||
uint32 vs. uint16 definition, whereas the VM requirements are doubled for
|
||||
the former.
|
||||
*/
|
||||
|
||||
typedef uint16 MEMORY_WORD; /* HP 16-bit memory word representation */
|
||||
|
||||
|
||||
/* Supported breakpoint switches */
|
||||
|
||||
#define BP_EXEC (SWMASK ('E')) /* an execution breakpoint */
|
||||
@ -80,6 +67,7 @@ typedef uint16 MEMORY_WORD; /* HP 16-bit memory word represe
|
||||
#define UNIT_EIS_SHIFT (UNIT_V_UF + 1) /* the Extended Instruction Set firmware option */
|
||||
#define UNIT_CALTIME_SHIFT (UNIT_V_UF + 2) /* the process clock timing mode */
|
||||
#define UNIT_PFARS_SHIFT (UNIT_V_UF + 3) /* the power-fail auto-restart mode */
|
||||
#define UNIT_CIS_SHIFT (UNIT_V_UF + 4) /* the COBOL II Extended Instruction Set firmware option */
|
||||
|
||||
#define UNIT_MODEL_MASK 0000001u /* model ID mask */
|
||||
|
||||
@ -90,6 +78,7 @@ typedef uint16 MEMORY_WORD; /* HP 16-bit memory word represe
|
||||
#define UNIT_EIS (1u << UNIT_EIS_SHIFT) /* the Extended Instruction Set is installed */
|
||||
#define UNIT_CALTIME (1u << UNIT_CALTIME_SHIFT) /* the process clock is calibrated to wall time */
|
||||
#define UNIT_PFARS (1u << UNIT_PFARS_SHIFT) /* the system will auto-restart after a power failure */
|
||||
#define UNIT_CIS (1u << UNIT_CIS_SHIFT) /* the COBOL II Extended Instruction Set is installed */
|
||||
|
||||
#define UNIT_CPU_MODEL (cpu_unit [0].flags & UNIT_MODEL)
|
||||
|
||||
@ -100,11 +89,12 @@ typedef uint16 MEMORY_WORD; /* HP 16-bit memory word represe
|
||||
|
||||
/* CPU debug flags */
|
||||
|
||||
#define DEB_MDATA (1u << 0) /* trace memory data accesses */
|
||||
#define DEB_INSTR (1u << 1) /* trace instruction execution */
|
||||
#define DEB_FETCH (1u << 2) /* trace instruction fetches */
|
||||
#define DEB_REG (1u << 3) /* trace register values */
|
||||
#define DEB_PSERV (1u << 4) /* trace PCLK service events */
|
||||
#define DEB_ALL ~0u /* trace everything */
|
||||
|
||||
#define DEB_INSTR (1u << 0) /* trace instructions */
|
||||
#define DEB_REG (1u << 1) /* trace register values */
|
||||
#define DEB_PSERV (1u << 2) /* trace PCLK service events */
|
||||
#define DEB_EXEC (1u << 3) /* trace matched instruction executions */
|
||||
|
||||
#define BOV_FORMAT "%02o.%06o %06o " /* bank-offset-value trace format string */
|
||||
|
||||
@ -118,6 +108,13 @@ typedef uint16 MEMORY_WORD; /* HP 16-bit memory word represe
|
||||
#define SS_BYPASSED (1u << 31) /* stops are bypassed for this instruction */
|
||||
|
||||
|
||||
/* Memory access macros */
|
||||
|
||||
#define cpu_read_memory(c,o,v) mem_read (&cpu_dev, c, o, v)
|
||||
#define cpu_write_memory(c,o,v) mem_write (&cpu_dev, c, o, v)
|
||||
|
||||
|
||||
|
||||
/* System power state.
|
||||
|
||||
The HP 3000 power supply uses two signals to indicate its state: PON (power
|
||||
@ -157,38 +154,6 @@ typedef enum {
|
||||
} EXEC_STATE;
|
||||
|
||||
|
||||
/* Memory access classifications.
|
||||
|
||||
The access classification determines which bank register is used with the
|
||||
supplied offset to access memory, and whether or not the access is bounds
|
||||
checked.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The "_iop" and "_sel" classifications are identical. The only difference
|
||||
is which device's trace flag is checked to print debugging information.
|
||||
All of the other classifications check the CPU's trace flags.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
absolute_iop, /* absolute bank, IOP request */
|
||||
dma_iop, /* DMA channel bank, IOP request */
|
||||
absolute_sel, /* absolute bank, selector channel request */
|
||||
dma_sel, /* DMA channel bank, selector channel request */
|
||||
absolute, /* absolute bank */
|
||||
absolute_checked, /* absolute bank, bounds checked */
|
||||
fetch, /* program bank, instruction fetch */
|
||||
fetch_checked, /* program bank, instruction fetch, bounds checked */
|
||||
program, /* program bank, data access */
|
||||
program_checked, /* program bank, data access, bounds checked */
|
||||
data, /* data bank, data access */
|
||||
data_checked, /* data bank, data access, bounds checked */
|
||||
stack, /* stack bank, data access */
|
||||
stack_checked /* stack bank, data access, bounds checked */
|
||||
} ACCESS_CLASS;
|
||||
|
||||
|
||||
/* CPX register flags.
|
||||
|
||||
The CPX1 register contains flags that designate the run-time interrupts. The
|
||||
@ -435,9 +400,9 @@ typedef enum {
|
||||
|
||||
Condition Code:
|
||||
|
||||
00 = CCL (less than)
|
||||
01 = CCE (equal to)
|
||||
10 = CCG (greater than)
|
||||
00 = CCG (greater than)
|
||||
01 = CCL (less than)
|
||||
10 = CCE (equal to)
|
||||
11 = invalid
|
||||
*/
|
||||
|
||||
@ -451,13 +416,18 @@ typedef enum {
|
||||
#define STATUS_CCG 0000000u /* condition code greater than */
|
||||
#define STATUS_CCL 0000400u /* condition code less than */
|
||||
#define STATUS_CCE 0001000u /* condition code equal to */
|
||||
#define STATUS_CCI 0001400u /* condition code invalid */
|
||||
|
||||
#define STATUS_CC_MASK 0001400u /* condition code mask */
|
||||
#define STATUS_CC_SHIFT 8 /* condition code alignment */
|
||||
|
||||
#define STATUS_CS_MASK 0000377u /* code segment mask */
|
||||
#define STATUS_CS_SHIFT 0 /* code segment alignment */
|
||||
#define STATUS_CS_WIDTH 8 /* code segment mask width */
|
||||
|
||||
#define STATUS_CS(s) (((s) & STATUS_CS_MASK) >> STATUS_CS_SHIFT)
|
||||
|
||||
|
||||
#define STATUS_OVTRAP (STATUS_T | STATUS_O)
|
||||
#define STATUS_NPRV (STATUS_T | STATUS_O | STATUS_C | STATUS_CC_MASK)
|
||||
|
||||
@ -822,7 +792,7 @@ typedef enum {
|
||||
#define FMEXSUBOP(v) BITS_12_15(v) /* firmware extension suboperation accessor */
|
||||
|
||||
|
||||
/* Specific instruction accessors */
|
||||
/* General instruction accessors */
|
||||
|
||||
#define IOOP_K_MASK 0000017u /* I/O K-field mask */
|
||||
#define IOOP_K_SHIFT 0000000u /* I/O K-field alignment shift */
|
||||
@ -876,18 +846,8 @@ typedef enum {
|
||||
#define SDEC2(v) (((v) & SDEC2_MASK) >> SDEC_SHIFT)
|
||||
#define SDEC3(v) (((v) & SDEC3_MASK) >> SDEC_SHIFT)
|
||||
|
||||
#define DB_FLAG 0000020u /* PB/DB base flag */
|
||||
|
||||
#define MVBW_CCF 0000030u /* MVBW condition code flags */
|
||||
#define MVBW_N_FLAG 0000020u /* MVBW numeric flag */
|
||||
#define MVBW_A_FLAG 0000010u /* MVBW alphabetic flag */
|
||||
#define MVBW_S_FLAG 0000004u /* MVBW upshift flag */
|
||||
#define MVBW_CCF_SHIFT 6 /* CCF alignment in MVBW instruction */
|
||||
|
||||
#define NABS_FLAG 0000100u /* CVDA negative absolute value flag */
|
||||
#define ABS_FLAG 0000040u /* CVDA absolute value flag */
|
||||
|
||||
#define EIS_SDEC_SHIFT 4 /* EIS S-decrement alignment shift */
|
||||
#define DB_FLAG 0000020u /* base set PB/DB base register flag */
|
||||
#define CIS_DB_FLAG 0000001u /* CIS set PB/DB base register flag */
|
||||
|
||||
|
||||
/* Explicit instruction opcodes and accessors */
|
||||
@ -896,6 +856,8 @@ typedef enum {
|
||||
#define QASR 0015700u /* quadruple arithmetic right shift */
|
||||
#define DMUL 0020570u /* double integer multiply */
|
||||
#define DDIV 0020571u /* double integer divide */
|
||||
#define SETR 0027400u /* set registers (none) */
|
||||
#define SETR_X 0027404u /* set registers (index) */
|
||||
#define SED_1 0030041u /* set enable interrupt */
|
||||
#define HALT_10 0030370u /* halt 10 */
|
||||
|
||||
@ -932,6 +894,26 @@ typedef enum {
|
||||
#define CMD_TO(v) (((v) & CMD_TO_MASK) >> CMD_TO_SHIFT)
|
||||
#define CMD_MOP(v) (((v) & CMD_MOP_MASK) >> CMD_MOP_SHIFT)
|
||||
|
||||
#define MVBW_CCF 0000030u /* MVBW condition code flags */
|
||||
#define MVBW_N_FLAG 0000020u /* MVBW numeric flag */
|
||||
#define MVBW_A_FLAG 0000010u /* MVBW alphabetic flag */
|
||||
#define MVBW_S_FLAG 0000004u /* MVBW upshift flag */
|
||||
#define MVBW_CCF_SHIFT 6 /* CCF alignment in MVBW instruction */
|
||||
|
||||
#define NABS_FLAG 0000100u /* CVDA negative absolute value flag */
|
||||
#define ABS_FLAG 0000040u /* CVDA absolute value flag */
|
||||
|
||||
#define CVND_SC_MASK 0000016u /* CVND sign-control mask */
|
||||
#define CVND_SC_SHIFT 1 /* CVND sign-control field alignment shift */
|
||||
|
||||
#define EIS_SDEC_MASK 0000020u /* EIS S-decrement mask */
|
||||
#define EIS_SDEC_SHIFT 4 /* EIS S-decrement alignment shift */
|
||||
|
||||
#define CIS_SDEC_MASK 0000001u /* CIS S-decrement mask */
|
||||
#define CIS_SDEC_SHIFT 0 /* CIS S-decrement alignment shift */
|
||||
|
||||
#define TCCS_CCF_SHIFT 8 /* CIS TCCS instruction CCF alignment */
|
||||
|
||||
|
||||
/* PSHR/SETR instruction accessors */
|
||||
|
||||
@ -956,6 +938,16 @@ typedef enum {
|
||||
#define PCN_SERIES_III 2 /* CPU number for the Series III */
|
||||
|
||||
|
||||
/* EDIT instruction subprogram operation values */
|
||||
|
||||
#define EDIT_SUFS 013 /* highest opcode with an extended immediate operand */
|
||||
#define EDIT_EXOP 017 /* extended opcode prefix */
|
||||
|
||||
#define EDIT_TE (EDIT_EXOP + 000) /* first extended opcode with no operand */
|
||||
#define EDIT_MDWO (EDIT_EXOP + 004) /* last extended opcode with no operand */
|
||||
#define EDIT_DBNZ (EDIT_EXOP + 011) /* last extended opcode */
|
||||
|
||||
|
||||
/* Reserved memory addresses */
|
||||
|
||||
#define CSTB_POINTER 0000000u /* code segment table base pointer */
|
||||
@ -1006,6 +998,7 @@ typedef enum {
|
||||
#define LABEL_STTN_SHIFT 8 /* STT number alignment shift */
|
||||
#define LABEL_SEGMENT_SHIFT 0 /* segment number alignment shift */
|
||||
|
||||
#define LABEL_LOCAL 0000000u /* local program label flag */
|
||||
#define LABEL_UNCALLABLE 0040000u /* local program label uncallable flag */
|
||||
#define LABEL_ADDRESS_MASK 0037777u /* local program label address mask */
|
||||
|
||||
@ -1017,7 +1010,7 @@ typedef enum {
|
||||
#define LABEL_IRQ (LABEL_EXTERNAL | ISR_SEGMENT) /* label for interrupt requests */
|
||||
#define LABEL_STTN_MAX (LABEL_STTN_MASK >> LABEL_STTN_SHIFT) /* STT number maximum value */
|
||||
|
||||
#define TO_LABEL(s,n) ((s) | (n) << LABEL_STTN_SHIFT)
|
||||
#define TO_LABEL(s,n) ((s) | (n) << LABEL_STTN_SHIFT) /* s = segment number, n = STT number */
|
||||
|
||||
|
||||
/* Stack marker accessors */
|
||||
@ -1063,6 +1056,11 @@ extern HP_WORD CNTR; /* Microcode Counter */
|
||||
#define RD TR [3]
|
||||
|
||||
|
||||
/* CPU device */
|
||||
|
||||
extern DEVICE cpu_dev; /* Central Processing Unit */
|
||||
|
||||
|
||||
/* CPU state */
|
||||
|
||||
extern jmp_buf cpu_save_env; /* saved environment for microcode aborts */
|
||||
@ -1088,14 +1086,15 @@ extern void cpu_flush (void);
|
||||
extern void cpu_adjust_sr (uint32 target);
|
||||
extern void cpu_mark_stack (void);
|
||||
|
||||
extern void cpu_ea (HP_WORD mode_disp, ACCESS_CLASS *classification, HP_WORD *offset, BYTE_SELECTOR *selector);
|
||||
extern void cpu_ea (HP_WORD mode_disp, ACCESS_CLASS *class, HP_WORD *offset, BYTE_SELECTOR *selector);
|
||||
extern uint32 cpu_byte_ea (ACCESS_CLASS class, uint32 byte_offset, uint32 block_length);
|
||||
|
||||
extern void cpu_setup_irq_handler (IRQ_CLASS class, HP_WORD parameter);
|
||||
extern void cpu_setup_ics_irq (IRQ_CLASS class, TRAP_CLASS trap);
|
||||
extern void cpu_run_mode_interrupt (HP_WORD device_number);
|
||||
extern void cpu_setup_code_segment (HP_WORD label, HP_WORD* status, HP_WORD *entry_0);
|
||||
extern void cpu_setup_data_segment (HP_WORD segment_number, HP_WORD *bank, HP_WORD *address);
|
||||
extern void cpu_call_procedure (HP_WORD label);
|
||||
extern void cpu_call_procedure (HP_WORD label, HP_WORD offset);
|
||||
extern void cpu_exit_procedure (HP_WORD new_q, HP_WORD new_sm, HP_WORD parameter);
|
||||
extern void cpu_start_dispatcher (void);
|
||||
extern void cpu_update_pclk (void);
|
||||
@ -1103,7 +1102,8 @@ extern void cpu_update_pclk (void);
|
||||
|
||||
/* Global CPU instruction execution routines */
|
||||
|
||||
extern t_stat cpu_branch_short (t_bool check_loop);
|
||||
extern t_bool cpu_interrupt_pending (t_stat *status);
|
||||
extern t_stat cpu_branch_short (t_bool check_loop);
|
||||
|
||||
extern HP_WORD cpu_add_16 (HP_WORD augend, HP_WORD addend);
|
||||
extern HP_WORD cpu_sub_16 (HP_WORD minuend, HP_WORD subtrahend);
|
||||
@ -1113,3 +1113,4 @@ extern t_stat cpu_stack_op (void);
|
||||
extern t_stat cpu_shift_branch_bit_op (void);
|
||||
extern t_stat cpu_move_spec_fw_imm_field_reg_op (void);
|
||||
extern t_stat cpu_io_cntl_prog_imm_mem_op (void);
|
||||
extern t_stat cpu_cis_op (void);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* hp3000_cpu_base.c: HP 3000 CPU base set instruction simulator
|
||||
|
||||
Copyright (c) 2016, J. David Bryan
|
||||
Copyright (c) 2016-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -23,6 +23,15 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
08-Jan-17 JDB Fixed bug in SCAL 0/PCAL 0 if a stack overflow occurs
|
||||
07-Nov-16 JDB SETR doesn't set cpu_base_changed if no register change;
|
||||
renamed cpu_byte_to_word_ea to cpu_byte_ea
|
||||
03-Nov-16 JDB Added zero offsets to the cpu_call_procedure calls
|
||||
24-Oct-16 JDB Renamed SEXT macro to SEXT16
|
||||
22-Oct-16 JDB Changed "interrupt_pending" to global for use by CIS
|
||||
07-Oct-16 JDB Moved "extern cpu_dev" to hp3000_cpu.h where it belongs
|
||||
22-Sep-16 JDB Moved byte_to_word_address to hp3000_cpu.c
|
||||
21-Sep-16 JDB Added the COBOL II Extended Instruction Set dispatcher
|
||||
12-Sep-16 JDB Use the PCN_SERIES_II and PCN_SERIES_III constants
|
||||
23-Aug-16 JDB Implement the CMD instruction and module interrupts
|
||||
11-Jun-16 JDB Bit mask constants are now unsigned
|
||||
@ -69,14 +78,10 @@
|
||||
#include "hp3000_cpu.h"
|
||||
#include "hp3000_cpu_fp.h"
|
||||
#include "hp3000_cpu_ims.h"
|
||||
#include "hp3000_mem.h"
|
||||
|
||||
|
||||
|
||||
/* External I/O data structures */
|
||||
|
||||
extern DEVICE cpu_dev; /* Central Processing Unit */
|
||||
|
||||
|
||||
/* Program constants */
|
||||
|
||||
#define SIO_OK 0100000u /* TIO bit 0 = SIO OK */
|
||||
@ -114,9 +119,7 @@ static void shift_48_64 (HP_WORD opcode, SHIFT_TYPE shift, OPERAND_SI
|
||||
static void check_stack_bounds (HP_WORD new_value);
|
||||
static uint32 tcs_io (IO_COMMAND command);
|
||||
static uint32 srw_io (IO_COMMAND command, HP_WORD ready_flag);
|
||||
static t_bool interrupt_pending (t_stat *status);
|
||||
static void decrement_stack (uint32 decrement);
|
||||
static uint32 byte_to_word_address (ACCESS_CLASS class, uint32 byte_offset, uint32 block_length);
|
||||
|
||||
static t_stat move_words (ACCESS_CLASS source_class, uint32 source_base,
|
||||
ACCESS_CLASS dest_class, uint32 dest_base,
|
||||
@ -133,6 +136,80 @@ static t_stat io_control (void);
|
||||
/* CPU base set global utility routines */
|
||||
|
||||
|
||||
/* Test for a pending interrupt.
|
||||
|
||||
This routine is called from within an executor for an interruptible
|
||||
instruction to test for a pending interrupt. It counts an event tick and
|
||||
returns TRUE if the instruction should yield, either for an interrupt or for
|
||||
an event error, or FALSE if the instruction should continue.
|
||||
|
||||
Instructions that potentially take a long time (e.g., MOVE, SCU, LLSH) test
|
||||
for pending interrupts after each word or byte moved or scanned. The design
|
||||
of these instructions is such that an interrupt may be serviced and the
|
||||
instruction resumed without disruption. For example, the MOVE instruction
|
||||
updates the source and target addresses and word count on the stack after
|
||||
each word moved. If the instruction is interrupted, the values on the stack
|
||||
indicate where to resume after the interrupt handler completes.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The routine is essentially the same sequence as is performed at the top
|
||||
of the instruction execution loop in the "sim_instr" routine. The
|
||||
differences are that this routine backs up P to rerun the instruction
|
||||
after the interrupt is serviced, and the interrupt holdoff test necessary
|
||||
for the SED instruction isn't done here, as this routine is not called by
|
||||
the SED executor.
|
||||
|
||||
2. The event interval decrement that occurs in the main instruction loop
|
||||
after each instruction execution is cancelled here if "sim_process_event"
|
||||
returns an error code. This is done so that a STEP command does not
|
||||
decrement sim_interval twice. Note that skipping the initial decrement
|
||||
here does not help, as it's the sim_interval value AFTER the call to
|
||||
sim_process_event that must be preserved.
|
||||
*/
|
||||
|
||||
t_bool cpu_interrupt_pending (t_stat *status)
|
||||
{
|
||||
uint32 device_number = 0;
|
||||
|
||||
sim_interval = sim_interval - 1; /* count the cycle */
|
||||
|
||||
if (sim_interval <= 0) { /* if an event timeout expired */
|
||||
*status = sim_process_event (); /* then process the event service */
|
||||
|
||||
if (*status != SCPE_OK) { /* if the service failed */
|
||||
P = P - 1 & R_MASK; /* then back up to reenter the instruction */
|
||||
sim_interval = sim_interval + 1; /* and cancel the instruction loop increment */
|
||||
|
||||
return TRUE; /* abort the instruction and stop the simulator */
|
||||
}
|
||||
}
|
||||
|
||||
else /* otherwise */
|
||||
*status = SCPE_OK; /* indicate good status from the service */
|
||||
|
||||
if (sel_request) /* if a selector channel request is pending */
|
||||
sel_service (1); /* then service it */
|
||||
|
||||
if (mpx_request_set) /* if a multiplexer channel request is pending */
|
||||
mpx_service (1); /* then service it */
|
||||
|
||||
if (iop_interrupt_request_set && STA & STATUS_I) /* if a hardware interrupt request is pending and enabled */
|
||||
device_number = iop_poll (); /* then poll to acknowledge the request */
|
||||
|
||||
if (CPX1 & CPX1_IRQ_SET) { /* if an interrupt is pending */
|
||||
P = P - 1 & R_MASK; /* then back up to reenter the instruction */
|
||||
cpu_run_mode_interrupt (device_number); /* and set up the service routine */
|
||||
|
||||
return TRUE; /* abort the instruction */
|
||||
}
|
||||
|
||||
else /* otherwise */
|
||||
return FALSE; /* continue with the current instruction */
|
||||
}
|
||||
|
||||
|
||||
/* Execute a short branch.
|
||||
|
||||
The program counter is adjusted by the displacement specified in the CIR, and
|
||||
@ -259,7 +336,7 @@ HP_WORD cpu_mpy_16 (HP_WORD multiplicand, HP_WORD multiplier)
|
||||
int32 product;
|
||||
uint32 check;
|
||||
|
||||
product = SEXT (multiplicand) * SEXT (multiplier); /* sign-extend the operands and multiply */
|
||||
product = SEXT16 (multiplicand) * SEXT16 (multiplier); /* sign-extend the operands and multiply */
|
||||
|
||||
check = (uint32) product & S16_OVFL_MASK; /* check the top 17 bits and set overflow */
|
||||
SET_OVERFLOW (check != 0 && check != S16_OVFL_MASK); /* if they are not all zeros or all ones */
|
||||
@ -458,7 +535,7 @@ switch (operation) { /* dispatch the stack op
|
||||
|
||||
|
||||
case 013: /* MPYL (CCA, C, O; STUN, ARITH) */
|
||||
product = SEXT (RA) * SEXT (RB); /* sign-extend the 16-bit operands and multiply */
|
||||
product = SEXT16 (RA) * SEXT16 (RB); /* sign-extend the 16-bit operands and multiply */
|
||||
|
||||
RB = UPPER_WORD (product); /* split the MSW */
|
||||
RA = LOWER_WORD (product); /* and the LSW of the product */
|
||||
@ -474,7 +551,7 @@ switch (operation) { /* dispatch the stack op
|
||||
|
||||
case 014: /* DIVL (CCA, O; STUN, ARITH) */
|
||||
dividend = INT32 (TO_DWORD (RC, RB)); /* convert the 32-bit dividend to a signed value */
|
||||
divisor = SEXT (RA); /* and sign-extend the 16-bit divisor */
|
||||
divisor = SEXT16 (RA); /* and sign-extend the 16-bit divisor */
|
||||
|
||||
RB = RA; /* delete the LSW from the stack now */
|
||||
cpu_pop (); /* to conform with the microcode */
|
||||
@ -482,7 +559,7 @@ switch (operation) { /* dispatch the stack op
|
||||
if (RA == 0) /* if dividing by zero */
|
||||
MICRO_ABORT (trap_Integer_Zero_Divide); /* then trap or set the overflow flag */
|
||||
|
||||
if (abs (divisor) <= abs (SEXT (RB))) /* if the divisor is <= the MSW of the dividend */
|
||||
if (abs (divisor) <= abs (SEXT16 (RB))) /* if the divisor is <= the MSW of the dividend */
|
||||
SET_OVERFLOW (TRUE); /* an overflow will occur on the division */
|
||||
|
||||
else { /* otherwise, the divisor might be large enough */
|
||||
@ -558,8 +635,8 @@ switch (operation) { /* dispatch the stack op
|
||||
if (RA == 0) /* if dividing by zero */
|
||||
MICRO_ABORT (trap_Integer_Zero_Divide); /* then trap or set the overflow flag */
|
||||
|
||||
dividend = SEXT (RB); /* sign-extend the 16-bit dividend */
|
||||
divisor = SEXT (RA); /* and the 16-bit divisor */
|
||||
dividend = SEXT16 (RB); /* sign-extend the 16-bit dividend */
|
||||
divisor = SEXT16 (RA); /* and the 16-bit divisor */
|
||||
|
||||
quotient = dividend / divisor; /* form the 32-bit signed quotient */
|
||||
remainder = dividend % divisor; /* and 32-bit signed remainder */
|
||||
@ -1142,10 +1219,10 @@ switch (operation) { /* dispatch the shift/br
|
||||
|
||||
|
||||
case 026: /* CPRB (CCE, CCL, CCG; STUN, BNDV) */
|
||||
if (SEXT (X) < SEXT (RB)) /* if X is less than the lower bound */
|
||||
if (SEXT16 (X) < SEXT16 (RB)) /* if X is less than the lower bound */
|
||||
SET_CCL; /* then set CCL and continue */
|
||||
|
||||
else if (SEXT (X) > SEXT (RA)) /* otherwise if X is greater than the upper bound */
|
||||
else if (SEXT16 (X) > SEXT16 (RA)) /* otherwise if X is greater than the upper bound */
|
||||
SET_CCG; /* then set CCG and continue */
|
||||
|
||||
else { /* otherwise lower bound <= X <= upper bound */
|
||||
@ -1349,7 +1426,7 @@ switch (operation) { /* dispatch the operatio
|
||||
if (divisor == 0) /* if dividing by zero */
|
||||
MICRO_ABORT (trap_Integer_Zero_Divide); /* then trap or set the overflow flag */
|
||||
|
||||
RA = SEXT (RA) / divisor & R_MASK; /* store the quotient (which cannot overflow) on the TOS */
|
||||
RA = SEXT16 (RA) / divisor & R_MASK; /* store the quotient (which cannot overflow) on the TOS */
|
||||
SET_CCA (RA, 0); /* and set the condition code */
|
||||
break;
|
||||
|
||||
@ -1549,7 +1626,7 @@ switch (operation) { /* dispatch the operatio
|
||||
if (CIR & PSR_SBANK) /* if SBANK is to be set */
|
||||
SBANK = new_sbank & BA_MASK; /* then update the new value now */
|
||||
|
||||
cpu_base_changed = TRUE; /* this instruction changed the base registers */
|
||||
cpu_base_changed = (CIR != SETR && CIR != SETR_X); /* set the flag if the base registers changed */
|
||||
break;
|
||||
} /* all cases are handled */
|
||||
|
||||
@ -1656,8 +1733,14 @@ switch (operation) { /* dispatch the operatio
|
||||
|
||||
cpu_flush (); /* flush the TOS registers to memory */
|
||||
|
||||
if (SM > Z) /* if the stack limit was exceeded */
|
||||
MICRO_ABORT (trap_Stack_Overflow); /* then trap for a stack overflow */
|
||||
if (SM > Z) { /* if the stack limit was exceeded */
|
||||
if (field == 0) { /* then if the label was on the TOS */
|
||||
cpu_push (); /* then push the stack down */
|
||||
RA = label; /* and restore the label to the TOS */
|
||||
}
|
||||
|
||||
MICRO_ABORT (trap_Stack_Overflow); /* trap for a stack overflow */
|
||||
}
|
||||
|
||||
if (label & LABEL_EXTERNAL) /* if the label is non-local */
|
||||
MICRO_ABORTP (trap_STT_Violation, STA); /* then trap for an STT violation */
|
||||
@ -1685,12 +1768,18 @@ switch (operation) { /* dispatch the operatio
|
||||
|
||||
cpu_flush (); /* flush the TOS registers to memory */
|
||||
|
||||
if (SM > Z) /* if the stack limit was exceeded */
|
||||
MICRO_ABORT (trap_Stack_Overflow); /* then trap for a stack overflow */
|
||||
if (SM > Z) { /* if the stack limit was exceeded */
|
||||
if (field == 0) { /* then if the label was on the TOS */
|
||||
cpu_push (); /* then push the stack down */
|
||||
RA = label; /* and restore the label to the TOS */
|
||||
}
|
||||
|
||||
MICRO_ABORT (trap_Stack_Overflow); /* trap for a stack overflow */
|
||||
}
|
||||
|
||||
cpu_mark_stack (); /* write a stack marker */
|
||||
|
||||
cpu_call_procedure (label); /* set up PB, P, PL, and STA to call the procedure */
|
||||
cpu_call_procedure (label, 0); /* set up PB, P, PL, and STA to call the procedure */
|
||||
break;
|
||||
|
||||
|
||||
@ -1702,7 +1791,7 @@ switch (operation) { /* dispatch the operatio
|
||||
|
||||
new_sm = Q - 4 - field & R_MASK; /* compute the new stack pointer value */
|
||||
|
||||
cpu_read_memory (stack_checked, Q, &operand); /* read the delta Q value from the stack marker */
|
||||
cpu_read_memory (stack, Q, &operand); /* read the delta Q value from the stack marker */
|
||||
new_q = Q - operand & R_MASK; /* and determine the new Q value */
|
||||
|
||||
cpu_exit_procedure (new_q, new_sm, field); /* set up the return code segment and stack */
|
||||
@ -1755,7 +1844,7 @@ switch (operation) { /* dispatch the operatio
|
||||
else /* otherwise */
|
||||
label = LABEL_EXTERNAL /* convert it to an external label */
|
||||
| (field << LABEL_STTN_SHIFT) /* by merging the STT number */
|
||||
| STA & STATUS_CS_MASK; /* with the currently executing segment number */
|
||||
| STATUS_CS (STA); /* with the currently executing segment number */
|
||||
|
||||
cpu_push (); /* push the stack down */
|
||||
RA = label; /* and store the label on the TOS */
|
||||
@ -2256,7 +2345,7 @@ if (NPRV) /* if the mode is not pr
|
||||
|
||||
address = SM + SR - IO_K (CIR) & LA_MASK; /* get the location of the device number */
|
||||
|
||||
cpu_read_memory (stack_checked, address, &device); /* read it from the stack */
|
||||
cpu_read_memory (stack, address, &device); /* read it from the stack or TOS registers */
|
||||
device = LOWER_BYTE (device); /* and use only the lower byte of the value */
|
||||
|
||||
result = iop_direct_io (device, command, /* send the I/O order to the device */
|
||||
@ -2341,80 +2430,6 @@ else { /* otherwise the device
|
||||
}
|
||||
|
||||
|
||||
/* Test for a pending interrupt.
|
||||
|
||||
This routine is called from within an executor for an interruptible
|
||||
instruction to test for a pending interrupt. It counts an event tick and
|
||||
returns TRUE if the instruction should yield, either for an interrupt or for
|
||||
an event error, or FALSE if the instruction should continue.
|
||||
|
||||
Instructions that potentially take a long time (e.g., MOVE, SCU, LLSH) test
|
||||
for pending interrupts after each word or byte moved or scanned. The design
|
||||
of these instructions is such that an interrupt may be serviced and the
|
||||
instruction resumed without disruption. For example, the MOVE instruction
|
||||
updates the source and target addresses and word count on the stack after
|
||||
each word moved. If the instruction is interrupted, the values on the stack
|
||||
indicate where to resume after the interrupt handler completes.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The routine is essentially the same sequence as is performed at the top
|
||||
of the instruction execution loop in the "sim_instr" routine. The
|
||||
differences are that this routine backs up P to rerun the instruction
|
||||
after the interrupt is serviced, and the interrupt holdoff test necessary
|
||||
for the SED instruction isn't done here, as this routine is not called by
|
||||
the SED executor.
|
||||
|
||||
2. The event interval decrement that occurs in the main instruction loop
|
||||
after each instruction execution is cancelled here if "sim_process_event"
|
||||
returns an error code. This is done so that a STEP command does not
|
||||
decrement sim_interval twice. Note that skipping the initial decrement
|
||||
here does not help, as it's the sim_interval value AFTER the call to
|
||||
sim_process_event that must be preserved.
|
||||
*/
|
||||
|
||||
static t_bool interrupt_pending (t_stat *status)
|
||||
{
|
||||
uint32 device_number = 0;
|
||||
|
||||
sim_interval = sim_interval - 1; /* count the cycle */
|
||||
|
||||
if (sim_interval <= 0) { /* if an event timeout expired */
|
||||
*status = sim_process_event (); /* then process the event service */
|
||||
|
||||
if (*status != SCPE_OK) { /* if the service failed */
|
||||
P = P - 1 & R_MASK; /* then back up to reenter the instruction */
|
||||
sim_interval = sim_interval + 1; /* and cancel the instruction loop increment */
|
||||
|
||||
return TRUE; /* abort the instruction and stop the simulator */
|
||||
}
|
||||
}
|
||||
|
||||
else /* otherwise */
|
||||
*status = SCPE_OK; /* indicate good status from the service */
|
||||
|
||||
if (sel_request) /* if a selector channel request is pending */
|
||||
sel_service (1); /* then service it */
|
||||
|
||||
if (mpx_request_set) /* if a multiplexer channel request is pending */
|
||||
mpx_service (1); /* then service it */
|
||||
|
||||
if (iop_interrupt_request_set && STA & STATUS_I) /* if a hardware interrupt request is pending and enabled */
|
||||
device_number = iop_poll (); /* then poll to acknowledge the request */
|
||||
|
||||
if (CPX1 & CPX1_IRQ_SET) { /* if an interrupt is pending */
|
||||
P = P - 1 & R_MASK; /* then back up to reenter the instruction */
|
||||
cpu_run_mode_interrupt (device_number); /* and set up the service routine */
|
||||
|
||||
return TRUE; /* abort the instruction */
|
||||
}
|
||||
|
||||
else /* otherwise */
|
||||
return FALSE; /* continue with the current instruction */
|
||||
}
|
||||
|
||||
|
||||
/* Decrement the stack pointer.
|
||||
|
||||
Pop values from the stack until the stack pointer has been decremented by the
|
||||
@ -2442,87 +2457,6 @@ return;
|
||||
}
|
||||
|
||||
|
||||
/* Convert a data- or program-relative byte address to a word address.
|
||||
|
||||
The supplied byte offset from DB or PB is converted to a memory address,
|
||||
bounds-checked, and then returned. If the supplied block length is not zero,
|
||||
the converted address is assumed to be the starting address of a block, and
|
||||
an ending address, based on the block length, is calculated and
|
||||
bounds-checked. If either address lies outside of the segment associated
|
||||
with the access class, a Bounds Violation trap occurs, unless a privileged
|
||||
data access is requested.
|
||||
|
||||
Byte offsets into data segments present problems, in that negative offsets
|
||||
are permitted (to access the DL-to-DB area), but there are not enough bits to
|
||||
represent all locations unambiguously in the potential -32K to +32K word
|
||||
offset range. Therefore, a byte offset with bit 0 = 1 can represent either a
|
||||
positive or negative word offset from DB, depending on the interpretation.
|
||||
The HP 3000 adopts the convention that if the address resulting from a
|
||||
positive-offset interpretation does not fall within the DL-to-S range, then
|
||||
32K is added to the address, effectively changing the interpretation from a
|
||||
positive to a negative offset. If this new address does not fall within the
|
||||
DL-to-S range, a Bounds Violation trap occurs if the mode is non-privileged.
|
||||
|
||||
The reinterpretation as a negative offset is performed only if the CPU is not
|
||||
in split-stack mode (where either DBANK is different from SBANK, or DB does
|
||||
not lie between DL and Z), as extra data segments do not permit negative-DB
|
||||
addressing. Reinterpretation is also not used for code segments, as negative
|
||||
offsets from PB are not permitted.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. This routine implements the DBBC microcode subroutine.
|
||||
*/
|
||||
|
||||
static uint32 byte_to_word_address (ACCESS_CLASS class, uint32 byte_offset, uint32 block_length)
|
||||
{
|
||||
uint32 starting_word, ending_word, increment;
|
||||
|
||||
if (block_length & D16_SIGN) /* if the block length is negative */
|
||||
increment = 0177777; /* then the memory increment is negative also */
|
||||
else /* otherwise */
|
||||
increment = 1; /* the increment is positive */
|
||||
|
||||
if (class == data) { /* if this is a data access */
|
||||
starting_word = DB + (byte_offset >> 1) & LA_MASK; /* then determine the starting word address */
|
||||
|
||||
if (DBANK == SBANK && DL <= DB && DB <= Z /* if not in split-stack mode */
|
||||
&& (starting_word < DL || starting_word > SM)) { /* and the word address is out of range */
|
||||
starting_word = starting_word ^ D16_SIGN; /* then add 32K and try again */
|
||||
|
||||
if (NPRV && (starting_word < DL || starting_word > SM)) /* if non-privileged and still out of range */
|
||||
MICRO_ABORT (trap_Bounds_Violation); /* then trap for a bounds violation */
|
||||
}
|
||||
|
||||
if (block_length != 0) { /* if a block length was supplied */
|
||||
ending_word = /* then determine the ending word address */
|
||||
starting_word + ((block_length - increment + (byte_offset & 1)) >> 1) & LA_MASK;
|
||||
|
||||
if (NPRV && (ending_word < DL || ending_word > SM)) /* if non-privileged and the address is out of range */
|
||||
MICRO_ABORT (trap_Bounds_Violation); /* then trap for a bounds violation */
|
||||
}
|
||||
}
|
||||
|
||||
else { /* otherwise this is a program address */
|
||||
starting_word = PB + (byte_offset >> 1) & LA_MASK; /* so determine the starting word address */
|
||||
|
||||
if (starting_word < PB || starting_word > PL) /* if the starting address is out of range */
|
||||
MICRO_ABORT (trap_Bounds_Violation); /* then trap for a bounds violation */
|
||||
|
||||
if (block_length != 0) { /* if a block length was supplied */
|
||||
ending_word = /* then determine the ending address */
|
||||
starting_word + ((block_length - increment + (byte_offset & 1)) >> 1) & LA_MASK;
|
||||
|
||||
if (ending_word < PB || ending_word > PL) /* if the ending address is out of range */
|
||||
MICRO_ABORT (trap_Bounds_Violation); /* then trap for a bounds violation */
|
||||
}
|
||||
}
|
||||
|
||||
return starting_word; /* return the starting word address */
|
||||
}
|
||||
|
||||
|
||||
/* Move a block of words in memory.
|
||||
|
||||
A block of words is moved from a source address to a destination address. If
|
||||
@ -2602,7 +2536,7 @@ while (RA != 0) { /* while there are words
|
||||
RB = RB + increment & R_MASK; /* and the source */
|
||||
*RX = *RX + increment & R_MASK; /* and destination offsets */
|
||||
|
||||
if (interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
if (cpu_interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
return status; /* then return with an interrupt set up or an error */
|
||||
}
|
||||
|
||||
@ -2629,6 +2563,11 @@ return SCPE_OK; /* and return the succ
|
||||
| 0 0 1 0 | 0 0 0 0 | special op | 0 0 | sp op | Special
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Byte move and compare instructions that specify byte counts (e.g., MVB, CMPB)
|
||||
bounds-check the starting and ending addresses to avoid checking each access
|
||||
separately. Instructions that do not (e.g., SCW, MVBW) must bounds-check
|
||||
each access, as the counts are indeterminate.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
@ -2788,13 +2727,17 @@ switch (operation) { /* dispatch the move or
|
||||
else /* otherwise */
|
||||
increment = 1; /* the increment is positive */
|
||||
|
||||
if (CIR & DB_FLAG) /* if the move is from the data segment */
|
||||
class = data; /* then classify as a data access */
|
||||
else /* otherwise the move is from the code segment */
|
||||
class = program; /* so classify as a program access */
|
||||
if (CIR & DB_FLAG) { /* if the move is from the data segment */
|
||||
class = data; /* then classify as a data access */
|
||||
source = cpu_byte_ea (data_checked, RB, RA); /* and convert and check the byte address */
|
||||
}
|
||||
|
||||
source = byte_to_word_address (class, RB, RA); /* convert the source byte address and check bounds */
|
||||
target = byte_to_word_address (data, RC, RA); /* convert the target byte address and check bounds */
|
||||
else { /* otherwise the move is from the code segment */
|
||||
class = program; /* so classify as a program access */
|
||||
source = cpu_byte_ea (program_checked, RB, RA); /* and convert and check the byte address */
|
||||
}
|
||||
|
||||
target = cpu_byte_ea (data_checked, RC, RA); /* convert the target byte address and check the bounds */
|
||||
|
||||
while (RA != 0) { /* while there are bytes to move */
|
||||
cpu_read_memory (class, source, &operand); /* read a source word */
|
||||
@ -2823,7 +2766,7 @@ switch (operation) { /* dispatch the move or
|
||||
RB = RB + increment & R_MASK; /* and the source */
|
||||
RC = RC + increment & R_MASK; /* and destination offsets */
|
||||
|
||||
if (interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
if (cpu_interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
return status; /* then return with an interrupt set up or an error */
|
||||
}
|
||||
}
|
||||
@ -2872,13 +2815,13 @@ switch (operation) { /* dispatch the move or
|
||||
test_byte = LOWER_BYTE (RA); /* get the test byte */
|
||||
terminal_byte = UPPER_BYTE (RA); /* and the terminal byte */
|
||||
|
||||
source = byte_to_word_address (data, RB, 0); /* convert the source byte address and check the bounds */
|
||||
source = cpu_byte_ea (data_checked, RB, 0); /* convert the source byte address and check the bounds */
|
||||
|
||||
cpu_read_memory (data, source, &operand); /* read the first word */
|
||||
|
||||
while (TRUE) {
|
||||
if (RB & 1) { /* if the byte address is odd */
|
||||
if (interrupt_pending (&status)) /* then if an interrupt is pending */
|
||||
if (cpu_interrupt_pending (&status)) /* then if an interrupt is pending */
|
||||
return status; /* then return with an interrupt set up or an error */
|
||||
|
||||
byte = LOWER_BYTE (operand); /* get the lower byte */
|
||||
@ -3000,8 +2943,8 @@ switch (operation) { /* dispatch the move or
|
||||
while (SR > 2) /* if more than two TOS registers are valid */
|
||||
cpu_queue_down (); /* then queue them down until exactly two are left */
|
||||
|
||||
source = byte_to_word_address (data, RA, 0); /* convert the source */
|
||||
target = byte_to_word_address (data, RB, 0); /* and target byte addresses and check the bounds */
|
||||
source = cpu_byte_ea (data_checked, RA, 0); /* convert the source and target */
|
||||
target = cpu_byte_ea (data_checked, RB, 0); /* byte addresses and check the starting bounds */
|
||||
|
||||
if (source > target) { /* if the source is closer to SM than the target */
|
||||
byte_count = (int32) (SM - source + 1) * 2; /* then set the byte count from the source */
|
||||
@ -3057,7 +3000,7 @@ switch (operation) { /* dispatch the move or
|
||||
RA = RA + 1 & R_MASK; /* and the source */
|
||||
RB = RB + 1 & R_MASK; /* and destination offsets */
|
||||
|
||||
if (interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
if (cpu_interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
return status; /* then return with an interrupt set up or an error */
|
||||
}
|
||||
|
||||
@ -3080,13 +3023,17 @@ switch (operation) { /* dispatch the move or
|
||||
else /* otherwise */
|
||||
increment = 1; /* the increment is positive */
|
||||
|
||||
if (CIR & DB_FLAG) /* if the move is from the data segment */
|
||||
class = data; /* then classify as a data access */
|
||||
else /* otherwise the move is from the code segment */
|
||||
class = program; /* so classify as a program access */
|
||||
if (CIR & DB_FLAG) { /* if the comparison is from the data segment */
|
||||
class = data; /* then classify as a data access */
|
||||
source = cpu_byte_ea (data_checked, RB, RA); /* and convert and check the byte address */
|
||||
}
|
||||
|
||||
source = byte_to_word_address (class, RB, RA); /* convert the source byte address and check bounds */
|
||||
target = byte_to_word_address (data, RC, RA); /* convert the target byte address and check bounds */
|
||||
else { /* otherwise the comparison is from the code segment */
|
||||
class = program; /* so classify as a program access */
|
||||
source = cpu_byte_ea (program_checked, RB, RA); /* and convert and check the byte address */
|
||||
}
|
||||
|
||||
target = cpu_byte_ea (data_checked, RC, RA); /* convert the target byte address and check the bounds */
|
||||
|
||||
while (RA != 0) { /* while there are bytes to compare */
|
||||
cpu_read_memory (class, source, &operand); /* read a source word */
|
||||
@ -3116,7 +3063,7 @@ switch (operation) { /* dispatch the move or
|
||||
RB = RB + increment & R_MASK; /* and the source */
|
||||
RC = RC + increment & R_MASK; /* and destination offsets */
|
||||
|
||||
if (interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
if (cpu_interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
return status; /* then return with an interrupt set up or an error */
|
||||
}
|
||||
}
|
||||
@ -3160,7 +3107,7 @@ switch (operation) { /* dispatch the move or
|
||||
|
||||
X = X - 1 & R_MASK; /* decrement the count */
|
||||
|
||||
if (interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
if (cpu_interrupt_pending (&status)) /* if an interrupt is pending */
|
||||
return status; /* then return with an interrupt set up or an error */
|
||||
}
|
||||
|
||||
@ -3182,14 +3129,14 @@ switch (operation) { /* dispatch the move or
|
||||
if (PRIV) /* if the mode is privileged */
|
||||
if (CIR & 1) { /* PSTA (none; STUN, MODE) */
|
||||
PREADJUST_SR (1); /* ensure a valid TOS register */
|
||||
cpu_write_memory (absolute_checked, /* before writing the TOS to memory */
|
||||
cpu_write_memory (absolute_mapped, /* before writing the TOS to memory */
|
||||
X, RA); /* at address X */
|
||||
cpu_pop (); /* and popping the stack */
|
||||
}
|
||||
|
||||
else { /* PLDA (CCA; STOV, MODE) */
|
||||
cpu_read_memory (absolute_checked, /* read the value at address X */
|
||||
X, &operand);
|
||||
cpu_read_memory (absolute_mapped, /* read the value at address X */
|
||||
X, &operand);
|
||||
cpu_push (); /* push the stack down */
|
||||
RA = operand; /* and store the value on the TOS */
|
||||
|
||||
@ -3213,7 +3160,7 @@ switch (operation) { /* dispatch the move or
|
||||
cpu_queue_down (); /* then queue them down until exactly two are left */
|
||||
|
||||
address = TO_PA (RB, RA); /* form the physical address */
|
||||
cpu_read_memory (absolute_checked, /* and read the word from memory */
|
||||
cpu_read_memory (absolute, /* and read the word from memory */
|
||||
address, &operand);
|
||||
|
||||
cpu_push (); /* push the stack down */
|
||||
@ -3230,7 +3177,7 @@ switch (operation) { /* dispatch the move or
|
||||
cpu_queue_down (); /* then queue them down until exactly three are left */
|
||||
|
||||
address = TO_PA (RC, RB); /* form the physical address */
|
||||
cpu_write_memory (absolute_checked, /* and write the word on the TOS to memory */
|
||||
cpu_write_memory (absolute, /* and write the word on the TOS to memory */
|
||||
address, RA);
|
||||
|
||||
cpu_pop (); /* pop the TOS */
|
||||
@ -3242,15 +3189,14 @@ switch (operation) { /* dispatch the move or
|
||||
cpu_queue_down (); /* then queue them down until exactly two are left */
|
||||
|
||||
address = TO_PA (RB, RA); /* form the physical address */
|
||||
cpu_read_memory (absolute_checked, /* and read the MSW from memory */
|
||||
cpu_read_memory (absolute, /* and read the MSW from memory */
|
||||
address, &operand);
|
||||
|
||||
cpu_push (); /* push the stack down */
|
||||
RA = operand; /* and store the MSW on the TOS */
|
||||
|
||||
address = TO_PA (RC, RB + 1 & LA_MASK); /* increment the physical address */
|
||||
|
||||
cpu_read_memory (absolute_checked, /* read the LSW from memory */
|
||||
cpu_read_memory (absolute, /* and read the LSW from memory */
|
||||
address, &operand);
|
||||
|
||||
cpu_push (); /* push the stack down again */
|
||||
@ -3264,12 +3210,11 @@ switch (operation) { /* dispatch the move or
|
||||
PREADJUST_SR (4); /* ensure there are four valid TOS registers */
|
||||
|
||||
address = TO_PA (RD, RC); /* form the physical address */
|
||||
cpu_write_memory (absolute_checked, /* write the MSW from the NOS to memory */
|
||||
cpu_write_memory (absolute, /* write the MSW from the NOS to memory */
|
||||
address, RB);
|
||||
|
||||
address = TO_PA (RD, RC + 1 & LA_MASK); /* increment the physical address */
|
||||
|
||||
cpu_write_memory (absolute_checked, /* write the LSW on the TOS to memory */
|
||||
cpu_write_memory (absolute, /* and write the LSW on the TOS to memory */
|
||||
address, RA);
|
||||
|
||||
cpu_pop (); /* pop the TOS */
|
||||
@ -3302,7 +3247,7 @@ switch (operation) { /* dispatch the move or
|
||||
new_q = 0; /* but the compiler doesn't realize this and so warns */
|
||||
|
||||
if (!disp_active) { /* if not called by the dispatcher to start a process */
|
||||
if ((STA & STATUS_CS_MASK) > 1) { /* then if an external interrupt was serviced */
|
||||
if (STATUS_CS (STA) > 1) { /* then if an external interrupt was serviced */
|
||||
cpu_read_memory (stack, /* then get the device number (parameter) */
|
||||
Q + 3 & LA_MASK,
|
||||
&device);
|
||||
@ -3465,11 +3410,15 @@ return status; /* return the execution
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| 0 0 1 0 | 0 0 0 1 | 0 1 1 1 1 0 0 | x | DMUL/DDIV
|
||||
| 0 0 1 0 | 0 0 0 1 | 0 1 1 1 | 1 0 0 | x | DMUL/DDIV
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| 0 0 1 0 | 0 0 0 1 | 0 0 0 0 1 | ext fp op | Extended FP
|
||||
| 0 0 1 0 | 0 0 0 1 | 0 0 0 0 | 1 | ext fp op | Extended FP
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| 0 0 1 0 | 0 0 0 1 | 0 0 1 1 | COBOL op | COBOL
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
@ -3491,19 +3440,16 @@ return status; /* return the execution
|
||||
W1 0000 020400-020417 Extended Instruction Set (Floating Point)
|
||||
W2 0001 020420-020437 32105A APL Instruction Set
|
||||
W3 0010 020440-020457
|
||||
W4 0011 020460-020477 32234A COBOL II Instruction Set
|
||||
W4 0011 020460-020477 32234A COBOL II Extended Instruction Set
|
||||
W5 0100 020500-020517
|
||||
W6 0101 020520-020537
|
||||
W7 0110 020540-020557
|
||||
-- 0111 020560-020577 Base Set (DMUL/DDIV)
|
||||
W8 1000 020600-020777 Extended Instruction Set (Decimal Arith)
|
||||
W8 1xxx 020600-020777 Extended Instruction Set (Decimal Arith)
|
||||
|
||||
The range occupied by the base set has no jumper and is hardwired as
|
||||
"present".
|
||||
|
||||
In simulation, presence is determined by the settings of the CPU unit flags.
|
||||
Currently, the only defined option flag is UNIT_EIS, although the EIS itself
|
||||
has not been implemented.
|
||||
"present". In simulation, presence is determined by the settings of the CPU
|
||||
unit flags.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
@ -3525,6 +3471,14 @@ operation = FIRMEXTOP (CIR); /* get the operation fro
|
||||
|
||||
switch (operation) { /* dispatch the operation */
|
||||
|
||||
case 003: /* COBOL II Extended Instruction Set */
|
||||
if (cpu_unit [0].flags & UNIT_CIS) /* if the firmware is installed */
|
||||
status = cpu_cis_op (); /* then call the CIS dispatcher */
|
||||
else /* otherwise */
|
||||
status = STOP_UNIMPL; /* the instruction range decodes as unimplemented */
|
||||
break;
|
||||
|
||||
|
||||
case 007: /* base set */
|
||||
suboperation = FMEXSUBOP (CIR); /* get the suboperation from the instruction */
|
||||
|
||||
@ -3915,11 +3869,11 @@ switch (operation) { /* dispatch the I/O or c
|
||||
case 006: /* XEQ (none; BNDV) */
|
||||
address = SM + SR - IO_K (CIR) & LA_MASK; /* get the address of the target instruction */
|
||||
|
||||
if (address >= DB || PRIV) { /* if the address is not below DB or the mode is privileged */
|
||||
cpu_read_memory (stack_checked, address, &NIR); /* the read the word at S - K into the NIR */
|
||||
if (address >= DB || PRIV) { /* if the address is not below DB or the mode is privileged */
|
||||
cpu_read_memory (stack, address, &NIR); /* then read the word at S - K into the NIR */
|
||||
|
||||
P = P - 1 & R_MASK; /* decrement P so the instruction after XEQ is next */
|
||||
sim_interval = sim_interval + 1; /* but don't count the XEQ against a STEP count */
|
||||
P = P - 1 & R_MASK; /* decrement P so the instruction after XEQ is next */
|
||||
sim_interval = sim_interval + 1; /* but don't count the XEQ against a STEP count */
|
||||
}
|
||||
|
||||
else /* otherwise the address is below DB and not privileged */
|
||||
@ -3975,8 +3929,8 @@ switch (operation) { /* dispatch the I/O or c
|
||||
if (NPRV) /* if the mode is not privileged */
|
||||
MICRO_ABORT (trap_Privilege_Violation); /* then abort with a privilege violation */
|
||||
|
||||
address = SM + SR - IO_K (CIR) & LA_MASK; /* get the location of the command word */
|
||||
cpu_read_memory (stack_checked, address, &command); /* and read it from the stack */
|
||||
address = SM + SR - IO_K (CIR) & LA_MASK; /* get the location of the command word */
|
||||
cpu_read_memory (stack, address, &command); /* and read it from the stack or TOS registers */
|
||||
|
||||
module = CMD_TO (command); /* get the addressed (TO) module number */
|
||||
|
||||
|
||||
1970
HP3000/hp3000_cpu_cis.c
Normal file
1970
HP3000/hp3000_cpu_cis.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
10-Oct-16 JDB Moved cpu_read_memory, cpu_write_memory to hp3000_cpu.h
|
||||
01-Sep-16 JDB Added the cpu_cold_cmd and cpu_power_cmd routines
|
||||
15-Aug-16 JDB Removed obsolete comment mentioning iop_read/write_memory
|
||||
15-Jul-16 JDB Corrected the IOCW_COUNT macro to return the correct value
|
||||
@ -146,16 +147,11 @@ typedef enum {
|
||||
|
||||
cpu_cold_cmd : process the LOAD and DUMP commands
|
||||
cpu_power_cmd : process the POWER commands
|
||||
cpu_read_memory : read a word from main memory
|
||||
cpu_write_memory : write a word to main memory
|
||||
*/
|
||||
|
||||
extern t_stat cpu_cold_cmd (int32 arg, CONST char *buf);
|
||||
extern t_stat cpu_power_cmd (int32 arg, CONST char *buf);
|
||||
|
||||
extern t_bool cpu_read_memory (ACCESS_CLASS classification, uint32 offset, HP_WORD *value);
|
||||
extern t_bool cpu_write_memory (ACCESS_CLASS classification, uint32 offset, HP_WORD value);
|
||||
|
||||
|
||||
/* Global SIO order structures.
|
||||
|
||||
|
||||
@ -23,6 +23,10 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
29_Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T
|
||||
20-Nov-16 JDB Added mapped memory access classes
|
||||
24-Oct-16 JDB Added half-byte definitions for CIS decoding
|
||||
10-Oct-16 JDB Moved ACCESS_CLASS definition here from hp3000_cpu.h
|
||||
03-Sep-16 JDB Added the STOP_POWER and STOP_ARSINH codes
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
@ -107,10 +111,6 @@
|
||||
|
||||
|
||||
|
||||
#ifndef HP3000_DEFS_H_
|
||||
#define HP3000_DEFS_H_
|
||||
|
||||
|
||||
#include "sim_rev.h"
|
||||
#include "sim_defs.h"
|
||||
|
||||
@ -150,7 +150,7 @@
|
||||
#define REG_A (1u << REG_V_UF + 0) /* permit any display */
|
||||
#define REG_B (1u << REG_V_UF + 1) /* permit binary display */
|
||||
#define REG_M (1u << REG_V_UF + 2) /* default to instruction mnemonic display */
|
||||
#define REG_S (1u << REG_V_UF + 3) /* default to status mnemonic display */
|
||||
#define REG_T (1u << REG_V_UF + 3) /* default to status mnemonic display */
|
||||
|
||||
|
||||
/* Register macros.
|
||||
@ -264,21 +264,24 @@
|
||||
printf (__VA_ARGS__); \
|
||||
if (sim_log) \
|
||||
fprintf (sim_log, __VA_ARGS__); \
|
||||
} while (0)
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define cputs(str) \
|
||||
do { \
|
||||
fputs (str, stdout); \
|
||||
if (sim_log) \
|
||||
fputs (str, sim_log); \
|
||||
} while (0)
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define cputc(ch) \
|
||||
do { \
|
||||
putc (ch); \
|
||||
if (sim_log) \
|
||||
fputc (ch, sim_log); \
|
||||
} while (0)
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
/* Simulation stop codes.
|
||||
@ -396,6 +399,9 @@ typedef uint32 HP_WORD; /* HP 16-bit data word r
|
||||
|
||||
#define R_MASK 0177777u /* 16-bit register mask */
|
||||
|
||||
#define D4_WIDTH 4 /* 4-bit data bit width */
|
||||
#define D4_MASK 0017u /* 4-bit data mask */
|
||||
|
||||
#define D8_WIDTH 8 /* 8-bit data bit width */
|
||||
#define D8_MASK 0377u /* 8-bit data mask */
|
||||
#define D8_UMAX 0377u /* 8-bit unsigned maximum value */
|
||||
@ -481,6 +487,67 @@ typedef uint32 HP_WORD; /* HP 16-bit data word r
|
||||
#define TO_OFFSET(p) ((p) & LA_MASK)
|
||||
|
||||
|
||||
/* Memory access classifications.
|
||||
|
||||
The access classification determines which bank register is used with the
|
||||
supplied offset to access memory, whether or not the access is bounds
|
||||
checked, and whether or not the access is mapped to the TOS registers if the
|
||||
address is between SM and SM + SR.
|
||||
|
||||
Bounds checking is optionally performed on program (including instruction
|
||||
fetch), data, and stack accesses when not in privileged mode. Absolute
|
||||
addresses are always accessed in privileged mode, so bounds checking is never
|
||||
performed.
|
||||
|
||||
If the memory address lies between SM and SM + SR within the stack bank, then
|
||||
access to the TOS registers may be substituted for access to memory.
|
||||
Register mapping is always performed on stack accesses, optionally performed
|
||||
on absolute and data accesses, and is never performed on program (and fetch)
|
||||
accesses.
|
||||
|
||||
To summarize bounds checking and TOS register mapping:
|
||||
|
||||
Bounds TOS
|
||||
Access Check Mapping
|
||||
-------- ------ -------
|
||||
absolute N O
|
||||
fetch O N
|
||||
program O N
|
||||
data O O
|
||||
stack O Y
|
||||
dma N N
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The enumeration values must be ordered such that the "checked" classes
|
||||
are odd and differ from their corresponding "unchecked" classes only in
|
||||
the LSBs.
|
||||
|
||||
2. There is no hardware DMA bank register. The "dma" class exists only to
|
||||
differentiate DMA memory accesses from CPU memory accesses when tracing.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
absolute, /* absolute bank */
|
||||
absolute_mapped, /* absolute bank, TOS registers mapped */
|
||||
fetch, /* program bank, instruction fetch */
|
||||
fetch_checked, /* program bank, instruction fetch, bounds checked */
|
||||
program, /* program bank, data access */
|
||||
program_checked, /* program bank, data access, bounds checked */
|
||||
data, /* data bank, data access */
|
||||
data_checked, /* data bank, data access, bounds checked */
|
||||
data_mapped, /* data bank, data or TOS register access */
|
||||
data_mapped_checked, /* data bank, data or TOS register access, bounds checked */
|
||||
stack, /* stack bank, data or TOS register access */
|
||||
stack_checked, /* stack bank, data or TOS register access, bounds checked */
|
||||
dma /* DMA bank */
|
||||
} ACCESS_CLASS;
|
||||
|
||||
#define UNCHECKED(c) ((c) & ~1u) /* reclassify a request as unchecked */
|
||||
#define INVERT_CHECK(c) ((c) ^ 1u) /* convert checked to unchecked and vice versa */
|
||||
|
||||
|
||||
/* Portable conversions.
|
||||
|
||||
SIMH is written with the assumption that the defined-size types (e.g.,
|
||||
@ -495,11 +562,13 @@ typedef uint32 HP_WORD; /* HP 16-bit data word r
|
||||
|
||||
The conversions available are:
|
||||
|
||||
- SEXT -- int16 sign-extended to int32
|
||||
- NEG16 -- int16 negated
|
||||
- NEG32 -- int32 negated
|
||||
- INT16 -- uint16 to int16
|
||||
- INT32 -- uint32 to int32
|
||||
- SEXT8 -- int8 sign-extended to int32
|
||||
- SEXT16 -- int16 sign-extended to int32
|
||||
- NEG16 -- int8 negated
|
||||
- NEG16 -- int16 negated
|
||||
- NEG32 -- int32 negated
|
||||
- INT16 -- uint16 to int16
|
||||
- INT32 -- uint32 to int32
|
||||
|
||||
|
||||
Implementation notes:
|
||||
@ -508,8 +577,10 @@ typedef uint32 HP_WORD; /* HP 16-bit data word r
|
||||
before invoking.
|
||||
*/
|
||||
|
||||
#define SEXT(x) (int32) ((x) & D16_SIGN ? (x) | ~D16_MASK : (x))
|
||||
#define SEXT8(x) (int32) ((x) & D8_SIGN ? (x) | ~D8_MASK : (x))
|
||||
#define SEXT16(x) (int32) ((x) & D16_SIGN ? (x) | ~D16_MASK : (x))
|
||||
|
||||
#define NEG8(x) ((~(x) + 1) & D8_MASK)
|
||||
#define NEG16(x) ((~(x) + 1) & D16_MASK)
|
||||
#define NEG32(x) ((~(x) + 1) & D32_MASK)
|
||||
|
||||
@ -517,6 +588,12 @@ typedef uint32 HP_WORD; /* HP 16-bit data word r
|
||||
#define INT32(u) ((u) > D32_SMAX ? (-(int32) (D32_UMAX - (u)) - 1) : (int32) (u))
|
||||
|
||||
|
||||
/* Half-byte accessors */
|
||||
|
||||
#define UPPER_HALF(b) ((b) >> D4_WIDTH & D4_MASK)
|
||||
#define LOWER_HALF(b) ((b) & D4_MASK)
|
||||
|
||||
|
||||
/* Byte accessors.
|
||||
|
||||
These macros extract the upper and lower bytes from a word and form a word
|
||||
@ -614,8 +691,8 @@ extern const BITSET_FORMAT inbound_format; /* the inbound signal format str
|
||||
extern const BITSET_FORMAT outbound_format; /* the outbound signal format structure */
|
||||
|
||||
|
||||
/* System interface global SCP support routines previously declared in scp.h */
|
||||
/*
|
||||
/* System interface global SCP support routines declared in scp.h
|
||||
|
||||
extern t_stat sim_load (FILE *fptr, CONST char *cptr, CONST char *fnam, int flag);
|
||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
|
||||
extern t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw);
|
||||
@ -629,14 +706,12 @@ extern t_stat hp_show_dib (FILE *st, UNIT *uptr, int32 code, CONST void
|
||||
|
||||
/* System interface global utility routines */
|
||||
|
||||
extern t_bool hp_device_conflict (void);
|
||||
extern t_stat fprint_cpu (FILE *ofile, t_value *val, uint32 radix, int32 switches);
|
||||
extern t_stat fprint_cpu (FILE *ofile, t_value *val, uint32 radix, int32 switches);
|
||||
extern uint32 fprint_edit (FILE *ofile, t_value *val, uint32 radix, uint32 byte_address);
|
||||
|
||||
extern const char *fmt_status (uint32 status);
|
||||
extern const char *fmt_char (uint32 charval);
|
||||
extern const char *fmt_bitset (uint32 bitset, const BITSET_FORMAT bitfmt);
|
||||
|
||||
extern void hp_debug (DEVICE *dptr, uint32 flag, ...);
|
||||
|
||||
|
||||
#endif
|
||||
extern void hp_debug (DEVICE *dptr, uint32 flag, ...);
|
||||
extern t_bool hp_device_conflict (void);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
SIMH/HP 3000 DIAGNOSTICS PERFORMANCE
|
||||
====================================
|
||||
Last update: 2016-09-07
|
||||
Last update: 2016-12-01
|
||||
|
||||
|
||||
The HP 32230 diagnostic suite has been run against the SIMH HP 3000 simulation.
|
||||
@ -60,8 +60,8 @@ The results of the diagnostic runs are summarized below:
|
||||
PD435A Universal Interface 01.01 Passed
|
||||
PD438A Terminal Control Interface 01.00 Passed
|
||||
PD439A CALCOMP Plotter Interface 01.01 No simulation
|
||||
PD441A COBOL-II A Firmware 00.00 No simulation
|
||||
PD442A COBOL-II B Firmware 00.00 No simulation
|
||||
PD441A COBOL-II A Firmware 00.00 Passed
|
||||
PD442A COBOL-II B Firmware 00.00 Passed
|
||||
PD466A Online Line Printer Verifier 01.06 Passed
|
||||
|
||||
The "Result" column indicates the level of success in passing the given
|
||||
@ -1548,7 +1548,9 @@ CONFIGURATION: sim> set lp diagnostic,intmask=8
|
||||
sim> set clk realtime
|
||||
sim> go
|
||||
|
||||
TEST REPORT: D100 UNIV. INTERFACE TEST (HP D435A.01.01)
|
||||
TEST REPORT: [CR entered]
|
||||
|
||||
D100 UNIV. INTERFACE TEST (HP D435A.01.01)
|
||||
(C)COPYRIGHT HEWLETT PACKARD COMPANY 1976.
|
||||
****************** WARNING ******************
|
||||
this diagnostic has tests which will produce error
|
||||
@ -1852,6 +1854,239 @@ TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
D441A - COBOL-II A Firmware
|
||||
---------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> set cpu cis
|
||||
sim> go
|
||||
|
||||
TEST REPORT: [CTRL+E]
|
||||
|
||||
sim> deposit SWCH 100011
|
||||
sim> go
|
||||
|
||||
[CR entered]
|
||||
|
||||
COBOLIIA F/W DIAG. (D441A.00.00)
|
||||
|
||||
|
||||
TESTING MFL OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
MFL OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING MC'N OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
MCN OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING IC AND SUFT OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
IC OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
SUFT OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING MA'N OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
MA OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING ICS AND SST0 AND SST1 OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
ICS OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
SST0 OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
SST1 OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING ICI OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
ICI OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
BRIS OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
TESTING MN'N OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
MN OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING SFC AND ICSI OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
SFC OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
ICSI OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING MNS OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
MNS OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING DBNZ AND SETC OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
DBNZ OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
SETC OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING MDWO AND SUFS OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
MDWO OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
SUFS OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING ICP OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
ICP OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING ICPS OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
ICPS OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING "IS" OF EDIT
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
"IS" OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
|
||||
TESTING "ENDF" OF EDIT
|
||||
|
||||
TESTING "SFLC" OF EDIT
|
||||
|
||||
TESTING "DFLC" OF EDIT
|
||||
|
||||
PB'DB'MODE= 0
|
||||
PB'DB'MODE= 1
|
||||
"ENDF" OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
"SFLC" OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
"DFLC" OF EDIT PASSED ALL TESTS WITHOUT ERROR
|
||||
********************************************************************************
|
||||
END OF PASS 0
|
||||
|
||||
Programmed halt, CIR: 030375 (HALT 15), P: 010330 (RSW)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
---------------------------
|
||||
D442A - COBOL-II B Firmware
|
||||
---------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> set cpu cis
|
||||
sim> go
|
||||
|
||||
TEST REPORT: [CTRL+E]
|
||||
|
||||
sim> deposit SWCH 100011
|
||||
sim> go
|
||||
|
||||
[CR entered]
|
||||
|
||||
COBOLIIB FIRMWARE DIAGNOSTIC (D442A.00.00)
|
||||
|
||||
|
||||
TESTING ABSD
|
||||
ABSD PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
TESTING ABSN
|
||||
ABSN PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
TESTING XBR
|
||||
|
||||
XBR PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
TESTING NEGD
|
||||
SDEC= 0
|
||||
|
||||
SDEC= 1
|
||||
|
||||
NEGD PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
TESTING PARC AND ENDP
|
||||
|
||||
I AM IN OUTER'BLOCK OF PARC
|
||||
I AM IN PAR6
|
||||
I AM IN OUTER'BLOCK OF PARC
|
||||
PARC AND ENDP PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
|
||||
TESTING TR
|
||||
TESTING DB TABLE ACCESS
|
||||
TESTING PB TABLE ACCESS
|
||||
TR PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
TESTING CVND
|
||||
SDEC = 0
|
||||
|
||||
SDEC = 1
|
||||
|
||||
CVND PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
|
||||
TESTING CMPS
|
||||
TESTING DB-TARGET ACCESS
|
||||
|
||||
TESTING PB-TARGET ACCESS
|
||||
|
||||
CMPS PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
TESTING CMPT
|
||||
TESTING TRANSLATION TABLE IN PB
|
||||
|
||||
TESTING DB-TARGET ACCESS
|
||||
|
||||
TESTING PB-TARGET ACCESS
|
||||
|
||||
CMPT PASSED ALL TESTS WITHOUT ERRORS
|
||||
|
||||
|
||||
TESTING TCCS
|
||||
TCCS PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
|
||||
TESTING LDW
|
||||
SDEC=0
|
||||
SDEC=1
|
||||
TESTING LDDW
|
||||
SDEC=0
|
||||
SDEC=1
|
||||
LDW AND LDWW PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
TESTING ALGN
|
||||
ALGN PASSED ALL TESTS WITHOUT ERROR
|
||||
|
||||
END OF PASS 0
|
||||
|
||||
Programmed halt, CIR: 030375 (HALT 15), P: 010315 (RSW)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
------------------------------------
|
||||
D466A - Online Line Printer Verifier
|
||||
------------------------------------
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
IOP HP 3000 Series III I/O Processor
|
||||
|
||||
10-Oct-16 JDB Renumbered debug flags to start at bit 0
|
||||
03-Sep-16 JDB Added "iop_assert_PFWARN" to warn devices of power loss
|
||||
01-Aug-16 JDB Added "iop_reset" to initialize the IOP
|
||||
30-Jun-16 JDB Changed REG type of filter array to BRDATA
|
||||
@ -174,6 +175,7 @@
|
||||
#include "hp3000_cpu.h"
|
||||
#include "hp3000_cpu_ims.h"
|
||||
#include "hp3000_io.h"
|
||||
#include "hp3000_mem.h"
|
||||
|
||||
|
||||
|
||||
@ -188,15 +190,10 @@
|
||||
the trace stream. It returns the bit in the filter array corresponding to
|
||||
the device number. If the bit is set, the trace will be generated;
|
||||
otherwise, it will be suppressed.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. Bit 0 is reserved for the memory data trace flag.
|
||||
*/
|
||||
|
||||
#define DEB_DIO (1u << 1) /* trace direct I/O commands */
|
||||
#define DEB_IRQ (1u << 2) /* trace interrupt requests */
|
||||
#define DEB_DIO (1u << 0) /* trace direct I/O commands */
|
||||
#define DEB_IRQ (1u << 1) /* trace interrupt requests */
|
||||
|
||||
#define FILTER(d) (1u << (d) % 32 & filter [(d) / 32])
|
||||
|
||||
|
||||
1051
HP3000/hp3000_mem.c
Normal file
1051
HP3000/hp3000_mem.c
Normal file
File diff suppressed because it is too large
Load Diff
162
HP3000/hp3000_mem.h
Normal file
162
HP3000/hp3000_mem.h
Normal file
@ -0,0 +1,162 @@
|
||||
/* hp3000_mem.h: HP 3000 memory subsystem interface declarations
|
||||
|
||||
Copyright (c) 2016, J. David Bryan
|
||||
|
||||
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 THE
|
||||
AUTHOR 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 the author shall not be used
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
10-Oct-16 JDB Created
|
||||
|
||||
|
||||
This file contains declarations used by the CPU, I/O Processor, Multiplexer
|
||||
Channel, and Selector Channel to interface with the HP 3000 memory subsystem.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Debug flags.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. Memory debug flags are allocated in descending order, as they may be used
|
||||
by other modules (e.g., CPU) that allocate their own flags in ascending
|
||||
order. No check is made for overlapping values.
|
||||
*/
|
||||
|
||||
#define DEB_MDATA (1u << 31) /* trace memory reads and writes */
|
||||
#define DEB_MFETCH (1u << 30) /* trace memory instruction fetches */
|
||||
#define DEB_MOPND (1u << 29) /* trace memory operand accesses */
|
||||
|
||||
|
||||
/* Architectural constants.
|
||||
|
||||
The type used to represent a main memory word value is defined. An array of
|
||||
this type is used to simulate the CPU main memory.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The MEMORY_WORD type is a 16-bit unsigned type, corresponding with the
|
||||
16-bit main memory in the HP 3000. Unlike the general data type, which
|
||||
is a 32-bit type for speed, main memory does not benefit from the faster
|
||||
32-bit execution on IA-32 processors, as only one instruction in the
|
||||
cpu_read_memory and cpu_write_memory routines has an operand override
|
||||
that invokes the slower instruction fetch path. There is a negligible
|
||||
difference in the Memory Pattern Test diagnostic execution speeds for the
|
||||
uint32 vs. uint16 definition, whereas the VM requirements are doubled for
|
||||
the former.
|
||||
*/
|
||||
|
||||
typedef uint16 MEMORY_WORD; /* HP 16-bit memory word representation */
|
||||
|
||||
|
||||
/* Byte accessors.
|
||||
|
||||
The HP 3000 is a word-addressable machine. Byte addressing is implemented by
|
||||
assuming that a memory of N physical words may be addressed as 2N bytes. The
|
||||
"byte-capable" machine instructions use "relative byte addresses" that are
|
||||
used to obtain absolute word addresses by dividing by two and then accessing
|
||||
the upper or lower byte of the resulting word, depending on the LSB of the
|
||||
byte address.
|
||||
|
||||
In simulation, this module provides a byte access structure and a set of
|
||||
routines that read or write the next byte in ascending byte-offset order.
|
||||
The structure is initialized with the starting byte offset from a specified
|
||||
base register value and then is passed as a parameter to the other routines,
|
||||
which update the fields accordingly for the access requested. This relieves
|
||||
the caller from having to manage the continual logical-to-physical address
|
||||
translation, word buffering, byte selection, etc.
|
||||
|
||||
Byte accessors are also used to provide debug traces of byte operands in
|
||||
memory. Initializing an accessor sets a field containing the absolute byte
|
||||
memory address; this address may be passed to the byte formatters to print
|
||||
the operand.
|
||||
|
||||
In most cases, operands are defined by starting byte addresses and byte
|
||||
counts. However, some operands (e.g., EDIT instruction operands) are
|
||||
delineated only by the extents of the accesses. For these operands, byte
|
||||
accessors maintain the lowest byte addresses and offsets actually accessed,
|
||||
as well as the lengths of the extent of the accesses.
|
||||
*/
|
||||
|
||||
typedef struct { /* byte access descriptor */
|
||||
HP_WORD *byte_offset; /* relative byte offset of the next byte */
|
||||
HP_WORD data_word; /* memory data word containing the current byte */
|
||||
ACCESS_CLASS class; /* memory access classification */
|
||||
uint32 word_address; /* logical word address containing the next byte */
|
||||
t_bool write_needed; /* TRUE if the data word must be written to memory */
|
||||
uint32 count; /* current count of bytes accessed */
|
||||
uint32 length; /* (trace) length of extent of access */
|
||||
uint32 initial_byte_address; /* (trace) initial absolute byte address */
|
||||
uint32 initial_byte_offset; /* (trace) initial relative byte offset */
|
||||
uint32 first_byte_address; /* (trace) lowest absolute byte address accessed */
|
||||
uint32 first_byte_offset; /* (trace) lowest relative byte offset accessed */
|
||||
} BYTE_ACCESS;
|
||||
|
||||
|
||||
/* Memory global SCP support routines */
|
||||
|
||||
t_stat mem_examine (t_value *eval_array, t_addr address, UNIT *uptr, int32 switches);
|
||||
t_stat mem_deposit (t_value value, t_addr address, UNIT *uptr, int32 switches);
|
||||
|
||||
|
||||
/* Global memory functions.
|
||||
|
||||
mem_initialize : allocate main memory
|
||||
mem_is_empty : check for a non-zero value within a range of memory locations
|
||||
mem_fill : set all memory locations to a specified value
|
||||
|
||||
mem_read : read a word from main memory
|
||||
mem_write : write a word to main memory
|
||||
|
||||
mem_init_byte : initialize a memory byte access structure
|
||||
mem_set_byte : set the access structure to a new byte offset
|
||||
mem_lookup_byte : return a byte at a specified index in a table
|
||||
mem_read_byte : read the next byte from memory
|
||||
mem_write_byte : write the next byte to memory
|
||||
mem_modify_byte : replace the last byte written to memory
|
||||
mem_post_byte : post the word containing the last byte modified in place to memory
|
||||
mem_update_byte : rewrite the word containing the last byte written to memory
|
||||
|
||||
fmt_byte_operand : format a byte operand in memory into a character string
|
||||
fmt_bcd_operand : format a BCD operand in memory into a character string
|
||||
*/
|
||||
|
||||
extern t_bool mem_initialize (uint32 memory_size);
|
||||
extern t_bool mem_is_empty (uint32 starting_address);
|
||||
extern void mem_fill (uint32 starting_address, HP_WORD fill_value);
|
||||
|
||||
extern t_bool mem_read (DEVICE *dptr, ACCESS_CLASS classification, uint32 offset, HP_WORD *value);
|
||||
extern t_bool mem_write (DEVICE *dptr, ACCESS_CLASS classification, uint32 offset, HP_WORD value);
|
||||
|
||||
extern void mem_init_byte (BYTE_ACCESS *bap, ACCESS_CLASS class, HP_WORD *byte_offset, uint32 block_length);
|
||||
extern void mem_set_byte (BYTE_ACCESS *bap);
|
||||
extern uint8 mem_lookup_byte (BYTE_ACCESS *bap, uint8 index);
|
||||
extern uint8 mem_read_byte (BYTE_ACCESS *bap);
|
||||
extern void mem_write_byte (BYTE_ACCESS *bap, uint8 byte);
|
||||
extern void mem_modify_byte (BYTE_ACCESS *bap, uint8 byte);
|
||||
extern void mem_post_byte (BYTE_ACCESS *bap);
|
||||
extern void mem_update_byte (BYTE_ACCESS *bap);
|
||||
|
||||
extern char *fmt_byte_operand (uint32 byte_address, uint32 byte_count);
|
||||
extern char *fmt_translated_byte_operand (uint32 byte_address, uint32 byte_count, uint32 table_address);
|
||||
extern char *fmt_bcd_operand (uint32 byte_address, uint32 digit_count);
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
MPX HP 3000 Series III Multiplexer Channel
|
||||
|
||||
24-Oct-16 JDB Renamed SEXT macro to SEXT16
|
||||
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
|
||||
15-Jul-16 JDB Fixed the word count display for DREADSTB trace
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
@ -322,12 +323,23 @@
|
||||
|
||||
|
||||
#include "hp3000_defs.h"
|
||||
#include "hp3000_cpu.h"
|
||||
#include "hp3000_cpu_ims.h"
|
||||
#include "hp3000_io.h"
|
||||
#include "hp3000_mem.h"
|
||||
|
||||
|
||||
|
||||
/* IOP device */
|
||||
|
||||
extern DEVICE iop_dev; /* I/O Processor */
|
||||
|
||||
|
||||
/* Memory access macros */
|
||||
|
||||
#define iop_read_memory(c,o,v) mem_read (&iop_dev, c, o, v)
|
||||
#define iop_write_memory(c,o,v) mem_write (&iop_dev, c, o, v)
|
||||
|
||||
|
||||
/* Program constants.
|
||||
|
||||
The multiplexer channel clock period is 175 nanoseconds. The channel runs
|
||||
@ -1230,8 +1242,8 @@ while (cycles > 0) { /* execute as long as cy
|
||||
else /* otherwise */
|
||||
inbound_signals = NO_SIGNALS; /* no acknowledgement is needed */
|
||||
|
||||
cpu_read_memory (absolute_iop, addr_reg, &iocw); /* fetch the IOCW from memory */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
iop_read_memory (absolute, addr_reg, &iocw); /* fetch the IOCW from memory */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
|
||||
order_reg = IOCW_ORDER (iocw); /* get the translated order from the IOCW */
|
||||
|
||||
@ -1326,25 +1338,25 @@ while (cycles > 0) { /* execute as long as cy
|
||||
break;
|
||||
}
|
||||
|
||||
if (store_ioaw == FALSE) { /* if a fetch is needed */
|
||||
cpu_read_memory (absolute_iop, addr_reg, &ioaw); /* then load the IOAW from memory */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
if (store_ioaw == FALSE) { /* if a fetch is needed */
|
||||
iop_read_memory (absolute, addr_reg, &ioaw); /* then load the IOAW from memory */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %u loaded IOAW %06o from address %06o\n",
|
||||
srn, ioaw, addr_reg);
|
||||
}
|
||||
|
||||
else /* otherwise provide a dummy value */
|
||||
ioaw = 0; /* that will be overwritten */
|
||||
else /* otherwise provide a dummy value */
|
||||
ioaw = 0; /* that will be overwritten */
|
||||
|
||||
if (inbound_signals) /* if there are signals to assert */
|
||||
outbound = dibptr->io_interface (dibptr, /* then pass them to the interface */
|
||||
if (inbound_signals) /* if there are signals to assert */
|
||||
outbound = dibptr->io_interface (dibptr, /* then pass them to the interface */
|
||||
inbound_signals, ioaw);
|
||||
|
||||
if (store_ioaw == TRUE) { /* if a store is needed */
|
||||
ioaw = IODATA (outbound); /* then set the IOAW from the returned value */
|
||||
cpu_write_memory (absolute_iop, addr_reg, ioaw); /* and store it in memory */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* count the memory access */
|
||||
if (store_ioaw == TRUE) { /* if a store is needed */
|
||||
ioaw = IODATA (outbound); /* then set the IOAW from the returned value */
|
||||
iop_write_memory (absolute, addr_reg, ioaw); /* and store it in memory */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* count the memory access */
|
||||
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %u stored IOAW %06o to address %06o\n",
|
||||
srn, ioaw, addr_reg);
|
||||
@ -1393,15 +1405,15 @@ while (cycles > 0) { /* execute as long as cy
|
||||
|
||||
outbound = dibptr->io_interface (dibptr, inbound_signals, 0);
|
||||
|
||||
if (sio_order != sioJUMP /* if we're not completing */
|
||||
&& (sio_order != sioJUMPC || (outbound & JMPMET) == 0)) { /* a successful jump order */
|
||||
cpu_read_memory (absolute_iop, IODATA (outbound), &addr_reg); /* then get the I/O program pointer */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
if (sio_order != sioJUMP /* if we're not completing */
|
||||
&& (sio_order != sioJUMPC || (outbound & JMPMET) == 0)) { /* a successful jump order */
|
||||
iop_read_memory (absolute, IODATA (outbound), &addr_reg); /* then get the I/O program pointer */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
}
|
||||
|
||||
cpu_write_memory (absolute_iop, IODATA (outbound), /* write the updated program pointer */
|
||||
addr_reg + 2 & R_MASK); /* back to the DRT */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* and count the access */
|
||||
iop_write_memory (absolute, IODATA (outbound), /* write the updated program pointer */
|
||||
addr_reg + 2 & R_MASK); /* back to the DRT */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* and count the access */
|
||||
|
||||
break;
|
||||
|
||||
@ -1409,9 +1421,9 @@ while (cycles > 0) { /* execute as long as cy
|
||||
case State_D:
|
||||
inbound_data = 0; /* assume there is no inbound data */
|
||||
|
||||
if (sio_order == sioSBANK) { /* if this is a Set Bank order */
|
||||
cpu_read_memory (absolute_iop, addr_reg, &ioaw); /* then read the IOAW */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
if (sio_order == sioSBANK) { /* if this is a Set Bank order */
|
||||
iop_read_memory (absolute, addr_reg, &ioaw); /* then read the IOAW */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %u loaded IOAW %06o from address %06o\n",
|
||||
srn, ioaw, addr_reg);
|
||||
@ -1449,7 +1461,7 @@ while (cycles > 0) { /* execute as long as cy
|
||||
else /* otherwise */
|
||||
inbound_signals |= EOT | TOGGLEOUTXFER; /* assert EOT and end the transfer */
|
||||
|
||||
if (cpu_read_memory (dma_iop, /* read the word from memory */
|
||||
if (iop_read_memory (dma, /* read the word from memory */
|
||||
TO_PA (AUX_BANK (aux_reg), addr_reg), /* at the indicated bank and offset */
|
||||
&inbound_data)) /* if the read succeeds */
|
||||
cycles = cycles - CYCLES_PER_READ; /* then count the memory access */
|
||||
@ -1467,10 +1479,10 @@ while (cycles > 0) { /* execute as long as cy
|
||||
if (device_end == SET) { /* if the transfer was aborted by the interface */
|
||||
outbound_data = IODATA (outbound); /* then it returned the DRT program pointer address */
|
||||
|
||||
cpu_read_memory (absolute_iop, outbound_data, &addr_reg); /* do the I/O program pointer fetch here */
|
||||
cpu_write_memory (absolute_iop, outbound_data, /* so we don't have to do State C */
|
||||
iop_read_memory (absolute, outbound_data, &addr_reg); /* do the I/O program pointer fetch here */
|
||||
iop_write_memory (absolute, outbound_data, /* so we don't have to do State C */
|
||||
addr_reg + 2 & R_MASK);
|
||||
cycles = cycles - CYCLES_PER_READ - CYCLES_PER_WRITE; /* count the two memory accesses */
|
||||
cycles = cycles - CYCLES_PER_READ - CYCLES_PER_WRITE; /* count the two memory accesses */
|
||||
|
||||
if (cntr_reg == CNTR_MAX) /* if the word count is now exhausted */
|
||||
if (order_reg & ORDER_DC) /* then if the order is chained */
|
||||
@ -1498,7 +1510,7 @@ while (cycles > 0) { /* execute as long as cy
|
||||
|
||||
else { /* otherwise the transfer succeeded */
|
||||
if (sio_order == sioREAD || sio_order == sioREADC) /* if this is a Read or Read Chained order */
|
||||
if (cpu_write_memory (dma_iop, /* then write the word to memory */
|
||||
if (iop_write_memory (dma, /* then write the word to memory */
|
||||
TO_PA (AUX_BANK (aux_reg), addr_reg), /* at the indicated bank and offset */
|
||||
IODATA (outbound))) /* if the write succeeds */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* then count the memory access */
|
||||
@ -1739,7 +1751,7 @@ while (working_set) {
|
||||
dprintf (mpx_dev, DEB_CSRW, "Order register value %02o (%s) "
|
||||
"and counter register value %d returned\n",
|
||||
order_reg & ORDER_MASK, sio_order_name [IOCW_ORDER (outbound_value)],
|
||||
SEXT (IOCW_COUNT (outbound_value)));
|
||||
SEXT16 (IOCW_COUNT (outbound_value)));
|
||||
}
|
||||
|
||||
if (control_word & CN_ADDR_RAM) { /* if the address register is selected */
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
SIMH/HP 3000 RELEASE NOTES
|
||||
==========================
|
||||
Last update: 2016-09-20
|
||||
Last update: 2017-01-08
|
||||
|
||||
|
||||
This file documents the release history of the Hewlett-Packard 3000 simulator.
|
||||
@ -158,6 +158,149 @@ the MPE version used:
|
||||
|
||||
|
||||
|
||||
=====================
|
||||
Release 4, 2017-01-08
|
||||
=====================
|
||||
|
||||
This release of the HP 3000 simulator adds the following features:
|
||||
|
||||
- The HP 32234A COBOL II Extended Instruction Set firmware is now available.
|
||||
The new SET CPU CIS option enables the firmware.
|
||||
|
||||
- Subprograms in memory associated with the EDIT instruction may be examined
|
||||
symbolically with the -E switch.
|
||||
|
||||
- The new CPU "OPND" trace option traces memory byte operands.
|
||||
|
||||
- The new CPU "EXEC" trace option turns on full tracing for instructions
|
||||
that match a value specified by the new "SET CPU EXEC=<match>{;<mask>}"
|
||||
command.
|
||||
|
||||
- The diagnostics coverage is extended to the COBOL II firmware.
|
||||
|
||||
|
||||
--------------------
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
- The MPE-V/R software kit has been updated to add the COBOL II runtime
|
||||
routines to the system SL and COBOL example programs to the OPERATOR.SYS
|
||||
account. The startup command files also enable the COBOL II instruction set.
|
||||
|
||||
- New "hp3000_cpu_cis.c" and "hp3000_mem.c" modules have been added.
|
||||
|
||||
- For this release, checking for interrupts is not performed during execution
|
||||
of the COBOL II EDIT, TR, CMPS, and CMPT instructions. A future release will
|
||||
add interruptibility to these instructions to comply with their hardware
|
||||
behavior.
|
||||
|
||||
- The new OPND trace option does not currently trace byte operands for
|
||||
instructions in the base set (e.g., MOVB or CMPB). Operands for the
|
||||
COBOL II firmware instructions are fully covered.
|
||||
|
||||
- The command-line switch for the EXAMINE command to request display in
|
||||
status-register format has been changed from "-S" to "-T" to avoid conflict
|
||||
with the "-S" switch used to indicate an address offset from SBANK.
|
||||
|
||||
|
||||
----------
|
||||
Bugs Fixed
|
||||
----------
|
||||
|
||||
1. PROBLEM: SETR prints a base register trace when values are not changed.
|
||||
|
||||
VERSION: Release 3
|
||||
|
||||
OBSERVATION: The SETR instruction may be used to change any combination of
|
||||
the SBANK, DB, DL, Z, STA, X, Q, and SM register values. If the REG trace
|
||||
is active, the base register values will be printed after the instruction
|
||||
completes. This occurs whether or not the base register values were
|
||||
actually changed. In particular, the CPU diagnostic uses the SETR
|
||||
instruction to flush the stack to memory without changing any base
|
||||
registers. The REG trace in this case is unnecessary.
|
||||
|
||||
CAUSE: The "cpu_base_changed" flag is set unconditionally when the
|
||||
instruction completes. It should be set only if the SETR instruction
|
||||
specifies one or more base registers to change.
|
||||
|
||||
RESOLUTION: Modify "cpu_move_spec_fw_imm_field_reg_op" (hp3000_cpu_base.c)
|
||||
to set the "cpu_base_changed" flag only if one or more base register change
|
||||
bits are set in the instruction operand field.
|
||||
|
||||
STATUS: Fixed in Release 4.
|
||||
|
||||
|
||||
2. PROBLEM: Invalid bank and offset values are accepted for address entry.
|
||||
|
||||
VERSION: Release 3
|
||||
|
||||
OBSERVATION: Bank-offset addresses with out-of-range the bank or offset
|
||||
values, e.g., EXAMINE 30.0 and EXAMINE 0.1777777, are accepted without
|
||||
complaint. The bank value is taken modulo 20, and the higher order bits of
|
||||
the offset value are merged into the bank number. Values out of range
|
||||
should be rejected with errors.
|
||||
|
||||
CAUSE: Incomplete range verification.
|
||||
|
||||
RESOLUTION: Modify "parse_addr" (hp3000_sys.c) to check the parsed bank
|
||||
and offset values against their respective maximums and return an "Invalid
|
||||
argument" error if either is exceeded.
|
||||
|
||||
STATUS: Fixed in Release 4.
|
||||
|
||||
|
||||
3. PROBLEM: The "-S" (SBANK-offset) switch displays values in status-register
|
||||
format.
|
||||
|
||||
VERSION: Release 3
|
||||
|
||||
OBSERVATION: The HP 3000 User's Manual states that adding the "-S" switch
|
||||
to the EXAMINE command implies that the offset is from the bank number in
|
||||
the SBANK register. The example given, "EXAMINE -S <sbank-offset>", should
|
||||
display the memory data value at the address <SBANK-number>.<offset> in
|
||||
octal format. Instead, it displays the value in status-register format.
|
||||
|
||||
CAUSE: The "-S" switch is used for both SBANK and STA formats. Section
|
||||
2.1.3 says that -S means that "The implied bank number is obtained from
|
||||
SBANK." Section 2.1.2 says that -S means that "A CPU status mnemonic" is
|
||||
being displayed. For EXAMINE -S, the latter interpretation causes the
|
||||
expected octal value to be displayed in status-register format.
|
||||
|
||||
RESOLUTION: Modify "fprint_sym" (hp3000_sys.c) to use the "-T" switch to
|
||||
designate status-register format. Modify hp3000_sys.c, hp3000_cpu.c, and
|
||||
hp3000_defs.h to rename the "REG_S" format indicator to "REG_T" for
|
||||
consistency with the switch change.
|
||||
|
||||
STATUS: Fixed in Release 4.
|
||||
|
||||
|
||||
4. PROBLEM: SCAL 0 and PCAL 0 instructions fail when a stack overflow occurs.
|
||||
|
||||
VERSION: Release 3
|
||||
|
||||
OBSERVATION: The SCAL 0 and PCAL 0 instructions transfer control via
|
||||
subroutine or procedure calls, respectively, through program labels
|
||||
residing on the top of the stack. If a stack overflow occurs during
|
||||
instruction execution, the stack overflow trap handler is called to enlarge
|
||||
the stack, and the instruction is reexecuted. However, the program label
|
||||
has been lost, so control transfers to a random location.
|
||||
|
||||
CAUSE: The instructions obtain the label and then delete the TOS, flush
|
||||
the rest of the stack registers to memory, and then check that SM <= Z,
|
||||
i.e., that the current top of the stack in memory does not exceed the
|
||||
stack limit. If SM > Z, a stack overflow has occurred, and the trap
|
||||
handler is called. However, the label has not been restored to the stack,
|
||||
so when the instruction is reexecuted after the stack is enlarged, the
|
||||
wrong value is pulled from the TOS.
|
||||
|
||||
RESOLUTION: Modify "cpu_io_cntl_prog_imm_mem_op" SCAL and PCAL executors
|
||||
(hp3000_cpu_base.c) to push the label back onto the stack before taking the
|
||||
stack overflow trap.
|
||||
|
||||
STATUS: Fixed in Release 4.
|
||||
|
||||
|
||||
|
||||
=====================
|
||||
Release 3, 2016-09-20
|
||||
=====================
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
|
||||
SEL HP 3000 Series III Selector Channel
|
||||
|
||||
10-Oct-16 JDB Renumbered debug flags to start at 0
|
||||
Added port_read_memory, port_write_memory macros
|
||||
11-Jul-16 JDB Change "sel_unit" from a UNIT to an array of one UNIT
|
||||
30-Jun-16 JDB Reestablish active_dib pointer during sel_initialize
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
@ -289,9 +291,9 @@
|
||||
|
||||
|
||||
#include "hp3000_defs.h"
|
||||
#include "hp3000_cpu.h"
|
||||
#include "hp3000_cpu_ims.h"
|
||||
#include "hp3000_io.h"
|
||||
#include "hp3000_mem.h"
|
||||
|
||||
|
||||
|
||||
@ -364,18 +366,18 @@ static const char *const action_name [] = { /* indexed by SEQ_STATE */
|
||||
};
|
||||
|
||||
|
||||
/* Debug flags.
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CSRW (1u << 0) /* trace channel command initiations and completions */
|
||||
#define DEB_PIO (1u << 1) /* trace programmed I/O commands */
|
||||
#define DEB_STATE (1u << 2) /* trace state changes */
|
||||
#define DEB_SR (1u << 3) /* trace service requests */
|
||||
|
||||
|
||||
Implementation notes:
|
||||
/* Memory access macros */
|
||||
|
||||
1. Bit 0 is reserved for the memory data trace flag.
|
||||
*/
|
||||
|
||||
#define DEB_CSRW (1u << 1) /* trace channel command initiations and completions */
|
||||
#define DEB_PIO (1u << 2) /* trace programmed I/O commands */
|
||||
#define DEB_STATE (1u << 3) /* trace state changes */
|
||||
#define DEB_SR (1u << 4) /* trace service requests */
|
||||
#define port_read_memory(c,o,v) mem_read (&sel_dev, c, o, v)
|
||||
#define port_write_memory(c,o,v) mem_write (&sel_dev, c, o, v)
|
||||
|
||||
|
||||
/* Channel global state */
|
||||
@ -600,8 +602,8 @@ if (sel_is_idle) { /* if the channel is idl
|
||||
active_dib = dibptr; /* save the interface's DIB pointer */
|
||||
device_number = dibptr->device_number; /* and set the device number register */
|
||||
|
||||
cpu_read_memory (absolute_sel, device_number * 4, /* read the initial program counter from the DRT */
|
||||
&program_counter);
|
||||
port_read_memory (absolute, device_number * 4, /* read the initial program counter from the DRT */
|
||||
&program_counter);
|
||||
}
|
||||
|
||||
else { /* otherwise abort the transfer in progress */
|
||||
@ -935,7 +937,7 @@ while (sel_request && cycles > 0) { /* execute as long as a
|
||||
outbound_data = IODATA (outbound); /* get the status or residue to return */
|
||||
return_address = program_counter - 1 & LA_MASK; /* point at the second of the program words */
|
||||
|
||||
cpu_write_memory (absolute_sel, return_address, outbound_data); /* save the word */
|
||||
port_write_memory (absolute, return_address, outbound_data); /* save the word */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* and count the access */
|
||||
|
||||
dprintf (sel_dev, DEB_PIO, "Channel stored IOAW %06o to address %06o\n",
|
||||
@ -1029,9 +1031,9 @@ while (sel_request && cycles > 0) { /* execute as long as a
|
||||
}
|
||||
|
||||
else { /* otherwise it's a Write or Write Chained order */
|
||||
if (cpu_read_memory (dma_sel, /* if the memory read */
|
||||
TO_PA (bank, address_word), /* from the specified bank and offset */
|
||||
&input_buffer)) { /* succeeds */
|
||||
if (port_read_memory (dma, /* if the memory read */
|
||||
TO_PA (bank, address_word), /* from the specified bank and offset */
|
||||
&input_buffer)) { /* succeeds */
|
||||
cycles = cycles - CYCLES_PER_READ; /* then count the access */
|
||||
|
||||
inbound_data = input_buffer; /* get the word to supply */
|
||||
@ -1098,9 +1100,9 @@ while (sel_request && cycles > 0) { /* execute as long as a
|
||||
|| order == sioREADC) { /* and if this is a Read or Read Chained order */
|
||||
output_buffer = IODATA (outbound); /* then pick up the returned data word */
|
||||
|
||||
if (cpu_write_memory (dma_sel, /* if the memory write */
|
||||
TO_PA (bank, address_word), /* to the specified bank and offset */
|
||||
output_buffer)) /* succeeds */
|
||||
if (port_write_memory (dma, /* if the memory write */
|
||||
TO_PA (bank, address_word), /* to the specified bank and offset */
|
||||
output_buffer)) /* succeeds */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* then count the access */
|
||||
|
||||
else { /* otherwise the memory write failed */
|
||||
@ -1264,8 +1266,8 @@ return SCPE_OK;
|
||||
|
||||
static void end_channel (DIB *dibptr)
|
||||
{
|
||||
cpu_write_memory (absolute_sel, device_number * 4, /* write the program counter back to the DRT */
|
||||
program_counter);
|
||||
port_write_memory (absolute, device_number * 4, /* write the program counter back to the DRT */
|
||||
program_counter);
|
||||
|
||||
dibptr->service_request = FALSE; /* clear any outstanding device service request */
|
||||
|
||||
@ -1302,7 +1304,7 @@ return active_dib->io_interface (active_dib, XFERERROR | CHANSO, 0); /* tell
|
||||
|
||||
static void load_control (HP_WORD *value)
|
||||
{
|
||||
cpu_read_memory (absolute_sel, program_counter, value); /* read the IOCW from memory */
|
||||
port_read_memory (absolute, program_counter, value); /* read the IOCW from memory */
|
||||
|
||||
dprintf (sel_dev, DEB_PIO, "Channel %s IOCW %06o (%s) from address %06o\n",
|
||||
action_name [sequencer], *value,
|
||||
@ -1324,7 +1326,7 @@ return;
|
||||
|
||||
static void load_address (HP_WORD *value)
|
||||
{
|
||||
cpu_read_memory (absolute_sel, program_counter, value); /* read the IOAW from memory */
|
||||
port_read_memory (absolute, program_counter, value); /* read the IOAW from memory */
|
||||
|
||||
dprintf (sel_dev, DEB_PIO, "Channel %s IOAW %06o from address %06o\n",
|
||||
action_name [sequencer], *value, program_counter);
|
||||
|
||||
1212
HP3000/hp3000_sys.c
1212
HP3000/hp3000_sys.c
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,7 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion from "hp_disclib.h"
|
||||
03-Aug-16 JDB "fmt_bitset" now allows multiple concurrent calls
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
@ -372,21 +373,22 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "hp3000_defs.h" /* this must reflect the machine used */
|
||||
#include "hp_disclib.h"
|
||||
|
||||
|
||||
|
||||
/* Program constants */
|
||||
|
||||
#define CNTLR_UNIT (DL_MAXDRIVE + 1) /* controller unit number */
|
||||
#define MAX_UNIT 10 /* last legal unit number */
|
||||
#define CNTLR_UNIT (DL_MAXDRIVE + 1) /* controller unit number */
|
||||
#define MAX_UNIT 10 /* last legal unit number */
|
||||
|
||||
#define WORDS_PER_SECTOR 128 /* data words per sector */
|
||||
#define WORDS_PER_SECTOR 128 /* data words per sector */
|
||||
|
||||
#define UNTALK_DELAY 160 /* ICD untalk delay (constant instruction count) */
|
||||
#define CNTLR_TIMEOUT S (1.74) /* command and parameter wait timeout (1.74 seconds) */
|
||||
#define UNTALK_DELAY 160 /* ICD untalk delay (constant instruction count) */
|
||||
#define CNTLR_TIMEOUT S (1.74) /* command and parameter wait timeout (1.74 seconds) */
|
||||
|
||||
#define NO_EVENT -1 /* do not schedule an event */
|
||||
#define NO_EVENT -1 /* do not schedule an event */
|
||||
|
||||
#define NO_ACTION (CNTLR_IFN_IBUS) (NO_FUNCTIONS | NO_DATA)
|
||||
|
||||
@ -404,9 +406,9 @@
|
||||
/* Controller clear types */
|
||||
|
||||
typedef enum {
|
||||
Hard_Clear, /* power-on/preset hard clear */
|
||||
Timeout_Clear, /* command or parameter timeout clear */
|
||||
Soft_Clear /* programmed soft clear */
|
||||
Hard_Clear, /* power-on/preset hard clear */
|
||||
Timeout_Clear, /* command or parameter timeout clear */
|
||||
Soft_Clear /* programmed soft clear */
|
||||
} CNTLR_CLEAR;
|
||||
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the authors.
|
||||
|
||||
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_disclib.c"
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Mar-16 JDB Added the DL_BUFFER type to define the disc buffer array
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
@ -42,10 +43,6 @@
|
||||
|
||||
|
||||
|
||||
#include "hp3000_defs.h" /* this must reflect the machine used */
|
||||
|
||||
|
||||
|
||||
/* Architectural constants.
|
||||
|
||||
The type of the disc buffer element is defined. This must be a 16-bit array
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion from "hp_tapelib.h"
|
||||
01-Jul-16 JDB Changed tl_attach to reset the event delay times pointer
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
@ -326,6 +327,7 @@
|
||||
|
||||
|
||||
|
||||
#include "hp3000_defs.h" /* this must reflect the machine used */
|
||||
#include "hp_tapelib.h"
|
||||
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the authors.
|
||||
|
||||
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_tapelib.c"
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Mar-16 JDB Added the TL_BUFFER type to define the tape buffer array
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
@ -38,8 +39,6 @@
|
||||
|
||||
|
||||
|
||||
#include "hp3000_defs.h" /* this must reflect the machine used */
|
||||
|
||||
#include "sim_tape.h"
|
||||
|
||||
|
||||
|
||||
@ -204,6 +204,10 @@
|
||||
RelativePath="..\HP3000\hp3000_cpu_base.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp3000_cpu_cis.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp3000_cpu_fp.c"
|
||||
>
|
||||
@ -220,6 +224,10 @@
|
||||
RelativePath="..\HP3000\hp3000_lp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp3000_mem.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp3000_mpx.c"
|
||||
>
|
||||
@ -317,6 +325,10 @@
|
||||
RelativePath="..\HP3000\hp3000_io.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp3000_mem.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp_disclib.h"
|
||||
>
|
||||
|
||||
@ -432,9 +432,10 @@ HP3000_DIR = SYS$DISK:[.HP3000]
|
||||
HP3000_LIB1 = $(LIB_DIR)HP3000L1-$(ARCH).OLB
|
||||
HP3000_SOURCE1 = $(HP3000_DIR)HP3000_ATC.C,$(HP3000_DIR)HP3000_CLK.C,\
|
||||
$(HP3000_DIR)HP3000_CPU.C,$(HP3000_DIR)HP3000_CPU_BASE.C,\
|
||||
$(HP3000_DIR)HP3000_CPU_FP.C,$(HP3000_DIR)HP3000_DS.C,\
|
||||
$(HP3000_DIR)HP3000_LP.C,\
|
||||
$(HP3000_DIR)HP3000_IOP.C,$(HP3000_DIR)HP3000_MPX.C,\
|
||||
$(HP3000_DIR)HP3000_CPU_CIS.C,$(HP3000_DIR)HP3000_CPU_FP.C,\
|
||||
$(HP3000_DIR)HP3000_DS.C,$(HP3000_DIR)HP3000_LP.C,\
|
||||
$(HP3000_DIR)HP3000_IOP.C,$(HP3000_DIR)HP3000_MEM.C,\
|
||||
$(HP3000_DIR)HP3000_MPX.C,\
|
||||
$(HP3000_DIR)HP3000_MS.C,$(HP3000_DIR)HP3000_SCMB.C,\
|
||||
$(HP3000_DIR)HP3000_SEL.C,$(HP3000_DIR)HP3000_SYS.C
|
||||
HP3000_LIB2 = $(LIB_DIR)HP3000L2-$(ARCH).OLB
|
||||
|
||||
Binary file not shown.
7
makefile
7
makefile
@ -1215,9 +1215,10 @@ HP2100_OPT = -DHAVE_INT64 -I ${HP2100D}
|
||||
HP3000D = HP3000
|
||||
HP3000 = ${HP3000D}/hp_disclib.c ${HP3000D}/hp_tapelib.c ${HP3000D}/hp3000_atc.c \
|
||||
${HP3000D}/hp3000_clk.c ${HP3000D}/hp3000_cpu.c ${HP3000D}/hp3000_cpu_base.c \
|
||||
${HP3000D}/hp3000_cpu_fp.c ${HP3000D}/hp3000_ds.c ${HP3000D}/hp3000_iop.c \
|
||||
${HP3000D}/hp3000_lp.c ${HP3000D}/hp3000_mpx.c ${HP3000D}/hp3000_ms.c \
|
||||
${HP3000D}/hp3000_scmb.c ${HP3000D}/hp3000_sel.c ${HP3000D}/hp3000_sys.c
|
||||
${HP3000D}/hp3000_cpu_fp.c ${HP3000D}/hp3000_cpu_cis.c ${HP3000D}/hp3000_ds.c \
|
||||
${HP3000D}/hp3000_iop.c ${HP3000D}/hp3000_lp.c ${HP3000D}/hp3000_mem.c \
|
||||
${HP3000D}/hp3000_mpx.c ${HP3000D}/hp3000_ms.c ${HP3000D}/hp3000_scmb.c \
|
||||
${HP3000D}/hp3000_sel.c ${HP3000D}/hp3000_sys.c
|
||||
HP3000_OPT = -I ${HP3000D}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user