PDP-8-E-Simulator/Emulation/PDP8.h

317 lines
12 KiB
Objective-C

/*
* PDP-8/E Simulator
*
* Copyright © 1994-2015 Bernhard Baehr
*
* PDP8.h - The PDP-8/E Emulator Class
*
* This file is part of PDP-8/E Simulator.
*
* PDP-8/E Simulator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@class BreakpointArray;
#define MEMORY_CHANGED_NOTIFICATION @"pdp8MemoryChangedNotification"
#define PROGRAM_COUNTER_CHANGED_NOTIFICATION @"pdp8PCChangedNotification"
#define ACCUMULATOR_CHANGED_NOTIFICATION @"pdp8LACChangedNotification"
#define SR_CHANGED_NOTIFICATION @"pdp8SRChangedNotification"
#define SC_CHANGED_NOTIFICATION @"pdp8SCChangedNotification"
#define GTF_CHANGED_NOTIFICATION @"pdp8GTFChangedNotification"
#define MQ_CHANGED_NOTIFICATION @"pdp8MQChangedNotification"
#define EAE_MODE_CHANGED_NOTIFICATION @"pdp8EAEModeChangedNotification"
#define DF_CHANGED_NOTIFICATION @"pdp8DFChangedNotification"
#define UF_CHANGED_NOTIFICATION @"pdp8UFChangedNotification"
#define UB_CHANGED_NOTIFICATION @"pdp8UBChangedNotification"
#define SF_CHANGED_NOTIFICATION @"pdp8SFChangedNotification"
#define ENABLE_CHANGED_NOTIFICATION @"pdp8EnableChangedNotification"
#define DELAY_CHANGED_NOTIFICATION @"pdp8DelayChangedNotification"
#define INHIBIT_CHANGED_NOTIFICATION @"pdp8InhibitChangedNotification"
#define IOFLAGS_CHANGED_NOTIFICATION @"pdp8IOFlagsChangedNotification"
#define EAE_MOUNT_NOTIFICATION @"pdp8EAEMountNotification"
#define KM8E_MOUNT_NOTIFICATION @"pdp8KM8EMountNotification"
#define CLEAR_ALL_FLAGS_NOTIFICATION @"pdp8ClearAllFlagsNotification"
#define PDP8_STEP_NOTIFICATION @"pdp8StepNotification"
#define PDP8_TRACE_NOTIFICATION @"pdp8TraceNotification"
#define PDP8_GO_NOTIFICATION @"pdp8GoNotification"
#define PDP8_STOP_NOTIFICATION @"pdp8StopNotification"
#define PDP8_FIELDSIZE 0010000 /* size of a 4K PDP-8 memory field */
#define PDP8_MEMSIZE 0100000 /* maximal PDP-8 memory size is 32K */
#define PDP8_IOADDRS 0100 /* number of I/O addresses: 6xx? */
#define EAE_MODE_A 'A' /* values for pdp8->eaeMode */
#define EAE_MODE_B 'B'
#define userFLAG 1ul /* hard coded user mode flag (see IOFlagController) */
#define STOPPED 0 /* for state.running */
#define GOING 1
#define TRACING 2
#define RUNNING (GOING | TRACING)
#define GO_AS_FAST_AS_POSSIBLE 0 /* for state.goSpeed, setGoSpeed: and getGoSpeed */
#define GO_WITH_PDP8_SPEED 1
#define GO_WITH_PDP8_SPEED_PRECISE 2
#define NO_STOP_ADDRESS -1 /* for trace: and go: without stop address */
typedef unsigned long ulong;
typedef void (*PDP8InstructionFunctionPointer)(void);
/* Structure with information about the optional devices currently simulated */
typedef struct {
ushort memsize; /* memory size in 12-bit words - Data Break I/O devices must know
this value to avoid writing into non-existing PDP-8 memory */
BOOL hasEAE; /* the simulated hardware has an EAE */
BOOL hasKM8E; /* the simulated hardware has an KM8-E */
BOOL hasKM8Etimesharing; /* the time sharing jumper of the KM8-E is present */
} HW;
/* Registers of the TSC8-75 board are kept within the PDP-8 class */
typedef struct {
ulong flag; /* interrupt mask of the TSC8-75 (0 when TSC8-75 not present) */
ushort eriot; /* last instruction (IOT, JMP, JMS) that caused an user mode trap */
ushort ertb; /* address of last JMP or JMS that caused an user mode trap */
ushort ecdf; /* set when a CDF is executed in user mode, cleared by ECDF or ESME */
ushort esmeEnabled; /* TSC8-75 supports the ESME mode, i. e. the IOT 6365 */
} TSC8_75;
/* Structure with information about the internal state of the PDP-8/E emulation */
typedef struct {
ushort running; /* STOPPED, TRACING or GOING */
BOOL halted; /* YES iff the HALT or SINGSTEP key of the KC8-EA console is pressed */
ushort currInst; /* code of current PDP-8 instruction, the functions */
/* implementing the PDP-8 instructions can inspect this */
ulong executionTime; /* every PDP-8 instruction must add to this value the execution */
/* time (in 0.1 microseconds) of the instruction */
/* for IOTs of I/O devices implemented by plugins these are: */
/* 12 (1.2 microseconds) for IOTs of devices directly attached to */
/* the OMNIBUS; */
/* for devices attached via the KA8-E Positive I/O Bus Interface: */
/* 12 (1.2 microseconds) for IOTs ending in 0 */
/* 26 (2.6 microseconds) for IOTs ending in 1, 2 or 4 */
/* 36 (3.6 microseconds) for IOTs ending in 3, 5 or 6 */
/* 46 (4.6 microseconds) for IOTs ending in 7 */
/* use the macro EXECUTION_TIME() for this purpose */
uint64_t absoluteTime; /* Mach kernel absolut time corresponding to PDP-8 executionTime */
int goSpeed; /* GO_AS_FAST_AS_POSSIBLE, GO_WITH_PDP8_SPEED, GO_WITH_PDP8_SPEED_PRECISE */
ulong usecTraceDelay; /* delay (in microseconds) between two instructions in trace mode */
void *pluginPointer[PDP8_IOADDRS]; /* for each I/O address, a pointer pointing to the plugin */
} STATE;
@interface PDP8 : NSObject <NSCoding> {
@public
/* The attributes are public, so the C functions implementing the PDP-8 instructions can
access them directly. No other Cocoa code should use them directly. To ensure this,
the register names are mapped to dummy names with the #defines below. In the source
code files with the instruction C functions, #define USE_PDP8_REGISTERS_DIRECTLY
to make the registers available. */
/* Registers of the PDP-8/E CPU */
ushort SR;
ushort AC; /* including L flag */
ushort PC;
ushort SC;
ushort MQ;
ushort GTF;
ushort IF; /* W: for write access to nonexisting memory */
ushort IB, W_IB; /* W_IB == IB when memory exists, */
ushort DF, W_DF; /* W_IB == 0100000 when memory does not exist */
/* write accesses to current IF are only by JMS, */
/* but then IB is used, so no W_IF needed. */
/* dto. for DF, W_DF */
/* field registers are 0n0000 for field n (0 <= n <= 7) */
ushort UF;
ushort UB; /* UF, UB is 000000 or 010000 */
ushort SF;
ushort IENABLE;
ushort IINHIBIT;
ushort IDELAY;
ulong IMASK;
ulong IOFLAGS;
char eaeMode; /* 'A' - Mode A, 'B' - Mode B */
ushort mem[PDP8_MEMSIZE + PDP8_FIELDSIZE]; /* 9th field for non-existing core */
/* additional attributes */
TSC8_75 _tsc8;
HW _hw;
STATE _state;
@private
IBOutlet BreakpointArray *breakpoints;
IBOutlet BreakpointArray *breakopcodes;
char bp[PDP8_MEMSIZE];
NSMutableDictionary *saveopcodes;
}
- (void) mountEAE:(BOOL)mount; // mount or unmount
- (BOOL) hasEAE;
- (void) mountKM8E:(BOOL)mount memorySize:(unsigned)memsize timesharingEnabled:(BOOL)timesharing;
- (BOOL) hasKM8E;
- (BOOL) isTimesharingEnabled;
- (ushort) memorySize; // memory size in 12-bit words, e. g. 010000 for a 4K machine
- (BOOL) isIOAddressAvailable:(int)addr;
- (void) setIOT:(NSValue *)iot forOpcode:(int)opcode;
- (void) setPluginPointer:(void *)pointer forIOAddress:(int)addr; // see PLUGIN_POINTER macro below
- (NSString *) loadPaperTape:(NSString *)filename toField:(ushort)field;
// returns an error message; nil == everything ok
- (void) setTraceSpeed:(double)speed; // trace with frequency of 1/speed Hz
- (void) setGoSpeed:(int)goSpeed; // see state.goSpeed and the three GO_ macros
- (int) getGoSpeed; // may change with a NSUserDefaultsDidChangeNotification
- (void) step;
- (void) trace:(int)stopAddress; // stopAddress == -1 for no stop address
- (void) go:(int)stopAddress;
- (void) stop; // stop the running or tracing PDP-8
- (void) clearAllFlags;
- (void) loadExtendedAddress;
- (void) reset;
- (BOOL) isStopped;
- (BOOL) isTracing;
- (BOOL) isGoing;
- (BOOL) isRunning; // running in trace or go mode
- (BOOL) isHalted; // restart is inhibited (HALT or SINGSTEP console key is up)
- (void) setHalt:(BOOL)halt; // stop and inhibit restart (for the HALT or SINGSTEP console keys)
- (ushort) getPC;
- (void) setPC:(ushort)pc;
- (ushort) getProgramCounter; // returns IF | PC
- (void) setProgramCounter:(ushort)programCounter; // sets IB, IF and PC
- (ushort) getIF;
- (void) setIF:(ushort)_if;
- (ushort) getIB;
- (void) setIB:(ushort)ib;
- (ushort) getDF;
- (void) setDF:(ushort)df;
- (ushort) getUF;
- (void) setUF:(ushort)uf;
- (ushort) getUB;
- (void) setUB:(ushort)ub;
- (ushort) getSF;
- (void) setSF:(ushort)sf;
- (ushort) getSR;
- (void) setSR:(ushort)sr;
- (ushort) getL;
- (void) setL:(ushort)l;
- (ushort) getAC;
- (void) setAC:(ushort)ac;
- (ushort) getLAC;
- (void) setLAC:(ushort)lac;
- (ushort) getSC;
- (void) setSC:(ushort)sc;
- (ushort) getGTF;
- (void) setGTF:(ushort)gtf;
- (ushort) getMQ;
- (void) setMQ:(ushort)mq;
- (char) getEAEmode;
- (void) setEAEmode:(char)mode;
- (ushort) getEnable;
- (void) setEnable:(ushort)enable;
- (ushort) getDelay;
- (void) setDelay:(ushort)delay;
- (ushort) getInhibit;
- (void) setInhibit:(ushort)inhibit;
- (ulong) getInterruptMaskBits:(ulong)bitmask;
- (void) setInterruptMaskBits:(ulong)bitmask;
- (void) clearInterruptMaskBits:(ulong)bitmask;
- (ulong) getIOFlagBits:(ulong)bitmask;
- (void) setIOFlagBits:(ulong)bitmask;
- (void) clearIOFlagBits:(ulong)bitmask;
- (BOOL) interruptRequest;
- (ushort) memoryAt:(int)address;
- (ushort) memoryAtNext:(int)address;
- (ushort *) directMemoryAccess; // pointer to the PDP-8 memory, only for Data Break I/O devices
- (void) directMemoryWriteFinished; // call this method when the memory modifying Data Break is finished
- (void) setMemoryAtAddress:(int)address toValue:(int)value;
- (void) setMemoryAtNextAddress:(int)address toValue:(int)value;
- (void) setMemoryAtAddress:(int)address toValues:(NSArray *)values withMask:(BOOL)withMask;
- (void) clearMemory;
- (ushort) getCurrentOpcode;
- (PDP8InstructionFunctionPointer) getNextInstruction;
- (ushort) getTSC8ertb;
- (void) setTSC8ertb:(ushort)ertb;
- (ushort) getTSC8eriot;
- (void) setTSC8eriot:(ushort)eriot;
- (ushort) getTSC8ecdf;
- (void) setTSC8ecdf:(ushort)ecdf;
- (ulong) getTSC8flag;
- (void) setTSC8flag:(ulong)flag;
- (BOOL) getTSC8esmeEnabled;
- (void) setTSC8esmeEnabled:(BOOL)enabled;
#if ! defined(NS_BLOCK_ASSERTIONS)
- (id) pluginPointer:(Class)pluginClass; // with assertion; see PLUGIN_POINTER macro below
#endif
@end
#if USE_PDP8_REGISTERS_DIRECTLY
extern PDP8 *pdp8;
#define EXECUTION_TIME(time) (pdp8->_state.executionTime += (time))
#if defined(NS_BLOCK_ASSERTIONS)
#define PLUGIN_POINTER(plugin) ((plugin *) pdp8->_state.pluginPointer[(pdp8->_state.currInst >> 3) & 077])
#else
#define PLUGIN_POINTER(plugin) ((plugin *) [pdp8 pluginPointer:[plugin class]])
#endif
#else
#define SR __dont_use_SR__
#define AC __dont_use_AC__
#define PC __dont_use_PC__
#define SC __dont_use_SC__
#define MQ __dont_use_MQ__
#define GTF __dont_use_GTF__
#define IF __dont_use_IF__
#define IB __dont_use_IB__
#define W_IB __dont_use_W_IB__
#define DF __dont_use_DF__
#define W_DF __dont_use_W_DF__
#define UF __dont_use_UF__
#define UB __dont_use_UB__
#define SF __dont_use_SF__
#define IENABLE __dont_use_IENABLE__
#define IINHIBIT __dont_use_IINHIBIT__
#define IDELAY __dont_use_IDELAY__
#define IMASK __dont_use_IMASK__
#define IOFLAGS __dont_use_IOFLAGS__
#define eaeMode __dont_use_eaeMode__
#define mem __dont_use_mem__
#define _tsc8 __dont_use_tsc8__
#define _hw __dont_use_hw__
#define _state __dont_use_state__
#endif