AltairZ80: Added Motorola 68000 CPU support for CP/M-68K, support for Altair mini-disk format, added descriptions for all device registers

This commit is contained in:
Peter Schorn 2014-05-27 20:01:30 +02:00
parent 709016c356
commit 589aca19f4
43 changed files with 46967 additions and 1095 deletions

View file

@ -27,7 +27,8 @@
Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license) Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license)
*/ */
#include "altairz80_defs.h" #include "m68k.h"
#include "assert.h"
#include <ctype.h> #include <ctype.h>
#define SWITCHCPU_DEFAULT 0xfd #define SWITCHCPU_DEFAULT 0xfd
@ -183,7 +184,7 @@ void out(const uint32 Port, const uint32 Value);
uint32 in(const uint32 Port); uint32 in(const uint32 Port);
void altairz80_init(void); void altairz80_init(void);
t_stat sim_instr(void); t_stat sim_instr(void);
t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); t_stat install_bootrom(const int32 bootrom[], const int32 size, const int32 addr, const int32 makeROM);
uint8 GetBYTEWrapper(const uint32 Addr); uint8 GetBYTEWrapper(const uint32 Addr);
void PutBYTEWrapper(const uint32 Addr, const uint32 Value); void PutBYTEWrapper(const uint32 Addr, const uint32 Value);
uint8 GetByteDMA(const uint32 Addr); uint8 GetByteDMA(const uint32 Addr);
@ -254,6 +255,9 @@ static uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue
static int32 pcq_p = 0; /* PC queue ptr */ static int32 pcq_p = 0; /* PC queue ptr */
static REG *pcq_r = NULL; /* PC queue reg ptr */ static REG *pcq_r = NULL; /* PC queue reg ptr */
uint32 m68k_registers[M68K_REG_CPU_TYPE + 1]; /* M68K CPU registers */
/* data structure for IN/OUT instructions */ /* data structure for IN/OUT instructions */
struct idev { struct idev {
int32 (*routine)(const int32, const int32, const int32); int32 (*routine)(const int32, const int32, const int32);
@ -262,107 +266,275 @@ struct idev {
static int32 switcherPort = SWITCHCPU_DEFAULT; static int32 switcherPort = SWITCHCPU_DEFAULT;
static struct idev oldSwitcherDevice = { NULL }; static struct idev oldSwitcherDevice = { NULL };
// CPU_INDEX_8080 is defined in altairz80_defs.h
#define CPU_INDEX_8086 26
#define CPU_INDEX_M68K 53
REG cpu_reg[] = { REG cpu_reg[] = {
{ HRDATA (AF, AF_S, 16) }, // 8080 and Z80 registers
{ HRDATA (BC, BC_S, 16) }, { HRDATAD (AF, AF_S, 16, "8080 / Z80 Accumulator Flag register")
{ HRDATA (DE, DE_S, 16) }, }, /* 0 */
{ HRDATA (HL, HL_S, 16) }, { HRDATAD (BC, BC_S, 16, "8080 / Z80 BC register")
{ HRDATA (IX, IX_S, 16) }, }, /* 1 */
{ HRDATA (IY, IY_S, 16) }, { HRDATAD (DE, DE_S, 16, "8080 / Z80 DE register")
{ HRDATA (PC, PC_S, 16 + MAXBANKSLOG2) }, /* 8080 / Z80 PC [6] */ }, /* 2 */
{ HRDATA (PCX, PCX_S, 16 + MAXBANKSLOG2) }, /* 8086 PC [7] */ { HRDATAD (HL, HL_S, 16, "8080 / Z80 HL register")
{ HRDATA (SP, SP_S, 16) }, }, /* 3 */
{ HRDATA (AF1, AF1_S, 16) }, { HRDATAD (PC, PC_S, 16 + MAXBANKSLOG2, "8080 / Z80 Program Counter register")
{ HRDATA (BC1, BC1_S, 16) }, }, /* 4 8080 / Z80 */
{ HRDATA (DE1, DE1_S, 16) }, { HRDATAD (SP, SP_S, 16, "8080 / Z80 Stack Pointer register")
{ HRDATA (HL1, HL1_S, 16) }, }, /* 5 */
{ GRDATA (IFF, IFF_S, 2, 2, 0) },
{ FLDATA (IR, IR_S, 8) }, // Z80 registers
{ HRDATA (AX, AX_S, 16) }, /* 8086 */ { HRDATAD (IX, IX_S, 16, "Z80 IX register")
{ GRDATA (AL, AX_S, 16, 8, 0) }, /* 8086, low 8 bits of AX */ }, /* 8 */
{ GRDATA (AH, AX_S, 16, 8, 8) }, /* 8086, high 8 bits of AX */ { HRDATAD (IY, IY_S, 16, "Z80 IY register")
{ HRDATA (BX, BX_S, 16) }, /* 8086 */ }, /* 9 */
{ GRDATA (BL, BX_S, 16, 8, 0) }, /* 8086, low 8 bits of BX */ { HRDATAD (AF1, AF1_S, 16, "Z80 Alternate Accumulator Flag register")
{ GRDATA (BH, BX_S, 16, 8, 8) }, /* 8086, high 8 bits of BX */ }, /* 10 */
{ HRDATA (CX, CX_S, 16) }, /* 8086 */ { HRDATAD (BC1, BC1_S, 16, "Z80 Alternate BC register")
{ GRDATA (CL, CX_S, 16, 8, 0) }, /* 8086, low 8 bits of CX */ }, /* 11 */
{ GRDATA (CH, CX_S, 16, 8, 8) }, /* 8086, high 8 bits of CX */ { HRDATAD (DE1, DE1_S, 16, "Z80 Alternate DE register")
{ HRDATA (DX, DX_S, 16) }, /* 8086 */ }, /* 12 */
{ GRDATA (DL, DX_S, 16, 8, 0) }, /* 8086, low 8 bits of DX */ { HRDATAD (HL1, HL1_S, 16, "Z80 Alternate HL register")
{ GRDATA (DH, DX_S, 16, 8, 8) }, /* 8086, high 8 bits of DX */ }, /* 13 */
{ HRDATA (SPX, SPX_S, 16) }, /* 8086 */ { GRDATAD (IFF, IFF_S, 2, 2, 0, "Z80 Interrupt Flip Flop register")
{ HRDATA (BP, BP_S, 16) }, /* 8086, Base Pointer */ }, /* 6 */
{ HRDATA (SI, SI_S, 16) }, /* 8086, Source Index */ { FLDATAD (IR, IR_S, 8, "8Z80 Interrupt (upper) / Refresh (lower) register")
{ HRDATA (DI, DI_S, 16) }, /* 8086, Destination Index */ }, /* 7 */
{ HRDATA (CS, CS_S, 16) }, /* 8086, Code Segment */
{ HRDATA (DS, DS_S, 16) }, /* 8086, Data Segment */ // 8086 registers
{ HRDATA (ES, ES_S, 16) }, /* 8086, Extra Segment */ { HRDATAD (AX, AX_S, 16, "8086 AX register")
{ HRDATA (SS, SS_S, 16) }, /* 8086, Stack Segment */ }, /* 14 8086 */
{ HRDATA (FLAGS, FLAGS_S, 16) }, /* 8086, FLAGS */ { GRDATAD (AL, AX_S, 16, 8, 0, "8086 low bits of AX register")
{ HRDATA (IP, IP_S, 16), REG_RO }, /* 8086, set via PC */ }, /* 15 8086, low 8 bits of AX */
{ FLDATA (OPSTOP, cpu_unit.flags, UNIT_CPU_V_OPSTOP), REG_HRO }, { GRDATAD (AH, AX_S, 16, 8, 8, "8086 high bits of AX register")
{ HRDATA (SR, SR, 8) }, }, /* 16 8086, high 8 bits of AX */
{ HRDATA (BANK, bankSelect, MAXBANKSLOG2) }, { HRDATAD (BX, BX_S, 16, "8086 BX register")
{ HRDATA (COMMON, common, 32) }, }, /* 17 8086 */
{ HRDATA (SWITCHERPORT, switcherPort, 8), }, { GRDATAD (BL, BX_S, 16, 8, 0, "8086 low bits of BX register")
{ DRDATA (CLOCK, clockFrequency, 32) }, }, /* 18 8086, low 8 bits of BX */
{ DRDATA (SLICE, sliceLength, 16) }, { GRDATAD (BH, BX_S, 16, 8, 8, "8086 high bits of BX register")
{ DRDATA (TSTATES, executedTStates, 32), REG_RO }, }, /* 19 8086, high 8 bits of BX */
{ HRDATA (CAPACITY, cpu_unit.capac, 32), REG_RO }, { HRDATAD (CX, CX_S, 16, "8086 CX register")
{ HRDATA (PREVCAP, previousCapacity, 32), REG_RO }, }, /* 20 8086 */
{ BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO + REG_CIRC }, { GRDATAD (CL, CX_S, 16, 8, 0, "8086 low bits of CX register")
{ DRDATA (PCQP, pcq_p, PCQ_SIZE_LOG2), REG_HRO }, }, /* 21 8086, low 8 bits of CX */
{ HRDATA (WRU, sim_int_char, 8) }, { GRDATAD (CH, CX_S, 16, 8, 8, "8086 high bits of CX register")
}, /* 22 8086, high 8 bits of CX */
{ HRDATAD (DX, DX_S, 16, "8086 DX register")
}, /* 23 8086 */
{ GRDATAD (DL, DX_S, 16, 8, 0, "8086 low bits of DX register")
}, /* 24 8086, low 8 bits of DX */
{ GRDATAD (DH, DX_S, 16, 8, 8, "8086 high bits of DX register")
}, /* 25 8086, high 8 bits of DX */
{ HRDATAD (PCX, PCX_S, 16 + MAXBANKSLOG2, "8086 Program Counter register")
}, /* 26 8086, Program Counter */
{ HRDATAD (SPX, SPX_S, 16, "8086 Stack Pointer register")
}, /* 27 8086, Stack Pointer */
{ HRDATAD (BP, BP_S, 16, "8086 Base Pointer register")
}, /* 28 8086, Base Pointer */
{ HRDATAD (SI, SI_S, 16, "8086 Source Index register")
}, /* 29 8086, Source Index */
{ HRDATAD (DI, DI_S, 16, "8086 Destination Index register")
}, /* 30 8086, Destination Index */
{ HRDATAD (CS, CS_S, 16, "8086 Code Segment register")
}, /* 31 8086, Code Segment */
{ HRDATAD (DS, DS_S, 16, "8086 Data Segment register")
}, /* 32 8086, Data Segment */
{ HRDATAD (ES, ES_S, 16, "8086 Extra Segment register")
}, /* 33 8086, Extra Segment */
{ HRDATAD (SS, SS_S, 16, "8086 Stack Segment register")
}, /* 34 8086, Stack Segment */
{ HRDATAD (FLAGS, FLAGS_S, 16, "8086 Flag register")
}, /* 35 8086, FLAGS */
{ HRDATAD (IP, IP_S, 16, "8086 Instruction Pointer register"),
REG_RO }, /* 36 8086, set via PC */
// M68K registers
{ HRDATAD (M68K_D0, m68k_registers[M68K_REG_D0], 32, "M68K D0 register"),
}, /* 37 M68K, D0 */
{ HRDATAD (M68K_D1, m68k_registers[M68K_REG_D1], 32, "M68K D1 register"),
}, /* 38 M68K, D1 */
{ HRDATAD (M68K_D2, m68k_registers[M68K_REG_D2], 32, "M68K D2 register"),
}, /* 39 M68K, D2 */
{ HRDATAD (M68K_D3, m68k_registers[M68K_REG_D3], 32, "M68K D3 register"),
}, /* 40 M68K, D3 */
{ HRDATAD (M68K_D4, m68k_registers[M68K_REG_D4], 32, "M68K D4 register"),
}, /* 41 M68K, D4 */
{ HRDATAD (M68K_D5, m68k_registers[M68K_REG_D5], 32, "M68K D5 register"),
}, /* 42 M68K, D5 */
{ HRDATAD (M68K_D6, m68k_registers[M68K_REG_D6], 32, "M68K D6 register"),
}, /* 43 M68K, D6 */
{ HRDATAD (M68K_D7, m68k_registers[M68K_REG_D7], 32, "M68K D7 register"),
}, /* 44 M68K, D7 */
{ HRDATAD (M68K_A0, m68k_registers[M68K_REG_A0], 32, "M68K A0 register"),
}, /* 45 M68K, A0 */
{ HRDATAD (M68K_A1, m68k_registers[M68K_REG_A1], 32, "M68K A1 register"),
}, /* 46 M68K, A1 */
{ HRDATAD (M68K_A2, m68k_registers[M68K_REG_A2], 32, "M68K A2 register"),
}, /* 47 M68K, A2 */
{ HRDATAD (M68K_A3, m68k_registers[M68K_REG_A3], 32, "M68K A3 register"),
}, /* 48 M68K, A3 */
{ HRDATAD (M68K_A4, m68k_registers[M68K_REG_A4], 32, "M68K A4 register"),
}, /* 49 M68K, A4 */
{ HRDATAD (M68K_A5, m68k_registers[M68K_REG_A5], 32, "M68K A5 register"),
}, /* 50 M68K, A5 */
{ HRDATAD (M68K_A6, m68k_registers[M68K_REG_A6], 32, "M68K A6 register"),
}, /* 51 M68K, A6 */
{ HRDATAD (M68K_A7, m68k_registers[M68K_REG_A7], 32, "M68K A7 register"),
}, /* 52 M68K, A7 */
{ HRDATAD (M68K_PC, m68k_registers[M68K_REG_PC], 32, "M68K Program Counter register"),
}, /* 53 M68K, PC */
{ HRDATAD (M68K_SR, m68k_registers[M68K_REG_SR], 32, "M68K Status Register"),
}, /* 54 M68K, SR */
{ HRDATAD (M68K_SP, m68k_registers[M68K_REG_SP], 32, "M68K Stack Pointer register"),
}, /* 55 M68K, SP */
{ HRDATAD (M68K_USP, m68k_registers[M68K_REG_USP], 32, "M68K User Stack Pointer register"),
}, /* 56 M68K, USP */
{ HRDATAD (M68K_ISP, m68k_registers[M68K_REG_ISP], 32, "M68K Interrupt Stack Pointer register"),
}, /* 57 M68K, ISP */
{ HRDATAD (M68K_MSP, m68k_registers[M68K_REG_MSP], 32, "M68K Master Stack Pointer register"),
}, /* 58 M68K, MSP */
{ HRDATAD (M68K_SFC, m68k_registers[M68K_REG_SFC], 32, "M68K Source Function Code register"),
}, /* 59 M68K, SFC */
{ HRDATAD (M68K_DFC, m68k_registers[M68K_REG_DFC], 32, "M68K Destination Function Code register"),
}, /* 60 M68K, DFC */
{ HRDATAD (M68K_VBR, m68k_registers[M68K_REG_VBR], 32, "M68K Vector Base Register"),
}, /* 61 M68K, VBR */
{ HRDATAD (M68K_CACR, m68k_registers[M68K_REG_CACR], 32, "M68K Cache Control Register"),
}, /* 62 M68K, CACR */
{ HRDATAD (M68K_CAAR, m68k_registers[M68K_REG_CAAR], 32, "M68K Cache Address Register"),
}, /* 63 M68K, CAAR */
{ HRDATAD (M68K_PREF_ADDR, m68k_registers[M68K_REG_PREF_ADDR], 32, "M68K Last Prefetch Address register"),
}, /* 64 M68K, PREF_ADDR */
{ HRDATAD (M68K_PREF_DATA, m68k_registers[M68K_REG_PREF_DATA], 32, "M68K Last Prefetch Data register"),
}, /* 65 M68K, PREF_DATA */
{ HRDATAD (M68K_PPC, m68k_registers[M68K_REG_PPC], 32, "M68K Previous Proram Counter register"),
}, /* 66 M68K, PPC */
{ HRDATAD (M68K_IR, m68k_registers[M68K_REG_IR], 32, "M68K Instruction Register"),
}, /* 67 M68K, IR */
{ HRDATAD (M68K_CPU_TYPE, m68k_registers[M68K_REG_CPU_TYPE], 32, "M68K CPU Type register"),
REG_RO }, /* 68 M68K, CPU_TYPE */
// Pseudo registers
{ FLDATAD (OPSTOP, cpu_unit.flags, UNIT_CPU_V_OPSTOP, "Stop on invalid operation pseudo register"),
REG_HRO }, /* 69 */
{ HRDATAD (SR, SR, 8, "Front panel switches pseudo register"),
}, /* 70 */
{ HRDATAD (BANK, bankSelect, MAXBANKSLOG2, "Active bank pseudo register"),
}, /* 71 */
{ HRDATAD (COMMON, common, 32, "Starting address of common memory pseudo register"),
}, /* 72 */
{ HRDATAD (SWITCHERPORT, switcherPort, 8, "I/O port for CPU switcher pseudo register"),
}, /* 73 */
{ DRDATAD (CLOCK, clockFrequency, 32, "Clock frequency in kHz for 8080 / Z80 pseudo register"),
}, /* 74 */
{ DRDATAD (SLICE, sliceLength, 16, "Length of time slice for 8080 / Z80 pseudo register"),
}, /* 75 */
{ DRDATAD (TSTATES, executedTStates, 32, "Executed t-states for 8080 / Z80 pseudo register"),
REG_RO }, /* 76 */
{ HRDATAD (CAPACITY, cpu_unit.capac, 32, "Size of RAM pseudo register"),
REG_RO }, /* 77 */
{ HRDATAD (PREVCAP, previousCapacity, 32, "Previous size of RAM pseudo register"),
REG_RO }, /* 78 */
{ BRDATAD (PCQ, pcq, 16, 16, PCQ_SIZE, "Program counter circular buffer for 8080 /Z80 pseudo register"),
REG_RO + REG_CIRC }, /* 79 */
{ DRDATAD (PCQP, pcq_p, PCQ_SIZE_LOG2, "Circular buffer head for 8080 / Z80 pseudo register"),
REG_HRO }, /* 80 */
{ HRDATAD (WRU, sim_int_char, 8, "Interrupt character pseudo register"),
}, /* 81 */
{ NULL } { NULL }
}; };
static MTAB cpu_mod[] = { static MTAB cpu_mod[] = {
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_8080, NULL, "8080", &cpu_set_chiptype }, { MTAB_XTD | MTAB_VDV, CHIP_TYPE_8080, NULL, "8080", &cpu_set_chiptype,
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_Z80, NULL, "Z80", &cpu_set_chiptype }, NULL, NULL, "Chooses 8080 CPU"},
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_8086, NULL, "8086", &cpu_set_chiptype }, { MTAB_XTD | MTAB_VDV, CHIP_TYPE_Z80, NULL, "Z80", &cpu_set_chiptype,
{ UNIT_CPU_OPSTOP, UNIT_CPU_OPSTOP, "ITRAP", "ITRAP", NULL, &chip_show }, NULL, NULL, "Chooses Z80 CPU" },
{ UNIT_CPU_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL, &chip_show }, { MTAB_XTD | MTAB_VDV, CHIP_TYPE_8086, NULL, "8086", &cpu_set_chiptype,
{ UNIT_CPU_STOPONHALT, UNIT_CPU_STOPONHALT,"STOPONHALT", "STOPONHALT", NULL }, NULL, NULL, "Chooses 8086 CPU" },
{ UNIT_CPU_STOPONHALT, 0, "LOOPONHALT", "LOOPONHALT", NULL }, { MTAB_XTD | MTAB_VDV, CHIP_TYPE_M68K, NULL, "M68K", &cpu_set_chiptype,
{ UNIT_CPU_BANKED, UNIT_CPU_BANKED, "BANKED", "BANKED", &cpu_set_banked }, NULL, NULL, "Chooses M68K CPU" },
{ UNIT_CPU_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked }, { UNIT_CPU_OPSTOP, UNIT_CPU_OPSTOP, "ITRAP", "ITRAP", NULL, &chip_show,
{ UNIT_CPU_ALTAIRROM, UNIT_CPU_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom }, NULL, "Stop on illegal instruction" },
{ UNIT_CPU_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", &cpu_set_noaltairrom}, { UNIT_CPU_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL, &chip_show,
{ UNIT_CPU_VERBOSE, UNIT_CPU_VERBOSE, "VERBOSE", "VERBOSE", NULL, &cpu_show }, NULL, "Do not stop on illegal instruction" },
{ UNIT_CPU_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_CPU_STOPONHALT, UNIT_CPU_STOPONHALT,"STOPONHALT", "STOPONHALT", NULL,
{ MTAB_VDV, 0, NULL, "CLEARMEMORY", &cpu_clear_command }, NULL, NULL, "Stop on halt instruction" },
{ UNIT_CPU_MMU, UNIT_CPU_MMU, "MMU", "MMU", NULL }, { UNIT_CPU_STOPONHALT, 0, "LOOPONHALT", "LOOPONHALT", NULL,
{ UNIT_CPU_MMU, 0, "NOMMU", "NOMMU", &cpu_set_nommu }, NULL, NULL, "Enter loop on halt instruction" },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "MEMORY", &cpu_set_memory }, { UNIT_CPU_BANKED, UNIT_CPU_BANKED, "BANKED", "BANKED", &cpu_set_banked,
{ UNIT_CPU_SWITCHER, UNIT_CPU_SWITCHER, "SWITCHER", "SWITCHER", &cpu_set_switcher, &cpu_show_switcher }, NULL, NULL, "Enable banked memory for 8080 / Z80" },
{ UNIT_CPU_SWITCHER, 0, "NOSWITCHER", "NOSWITCHER", &cpu_reset_switcher, &cpu_show_switcher }, { UNIT_CPU_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked,
{ MTAB_XTD | MTAB_VDV, 0, NULL, "AZ80", &cpu_set_ramtype }, NULL, NULL, "Disable banked memory for 8080 / Z80" },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "HRAM", &cpu_set_ramtype }, { UNIT_CPU_ALTAIRROM, UNIT_CPU_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom,
{ MTAB_XTD | MTAB_VDV, 2, NULL, "VRAM", &cpu_set_ramtype }, NULL, NULL, "Enable Altair ROM for 8080 / Z80" },
{ MTAB_XTD | MTAB_VDV, 3, NULL, "CRAM", &cpu_set_ramtype }, { UNIT_CPU_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", &cpu_set_noaltairrom,
{ MTAB_VDV, 4, NULL, "4KB", &cpu_set_size }, NULL, NULL, "Disable Altair ROM for 8080 / Z80"},
{ MTAB_VDV, 8, NULL, "8KB", &cpu_set_size }, { UNIT_CPU_VERBOSE, UNIT_CPU_VERBOSE, "VERBOSE", "VERBOSE", NULL, &cpu_show,
{ MTAB_VDV, 12, NULL, "12KB", &cpu_set_size }, NULL, "Enable verbose messages" },
{ MTAB_VDV, 16, NULL, "16KB", &cpu_set_size }, { UNIT_CPU_VERBOSE, 0, "QUIET", "QUIET", NULL, NULL,
{ MTAB_VDV, 20, NULL, "20KB", &cpu_set_size }, NULL, "Disable verbose messages" },
{ MTAB_VDV, 24, NULL, "24KB", &cpu_set_size }, { MTAB_VDV, 0, NULL, "CLEARMEMORY", &cpu_clear_command,
{ MTAB_VDV, 28, NULL, "28KB", &cpu_set_size }, NULL, NULL, "Clears the RAM" },
{ MTAB_VDV, 32, NULL, "32KB", &cpu_set_size }, { UNIT_CPU_MMU, UNIT_CPU_MMU, "MMU", "MMU", NULL, NULL,
{ MTAB_VDV, 36, NULL, "36KB", &cpu_set_size }, NULL, "Enable the Memory Management Unit for 8080 / Z80" },
{ MTAB_VDV, 40, NULL, "40KB", &cpu_set_size }, { UNIT_CPU_MMU, 0, "NOMMU", "NOMMU", &cpu_set_nommu,
{ MTAB_VDV, 44, NULL, "44KB", &cpu_set_size }, NULL, NULL, "Disable the Memory Management Unit for 8080 / Z80" },
{ MTAB_VDV, 48, NULL, "48KB", &cpu_set_size }, { MTAB_XTD | MTAB_VDV, 0, NULL, "MEMORY", &cpu_set_memory,
{ MTAB_VDV, 52, NULL, "52KB", &cpu_set_size }, NULL, NULL, "Sets the RAM size for 8080 / Z80 / 8086" },
{ MTAB_VDV, 56, NULL, "56KB", &cpu_set_size }, { UNIT_CPU_SWITCHER, UNIT_CPU_SWITCHER, "SWITCHER", "SWITCHER", &cpu_set_switcher, &cpu_show_switcher,
{ MTAB_VDV, 60, NULL, "60KB", &cpu_set_size }, NULL, "Sets CPU switcher port for 8080 / Z80 / 8086" },
{ MTAB_VDV, 64, NULL, "64KB", &cpu_set_size }, { UNIT_CPU_SWITCHER, 0, "NOSWITCHER", "NOSWITCHER", &cpu_reset_switcher, &cpu_show_switcher,
NULL, "Resets CPU switcher port for 8080 / Z80 / 8086" },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "AZ80", &cpu_set_ramtype,
NULL, NULL, "Sets the RAM type to AltairZ80 RAM for 8080 / Z80 / 8086" },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "HRAM", &cpu_set_ramtype,
NULL, NULL, "Sets the RAM type to NorthStar HRAM for 8080 / Z80 / 8086" },
{ MTAB_XTD | MTAB_VDV, 2, NULL, "VRAM", &cpu_set_ramtype,
NULL, NULL, "Sets the RAM type to Vector RAM for 8080 / Z80 / 8086" },
{ MTAB_XTD | MTAB_VDV, 3, NULL, "CRAM", &cpu_set_ramtype,
NULL, NULL, "Sets the RAM type to Cromemco RAM for 8080 / Z80 / 8086" },
{ MTAB_VDV, 4, NULL, "4KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 4KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 8, NULL, "8KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 8KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 12, NULL, "12KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 12KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 16, NULL, "16KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 16KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 20, NULL, "20KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 20KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 24, NULL, "24KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 24KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 28, NULL, "28KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 28KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 32, NULL, "32KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 32KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 36, NULL, "36KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 36KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 40, NULL, "40KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 40KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 44, NULL, "44KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 44KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 48, NULL, "48KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 48KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 52, NULL, "52KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 52KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 56, NULL, "56KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 56KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 60, NULL, "60KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 60KB for 8080 / Z80 / 8086" },
{ MTAB_VDV, 64, NULL, "64KB", &cpu_set_size,
NULL, NULL, "Sets the RAM size to 64KB for 8080 / Z80 / 8086" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB cpu_dt[] = { static DEBTAB cpu_dt[] = {
{ "LOG_IN", IN_MSG }, { "LOG_IN", IN_MSG, "Log IN operations" },
{ "LOG_OUT", OUT_MSG }, { "LOG_OUT", OUT_MSG, "Log OUT operations" },
{ NULL, 0 } { NULL, 0 }
}; };
@ -449,7 +621,7 @@ static struct idev dev_table[256] = {
static int32 ramtype = 0; static int32 ramtype = 0;
#define MAX_RAM_TYPE 3 #define MAX_RAM_TYPE 3
int32 chiptype = CHIP_TYPE_8080; ChipType chiptype = CHIP_TYPE_8080;
void out(const uint32 Port, const uint32 Value) { void out(const uint32 Port, const uint32 Value) {
if ((cpu_dev.dctrl & OUT_MSG) && sim_deb) { if ((cpu_dev.dctrl & OUT_MSG) && sim_deb) {
@ -1555,9 +1727,9 @@ static void altairz80_print_tables(void) {
#define LOG2PAGESIZE 8 #define LOG2PAGESIZE 8
#define PAGESIZE (1 << LOG2PAGESIZE) #define PAGESIZE (1 << LOG2PAGESIZE)
static uint8 M[MAXMEMORY]; /* RAM which is present */ static uint8 M[MAXMEMORY]; /* RAM which is present (for 8080, Z80 and 8086 */
struct mdev { /* Structure to describe a 2^LOG2PAGESIZE byte page of address space */ typedef struct { /* Structure to describe a 2^LOG2PAGESIZE byte page of address space */
/* There are four cases /* There are four cases
isRAM isEmpty routine code isRAM isEmpty routine code
TRUE FALSE NULL W page is random access memory (RAM) TRUE FALSE NULL W page is random access memory (RAM)
@ -1569,9 +1741,7 @@ struct mdev { /* Structure to describe a 2^LOG2PAGESIZE byte page of address spa
uint32 isRAM; uint32 isRAM;
uint32 isEmpty; uint32 isEmpty;
int32 (*routine)(const int32, const int32, const int32); int32 (*routine)(const int32, const int32, const int32);
}; } MDEV;
typedef struct mdev MDEV;
static MDEV ROM_PAGE = {FALSE, FALSE, NULL}; /* this makes a page ROM */ static MDEV ROM_PAGE = {FALSE, FALSE, NULL}; /* this makes a page ROM */
static MDEV RAM_PAGE = {TRUE, FALSE, NULL}; /* this makes a page RAM */ static MDEV RAM_PAGE = {TRUE, FALSE, NULL}; /* this makes a page RAM */
@ -1852,13 +2022,15 @@ static int32 sim_brk_lookup (const t_addr loc, const int32 btyp) {
int32 switch_cpu_now = TRUE; /* hharte */ int32 switch_cpu_now = TRUE; /* hharte */
t_stat sim_instr (void) { t_stat sim_instr (void) {
uint32 i;
t_stat result; t_stat result;
if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU)) if (chiptype == CHIP_TYPE_M68K) {
result = sim_instr_m68k();
} else if ((chiptype == CHIP_TYPE_8086) || (cpu_unit.flags & UNIT_CPU_MMU))
do { do {
result = (chiptype == CHIP_TYPE_8086) ? sim_instr_8086() : sim_instr_mmu(); result = (chiptype == CHIP_TYPE_8086) ? sim_instr_8086() : sim_instr_mmu();
} while (switch_cpu_now == FALSE); } while (switch_cpu_now == FALSE);
else { else {
uint32 i;
for (i = 0; i < MAXBANKSIZE; i++) for (i = 0; i < MAXBANKSIZE; i++)
MOPT[i] = M[i]; MOPT[i] = M[i];
result = sim_instr_nommu(); result = sim_instr_nommu();
@ -6350,6 +6522,7 @@ static t_stat cpu_reset(DEVICE *dptr) {
IFF_S = 3; IFF_S = 3;
setBankSelect(0); setBankSelect(0);
cpu8086reset(); cpu8086reset();
m68k_cpu_reset();
sim_brk_types = (SWMASK('E') | SWMASK('I') | SWMASK('M')); sim_brk_types = (SWMASK('E') | SWMASK('I') | SWMASK('M'));
sim_brk_dflt = SWMASK('E'); sim_brk_dflt = SWMASK('E');
for (i = 0; i < PCQ_SIZE; i++) for (i = 0; i < PCQ_SIZE; i++)
@ -6365,18 +6538,9 @@ static t_stat cpu_reset(DEVICE *dptr) {
static t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs) { static t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs) {
static t_addr returns[2] = {0, 0}; static t_addr returns[2] = {0, 0};
if (chiptype == CHIP_TYPE_8086) { switch (chiptype) {
switch (GetBYTE(PCX_S)) { case CHIP_TYPE_8080:
case 0x9a: /* i86op_call_far_IMM */ case CHIP_TYPE_Z80:
case 0xe8: /* Ci86op_call_near_IMM */
returns[0] = PCX_S + (1 - fprint_sym (stdnul, PCX_S, sim_eval,
&cpu_unit, SWMASK ('M')));
*ret_addrs = returns;
return TRUE;
default:
return FALSE;
}
} else { // 8080 or Z80
switch (GetBYTE(PC_S)) { switch (GetBYTE(PC_S)) {
case 0xc4: /* CALL NZ,nnnn */ case 0xc4: /* CALL NZ,nnnn */
case 0xcc: /* CALL Z,nnnn */ case 0xcc: /* CALL Z,nnnn */
@ -6393,10 +6557,42 @@ static t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs) {
default: default:
return FALSE; return FALSE;
} }
break;
case CHIP_TYPE_8086:
switch (GetBYTE(PCX_S)) {
case 0x9a: /* i86op_call_far_IMM */
case 0xe8: /* Ci86op_call_near_IMM */
returns[0] = PCX_S + (1 - fprint_sym (stdnul, PCX_S, sim_eval,
&cpu_unit, SWMASK ('M')));
*ret_addrs = returns;
return TRUE;
default:
return FALSE;
}
break;
case CHIP_TYPE_M68K: {
const uint32 localPC = m68k_registers[M68K_REG_PC];
const uint32 instr = m68k_cpu_read_word(localPC);
if (((instr & 0xff00) == 0x6100) || /* BSR */
((instr & 0xffc0) == 0x4e80)) { /* JSR */
returns[0] = localPC + (1 - fprint_sym (stdnul, localPC, sim_eval,
&cpu_unit, SWMASK ('M')));
*ret_addrs = returns;
return TRUE;
}
return FALSE;
}
break;
default:
return FALSE;
break;
} }
} }
t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM) { t_stat install_bootrom(const int32 bootrom[], const int32 size, const int32 addr, const int32 makeROM) {
int32 i; int32 i;
if (addr & (PAGESIZE - 1)) if (addr & (PAGESIZE - 1))
return SCPE_IERR; return SCPE_IERR;
@ -6410,83 +6606,126 @@ t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM) {
/* memory examine */ /* memory examine */
static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) {
int32 oldBankSelect; switch (chiptype) {
if (chiptype == CHIP_TYPE_8086) case CHIP_TYPE_8080:
*vptr = GetBYTEExtended(addr); case CHIP_TYPE_Z80: {
else { const int32 oldBankSelect = getBankSelect();
oldBankSelect = getBankSelect();
setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK); setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK);
*vptr = GetBYTE(addr & ADDRMASK); *vptr = GetBYTE(addr & ADDRMASK);
setBankSelect(oldBankSelect); setBankSelect(oldBankSelect);
}
break;
case CHIP_TYPE_8086:
*vptr = GetBYTEExtended(addr);
break;
case CHIP_TYPE_M68K:
*vptr = m68k_cpu_read_byte(addr);
break;
default:
return SCPE_AFAIL;
break;
} }
return SCPE_OK; return SCPE_OK;
} }
/* memory deposit */ /* memory deposit */
static t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) { static t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) {
int32 oldBankSelect; switch (chiptype) {
if (chiptype == CHIP_TYPE_8086) case CHIP_TYPE_8080:
PutBYTEExtended(addr, val); case CHIP_TYPE_Z80: {
else { const int32 oldBankSelect = getBankSelect();
oldBankSelect = getBankSelect();
setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK); setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK);
PutBYTE(addr & ADDRMASK, val); PutBYTE(addr & ADDRMASK, val);
setBankSelect(oldBankSelect); setBankSelect(oldBankSelect);
}
break;
case CHIP_TYPE_8086:
PutBYTEExtended(addr, val);
break;
case CHIP_TYPE_M68K:
m68k_cpu_write_byte(addr & M68K_MAX_RAM, val);
break;
default:
return SCPE_AFAIL;
break;
} }
return SCPE_OK; return SCPE_OK;
} }
struct cpuflag { typedef struct {
int32 mask; /* bit mask within CPU status register */ uint32 mask; /* bit mask within CPU status register */
char name; /* character to print if flag is set */ const char* flagName; /* string to print if flag is set */
}; } CPUFLAG;
typedef struct cpuflag CPUFLAG;
static CPUFLAG cpuflags8086[] = { const static CPUFLAG cpuflags8080[] = {
{1 << 11, 'O'}, {1 << 7, "S"},
{1 << 10, 'D'}, {1 << 6, "Z"},
{1 << 9, 'I'}, {1 << 4, "A"},
{1 << 8, 'T'}, {1 << 3, "P"},
{1 << 7, 'S'}, {1 << 1, "N"},
{1 << 6, 'Z'}, {1 << 0, "C"},
{1 << 4, 'A'},
{1 << 2, 'P'},
{1 << 0, 'C'},
{0, 0} /* last mask must be 0 */ {0, 0} /* last mask must be 0 */
}; };
static CPUFLAG cpuflags8080[] = { const static CPUFLAG cpuflagsZ80[] = {
{1 << 7, 'S'}, {1 << 7, "S"},
{1 << 6, 'Z'}, {1 << 6, "Z"},
{1 << 4, 'A'}, {1 << 4, "A"},
{1 << 3, 'P'}, {1 << 3, "V"},
{1 << 1, 'N'}, {1 << 1, "N"},
{1 << 0, 'C'}, {1 << 0, "C"},
{0, 0} /* last mask must be 0 */ {0, 0} /* last mask must be 0 */
}; };
static CPUFLAG cpuflagsZ80[] = { const static CPUFLAG cpuflags8086[] = {
{1 << 7, 'S'}, {1 << 11, "O"},
{1 << 6, 'Z'}, {1 << 10, "D"},
{1 << 4, 'A'}, {1 << 9, "I"},
{1 << 3, 'V'}, {1 << 8, "T"},
{1 << 1, 'N'}, {1 << 7, "S"},
{1 << 0, 'C'}, {1 << 6, "Z"},
{1 << 4, "A"},
{1 << 2, "P"},
{1 << 0, "C"},
{0, 0} /* last mask must be 0 */ {0, 0} /* last mask must be 0 */
}; };
/* needs to be set for each chiptype <= MAX_CHIP_TYPE */ const static CPUFLAG cpuflagsM68K[] = {
static char *chipTypeToString[] = { "8080", "Z80", "8086" }; {1 << 15, "T1"}, /* Trace Enable T1 */
static int32 *flagregister[] = { &AF_S, &AF_S, &FLAGS_S }; {1 << 14, "T0"}, /* Trace Enable T0 */
static CPUFLAG *cpuflags[] = { cpuflags8080, cpuflagsZ80, cpuflags8086 }; {1 << 13, "S"}, /* Supervisor / User State */
{1 << 12, "M"}, /* Master / Interrupt State */
{1 << 10, "I2"}, /* Interrupt Priority Mask I2 */
{1 << 9, "I1"}, /* Interrupt Priority Mask I1 */
{1 << 8, "I0"}, /* Interrupt Priority Mask I0 */
{1 << 4, "X"}, /* Extend */
{1 << 3, "N"}, /* Negative */
{1 << 2, "Z"}, /* Zero */
{1 << 1, "V"}, /* Overflow */
{1 << 0, "C"}, /* Carry */
{0, 0}, /* last mask must be 0 */
};
/* needs to be set for each chiptype < NUM_CHIP_TYPE */
const static uint32 *flagregister[NUM_CHIP_TYPE] = { (uint32*)&AF_S, (uint32*)&AF_S,
(uint32*)&FLAGS_S, &m68k_registers[M68K_REG_SR]};
const static CPUFLAG *cpuflags[NUM_CHIP_TYPE] = { cpuflags8080, cpuflagsZ80,
cpuflags8086, cpuflagsM68K, };
/* needs to be set for each ramtype <= MAX_RAM_TYPE */ /* needs to be set for each ramtype <= MAX_RAM_TYPE */
static char *ramTypeToString[] = { "AZ80", "HRAM", "VRAM", "CRAM" }; static char *ramTypeToString[] = { "AZ80", "HRAM", "VRAM", "CRAM" };
static t_stat chip_show(FILE *st, UNIT *uptr, int32 val, void *desc) { static t_stat chip_show(FILE *st, UNIT *uptr, int32 val, void *desc) {
fprintf(st, cpu_unit.flags & UNIT_CPU_OPSTOP ? "ITRAP, " : "NOITRAP, "); fprintf(st, cpu_unit.flags & UNIT_CPU_OPSTOP ? "ITRAP, " : "NOITRAP, ");
if (chiptype <= MAX_CHIP_TYPE) if (chiptype < NUM_CHIP_TYPE)
fprintf(st, "%s", chipTypeToString[chiptype]); fprintf(st, "%s", cpu_mod[chiptype].mstring);
fprintf(st, ", "); fprintf(st, ", ");
if (ramtype <= MAX_RAM_TYPE) if (ramtype <= MAX_RAM_TYPE)
fprintf(st, "%s", ramTypeToString[ramtype]); fprintf(st, "%s", ramTypeToString[ramtype]);
@ -6498,7 +6737,9 @@ static t_stat cpu_show(FILE *st, UNIT *uptr, int32 val, void *desc) {
MDEV m; MDEV m;
maxBanks = ((cpu_unit.flags & UNIT_CPU_BANKED) || maxBanks = ((cpu_unit.flags & UNIT_CPU_BANKED) ||
(chiptype == CHIP_TYPE_8086)) ? MAXBANKS : 1; (chiptype == CHIP_TYPE_8086)) ? MAXBANKS : 1;
fprintf(st, "VERBOSE,\n "); fprintf(st, "VERBOSE,");
if (chiptype < CHIP_TYPE_M68K) { /* 8080, Z80, 8086 */
fprintf(st, "\n ");
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
fprintf(st, "0123456789ABCDEF"); fprintf(st, "0123456789ABCDEF");
fprintf(st, " [16k]"); fprintf(st, " [16k]");
@ -6526,16 +6767,17 @@ static t_stat cpu_show(FILE *st, UNIT *uptr, int32 val, void *desc) {
fprintf(st, "%02X", i); fprintf(st, "%02X", i);
} }
fprintf(st, "]"); fprintf(st, "]");
if (chiptype <= MAX_CHIP_TYPE) { }
if (chiptype < NUM_CHIP_TYPE) {
first = TRUE; first = TRUE;
/* show verbose CPU flags */ /* show verbose CPU flags */
for (i = 0; cpuflags[chiptype][i].mask; i++) for (i = 0; cpuflags[chiptype][i].mask; i++)
if (*flagregister[chiptype] & cpuflags[chiptype][i].mask) { if (*flagregister[chiptype] & cpuflags[chiptype][i].mask) {
if (first) { if (first) {
first = FALSE; first = FALSE;
fprintf(st, " "); fprintf(st, "\nFlags");
} }
fprintf(st, "%c", cpuflags[chiptype][i].name); fprintf(st, " %s", cpuflags[chiptype][i].flagName);
} }
} }
return SCPE_OK; return SCPE_OK;
@ -6551,6 +6793,7 @@ static void cpu_clear(void) {
mmu_table[i] = EMPTY_PAGE; mmu_table[i] = EMPTY_PAGE;
if (cpu_unit.flags & UNIT_CPU_ALTAIRROM) if (cpu_unit.flags & UNIT_CPU_ALTAIRROM)
install_ALTAIRbootROM(); install_ALTAIRbootROM();
m68k_clear_memory();
clockHasChanged = FALSE; clockHasChanged = FALSE;
} }
@ -6699,9 +6942,8 @@ static int32 bankseldev(const int32 port, const int32 io, const int32 data) {
} }
} }
static void cpu_set_chiptype_short(int32 value, uint32 need_cpu_clear) { static void cpu_set_chiptype_short(const int32 value) {
extern REG *sim_PC; if ((chiptype == value) || (chiptype >= NUM_CHIP_TYPE))
if ((chiptype == value) || (chiptype > MAX_CHIP_TYPE))
return; /* nothing to do */ return; /* nothing to do */
if (((chiptype == CHIP_TYPE_8080) && (value == CHIP_TYPE_Z80)) || if (((chiptype == CHIP_TYPE_8080) && (value == CHIP_TYPE_Z80)) ||
((chiptype == CHIP_TYPE_Z80) && (value == CHIP_TYPE_8080))) { ((chiptype == CHIP_TYPE_Z80) && (value == CHIP_TYPE_8080))) {
@ -6709,28 +6951,38 @@ static void cpu_set_chiptype_short(int32 value, uint32 need_cpu_clear) {
return; return;
} }
chiptype = value; chiptype = value;
if (chiptype == CHIP_TYPE_8086) { switch (chiptype) {
case CHIP_TYPE_8080:
case CHIP_TYPE_Z80:
MEMORYSIZE = previousCapacity;
cpu_dev.awidth = MAXBANKSIZELOG2;
sim_PC = &cpu_reg[CPU_INDEX_8080];
break;
case CHIP_TYPE_8086:
if (MEMORYSIZE <= MAXBANKSIZE) if (MEMORYSIZE <= MAXBANKSIZE)
previousCapacity = MEMORYSIZE; previousCapacity = MEMORYSIZE;
MEMORYSIZE = MAXMEMORY; MEMORYSIZE = MAXMEMORY;
cpu_unit.flags &= ~(UNIT_CPU_BANKED | UNIT_CPU_ALTAIRROM); cpu_unit.flags &= ~(UNIT_CPU_BANKED | UNIT_CPU_ALTAIRROM);
cpu_unit.flags |= UNIT_CPU_MMU; cpu_unit.flags |= UNIT_CPU_MMU;
cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2; cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2;
if (need_cpu_clear) sim_PC = &cpu_reg[CPU_INDEX_8086];
cpu_clear(); break;
sim_PC = &cpu_reg[7];
} case CHIP_TYPE_M68K:
else if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) { MEMORYSIZE = M68K_MAX_RAM + 1;
MEMORYSIZE = previousCapacity; cpu_dev.awidth = M68K_MAX_RAM_LOG2;
cpu_dev.awidth = MAXBANKSIZELOG2; sim_PC = &cpu_reg[CPU_INDEX_M68K];
if (need_cpu_clear) break;
cpu_clear();
sim_PC = &cpu_reg[6]; default:
break;
} }
} }
static t_stat cpu_set_chiptype(UNIT *uptr, int32 value, char *cptr, void *desc) { static t_stat cpu_set_chiptype(UNIT *uptr, int32 value, char *cptr, void *desc) {
cpu_set_chiptype_short(value, TRUE); cpu_set_chiptype_short(value);
cpu_clear();
return SCPE_OK; return SCPE_OK;
} }
@ -6758,7 +7010,7 @@ static int32 switchcpu_io(const int32 port, const int32 io, const int32 data) {
break; break;
} }
cpu_set_chiptype_short(new_chiptype, FALSE); cpu_set_chiptype_short(new_chiptype);
return(0xFF); /* Return High-Z Data */ return(0xFF); /* Return High-Z Data */
} else { } else {
printf("%s: Set EXT_ADDR=%02x\n", __FUNCTION__, data); printf("%s: Set EXT_ADDR=%02x\n", __FUNCTION__, data);
@ -6854,7 +7106,13 @@ static t_stat cpu_set_ramtype(UNIT *uptr, int32 value, char *cptr, void *desc) {
/* set memory to 'size' kilo byte */ /* set memory to 'size' kilo byte */
static t_stat set_size(uint32 size) { static t_stat set_size(uint32 size) {
uint32 maxsize = (((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) && uint32 maxsize;
if (chiptype == CHIP_TYPE_M68K) { // ignore for M68K
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("Setting memory size to %ikB ignored for M68K.\n", size);
return SCPE_OK;
}
maxsize = (((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) &&
((cpu_unit.flags & UNIT_CPU_BANKED) == 0)) ? MAXBANKSIZE : MAXMEMORY; ((cpu_unit.flags & UNIT_CPU_BANKED) == 0)) ? MAXBANKSIZE : MAXMEMORY;
size <<= KBLOG2; size <<= KBLOG2;
if (cpu_unit.flags & UNIT_CPU_BANKED) if (cpu_unit.flags & UNIT_CPU_BANKED)
@ -6910,6 +7168,41 @@ void (*sim_vm_init) (void) = &altairz80_init;
#define PLURAL(x) (x), (x) == 1 ? "" : "s" #define PLURAL(x) (x), (x) == 1 ? "" : "s"
static t_stat sim_load_m68k(FILE *fileref, char *cptr, char *fnam, int flag) {
char gbuf[CBUFSIZE];
int32 i;
t_addr j, lo, hi;
uint32 addr, org, cnt = 0;
char* result;
if (flag ) {
result = get_range(NULL, cptr, &lo, &hi, 16, M68K_MAX_RAM, 0);
if (result == NULL)
return SCPE_ARG;
for (j = lo; j <= hi; j++) {
if (putc(m68k_cpu_read_byte(j), fileref) == EOF)
return SCPE_IOERR;
}
printf("%d byte%s dumped [%x - %x] to %s.\n", PLURAL(hi + 1 - lo), lo, hi, fnam);
} else {
if (*cptr == 0)
addr = m68k_registers[M68K_REG_PC];
else {
get_glyph(cptr, gbuf, 0);
addr = strtotv(cptr, &result, 16) & M68K_MAX_RAM;
if (cptr == result)
return SCPE_ARG;
}
org = addr;
while ((addr <= M68K_MAX_RAM) && ((i = getc(fileref)) != EOF)) {
m68k_cpu_write_byte(addr++, i);
cnt++;
}
printf("%d byte%s [%d page%s] loaded at %x.\n",
PLURAL(cnt), PLURAL((cnt + 0xff) >> 8), org);
}
return SCPE_OK;
}
t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int flag) { t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int flag) {
int32 i; int32 i;
uint32 addr, cnt = 0, org, pagesModified = 0, makeROM = FALSE; uint32 addr, cnt = 0, org, pagesModified = 0, makeROM = FALSE;
@ -6917,6 +7210,8 @@ t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int flag) {
char *result; char *result;
MDEV m; MDEV m;
char gbuf[CBUFSIZE]; char gbuf[CBUFSIZE];
if (chiptype == CHIP_TYPE_M68K)
return sim_load_m68k(fileref, cptr, fnam, flag);
if (flag) { if (flag) {
result = get_range(NULL, cptr, &lo, &hi, 16, ADDRMASKEXTENDED, 0); result = get_range(NULL, cptr, &lo, &hi, 16, ADDRMASKEXTENDED, 0);
if (result == NULL) if (result == NULL)
@ -6925,7 +7220,7 @@ t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int flag) {
if (putc(GetBYTEExtended(j), fileref) == EOF) if (putc(GetBYTEExtended(j), fileref) == EOF)
return SCPE_IOERR; return SCPE_IOERR;
} }
printf("%d byte%s dumped [%x - %x].\n", PLURAL(hi + 1 - lo), lo, hi); printf("%d byte%s dumped [%x - %x] to %s.\n", PLURAL(hi + 1 - lo), lo, hi, fnam);
} }
else { else {
if (*cptr == 0) if (*cptr == 0)
@ -6940,7 +7235,8 @@ t_stat sim_load(FILE *fileref, char *cptr, char *fnam, int flag) {
addr = strtotv(cptr, &result, 16) & ADDRMASKEXTENDED; addr = strtotv(cptr, &result, 16) & ADDRMASKEXTENDED;
if (cptr == result) if (cptr == result)
return SCPE_ARG; return SCPE_ARG;
while (isspace(*result)) result++; while (isspace(*result))
result++;
get_glyph(result, gbuf, 0); get_glyph(result, gbuf, 0);
if (strcmp(gbuf, "ROM") == 0) if (strcmp(gbuf, "ROM") == 0)
makeROM = TRUE; makeROM = TRUE;
@ -6981,6 +7277,6 @@ void cpu_raise_interrupt(uint32 irq) {
cpu8086_intr(irq); cpu8086_intr(irq);
} else if (cpu_unit.flags & UNIT_CPU_VERBOSE) { } else if (cpu_unit.flags & UNIT_CPU_VERBOSE) {
printf("Interrupts not fully supported for chiptype: %s\n", printf("Interrupts not fully supported for chiptype: %s\n",
(chiptype <= MAX_CHIP_TYPE) ? chipTypeToString[chiptype] : "????"); (chiptype < NUM_CHIP_TYPE) ? cpu_mod[chiptype].mstring : "????");
} }
} }

View file

@ -26,6 +26,9 @@
Based on work by Charles E Owen (c) 1997 Based on work by Charles E Owen (c) 1997
*/ */
#ifndef ALTAIRZ80_DEFS_H_
#define ALTAIRZ80_DEFS_H_ 0
#include "sim_defs.h" /* simulator definitions */ #include "sim_defs.h" /* simulator definitions */
#define MAXBANKSIZE 65536 /* maximum memory size, a power of 2 */ #define MAXBANKSIZE 65536 /* maximum memory size, a power of 2 */
@ -48,10 +51,15 @@
#define UNIT_NO_OFFSET_1 0x37 /* LD A,<unitno> */ #define UNIT_NO_OFFSET_1 0x37 /* LD A,<unitno> */
#define UNIT_NO_OFFSET_2 0xb4 /* LD a,80h | <unitno> */ #define UNIT_NO_OFFSET_2 0xb4 /* LD a,80h | <unitno> */
#define CHIP_TYPE_8080 0 #define CPU_INDEX_8080 4 /* index of default PC register */
#define CHIP_TYPE_Z80 1
#define CHIP_TYPE_8086 2 typedef enum {
#define MAX_CHIP_TYPE CHIP_TYPE_8086 CHIP_TYPE_8080 = 0,
CHIP_TYPE_Z80,
CHIP_TYPE_8086,
CHIP_TYPE_M68K, /* must come after 8080, Z80 and 8086 */
NUM_CHIP_TYPE, /* must be last */
} ChipType;
/* simulator stop codes */ /* simulator stop codes */
#define STOP_HALT 0 /* HALT */ #define STOP_HALT 0 /* HALT */
@ -81,7 +89,7 @@
#define UNIX_PLATFORM 0 #define UNIX_PLATFORM 0
#endif #endif
#define ADDRESS_FORMAT "[0x%05x]" #define ADDRESS_FORMAT "[0x%08x]"
/* use NLP for new line printing while the simulation is running */ /* use NLP for new line printing while the simulation is running */
#if UNIX_PLATFORM #if UNIX_PLATFORM
@ -100,3 +108,5 @@ typedef struct {
uint32 io_base; /* I/O Base Address */ uint32 io_base; /* I/O Base Address */
uint32 io_size; /* I/O Address Space requirement */ uint32 io_size; /* I/O Address Space requirement */
} PNP_INFO; } PNP_INFO;
#endif

Binary file not shown.

View file

@ -106,6 +106,11 @@
T = Sector True, is a 1 when the sector is positioned to read or T = Sector True, is a 1 when the sector is positioned to read or
write. write.
----------------------------------------------------------
5/22/2014 - Updated by Mike Douglas to support the Altair Mini-Disk.
This disk uses 35 (vs 70) tracks of 16 (vs 32) sectors
of 137 bytes each.
*/ */
#include "altairz80_defs.h" #include "altairz80_defs.h"
@ -131,21 +136,26 @@
#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1) #define NUM_OF_DSK_MASK (NUM_OF_DSK - 1)
#define BOOTROM_SIZE_DSK 256 /* size of boot rom */ #define BOOTROM_SIZE_DSK 256 /* size of boot rom */
#define MINI_DISK_SECT 16 /* mini disk sectors per track */
#define MINI_DISK_TRACKS 35 /* number of tracks on mini disk */
#define MINI_DISK_SIZE (MINI_DISK_TRACKS * MINI_DISK_SECT * DSK_SECTSIZE)
#define MINI_DISK_DELTA 4096 /* threshold for detecting mini disks */
int32 dsk10(const int32 port, const int32 io, const int32 data); int32 dsk10(const int32 port, const int32 io, const int32 data);
int32 dsk11(const int32 port, const int32 io, const int32 data); int32 dsk11(const int32 port, const int32 io, const int32 data);
int32 dsk12(const int32 port, const int32 io, const int32 data); int32 dsk12(const int32 port, const int32 io, const int32 data);
static t_stat dsk_boot(int32 unitno, DEVICE *dptr); static t_stat dsk_boot(int32 unitno, DEVICE *dptr);
static t_stat dsk_reset(DEVICE *dptr); static t_stat dsk_reset(DEVICE *dptr);
static t_stat dsk_attach(UNIT *uptr, char *cptr);
extern REG *sim_PC;
extern UNIT cpu_unit; extern UNIT cpu_unit;
extern uint32 PCX; extern uint32 PCX;
extern t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); extern t_stat install_bootrom(const int32 bootrom[], const int32 size, const int32 addr, const int32 makeROM);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
int32 (*routine)(const int32, const int32, const int32), uint8 unmap); int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
void install_ALTAIRbootROM(void); void install_ALTAIRbootROM(void);
extern int32 find_unit_index(UNIT *uptr);
/* global data on status */ /* global data on status */
@ -156,6 +166,10 @@ static int32 current_track [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
static int32 current_sector [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static int32 current_sector [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int32 current_byte [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static int32 current_byte [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int32 current_flag [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static int32 current_flag [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int32 sectors_per_track [NUM_OF_DSK] = { DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT,
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT,
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT,
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT };
static uint8 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, static uint8 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
@ -171,6 +185,41 @@ static int32 warnDSK11 = 0;
static int32 warnDSK12 = 0; static int32 warnDSK12 = 0;
static int8 dskbuf[DSK_SECTSIZE]; /* data Buffer */ static int8 dskbuf[DSK_SECTSIZE]; /* data Buffer */
const static int32 alt_bootrom_dsk[BOOTROM_SIZE_DSK] = { // boot ROM for mini disk support
0x21, 0x13, 0xff, 0x11, 0x00, 0x4c, 0x0e, 0xe3, /* ff00-ff07 */
0x7e, 0x12, 0x23, 0x13, 0x0d, 0xc2, 0x08, 0xff, /* ff08-ff0f */
0xc3, 0x00, 0x4c, 0xf3, 0xaf, 0xd3, 0x22, 0x2f, /* ff10-ff17 */
0xd3, 0x23, 0x3e, 0x2c, 0xd3, 0x22, 0x3e, 0x03, /* ff18-ff1f */
0xd3, 0x10, 0xdb, 0xff, 0xe6, 0x11, 0x0f, 0x0f, /* ff20-ff27 */
0xc6, 0x10, 0xd3, 0x10, 0x31, 0x71, 0x4d, 0xaf, /* ff28-ff2f */
0xd3, 0x08, 0xdb, 0x08, 0xe6, 0x08, 0xc2, 0x1c, /* ff30-ff37 */
0x4c, 0x3e, 0x04, 0xd3, 0x09, 0xc3, 0x38, 0x4c, /* ff38-ff3f */
0xdb, 0x08, 0xe6, 0x02, 0xc2, 0x2d, 0x4c, 0x3e, /* ff40-ff47 */
0x02, 0xd3, 0x09, 0xdb, 0x08, 0xe6, 0x40, 0xc2, /* ff48-ff4f */
0x2d, 0x4c, 0x11, 0x00, 0x00, 0x06, 0x00, 0x3e, /* ff50-ff57 */
0x10, 0xf5, 0xd5, 0xc5, 0xd5, 0x11, 0x86, 0x80, /* ff58-ff5f */
0x21, 0xe3, 0x4c, 0xdb, 0x09, 0x1f, 0xda, 0x50, /* ff60-ff67 */
0x4c, 0xe6, 0x1f, 0xb8, 0xc2, 0x50, 0x4c, 0xdb, /* ff68-ff6f */
0x08, 0xb7, 0xfa, 0x5c, 0x4c, 0xdb, 0x0a, 0x77, /* ff70-ff77 */
0x23, 0x1d, 0xc2, 0x5c, 0x4c, 0xe1, 0x11, 0xe6, /* ff78-ff7f */
0x4c, 0x01, 0x80, 0x00, 0x1a, 0x77, 0xbe, 0xc2, /* ff80-ff87 */
0xc3, 0x4c, 0x80, 0x47, 0x13, 0x23, 0x0d, 0xc2, /* ff88-ff8f */
0x71, 0x4c, 0x1a, 0xfe, 0xff, 0xc2, 0x88, 0x4c, /* ff90-ff97 */
0x13, 0x1a, 0xb8, 0xc1, 0xeb, 0xc2, 0xba, 0x4c, /* ff98-ff9f */
0xf1, 0xf1, 0x2a, 0xe4, 0x4c, 0xcd, 0xdd, 0x4c, /* ffa0-ffa7 */
0xd2, 0xb3, 0x4c, 0x04, 0x04, 0x78, 0xfe, 0x10, /* ffa8-ffaf */
0xda, 0x44, 0x4c, 0x06, 0x01, 0xca, 0x44, 0x4c, /* ffb0-ffb7 */
0xdb, 0x08, 0xe6, 0x02, 0xc2, 0xa5, 0x4c, 0x3e, /* ffb8-ffbf */
0x01, 0xd3, 0x09, 0xc3, 0x42, 0x4c, 0x3e, 0x80, /* ffc0-ffc7 */
0xd3, 0x08, 0xc3, 0x00, 0x00, 0xd1, 0xf1, 0x3d, /* ffc8-ffcf */
0xc2, 0x46, 0x4c, 0x3e, 0x43, 0x01, 0x3e, 0x4d, /* ffd0-ffd7 */
0xfb, 0x32, 0x00, 0x00, 0x22, 0x01, 0x00, 0x47, /* ffd8-ffdf */
0x3e, 0x80, 0xd3, 0x08, 0x78, 0xd3, 0x01, 0xd3, /* ffe0-ffe7 */
0x11, 0xd3, 0x05, 0xd3, 0x23, 0xc3, 0xd2, 0x4c, /* ffe8-ffef */
0x7a, 0xbc, 0xc0, 0x7b, 0xbd, 0xc9, 0x00, 0x00, /* fff0-fff7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff8-ffff */
};
/* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */ /* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */
int32 bootrom_dsk[BOOTROM_SIZE_DSK] = { int32 bootrom_dsk[BOOTROM_SIZE_DSK] = {
0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */ 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */
@ -229,40 +278,62 @@ static UNIT dsk_unit[] = {
}; };
static REG dsk_reg[] = { static REG dsk_reg[] = {
{ DRDATA (DISK, current_disk, 4) }, { DRDATAD (DISK, current_disk, 4,
{ BRDATA (CURTRACK, current_track, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, "Selected disk register"), },
{ BRDATA (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, { BRDATAD (CURTRACK, current_track, 10, 32, NUM_OF_DSK,
{ BRDATA (CURBYTE, current_byte, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, "Selected track register array"), REG_CIRC + REG_RO },
{ BRDATA (CURFLAG, current_flag, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, { BRDATAD (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK,
{ BRDATA (TRACKS, tracks, 10, 8, NUM_OF_DSK), REG_CIRC }, "Selected sector register array"), REG_CIRC + REG_RO },
{ DRDATA (IN9COUNT, in9_count, 4), REG_RO }, { BRDATAD (CURBYTE, current_byte, 10, 32, NUM_OF_DSK,
{ DRDATA (IN9MESSAGE, in9_message, 4), REG_RO }, "Current byte register arrayr"), REG_CIRC + REG_RO },
{ DRDATA (DIRTY, dirty, 4), REG_RO }, { BRDATAD (CURFLAG, current_flag, 10, 32, NUM_OF_DSK,
{ DRDATA (DSKWL, warnLevelDSK, 32) }, "Current flag register array"), REG_CIRC + REG_RO },
{ BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, { BRDATAD (TRACKS, tracks, 10, 8, NUM_OF_DSK,
{ BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, "Number of tracks register array"), REG_CIRC },
{ DRDATA (WARNDSK10, warnDSK10, 4), REG_RO }, { BRDATAD (SECTPERTRACK,sectors_per_track, 10, 8, NUM_OF_DSK,
{ DRDATA (WARNDSK11, warnDSK11, 4), REG_RO }, "Number of sectors per track register array"), REG_CIRC },
{ DRDATA (WARNDSK12, warnDSK12, 4), REG_RO }, { DRDATAD (IN9COUNT, in9_count, 4,
{ BRDATA (DISKBUFFER, dskbuf, 10, 8, DSK_SECTSIZE), REG_CIRC + REG_RO }, "Count of IN(9) register"), REG_RO },
{ DRDATAD (IN9MESSAGE, in9_message, 4,
"BOOL for IN(9) message register"), REG_RO },
{ DRDATAD (DIRTY, dirty, 4,
"BOOL for write needed register"), REG_RO },
{ DRDATAD (DSKWL, warnLevelDSK, 32,
"Warn level register") },
{ BRDATAD (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK,
"Count of write to locked register array"), REG_CIRC + REG_RO },
{ BRDATAD (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK,
"Count for selection of unattached disk register array"), REG_CIRC + REG_RO },
{ DRDATAD (WARNDSK10, warnDSK10, 4,
"Count of IN(8) on unattached disk register"), REG_RO },
{ DRDATAD (WARNDSK11, warnDSK11, 4,
"Count of IN/OUT(9) on unattached disk register"), REG_RO },
{ DRDATAD (WARNDSK12, warnDSK12, 4,
"Count of IN/OUT(10) on unattached disk register"), REG_RO },
{ BRDATAD (DISKBUFFER, dskbuf, 10, 8, DSK_SECTSIZE,
"Disk data buffer array"), REG_CIRC + REG_RO },
{ NULL } { NULL }
}; };
#define DSK_NAME "Altair Floppy Disk DSK"
static MTAB dsk_mod[] = { static MTAB dsk_mod[] = {
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL }, { UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL, NULL, NULL,
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL }, "Enables " DSK_NAME "n for writing" },
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL, NULL, NULL,
"Locks " DSK_NAME "n for writing" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB dsk_dt[] = { static DEBTAB dsk_dt[] = {
{ "IN", IN_MSG }, { "IN", IN_MSG, "IN operations" },
{ "OUT", OUT_MSG }, { "OUT", OUT_MSG, "OUT operations" },
{ "READ", READ_MSG }, { "READ", READ_MSG, "Read operations" },
{ "WRITE", WRITE_MSG }, { "WRITE", WRITE_MSG, "Write operations" },
{ "SECTOR_STUCK", SECTOR_STUCK_MSG }, { "SECTOR_STUCK", SECTOR_STUCK_MSG, "Sector stuck" },
{ "TRACK_STUCK", TRACK_STUCK_MSG }, { "TRACK_STUCK", TRACK_STUCK_MSG, "Track stuck" },
{ "VERBOSE", VERBOSE_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ NULL, 0 } { NULL, 0 }
}; };
@ -270,9 +341,9 @@ DEVICE dsk_dev = {
"DSK", dsk_unit, dsk_reg, dsk_mod, "DSK", dsk_unit, dsk_reg, dsk_mod,
NUM_OF_DSK, 10, 31, 1, 8, 8, NUM_OF_DSK, 10, 31, 1, 8, 8,
NULL, NULL, &dsk_reset, NULL, NULL, &dsk_reset,
&dsk_boot, NULL, NULL, &dsk_boot, &dsk_attach, NULL,
NULL, (DEV_DISABLE | DEV_DEBUG), 0, NULL, (DEV_DISABLE | DEV_DEBUG), 0,
dsk_dt, NULL, "Altair Floppy Disk DSK" dsk_dt, NULL, DSK_NAME
}; };
static char* selectInOut(const int32 io) { static char* selectInOut(const int32 io) {
@ -291,7 +362,6 @@ static t_stat dsk_reset(DEVICE *dptr) {
current_sector[i] = 0; current_sector[i] = 0;
current_byte[i] = 0; current_byte[i] = 0;
current_flag[i] = 0; current_flag[i] = 0;
tracks[i] = MAX_TRACKS;
} }
warnDSK10 = 0; warnDSK10 = 0;
warnDSK11 = 0; warnDSK11 = 0;
@ -304,6 +374,28 @@ static t_stat dsk_reset(DEVICE *dptr) {
sim_map_resource(0x0A, 1, RESOURCE_TYPE_IO, &dsk12, dptr->flags & DEV_DIS); sim_map_resource(0x0A, 1, RESOURCE_TYPE_IO, &dsk12, dptr->flags & DEV_DIS);
return SCPE_OK; return SCPE_OK;
} }
/* dsk_attach - determine type of drive attached based on disk image size */
static t_stat dsk_attach(UNIT *uptr, char *cptr) {
int32 thisUnitIndex;
int32 imageSize;
const t_stat r = attach_unit(uptr, cptr); /* attach unit */
if (r != SCPE_OK) /* error? */
return r;
assert(uptr != NULL);
thisUnitIndex = find_unit_index(uptr);
assert((0 <= thisUnitIndex) && (thisUnitIndex < NUM_OF_DSK));
/* If the file size is close to the mini-disk image size, set the number of
tracks to 16, otherwise, 32 sectors per track. */
imageSize = sim_fsize(uptr -> fileref);
sectors_per_track[thisUnitIndex] = (((MINI_DISK_SIZE - MINI_DISK_DELTA < imageSize) &&
(imageSize < MINI_DISK_SIZE + MINI_DISK_DELTA)) ?
MINI_DISK_SECT : DSK_SECT);
return SCPE_OK;
}
void install_ALTAIRbootROM(void) { void install_ALTAIRbootROM(void) {
const t_bool result = (install_bootrom(bootrom_dsk, BOOTROM_SIZE_DSK, ALTAIR_ROM_LOW, TRUE) == const t_bool result = (install_bootrom(bootrom_dsk, BOOTROM_SIZE_DSK, ALTAIR_ROM_LOW, TRUE) ==
@ -316,8 +408,14 @@ void install_ALTAIRbootROM(void) {
*/ */
static t_stat dsk_boot(int32 unitno, DEVICE *dptr) { static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) { if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) {
if (sectors_per_track[unitno] == MINI_DISK_SECT) {
const t_bool result = (install_bootrom(alt_bootrom_dsk, BOOTROM_SIZE_DSK,
ALTAIR_ROM_LOW, TRUE) == SCPE_OK);
assert(result);
} else {
/* check whether we are really modifying an LD A,<> instruction */ /* check whether we are really modifying an LD A,<> instruction */
if ((bootrom_dsk[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) && (bootrom_dsk[UNIT_NO_OFFSET_2 - 1] == LDA_INSTRUCTION)) { if ((bootrom_dsk[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) &&
(bootrom_dsk[UNIT_NO_OFFSET_2 - 1] == LDA_INSTRUCTION)) {
bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */ bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */
bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */ bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
} }
@ -327,12 +425,13 @@ static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
} }
install_ALTAIRbootROM(); /* install modified ROM */ install_ALTAIRbootROM(); /* install modified ROM */
} }
}
*((int32 *) sim_PC->loc) = ALTAIR_ROM_LOW; *((int32 *) sim_PC->loc) = ALTAIR_ROM_LOW;
return SCPE_OK; return SCPE_OK;
} }
static int32 dskseek(const UNIT *xptr) { static int32 dskseek(const UNIT *xptr) {
return sim_fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] + return sim_fseek(xptr -> fileref, DSK_SECTSIZE * sectors_per_track[current_disk] * current_track[current_disk] +
DSK_SECTSIZE * current_sector[current_disk], SEEK_SET); DSK_SECTSIZE * current_sector[current_disk], SEEK_SET);
} }
@ -465,7 +564,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
writebuf(); writebuf();
if (current_flag[current_disk] & 0x04) { /* head loaded? */ if (current_flag[current_disk] & 0x04) { /* head loaded? */
current_sector[current_disk]++; current_sector[current_disk]++;
if (current_sector[current_disk] >= DSK_SECT) if (current_sector[current_disk] >= sectors_per_track[current_disk])
current_sector[current_disk] = 0; current_sector[current_disk] = 0;
current_byte[current_disk] = 0xff; current_byte[current_disk] = 0xff;
return (((current_sector[current_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */ return (((current_sector[current_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */

View file

@ -26,7 +26,7 @@
Contains code from Howard M. Harte for defining and changing disk geometry. Contains code from Howard M. Harte for defining and changing disk geometry.
*/ */
#include "altairz80_defs.h" #include "m68k.h"
#include <assert.h> #include <assert.h>
#include "sim_imd.h" #include "sim_imd.h"
@ -56,7 +56,7 @@ static void verifyDiskInfo(const DISK_INFO *info, const char unitChar);
#define HDSK_NUMBER_OF_TRACKS u3 /* number of tracks */ #define HDSK_NUMBER_OF_TRACKS u3 /* number of tracks */
#define HDSK_FORMAT_TYPE u6 /* Disk Format Type */ #define HDSK_FORMAT_TYPE u6 /* Disk Format Type */
#define HDSK_CAPACITY (2048*32*128) /* Default Altair HDSK Capacity */ #define HDSK_CAPACITY (2048*32*128) /* Default Altair HDSK Capacity */
#define HDSK_NUMBER 8 /* number of hard disks */ #define HDSK_NUMBER 16 /* number of hard disks */
#define CPM_OK 0 /* indicates to CP/M everything ok */ #define CPM_OK 0 /* indicates to CP/M everything ok */
#define CPM_ERROR 1 /* indicates to CP/M an error condition */ #define CPM_ERROR 1 /* indicates to CP/M an error condition */
#define CPM_EMPTY 0xe5 /* default value for non-existing bytes */ #define CPM_EMPTY 0xe5 /* default value for non-existing bytes */
@ -70,13 +70,13 @@ static void verifyDiskInfo(const DISK_INFO *info, const char unitChar);
#define BOOTROM_SIZE_HDSK 256 #define BOOTROM_SIZE_HDSK 256
extern uint32 PCX; extern uint32 PCX;
extern REG *sim_PC;
extern UNIT cpu_unit; extern UNIT cpu_unit;
extern ChipType chiptype;
extern void install_ALTAIRbootROM(void); extern void install_ALTAIRbootROM(void);
extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value);
extern uint8 GetBYTEWrapper(const uint32 Addr); extern uint8 GetBYTEWrapper(const uint32 Addr);
extern t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); extern t_stat install_bootrom(const int32 bootrom[], const int32 size, const int32 addr, const int32 makeROM);
extern int32 bootrom_dsk[]; extern int32 bootrom_dsk[];
extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
@ -94,11 +94,40 @@ static int32 selectedDisk;
static int32 selectedSector; static int32 selectedSector;
static int32 selectedTrack; static int32 selectedTrack;
static int32 selectedDMA; static int32 selectedDMA;
static int32 hdskStatus;
void hdsk_prepareRead(void) {
hdskLastCommand = HDSK_READ;
}
void hdsk_prepareWrite(void) {
hdskLastCommand = HDSK_WRITE;
}
void hdsk_setSelectedDisk(const int32 disk) {
selectedDisk = disk;
}
void hdsk_setSelectedSector(const int32 sector) {
selectedSector = sector;
}
void hdsk_setSelectedTrack(const int32 track) {
selectedTrack = track;
}
void hdsk_setSelectedDMA(const int32 dma) {
selectedDMA = dma;
}
int32 hdsk_getStatus(void) {
return hdskStatus;
}
typedef struct { typedef struct {
char name[DPB_NAME_LENGTH + 1]; /* name of CP/M disk parameter block */ char name[DPB_NAME_LENGTH + 1]; /* name of CP/M disk parameter block */
t_addr capac; /* capacity */ t_addr capac; /* capacity */
uint16 spt; /* sectors per track */ uint32 spt; /* sectors per track */
uint8 bsh; /* data allocation block shift factor */ uint8 bsh; /* data allocation block shift factor */
uint8 blm; /* data allocation block mask */ uint8 blm; /* data allocation block mask */
uint8 exm; /* extent mask */ uint8 exm; /* extent mask */
@ -163,6 +192,9 @@ static DPB dpb[] = {
{ "HDSK", HDSK_CAPACITY, 32, 0x05, 0x1F, 0x01, 0x07f9, 0x03FF, { "HDSK", HDSK_CAPACITY, 32, 0x05, 0x1F, 0x01, 0x07f9, 0x03FF,
0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00, 0, 0, NULL }, /* AZ80 HDSK */ 0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00, 0, 0, NULL }, /* AZ80 HDSK */
{ "CPM68K", (1 << 24), (1<<17),0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, NULL }, /* CP/M-68K HDSK */
{ "EZ80FL", 131072, 32, 0x03, 0x07, 0x00, 127, 0x003E, { "EZ80FL", 131072, 32, 0x03, 0x07, 0x00, 127, 0x003E,
0xC0, 0x00, 0x0000, 0x0000, 0x02, 0x03, 0, 0, NULL }, /* 128K FLASH */ 0xC0, 0x00, 0x0000, 0x0000, 0x02, 0x03, 0, 0, NULL }, /* 128K FLASH */
@ -272,40 +304,60 @@ static UNIT hdsk_unit[] = {
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) } { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
}; };
static DISK_INFO* hdsk_imd[HDSK_NUMBER]; static DISK_INFO* hdsk_imd[HDSK_NUMBER];
static REG hdsk_reg[] = { static REG hdsk_reg[] = {
{ DRDATA (HDCMD, hdskLastCommand, 32), REG_RO }, { DRDATAD (HDCMD, hdskLastCommand, 32, "Last command"),
{ DRDATA (HDPOS, hdskCommandPosition, 32), REG_RO }, REG_RO },
{ DRDATA (HDDSK, selectedDisk, 32), REG_RO }, { DRDATAD (HDPOS, hdskCommandPosition, 32, "Commmand position"),
{ DRDATA (HDSEC, selectedSector, 32), REG_RO }, REG_RO },
{ DRDATA (HDTRK, selectedTrack, 32), REG_RO }, { DRDATAD (HDDSK, selectedDisk, 32, "Selected disk"),
{ DRDATA (HDDMA, selectedDMA, 32), REG_RO }, REG_RO },
{ DRDATAD (HDSEC, selectedSector, 32, "Selected sector"),
REG_RO },
{ DRDATAD (HDTRK, selectedTrack, 32, "Selected track"),
REG_RO },
{ DRDATAD (HDDMA, selectedDMA, 32, "Selected Direct Memory Access address"), REG_RO },
{ NULL } { NULL }
}; };
#define HDSK_NAME "Hard Disk HDSK"
static MTAB hdsk_mod[] = { static MTAB hdsk_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", &set_format, &show_format, NULL }, &set_iobase, &show_iobase, NULL, "Defines the I/O port assignment for device " HDSK_NAME },
{ UNIT_HDSK_WLK, 0, "WRTENB", "WRTENB", NULL }, { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
{ UNIT_HDSK_WLK, UNIT_HDSK_WLK, "WRTLCK", "WRTLCK", NULL }, &set_format, &show_format, NULL, "Defines the format for unit " HDSK_NAME "n" },
{ MTAB_XTD|MTAB_VUN, 0, "GEOM", "GEOM", &set_geom, &show_geom, NULL }, { UNIT_HDSK_WLK, 0, "WRTENB", "WRTENB",
NULL, NULL, NULL, "Enables " HDSK_NAME "n for writing" },
{ UNIT_HDSK_WLK, UNIT_HDSK_WLK, "WRTLCK", "WRTLCK",
NULL, NULL, NULL, "Locks " HDSK_NAME "n for writing" },
{ MTAB_XTD|MTAB_VUN, 0, "GEOM", "GEOM",
&set_geom, &show_geom, NULL, "Sets the disk geometry for unit " HDSK_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB hdsk_dt[] = { static DEBTAB hdsk_dt[] = {
{ "READ", READ_MSG }, { "READ", READ_MSG, "Disk read activity" },
{ "WRITE", WRITE_MSG }, { "WRITE", WRITE_MSG, "Disk write activity" },
{ "VERBOSE", VERBOSE_MSG }, { "VERBOSE", VERBOSE_MSG, "All disk activity" },
{ NULL, 0 } { NULL, 0 }
}; };
DEVICE hdsk_dev = { DEVICE hdsk_dev = {
"HDSK", hdsk_unit, hdsk_reg, hdsk_mod, "HDSK", hdsk_unit, hdsk_reg, hdsk_mod,
8, 10, 31, 1, 8, 8, HDSK_NUMBER, 10, 31, 1, 8, 8,
NULL, NULL, &hdsk_reset, NULL, NULL, &hdsk_reset,
&hdsk_boot, &hdsk_attach, &hdsk_detach, &hdsk_boot, &hdsk_attach, &hdsk_detach,
&hdsk_info_data, (DEV_DISABLE | DEV_DEBUG), 0, &hdsk_info_data, (DEV_DISABLE | DEV_DEBUG), 0,
@ -596,6 +648,8 @@ static int32 bootrom_hdsk[BOOTROM_SIZE_HDSK] = {
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) { static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
t_bool installSuccessful; t_bool installSuccessful;
if (chiptype == CHIP_TYPE_M68K)
return m68k_hdsk_boot(unitno, dptr, VERBOSE_MSG, HDSK_NUMBER);
if (MEMORYSIZE < 24 * KB) { if (MEMORYSIZE < 24 * KB) {
printf("Need at least 24KB RAM to boot from hard disk.\n"); printf("Need at least 24KB RAM to boot from hard disk.\n");
return SCPE_ARG; return SCPE_ARG;
@ -668,7 +722,7 @@ static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
*/ */
/* check the parameters and return TRUE iff parameters are correct or have been repaired */ /* check the parameters and return TRUE iff parameters are correct or have been repaired */
static int32 checkParameters(void) { t_bool hdsk_checkParameters(void) {
UNIT *uptr; UNIT *uptr;
if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) { if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
@ -684,7 +738,7 @@ static int32 checkParameters(void) {
} }
if ((selectedSector < 0) || (selectedSector >= uptr -> HDSK_SECTORS_PER_TRACK)) { if ((selectedSector < 0) || (selectedSector >= uptr -> HDSK_SECTORS_PER_TRACK)) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Constraint violation 0 <= Sector=%02d < %d, will use sector 0 instead.\n", " Constraint violation 0 <= Sector=%06d < %d, will use sector 0 instead.\n",
selectedDisk, PCX, selectedSector, uptr -> HDSK_SECTORS_PER_TRACK); selectedDisk, PCX, selectedSector, uptr -> HDSK_SECTORS_PER_TRACK);
selectedSector = 0; selectedSector = 0;
} }
@ -694,23 +748,36 @@ static int32 checkParameters(void) {
selectedDisk, PCX, selectedTrack, uptr -> HDSK_NUMBER_OF_TRACKS); selectedDisk, PCX, selectedTrack, uptr -> HDSK_NUMBER_OF_TRACKS);
selectedTrack = 0; selectedTrack = 0;
} }
if (chiptype == CHIP_TYPE_M68K) {
if (selectedDMA + uptr -> HDSK_SECTOR_SIZE > M68K_MAX_RAM) {
sim_debug(VERBOSE_MSG, &hdsk_dev,
"HDSK%d: " ADDRESS_FORMAT
" Error: DMA (0x%08x) + sector size (0x%02x) out of bounds. "
"Must be at most 0x%08x.\n",
selectedDisk, PCX, selectedDMA, uptr -> HDSK_SECTOR_SIZE, M68K_MAX_RAM);
return FALSE;
}
} else
selectedDMA &= ADDRMASK; selectedDMA &= ADDRMASK;
if (hdskLastCommand == HDSK_READ) { if (hdskLastCommand == HDSK_READ) {
sim_debug(READ_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT sim_debug(READ_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT
" Read Track=%04d Sector=%02d Len=%04d DMA=%04x\n", " Read Track=%04d Sector=%06d Len=%04d DMA=%08x\n",
selectedDisk, PCX, selectedTrack, selectedSector, uptr -> HDSK_SECTOR_SIZE, selectedDMA); selectedDisk, PCX, selectedTrack, selectedSector,
uptr -> HDSK_SECTOR_SIZE, selectedDMA);
} }
if (hdskLastCommand == HDSK_WRITE) { if (hdskLastCommand == HDSK_WRITE) {
sim_debug(WRITE_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT sim_debug(WRITE_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT
" Write Track=%04d Sector=%02d Len=%04d DMA=%04x\n", " Write Track=%04d Sector=%06d Len=%04d DMA=%08x\n",
selectedDisk, PCX, selectedTrack, selectedSector, uptr -> HDSK_SECTOR_SIZE, selectedDMA); selectedDisk, PCX, selectedTrack, selectedSector,
uptr -> HDSK_SECTOR_SIZE, selectedDMA);
} }
return TRUE; return TRUE;
} }
/* pre-condition: checkParameters has been executed to repair any faulty parameters */ /* pre-condition: hdsk_checkParameters has been executed to repair any faulty parameters */
static int32 doSeek(void) { static int32 doSeek(void) {
UNIT *uptr = &hdsk_dev.units[selectedDisk]; UNIT *uptr = &hdsk_dev.units[selectedDisk];
assert(uptr != NULL);
int32 hostSector = (dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ? int32 hostSector = (dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ?
selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector]; selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector];
int32 sectorSize = (dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize == 0) ? int32 sectorSize = (dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize == 0) ?
@ -719,7 +786,7 @@ static int32 doSeek(void) {
sectorSize * (uptr -> HDSK_SECTORS_PER_TRACK * selectedTrack + hostSector) + sectorSize * (uptr -> HDSK_SECTORS_PER_TRACK * selectedTrack + hostSector) +
dpb[uptr -> HDSK_FORMAT_TYPE].offset, SEEK_SET)) { dpb[uptr -> HDSK_FORMAT_TYPE].offset, SEEK_SET)) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not access Sector=%02d[=%02d] Track=%04d.\n", " Could not access Sector=%06d[=%06d] Track=%04d.\n",
selectedDisk, PCX, selectedSector, hostSector, selectedTrack); selectedDisk, PCX, selectedSector, hostSector, selectedTrack);
return CPM_ERROR; return CPM_ERROR;
} }
@ -728,8 +795,8 @@ static int32 doSeek(void) {
static uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */ static uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */
/* pre-condition: checkParameters has been executed to repair any faulty parameters */ /* pre-condition: hdsk_checkParameters has been executed to repair any faulty parameters */
static int32 doRead(void) { int32 hdsk_read(void) {
int32 i; int32 i;
t_stat result; t_stat result;
DISK_INFO *thisDisk; DISK_INFO *thisDisk;
@ -761,30 +828,39 @@ static int32 doRead(void) {
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = CPM_EMPTY; hdskbuf[i] = CPM_EMPTY;
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT
" . Could not read Sector=%02d Track=%04d.\n", " . Could not read Sector=%06d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack); selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_ERROR; hdskStatus = CPM_ERROR;
return hdskStatus;
} }
} else { } else {
if (doSeek()) if (doSeek()) {
return CPM_ERROR; hdskStatus = CPM_ERROR;
return hdskStatus;
}
if (sim_fread(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref) != (size_t)(uptr -> HDSK_SECTOR_SIZE)) { if (sim_fread(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref) != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = CPM_EMPTY; hdskbuf[i] = CPM_EMPTY;
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not read Sector=%02d Track=%04d.\n", " Could not read Sector=%06d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack); selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_OK; /* allows the creation of empty hard disks */ hdskStatus = CPM_OK;
return hdskStatus; /* allows the creation of empty hard disks */
} }
} }
if (chiptype == CHIP_TYPE_M68K)
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
m68k_cpu_write_byte_raw(selectedDMA + i, hdskbuf[i]);
else
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
PutBYTEWrapper(selectedDMA + i, hdskbuf[i]); PutBYTEWrapper(selectedDMA + i, hdskbuf[i]);
return CPM_OK; hdskStatus = CPM_OK;
return hdskStatus;
} }
/* pre-condition: checkParameters has been executed to repair any faulty parameters */ /* pre-condition: hdsk_checkParameters has been executed to repair any faulty parameters */
static int32 doWrite(void) { int32 hdsk_write(void) {
int32 i; int32 i;
t_stat result; t_stat result;
DISK_INFO *thisDisk; DISK_INFO *thisDisk;
@ -797,9 +873,13 @@ static int32 doWrite(void) {
size_t rtn; size_t rtn;
UNIT *uptr = &hdsk_dev.units[selectedDisk]; UNIT *uptr = &hdsk_dev.units[selectedDisk];
if (((uptr -> flags) & UNIT_HDSK_WLK) == 0) { /* write enabled */ if (((uptr -> flags) & UNIT_HDSK_WLK) == 0) { /* write enabled */
if (is_imd(uptr)) { if (chiptype == CHIP_TYPE_M68K)
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = m68k_cpu_read_byte_raw(selectedDMA + i);
else
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
if (is_imd(uptr)) {
thisDisk = hdsk_imd[selectedDisk]; thisDisk = hdsk_imd[selectedDisk];
hostSector = ((dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ? hostSector = ((dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ?
selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector]) + thisDisk -> track[1][0].start_sector; selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector]) + thisDisk -> track[1][0].start_sector;
@ -818,31 +898,53 @@ static int32 doWrite(void) {
sectorSize, &flags, &writelen); sectorSize, &flags, &writelen);
if (result != SCPE_OK) { if (result != SCPE_OK) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT
" . Could not write Sector=%02d Track=%04d.\n", " . Could not write Sector=%06d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack); selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_ERROR; hdskStatus = CPM_ERROR;
return hdskStatus;
} }
} else { } else {
if (doSeek()) if (doSeek()) {
return CPM_ERROR; hdskStatus = CPM_ERROR;
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++) return hdskStatus;
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); }
rtn = sim_fwrite(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref); rtn = sim_fwrite(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref);
if (rtn != (size_t)(uptr -> HDSK_SECTOR_SIZE)) { if (rtn != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not write Sector=%02d Track=%04d Result=%zd.\n", " Could not write Sector=%06d Track=%04d Result=%zd.\n",
selectedDisk, PCX, selectedSector, selectedTrack, rtn); selectedDisk, PCX, selectedSector, selectedTrack, rtn);
return CPM_ERROR; hdskStatus = CPM_ERROR;
return hdskStatus;
} }
} }
} }
else { else {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not write to locked disk Sector=%02d Track=%04d.\n", " Could not write to locked disk Sector=%06d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack); selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_ERROR; hdskStatus = CPM_ERROR;
return hdskStatus;
} }
return CPM_OK; hdskStatus = CPM_OK;
return hdskStatus;
}
/* flush all attached drives. Returns CPM_OK if everything fine, otherwise CPM_ERROR */
int32 hdsk_flush(void) {
uint32 drive;
hdskStatus = CPM_OK;
for (drive = 0; drive < HDSK_NUMBER; drive++) {
const UNIT *uptr = hdsk_dev.units + drive;
if ((uptr -> flags) & UNIT_ATT) {
const int result = fflush(uptr -> fileref);
sim_debug(VERBOSE_MSG, &hdsk_dev,
"HDSK%i: 0x%08x Drive flushed [%i = %s].\n", drive, PCX,
result, result == 0 ? "Ok" : "Error");
if (result)
hdskStatus = CPM_ERROR;
}
}
return hdskStatus;
} }
#define PARAMETER_BLOCK_SIZE 19 #define PARAMETER_BLOCK_SIZE 19
@ -850,7 +952,7 @@ static uint8 parameterBlock[PARAMETER_BLOCK_SIZE];
static int32 hdsk_in(const int32 port) { static int32 hdsk_in(const int32 port) {
if ((hdskCommandPosition == 6) && ((hdskLastCommand == HDSK_READ) || (hdskLastCommand == HDSK_WRITE))) { if ((hdskCommandPosition == 6) && ((hdskLastCommand == HDSK_READ) || (hdskLastCommand == HDSK_WRITE))) {
int32 result = checkParameters() ? ((hdskLastCommand == HDSK_READ) ? doRead() : doWrite()) : CPM_ERROR; int32 result = hdsk_checkParameters() ? ((hdskLastCommand == HDSK_READ) ? hdsk_read() : hdsk_write()) : CPM_ERROR;
hdskLastCommand = HDSK_NONE; hdskLastCommand = HDSK_NONE;
hdskCommandPosition = 0; hdskCommandPosition = 0;
return result; return result;

View file

@ -71,7 +71,7 @@ extern uint32 PCX;
#define BOOTROM_SIZE_MHDSK 256 #define BOOTROM_SIZE_MHDSK 256
#define MHDSK_BOOT_ADDRESS 0xfc00 #define MHDSK_BOOT_ADDRESS 0xfc00
static t_stat mhdsk_boot(int32 unitno, DEVICE *dptr); static t_stat mhdsk_boot(int32 unitno, DEVICE *dptr);
extern t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM); extern t_stat install_bootrom(const int32 bootrom[], const int32 size, const int32 addr, const int32 makeROM);
// Disk controller commands are in upper nibble of command high byte. // Disk controller commands are in upper nibble of command high byte.
@ -178,17 +178,21 @@ static UNIT dsk_unit[] = {
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }}; { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }};
#define MHDSK_NAME "MITS Hard Disk MHDSK"
static MTAB dsk_mod[] = { static MTAB dsk_mod[] = {
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL }, { UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL, NULL, NULL,
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL }, "Enables " MHDSK_NAME "n for writing" },
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL, NULL, NULL,
"Locks " MHDSK_NAME "n for writing" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB mhdsk_dt[] = { static DEBTAB mhdsk_dt[] = {
{ "READ", READ_MSG }, { "READ", READ_MSG, "Read messages" },
{ "WRITE", WRITE_MSG }, { "WRITE", WRITE_MSG, "Write messages" },
{ "VERBOSE", VERBOSE_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ NULL, 0 } { NULL, 0 }
}; };
@ -198,7 +202,7 @@ DEVICE mhdsk_dev = {
NULL, NULL, &dsk_reset, NULL, NULL, &dsk_reset,
&mhdsk_boot, NULL, NULL, &mhdsk_boot, NULL, NULL,
NULL, (DEV_DISABLE | DEV_DEBUG), 0, NULL, (DEV_DISABLE | DEV_DEBUG), 0,
mhdsk_dt, NULL, "MITS Hard Disk MHDSK" mhdsk_dt, NULL, MHDSK_NAME
}; };
static int32 bootrom_mhdsk[BOOTROM_SIZE_MHDSK] = { static int32 bootrom_mhdsk[BOOTROM_SIZE_MHDSK] = {

View file

@ -84,22 +84,24 @@ static UNIT net_unit = {
}; };
static REG net_reg[] = { static REG net_reg[] = {
{ DRDATA (POLL, net_unit.wait, 32) }, { DRDATAD (POLL, net_unit.wait, 32, "Polling interval") },
{ NULL } { NULL }
}; };
static MTAB net_mod[] = { static MTAB net_mod[] = {
{ UNIT_SERVER, 0, "CLIENT", "CLIENT", &set_net}, /* machine is a client */ { UNIT_SERVER, 0, "CLIENT", "CLIENT", &set_net, NULL, NULL,
{ UNIT_SERVER, UNIT_SERVER, "SERVER", "SERVER", &set_net}, /* machine is a server */ "Sets machine to client mode"}, /* machine is a client */
{ UNIT_SERVER, UNIT_SERVER, "SERVER", "SERVER", &set_net, NULL, NULL,
"Sets machine to server mode"}, /* machine is a server */
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB net_dt[] = { static DEBTAB net_dt[] = {
{ "ACCEPT", ACCEPT_MSG }, { "ACCEPT", ACCEPT_MSG, "Accept messages" },
{ "DROP", DROP_MSG }, { "DROP", DROP_MSG, "Drop messages" },
{ "IN", IN_MSG }, { "IN", IN_MSG, "Incoming messages" },
{ "OUT", OUT_MSG }, { "OUT", OUT_MSG, "Outgoing messages" },
{ NULL, 0 } { NULL, 0 }
}; };

View file

@ -172,11 +172,11 @@ extern volatile int32 stop_cpu;
/* Debug Flags */ /* Debug Flags */
static DEBTAB generic_dt[] = { static DEBTAB generic_dt[] = {
{ "IN", IN_MSG }, { "IN", IN_MSG, "IN messages" },
{ "OUT", OUT_MSG }, { "OUT", OUT_MSG, "OUT messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Commands" },
{ "VERBOSE", VERBOSE_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "BUFFEREMPTY", BUFFER_EMPTY_MSG }, { "BUFFEREMPTY", BUFFER_EMPTY_MSG, "IN for empty buffer" },
{ NULL, 0 } { NULL, 0 }
}; };
@ -279,40 +279,71 @@ static UNIT sio_unit = {
}; };
static REG sio_reg[] = { static REG sio_reg[] = {
{ DRDATA (SIOWLEV, warnLevelSIO, 32) }, { DRDATAD (SIOWLEV, warnLevelSIO, 32,
{ DRDATA (WRNUPTP, warnUnattachedPTP, 32) }, "Warn level SIO register") },
{ DRDATA (WRNUPTR, warnUnattachedPTR, 32) }, { DRDATAD (WRNUPTP, warnUnattachedPTP, 32,
{ DRDATA (WRNPTRE, warnPTREOF, 32) }, "Counter for unattached PTP access") },
{ DRDATA (WRUPORT, warnUnassignedPort, 32) }, { DRDATAD (WRNUPTR, warnUnattachedPTR, 32,
{ HRDATA (FILEATT, sio_unit.u4, 8), REG_RO }, /* TRUE iff terminal input is attached to a file */ "Counter for unattached PTR access") },
{ HRDATA (TSTATUS, sio_unit.u3, 8) }, /* TRUE iff a character available in sio_unit.buf */ { DRDATAD (WRNPTRE, warnPTREOF, 32,
{ DRDATA (TBUFFER, sio_unit.buf, 8) }, /* input buffer for one character */ "Counter for EOF reached for PTR") },
{ DRDATA (KEYBDI, keyboardInterrupt, 3), REG_RO }, { DRDATAD (WRUPORT, warnUnassignedPort, 32,
{ HRDATA (KEYBDH, keyboardInterruptHandler, 16) }, "Counter for unassigned port") },
{ HRDATAD (FILEATT, sio_unit.u4, 8,
"BOOL to determine whether terminal input is attached to a file"), REG_RO },
/* TRUE iff terminal input is attached to a file */
{ HRDATAD (TSTATUS, sio_unit.u3, 8,
"BOOL to determine whethere a character is available") },
/* TRUE iff a character available in sio_unit.buf */
{ DRDATAD (TBUFFER, sio_unit.buf, 8,
"Input buffer register") },
/* input buffer for one character */
{ DRDATAD (KEYBDI, keyboardInterrupt, 3,
"BOOL to determine whether a keyboard interrupt is pending"), REG_RO },
{ HRDATAD (KEYBDH, keyboardInterruptHandler, 16,
"Address of keyboard interrupt handler") },
{ NULL } { NULL }
}; };
static MTAB sio_mod[] = { static MTAB sio_mod[] = {
{ UNIT_SIO_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */ { UNIT_SIO_ANSI, 0, "TTY", "TTY", NULL, NULL, NULL,
{ UNIT_SIO_ANSI, UNIT_SIO_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */ "Do not touch bit 8 of console output"}, /* keep bit 8 as is for output */
{ UNIT_SIO_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */ { UNIT_SIO_ANSI, UNIT_SIO_ANSI, "ANSI", "ANSI", NULL, NULL, NULL,
{ UNIT_SIO_UPPER, UNIT_SIO_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */ "Set bit 8 of console output to 0"}, /* set bit 8 to 0 before output */
{ UNIT_SIO_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */ { UNIT_SIO_UPPER, 0, "ALL", "ALL", NULL, NULL, NULL,
{ UNIT_SIO_BS, UNIT_SIO_BS, "DEL", "DEL", NULL }, /* map backspace to delete */ "Console input remains unchanged" }, /* do not change case of input characters */
{ UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */ { UNIT_SIO_UPPER, UNIT_SIO_UPPER, "UPPER", "UPPER", NULL, NULL, NULL,
{ UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", NULL }, "Convert console input to upper case" }, /* change input characters to upper case */
/* verbose, display warning messages */ { UNIT_SIO_BS, 0, "BS", "BS", NULL, NULL, NULL,
{ UNIT_SIO_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */ "Map delete to backspace" }, /* map delete to backspace */
{ UNIT_SIO_MAP, UNIT_SIO_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */ { UNIT_SIO_BS, UNIT_SIO_BS, "DEL", "DEL", NULL, NULL, NULL,
{ UNIT_SIO_BELL, 0, "BELL", "BELL", NULL }, /* enable bell character */ "Map backspace to delete" }, /* map backspace to delete */
{ UNIT_SIO_BELL, UNIT_SIO_BELL, "NOBELL", "NOBELL", NULL }, /* suppress ringing the bell */ { UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL, NULL, NULL,
{ UNIT_SIO_SLEEP, 0, "NOSLEEP", "NOSLEEP", NULL }, /* no sleep after keyboard status check */ "Do not display SIO error messages" }, /* quiet, no error messages */
{ UNIT_SIO_SLEEP, UNIT_SIO_SLEEP, "SLEEP", "SLEEP", NULL }, /* sleep after keyboard status check */ { UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", NULL, NULL, NULL,
"Display verbose messages" }, /* verbose, display warning messages */
{ UNIT_SIO_MAP, 0, "NOMAP", "NOMAP", NULL, NULL, NULL,
"Do not map any character" }, /* disable character mapping */
{ UNIT_SIO_MAP, UNIT_SIO_MAP, "MAP", "MAP", NULL, NULL, NULL,
"Enable mapping of characters" }, /* enable all character mapping */
{ UNIT_SIO_BELL, 0, "BELL", "BELL", NULL, NULL, NULL,
"Control-G sounds the bell" }, /* enable bell character */
{ UNIT_SIO_BELL, UNIT_SIO_BELL, "NOBELL", "NOBELL", NULL, NULL, NULL,
"The bell sound is suppressed" }, /* suppress ringing the bell */
{ UNIT_SIO_SLEEP, 0, "NOSLEEP", "NOSLEEP", NULL, NULL, NULL,
"Do not sleep after SIO status checks" }, /* no sleep after keyboard status check */
{ UNIT_SIO_SLEEP, UNIT_SIO_SLEEP, "SLEEP", "SLEEP", NULL, NULL, NULL,
"Sleep after SIO status checks" }, /* sleep after keyboard status check */
/* no keyboard interrupts */ /* no keyboard interrupts */
{ UNIT_SIO_INTERRUPT, 0, "NOINTERRUPT","NOINTERRUPT",&sio_dev_set_interruptoff }, { UNIT_SIO_INTERRUPT, 0, "NOINTERRUPT", "NOINTERRUPT",
&sio_dev_set_interruptoff, NULL, NULL, "Status port 0 does not create interrupts" },
/* create keyboard interrupts */ /* create keyboard interrupts */
{ UNIT_SIO_INTERRUPT, UNIT_SIO_INTERRUPT, "INTERRUPT","INTERRUPT",&sio_dev_set_interrupton }, { UNIT_SIO_INTERRUPT, UNIT_SIO_INTERRUPT, "INTERRUPT", "INTERRUPT",
{ MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT", &sio_dev_set_port, &sio_dev_show_port }, &sio_dev_set_interrupton, NULL, NULL,
"Status port 0 creates an interrupt when a character becomes available" },
{ MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT",
&sio_dev_set_port, &sio_dev_show_port, NULL,
"Set port to Port/Terminal/Read/NotRead/Write/Reset/Reset/Data" },
{ 0 } { 0 }
}; };
@ -334,7 +365,7 @@ static UNIT ptr_unit = {
}; };
static REG ptr_reg[] = { static REG ptr_reg[] = {
{ HRDATA (STAT, ptr_unit.u3, 8) }, { HRDATAD (STAT, ptr_unit.u3, 8, "Status register") },
{ NULL } { NULL }
}; };
@ -367,43 +398,70 @@ static UNIT simh_unit = {
}; };
static REG simh_reg[] = { static REG simh_reg[] = {
{ DRDATA (CZD, ClockZSDOSDelta, 32) }, { DRDATAD (CZD, ClockZSDOSDelta, 32,
{ DRDATA (SCZP, setClockZSDOSPos, 8), REG_RO }, "ZSDOS Clock - Delta between real clock and AltairZ80 clock") },
{ HRDATA (SCZA, setClockZSDOSAdr, 16), REG_RO }, { DRDATAD (SCZP, setClockZSDOSPos, 8,
{ DRDATA (GCZP, getClockZSDOSPos, 8), REG_RO }, "ZSDOS Clock - Status register for receiving address of parameter block"), REG_RO },
{ HRDATAD (SCZA, setClockZSDOSAdr, 16,
"ZSDOS Clock - Address of 6 byte parameter block for setting time"), REG_RO },
{ DRDATAD (GCZP, getClockZSDOSPos, 8,
"ZSDOS Clock - Status register for sending clock information"), REG_RO },
{ DRDATA (CC3D, ClockCPM3Delta, 32) }, { DRDATAD (CC3D, ClockCPM3Delta, 32,
{ DRDATA (SC3DP, setClockCPM3Pos, 8), REG_RO }, "CP/M 3 Clock - Delta between real clock and AltairZ80 clock") },
{ HRDATA (SC3DA, setClockCPM3Adr, 16), REG_RO }, { DRDATAD (SC3DP, setClockCPM3Pos, 8,
{ DRDATA (GC3DP, getClockCPM3Pos, 8), REG_RO }, "CP/M 3 Clock - Status register for receiving address of parameter block"), REG_RO },
{ DRDATA (D3DO, daysCPM3SinceOrg, 32), REG_RO }, { HRDATAD (SC3DA, setClockCPM3Adr, 16,
"CP/M 3 Clock - Address of 5 byte parameter block for setting time"), REG_RO },
{ DRDATAD (GC3DP, getClockCPM3Pos, 8,
"CP/M 3 Clock - Status register for sending clock information"), REG_RO },
{ DRDATAD (D3DO, daysCPM3SinceOrg, 32,
"CP/M 3 Clock - Days since 1-Jan-1978"), REG_RO },
{ DRDATA (TOFNI, timeOfNextInterrupt, 32), REG_RO }, { DRDATAD (TOFNI, timeOfNextInterrupt, 32,
{ DRDATA (TIMI, timerInterrupt, 3) }, "Time when next interrupt is scheduled"), REG_RO },
{ HRDATA (TIMH, timerInterruptHandler, 16) }, { DRDATAD (TIMI, timerInterrupt, 3,
{ DRDATA (STIAP, setTimerInterruptAdrPos,8), REG_RO }, "BOOL - determines whether a timer interrupt is pending") },
{ DRDATA (TIMD, timerDelta, 32) }, { HRDATAD (TIMH, timerInterruptHandler, 16,
{ DRDATA (STDP, setTimerDeltaPos, 8), REG_RO }, "Address of timer interrupt handling routine") },
{ DRDATA (SLEEP, SIMHSleep, 32) }, { DRDATAD (STIAP, setTimerInterruptAdrPos,8,
{ DRDATA (VOSLP, sleepAllowedStart, 32) }, "Status register for receiving address of timer interrupt handler"), REG_RO },
{ DRDATAD (TIMD, timerDelta, 32,
"Time in milliseconds between timer interrupts") },
{ DRDATAD (STDP, setTimerDeltaPos, 8,
"Status register for receiving the timer delta"), REG_RO },
{ DRDATAD (SLEEP, SIMHSleep, 32,
"Sleep time in milliseconds after SIO status check (when enabled)") },
{ DRDATAD (VOSLP, sleepAllowedStart, 32,
"Only sleep when this many unsuccessful SIO status checks have been made") },
{ DRDATA (STPDT, stopWatchDelta, 32), REG_RO }, { DRDATAD (STPDT, stopWatchDelta, 32,
{ DRDATA (STPOS, getStopWatchDeltaPos, 8), REG_RO }, "Elapsed time of stop watch"), REG_RO },
{ DRDATA (STPNW, stopWatchNow, 32), REG_RO }, { DRDATAD (STPOS, getStopWatchDeltaPos, 8,
{ DRDATA (MTSP, markTimeSP, 8), REG_RO }, "Status register for receiving stop watch delta"), REG_RO },
{ DRDATAD (STPNW, stopWatchNow, 32,
"Starting time of stop watch"), REG_RO },
{ DRDATAD (MTSP, markTimeSP, 8,
"Stack pointer of timer stack"), REG_RO },
{ DRDATA (VPOS, versionPos, 8), REG_RO }, { DRDATAD (VPOS, versionPos, 8,
{ DRDATA (LCPMS, lastCPMStatus, 8), REG_RO }, "Status register for sending version information"), REG_RO },
{ DRDATA (LCMD, lastCommand, 8), REG_RO }, { DRDATAD (LCPMS, lastCPMStatus, 8,
{ DRDATA (CPOS, getCommonPos, 8), REG_RO }, "Result of last attachCPM command"), REG_RO },
{ DRDATAD (LCMD, lastCommand, 8,
"Last command processed on SIMH port"), REG_RO },
{ DRDATAD (CPOS, getCommonPos, 8,
"Status register for sending the COMMON register"), REG_RO },
{ NULL } { NULL }
}; };
static MTAB simh_mod[] = { static MTAB simh_mod[] = {
/* timer generated interrupts are off */ /* timer generated interrupts are off */
{ UNIT_SIMH_TIMERON, 0, "TIMEROFF", "TIMEROFF", &simh_dev_set_timeroff }, { UNIT_SIMH_TIMERON, 0, "TIMEROFF", "TIMEROFF", &simh_dev_set_timeroff,
NULL, NULL, "Stop periodic timer interrupts" },
/* timer generated interrupts are on */ /* timer generated interrupts are on */
{ UNIT_SIMH_TIMERON, UNIT_SIMH_TIMERON, "TIMERON", "TIMERON", &simh_dev_set_timeron }, { UNIT_SIMH_TIMERON, UNIT_SIMH_TIMERON, "TIMERON", "TIMERON", &simh_dev_set_timeron,
NULL, NULL, "Start periodic timer interrupts" },
{ 0 } { 0 }
}; };
@ -1191,7 +1249,6 @@ static t_stat simh_dev_reset(DEVICE *dptr) {
free(urlResult); free(urlResult);
urlResult = NULL; urlResult = NULL;
} }
if (simh_unit.flags & UNIT_SIMH_TIMERON)
simh_dev_set_timeron(NULL, 0, NULL, NULL); simh_dev_set_timeron(NULL, 0, NULL, NULL);
return SCPE_OK; return SCPE_OK;
} }
@ -1202,22 +1259,17 @@ static void warnNoRealTimeClock(void) {
} }
static t_stat simh_dev_set_timeron(UNIT *uptr, int32 value, char *cptr, void *desc) { static t_stat simh_dev_set_timeron(UNIT *uptr, int32 value, char *cptr, void *desc) {
if (rtc_avail) {
timeOfNextInterrupt = sim_os_msec() + timerDelta; timeOfNextInterrupt = sim_os_msec() + timerDelta;
return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */
} }
warnNoRealTimeClock();
return SCPE_ARG;
}
static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) { static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) {
timerInterrupt = FALSE; timerInterrupt = FALSE;
if (rtc_avail)
sim_cancel(&simh_unit);
return SCPE_OK; return SCPE_OK;
} }
static t_stat simh_svc(UNIT *uptr) { static t_stat simh_svc(UNIT *uptr) {
if (simh_unit.flags & UNIT_SIMH_TIMERON) {
uint32 now = sim_os_msec(); uint32 now = sim_os_msec();
if (now >= timeOfNextInterrupt) { if (now >= timeOfNextInterrupt) {
timerInterrupt = TRUE; timerInterrupt = TRUE;
@ -1236,7 +1288,7 @@ static t_stat simh_svc(UNIT *uptr) {
} }
} }
/* post condition: now < timeOfNextInterrupt */ /* post condition: now < timeOfNextInterrupt */
if (simh_unit.flags & UNIT_SIMH_TIMERON) }
sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ sim_activate(&simh_unit, simh_unit.wait); /* activate unit */
return SCPE_OK; return SCPE_OK;
} }

View file

@ -29,8 +29,8 @@
03/27/14 -- MWD Add MITS Hard Disk device (mhdsk_dev) 03/27/14 -- MWD Add MITS Hard Disk device (mhdsk_dev)
*/ */
#include "m68k.h"
#include <ctype.h> #include <ctype.h>
#include "altairz80_defs.h"
#define SIM_EMAX 6 #define SIM_EMAX 6
@ -72,10 +72,6 @@ extern DEVICE wdi2_dev;
extern DEVICE scp300f_dev; extern DEVICE scp300f_dev;
#ifdef USE_FPC
extern DEVICE fpc_dev;
#endif /* USE_FPC */
extern int32 chiptype; extern int32 chiptype;
extern long disasm (unsigned char *data, char *output, int segsize, long offset); extern long disasm (unsigned char *data, char *output, int segsize, long offset);
@ -98,7 +94,7 @@ t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
*/ */
char sim_name[] = "Altair 8800 (Z80)"; char sim_name[] = "Altair 8800 (Z80)";
REG *sim_PC = &cpu_reg[6]; REG *sim_PC = &cpu_reg[CPU_INDEX_8080];
int32 sim_emax = SIM_EMAX; int32 sim_emax = SIM_EMAX;
DEVICE *sim_devices[] = { DEVICE *sim_devices[] = {
/* AltairZ80 Devices */ /* AltairZ80 Devices */
@ -380,6 +376,7 @@ static void printHex4(char* string, const uint32 value) {
addr = current PC addr = current PC
Outputs: Outputs:
*S = output text *S = output text
return = length of instruction in bytes
DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997 DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997
You are not allowed to distribute this software You are not allowed to distribute this software
@ -494,7 +491,7 @@ static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const
t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) {
char disasm_result[128]; char disasm_result[128];
int32 ch = val[0] & 0x7f; int32 ch = val[0] & 0x7f;
long r; long r = 1;
unsigned char vals[SIM_EMAX]; unsigned char vals[SIM_EMAX];
int32 i; int32 i;
if (sw & (SWMASK('A') | SWMASK('C'))) { if (sw & (SWMASK('A') | SWMASK('C'))) {
@ -503,13 +500,26 @@ t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) {
} }
if (!(sw & SWMASK('M'))) if (!(sw & SWMASK('M')))
return SCPE_ARG; return SCPE_ARG;
if (chiptype == CHIP_TYPE_8086) { switch (chiptype) {
case CHIP_TYPE_8080:
r = DAsm(disasm_result, val, FALSE, addr);
break;
case CHIP_TYPE_Z80:
r = DAsm(disasm_result, val, TRUE, addr);
break;
case CHIP_TYPE_8086:
for (i = 0; i < SIM_EMAX; i++) for (i = 0; i < SIM_EMAX; i++)
vals[i] = val[i] & 0xff; vals[i] = val[i] & 0xff;
r = disasm(vals, disasm_result, 16, addr); r = disasm(vals, disasm_result, 16, addr);
break;
case CHIP_TYPE_M68K:
r = m68k_disassemble(disasm_result, addr, M68K_CPU_TYPE_68000);
break;
} }
else
r = DAsm(disasm_result, val, chiptype == CHIP_TYPE_Z80, addr);
fprintf(of, "%s", disasm_result); fprintf(of, "%s", disasm_result);
return 1 - r; return 1 - r;
} }
@ -769,14 +779,19 @@ static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *co
status = error status status = error status
*/ */
t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) { t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) {
static t_bool symbolicInputNotImplementedMessage = FALSE; static t_bool symbolicInputNotImplementedMessage8086 = FALSE;
#define NO_SYMBOLIC_INPUT_MESSAGE "Symbolic input is not supported for the 8086.\n" static t_bool symbolicInputNotImplementedMessageM68K = FALSE;
if (chiptype == CHIP_TYPE_8086) { if ((sw & (SWMASK('M'))) && (chiptype == CHIP_TYPE_8086)) {
if (!symbolicInputNotImplementedMessage) { if (!symbolicInputNotImplementedMessage8086) {
printf(NO_SYMBOLIC_INPUT_MESSAGE); sim_printf("Symbolic input is not supported for the 8086.\n");
if (sim_log) symbolicInputNotImplementedMessage8086 = TRUE;
fprintf(sim_log, NO_SYMBOLIC_INPUT_MESSAGE); }
symbolicInputNotImplementedMessage = TRUE; return SCPE_NOFNC;
}
if ((sw & (SWMASK('M'))) && (chiptype == CHIP_TYPE_M68K)) {
if (!symbolicInputNotImplementedMessageM68K) {
sim_printf("Symbolic input is not supported for the M68K.\n");
symbolicInputNotImplementedMessageM68K = TRUE;
} }
return SCPE_NOFNC; return SCPE_NOFNC;
} }

View file

@ -88,11 +88,15 @@ static UNIT fw2_unit[] = {
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) } { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }
}; };
#define FWII_NAME "Vector Graphic Flashwriter 2 FWII"
static MTAB fw2_mod[] = { static MTAB fw2_mod[] = {
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_FW2_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_FW2_VERBOSE, 0, "QUIET", "QUIET", NULL, NULL, NULL,
"No verbose messages for unit " FWII_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_FW2_VERBOSE, UNIT_FW2_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_FW2_VERBOSE, UNIT_FW2_VERBOSE, "VERBOSE", "VERBOSE", NULL, NULL, NULL,
"Verbose messages for unit " FWII_NAME "n" },
{ 0 } { 0 }
}; };
@ -102,7 +106,7 @@ DEVICE fw2_dev = {
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, &fw2_attach, &fw2_detach, NULL, &fw2_attach, &fw2_detach,
NULL, (DEV_DISABLE | DEV_DIS), 0, NULL, (DEV_DISABLE | DEV_DIS), 0,
NULL, NULL, "Vector Graphic Flashwriter 2 FWII" NULL, NULL, FWII_NAME
}; };
/* Attach routine */ /* Attach routine */

View file

@ -143,8 +143,6 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ
extern void PutByteDMA(const uint32 Addr, const uint32 Value); extern void PutByteDMA(const uint32 Addr, const uint32 Value);
extern uint8 GetByteDMA(const uint32 Addr); extern uint8 GetByteDMA(const uint32 Addr);
#define UNIT_V_I8272_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_I8272_WLK (1 << UNIT_V_I8272_WLK)
#define UNIT_V_I8272_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_I8272_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_I8272_VERBOSE (1 << UNIT_V_I8272_VERBOSE) #define UNIT_I8272_VERBOSE (1 << UNIT_V_I8272_VERBOSE)
#define I8272_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ #define I8272_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
@ -191,28 +189,31 @@ static UNIT i8272_unit[] = {
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) } { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, I8272_CAPACITY) }
}; };
#define I8272_NAME "Intel/NEC(765) FDC Core I8272"
static MTAB i8272_mod[] = { static MTAB i8272_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_I8272_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_I8272_WLK, UNIT_I8272_WLK, "WRTLCK", "WRTLCK", NULL },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_I8272_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_I8272_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " I8272_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_I8272_VERBOSE, UNIT_I8272_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_I8272_VERBOSE, UNIT_I8272_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " I8272_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB i8272_dt[] = { static DEBTAB i8272_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "STATUS", STATUS_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "FMT", FMT_MSG }, { "FMT", FMT_MSG, "Format messages" },
{ "VERBOSE",VERBOSE_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "IRQ", IRQ_MSG }, { "IRQ", IRQ_MSG, "IRQ messages" },
{ NULL, 0 } { NULL, 0 }
}; };
@ -222,7 +223,7 @@ DEVICE i8272_dev = {
NULL, NULL, &i8272_reset, NULL, NULL, &i8272_reset,
NULL, &i8272_attach, &i8272_detach, NULL, &i8272_attach, &i8272_detach,
&i8272_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &i8272_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
i8272_dt, NULL, "Intel/NEC(765) FDC Core I8272" i8272_dt, NULL, I8272_NAME
}; };
static uint8 I8272_Setup_Cmd(uint8 fdc_cmd); static uint8 I8272_Setup_Cmd(uint8 fdc_cmd);

339
AltairZ80/m68k.h Executable file
View file

@ -0,0 +1,339 @@
#ifndef M68K__HEADER
#define M68K__HEADER
/* ======================================================================== */
/* ========================= LICENSING & COPYRIGHT ======================== */
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
* http://kstenerud.cjb.net
*/
/* ======================================================================== */
/* ============================ GENERAL DEFINES =========================== */
/* ======================================================================== */
/* There are 7 levels of interrupt to the 68K.
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
*/
#define M68K_IRQ_NONE 0
#define M68K_IRQ_1 1
#define M68K_IRQ_2 2
#define M68K_IRQ_3 3
#define M68K_IRQ_4 4
#define M68K_IRQ_5 5
#define M68K_IRQ_6 6
#define M68K_IRQ_7 7
/* Special interrupt acknowledge values.
* Use these as special returns from the interrupt acknowledge callback
* (specified later in this header).
*/
/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
* This happens in a real 68K if VPA or AVEC is asserted during an interrupt
* acknowledge cycle instead of DTACK.
*/
#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
/* Causes the spurious interrupt vector (0x18) to be taken
* This happens in a real 68K if BERR is asserted during the interrupt
* acknowledge cycle (i.e. no devices responded to the acknowledge).
*/
#define M68K_INT_ACK_SPURIOUS 0xfffffffe
/* CPU types for use in m68k_set_cpu_type() */
enum
{
M68K_CPU_TYPE_INVALID,
M68K_CPU_TYPE_68000,
M68K_CPU_TYPE_68010,
M68K_CPU_TYPE_68EC020,
M68K_CPU_TYPE_68020,
M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
};
/* Registers used by m68k_get_reg() and m68k_set_reg() */
typedef enum
{
/* Real registers */
M68K_REG_D0, /* Data registers */
M68K_REG_D1,
M68K_REG_D2,
M68K_REG_D3,
M68K_REG_D4,
M68K_REG_D5,
M68K_REG_D6,
M68K_REG_D7,
M68K_REG_A0, /* Address registers */
M68K_REG_A1,
M68K_REG_A2,
M68K_REG_A3,
M68K_REG_A4,
M68K_REG_A5,
M68K_REG_A6,
M68K_REG_A7,
M68K_REG_PC, /* Program Counter */
M68K_REG_SR, /* Status Register */
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
M68K_REG_USP, /* User Stack Pointer */
M68K_REG_ISP, /* Interrupt Stack Pointer */
M68K_REG_MSP, /* Master Stack Pointer */
M68K_REG_SFC, /* Source Function Code */
M68K_REG_DFC, /* Destination Function Code */
M68K_REG_VBR, /* Vector Base Register */
M68K_REG_CACR, /* Cache Control Register */
M68K_REG_CAAR, /* Cache Address Register */
/* Assumed registers */
/* These are cheat registers which emulate the 1-longword prefetch
* present in the 68000 and 68010.
*/
M68K_REG_PREF_ADDR, /* Last prefetch address */
M68K_REG_PREF_DATA, /* Last prefetch data */
/* Convenience registers */
M68K_REG_PPC, /* Previous value in the program counter */
M68K_REG_IR, /* Instruction register */
M68K_REG_CPU_TYPE /* Type of CPU being run */
} m68k_register_t;
/* ======================================================================== */
/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
/* ======================================================================== */
/* You will have to implement these functions */
/* read/write functions called by the CPU to access memory.
* while values used are 32 bits, only the appropriate number
* of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
* of value should be written to memory).
*
* NOTE: I have separated the immediate and PC-relative memory fetches
* from the other memory fetches because some systems require
* differentiation between PROGRAM and DATA fetches (usually
* for security setups such as encryption).
* This separation can either be achieved by setting
* M68K_SEPARATE_READS in m68kconf.h and defining
* the read functions, or by setting M68K_EMULATE_FC and
* making a function code callback function.
* Using the callback offers better emulation coverage
* because you can also monitor whether the CPU is in SYSTEM or
* USER mode, but it is also slower.
*/
/* Read from anywhere */
unsigned int m68k_read_memory_8(unsigned int address);
unsigned int m68k_read_memory_16(unsigned int address);
unsigned int m68k_read_memory_32(unsigned int address);
/* Read data immediately following the PC */
unsigned int m68k_read_immediate_16(unsigned int address);
unsigned int m68k_read_immediate_32(unsigned int address);
/* Read data relative to the PC */
unsigned int m68k_read_pcrelative_8(unsigned int address);
unsigned int m68k_read_pcrelative_16(unsigned int address);
unsigned int m68k_read_pcrelative_32(unsigned int address);
/* Memory access for the disassembler */
unsigned int m68k_read_disassembler_8 (unsigned int address);
unsigned int m68k_read_disassembler_16 (unsigned int address);
unsigned int m68k_read_disassembler_32 (unsigned int address);
/* Write to anywhere */
void m68k_write_memory_8(unsigned int address, unsigned int value);
void m68k_write_memory_16(unsigned int address, unsigned int value);
void m68k_write_memory_32(unsigned int address, unsigned int value);
/* ======================================================================== */
/* ============================== CALLBACKS =============================== */
/* ======================================================================== */
/* These functions allow you to set callbacks to the host when specific events
* occur. Note that you must enable the corresponding value in m68kconf.h
* in order for these to do anything useful.
* Note: I have defined default callbacks which are used if you have enabled
* the corresponding #define in m68kconf.h but either haven't assigned a
* callback or have assigned a callback of NULL.
*/
/* Set the callback for an interrupt acknowledge.
* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
* The CPU will call the callback with the interrupt level being acknowledged.
* The host program must return either a vector from 0x02-0xff, or one of the
* special interrupt acknowledge values specified earlier in this header.
* If this is not implemented, the CPU will always assume an autovectored
* interrupt, and will automatically clear the interrupt request when it
* services the interrupt.
* Default behavior: return M68K_INT_ACK_AUTOVECTOR.
*/
void m68k_set_int_ack_callback(int (*callback)(int int_level));
/* Set the callback for a breakpoint acknowledge (68010+).
* You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h.
* The CPU will call the callback with whatever was in the data field of the
* BKPT instruction for 68020+, or 0 for 68010.
* Default behavior: do nothing.
*/
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
/* Set the callback for the RESET instruction.
* You must enable M68K_EMULATE_RESET in m68kconf.h.
* The CPU calls this callback every time it encounters a RESET instruction.
* Default behavior: do nothing.
*/
void m68k_set_reset_instr_callback(void (*callback)(void));
/* Set the callback for informing of a large PC change.
* You must enable M68K_MONITOR_PC in m68kconf.h.
* The CPU calls this callback with the new PC value every time the PC changes
* by a large value (currently set for changes by longwords).
* Default behavior: do nothing.
*/
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc));
/* Set the callback for CPU function code changes.
* You must enable M68K_EMULATE_FC in m68kconf.h.
* The CPU calls this callback with the function code before every memory
* access to set the CPU's function code according to what kind of memory
* access it is (supervisor/user, program/data and such).
* Default behavior: do nothing.
*/
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
/* Set a callback for the instruction cycle of the CPU.
* You must enable M68K_INSTRUCTION_HOOK in m68kconf.h.
* The CPU calls this callback just before fetching the opcode in the
* instruction cycle.
* Default behavior: do nothing.
*/
void m68k_set_instr_hook_callback(void (*callback)(void));
/* ======================================================================== */
/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
/* ======================================================================== */
/* Use this function to set the CPU type you want to emulate.
* Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010,
* M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
*/
void m68k_set_cpu_type(unsigned int cpu_type);
/* Pulse the RESET pin on the CPU.
* You *MUST* reset the CPU at least once to initialize the emulation
* Note: If you didn't call m68k_set_cpu_type() before resetting
* the CPU for the first time, the CPU will be set to
* M68K_CPU_TYPE_68000.
*/
void m68k_pulse_reset(void);
/* execute num_cycles worth of instructions. returns number of cycles used */
int m68k_execute(int num_cycles);
/* These functions let you read/write/modify the number of cycles left to run
* while m68k_execute() is running.
* These are useful if the 68k accesses a memory-mapped port on another device
* that requires immediate processing by another CPU.
*/
int m68k_cycles_run(void); /* Number of cycles run so far */
int m68k_cycles_remaining(void); /* Number of cycles left */
void m68k_modify_timeslice(int cycles); /* Modify cycles left */
void m68k_end_timeslice(void); /* End timeslice now */
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
* Setting IRQ to 0 will clear an interrupt request.
*/
void m68k_set_irq(unsigned int int_level);
/* Halt the CPU as if you pulsed the HALT pin. */
void m68k_pulse_halt(void);
/* Context switching to allow multiple CPUs */
/* Get the size of the cpu context in bytes */
unsigned int m68k_context_size(void);
/* Get a cpu context */
unsigned int m68k_get_context(void* dst);
/* set the current cpu context */
void m68k_set_context(void* dst);
/* Save the current cpu context to disk.
* You must provide a function pointer of the form:
* void save_value(char* identifier, unsigned int value)
*/
void m68k_save_context( void (*save_value)(char* identifier, unsigned int value));
/* Load a cpu context from disk.
* You must provide a function pointer of the form:
* unsigned int load_value(char* identifier)
*/
void m68k_load_context(unsigned int (*load_value)(char* identifier));
/* Peek at the internals of a CPU context. This can either be a context
* retrieved using m68k_get_context() or the currently running context.
* If context is NULL, the currently running CPU context will be used.
*/
unsigned int m68k_get_reg(void* context, m68k_register_t reg);
/* Poke values into the internals of the currently running CPU context */
void m68k_set_reg(m68k_register_t reg, unsigned int value);
/* Check if an instruction is valid for the specified CPU type */
unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
/* Disassemble 1 instruction using the epecified CPU type at pc. Stores
* disassembly in str_buff and returns the size of the instruction in bytes.
*/
unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
/* ======================================================================== */
/* ============================= CONFIGURATION ============================ */
/* ======================================================================== */
/* Import the configuration for this build */
#include "m68kconf.h"
/* ======================================================================== */
/* ============================== END OF FILE ============================= */
/* ======================================================================== */
#endif /* M68K__HEADER */

193
AltairZ80/m68kconf.h Normal file
View file

@ -0,0 +1,193 @@
/* ======================================================================== */
/* ========================= LICENSING & COPYRIGHT ======================== */
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
* http://kstenerud.cjb.net
*/
#ifndef M68KCONF__HEADER
#define M68KCONF__HEADER
/* Configuration switches.
* Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
* OPT_SPECIFY_HANDLER causes the core to link directly to the function
* or macro you specify, rather than using callback functions whose pointer
* must be passed in using m68k_set_xxx_callback().
*/
#define OPT_OFF 0
#define OPT_ON 1
#define OPT_SPECIFY_HANDLER 2
/* ======================================================================== */
/* ============================== MAME STUFF ============================== */
/* ======================================================================== */
/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME
* to OPT_ON and use m68kmame.h to configure the 68k core.
*/
#ifndef M68K_COMPILE_FOR_MAME
#define M68K_COMPILE_FOR_MAME OPT_OFF
#endif /* M68K_COMPILE_FOR_MAME */
#if M68K_COMPILE_FOR_MAME == OPT_ON
#include "m68kmame.h"
#else
/* ======================================================================== */
/* ============================= CONFIGURATION ============================ */
/* ======================================================================== */
/* Turn on if you want to use the following M68K variants */
#define M68K_EMULATE_010 OPT_OFF
#define M68K_EMULATE_EC020 OPT_OFF
#define M68K_EMULATE_020 OPT_OFF
/* If on, the CPU will call m68k_read_immediate_xx() for immediate addressing
* and m68k_read_pcrelative_xx() for PC-relative addressing.
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
*/
#define M68K_SEPARATE_READS OPT_OFF
/* If on, CPU will call the interrupt acknowledge callback when it services an
* interrupt.
* If off, all interrupts will be autovectored and all interrupt requests will
* auto-clear when the interrupt is serviced.
*/
#define M68K_EMULATE_INT_ACK OPT_SPECIFY_HANDLER
#define M68K_INT_ACK_CALLBACK(A) m68k_cpu_irq_ack(A)
/* If on, CPU will call the breakpoint acknowledge callback when it encounters
* a breakpoint instruction and it is running a 68010+.
*/
#define M68K_EMULATE_BKPT_ACK OPT_OFF
#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function()
/* If on, the CPU will monitor the trace flags and take trace exceptions
*/
#define M68K_EMULATE_TRACE OPT_OFF
/* If on, CPU will call the output reset callback when it encounters a reset
* instruction.
*/
#define M68K_EMULATE_RESET OPT_SPECIFY_HANDLER
#define M68K_RESET_CALLBACK() m68k_cpu_pulse_reset()
/* If on, CPU will call the set fc callback on every memory access to
* differentiate between user/supervisor, program/data access like a real
* 68000 would. This should be enabled and the callback should be set if you
* want to properly emulate the m68010 or higher. (moves uses function codes
* to read/write data from different address spaces)
*/
#define M68K_EMULATE_FC OPT_SPECIFY_HANDLER
#define M68K_SET_FC_CALLBACK(A) m68k_cpu_set_fc(A)
/* If on, CPU will call the pc changed callback when it changes the PC by a
* large value. This allows host programs to be nicer when it comes to
* fetching immediate data and instructions on a banked memory system.
*/
#define M68K_MONITOR_PC OPT_OFF
#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A)
/* If on, CPU will call the instruction hook callback before every
* instruction.
*/
#define M68K_INSTRUCTION_HOOK OPT_OFF
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
/* If on, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
#define M68K_EMULATE_PREFETCH OPT_ON
/* If on, the CPU will generate address error exceptions if it tries to
* access a word or longword at an odd address.
* NOTE: Do not enable this! It is not working!
*/
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
/* Turn on to enable logging of illegal instruction calls.
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
*/
#define M68K_LOG_ENABLE OPT_OFF
#define M68K_LOG_1010_1111 OPT_OFF
#define M68K_LOG_FILEHANDLE some_file_handle
/* ----------------------------- COMPATIBILITY ---------------------------- */
/* The following options set optimizations that violate the current ANSI
* standard, but will be compliant under the forthcoming C9X standard.
*/
/* If on, the emulation core will use 64-bit integers to speed up some
* operations.
*/
#define M68K_USE_64_BIT OPT_ON
/* Set to your compiler's static inline keyword to enable it, or
* set it to blank to disable it.
* If you define INLINE in the makefile, it will override this value.
* NOTE: not enabling inline functions will SEVERELY slow down emulation.
*/
#ifndef INLINE
#define INLINE static __inline
#endif /* INLINE */
/* If your environment requires special prefixes for system callback functions
* such as the argument to qsort(), then set them here or in the makefile.
*/
#ifndef DECL_SPEC
#define DECL_SPEC
#endif
#endif /* M68K_COMPILE_FOR_MAME */
#include "m68ksim.h"
#define m68k_read_memory_8(A) m68k_cpu_read_byte(A)
#define m68k_read_memory_16(A) m68k_cpu_read_word(A)
#define m68k_read_memory_32(A) m68k_cpu_read_long(A)
#define m68k_write_memory_8(A, V) m68k_cpu_write_byte(A, V)
#define m68k_write_memory_16(A, V) m68k_cpu_write_word(A, V)
#define m68k_write_memory_32(A, V) m68k_cpu_write_long(A, V)
/* ======================================================================== */
/* ============================== END OF FILE ============================= */
/* ======================================================================== */
#endif /* M68KCONF__HEADER */

894
AltairZ80/m68kcpu.c Executable file
View file

@ -0,0 +1,894 @@
/* ======================================================================== */
/* ========================= LICENSING & COPYRIGHT ======================== */
/* ======================================================================== */
#if 0
static const char* copyright_notice =
"MUSASHI\n"
"Version 3.3 (2001-01-29)\n"
"A portable Motorola M680x0 processor emulation engine.\n"
"Copyright 1998-2001 Karl Stenerud. All rights reserved.\n"
"\n"
"This code may be freely used for non-commercial purpooses as long as this\n"
"copyright notice remains unaltered in the source code and any binary files\n"
"containing this code in compiled form.\n"
"\n"
"All other lisencing terms must be negotiated with the author\n"
"(Karl Stenerud).\n"
"\n"
"The latest version of this code can be obtained at:\n"
"http://kstenerud.cjb.net\n"
;
#endif
/* ======================================================================== */
/* ================================= NOTES ================================ */
/* ======================================================================== */
/* ======================================================================== */
/* ================================ INCLUDES ============================== */
/* ======================================================================== */
#include "m68kops.h"
#include "m68kcpu.h"
/* ======================================================================== */
/* ================================= DATA ================================= */
/* ======================================================================== */
int m68ki_initial_cycles;
int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
uint m68ki_tracing = 0;
uint m68ki_address_space;
#ifdef M68K_LOG_ENABLE
char* m68ki_cpu_names[9] =
{
"Invalid CPU",
"M68000",
"M68010",
"Invalid CPU",
"M68EC020"
"Invalid CPU",
"Invalid CPU",
"Invalid CPU",
"M68020"
};
#endif /* M68K_LOG_ENABLE */
/* The CPU core */
m68ki_cpu_core m68ki_cpu = {0};
#if M68K_EMULATE_ADDRESS_ERROR
jmp_buf m68ki_address_error_trap;
#endif /* M68K_EMULATE_ADDRESS_ERROR */
/* Used by shift & rotate instructions */
uint8 m68ki_shift_8_table[65] =
{
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff
};
uint16 m68ki_shift_16_table[65] =
{
0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff
};
uint m68ki_shift_32_table[65] =
{
0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
/* Number of clock cycles to use for exception processing.
* I used 4 for any vectors that are undocumented for processing times.
*/
uint8 m68ki_exception_cycle_table[3][256] =
{
{ /* 000 */
4, /* 0: Reset - Initial Stack Pointer */
4, /* 1: Reset - Initial Program Counter */
50, /* 2: Bus Error (unemulated) */
50, /* 3: Address Error (unemulated) */
34, /* 4: Illegal Instruction */
38, /* 5: Divide by Zero -- ASG: changed from 42 */
40, /* 6: CHK -- ASG: chanaged from 44 */
34, /* 7: TRAPV */
34, /* 8: Privilege Violation */
34, /* 9: Trace */
4, /* 10: 1010 */
4, /* 11: 1111 */
4, /* 12: RESERVED */
4, /* 13: Coprocessor Protocol Violation (unemulated) */
4, /* 14: Format Error */
44, /* 15: Uninitialized Interrupt */
4, /* 16: RESERVED */
4, /* 17: RESERVED */
4, /* 18: RESERVED */
4, /* 19: RESERVED */
4, /* 20: RESERVED */
4, /* 21: RESERVED */
4, /* 22: RESERVED */
4, /* 23: RESERVED */
44, /* 24: Spurious Interrupt */
44, /* 25: Level 1 Interrupt Autovector */
44, /* 26: Level 2 Interrupt Autovector */
44, /* 27: Level 3 Interrupt Autovector */
44, /* 28: Level 4 Interrupt Autovector */
44, /* 29: Level 5 Interrupt Autovector */
44, /* 30: Level 6 Interrupt Autovector */
44, /* 31: Level 7 Interrupt Autovector */
34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
34, /* 33: TRAP #1 */
34, /* 34: TRAP #2 */
34, /* 35: TRAP #3 */
34, /* 36: TRAP #4 */
34, /* 37: TRAP #5 */
34, /* 38: TRAP #6 */
34, /* 39: TRAP #7 */
34, /* 40: TRAP #8 */
34, /* 41: TRAP #9 */
34, /* 42: TRAP #10 */
34, /* 43: TRAP #11 */
34, /* 44: TRAP #12 */
34, /* 45: TRAP #13 */
34, /* 46: TRAP #14 */
34, /* 47: TRAP #15 */
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
4, /* 49: FP Inexact Result (unemulated) */
4, /* 50: FP Divide by Zero (unemulated) */
4, /* 51: FP Underflow (unemulated) */
4, /* 52: FP Operand Error (unemulated) */
4, /* 53: FP Overflow (unemulated) */
4, /* 54: FP Signaling NAN (unemulated) */
4, /* 55: FP Unimplemented Data Type (unemulated) */
4, /* 56: MMU Configuration Error (unemulated) */
4, /* 57: MMU Illegal Operation Error (unemulated) */
4, /* 58: MMU Access Level Violation Error (unemulated) */
4, /* 59: RESERVED */
4, /* 60: RESERVED */
4, /* 61: RESERVED */
4, /* 62: RESERVED */
4, /* 63: RESERVED */
/* 64-255: User Defined */
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
},
{ /* 010 */
4, /* 0: Reset - Initial Stack Pointer */
4, /* 1: Reset - Initial Program Counter */
126, /* 2: Bus Error (unemulated) */
126, /* 3: Address Error (unemulated) */
38, /* 4: Illegal Instruction */
44, /* 5: Divide by Zero */
44, /* 6: CHK */
34, /* 7: TRAPV */
38, /* 8: Privilege Violation */
38, /* 9: Trace */
4, /* 10: 1010 */
4, /* 11: 1111 */
4, /* 12: RESERVED */
4, /* 13: Coprocessor Protocol Violation (unemulated) */
4, /* 14: Format Error */
44, /* 15: Uninitialized Interrupt */
4, /* 16: RESERVED */
4, /* 17: RESERVED */
4, /* 18: RESERVED */
4, /* 19: RESERVED */
4, /* 20: RESERVED */
4, /* 21: RESERVED */
4, /* 22: RESERVED */
4, /* 23: RESERVED */
46, /* 24: Spurious Interrupt */
46, /* 25: Level 1 Interrupt Autovector */
46, /* 26: Level 2 Interrupt Autovector */
46, /* 27: Level 3 Interrupt Autovector */
46, /* 28: Level 4 Interrupt Autovector */
46, /* 29: Level 5 Interrupt Autovector */
46, /* 30: Level 6 Interrupt Autovector */
46, /* 31: Level 7 Interrupt Autovector */
38, /* 32: TRAP #0 */
38, /* 33: TRAP #1 */
38, /* 34: TRAP #2 */
38, /* 35: TRAP #3 */
38, /* 36: TRAP #4 */
38, /* 37: TRAP #5 */
38, /* 38: TRAP #6 */
38, /* 39: TRAP #7 */
38, /* 40: TRAP #8 */
38, /* 41: TRAP #9 */
38, /* 42: TRAP #10 */
38, /* 43: TRAP #11 */
38, /* 44: TRAP #12 */
38, /* 45: TRAP #13 */
38, /* 46: TRAP #14 */
38, /* 47: TRAP #15 */
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
4, /* 49: FP Inexact Result (unemulated) */
4, /* 50: FP Divide by Zero (unemulated) */
4, /* 51: FP Underflow (unemulated) */
4, /* 52: FP Operand Error (unemulated) */
4, /* 53: FP Overflow (unemulated) */
4, /* 54: FP Signaling NAN (unemulated) */
4, /* 55: FP Unimplemented Data Type (unemulated) */
4, /* 56: MMU Configuration Error (unemulated) */
4, /* 57: MMU Illegal Operation Error (unemulated) */
4, /* 58: MMU Access Level Violation Error (unemulated) */
4, /* 59: RESERVED */
4, /* 60: RESERVED */
4, /* 61: RESERVED */
4, /* 62: RESERVED */
4, /* 63: RESERVED */
/* 64-255: User Defined */
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
},
{ /* 020 */
4, /* 0: Reset - Initial Stack Pointer */
4, /* 1: Reset - Initial Program Counter */
50, /* 2: Bus Error (unemulated) */
50, /* 3: Address Error (unemulated) */
20, /* 4: Illegal Instruction */
38, /* 5: Divide by Zero */
40, /* 6: CHK */
20, /* 7: TRAPV */
34, /* 8: Privilege Violation */
25, /* 9: Trace */
20, /* 10: 1010 */
20, /* 11: 1111 */
4, /* 12: RESERVED */
4, /* 13: Coprocessor Protocol Violation (unemulated) */
4, /* 14: Format Error */
30, /* 15: Uninitialized Interrupt */
4, /* 16: RESERVED */
4, /* 17: RESERVED */
4, /* 18: RESERVED */
4, /* 19: RESERVED */
4, /* 20: RESERVED */
4, /* 21: RESERVED */
4, /* 22: RESERVED */
4, /* 23: RESERVED */
30, /* 24: Spurious Interrupt */
30, /* 25: Level 1 Interrupt Autovector */
30, /* 26: Level 2 Interrupt Autovector */
30, /* 27: Level 3 Interrupt Autovector */
30, /* 28: Level 4 Interrupt Autovector */
30, /* 29: Level 5 Interrupt Autovector */
30, /* 30: Level 6 Interrupt Autovector */
30, /* 31: Level 7 Interrupt Autovector */
20, /* 32: TRAP #0 */
20, /* 33: TRAP #1 */
20, /* 34: TRAP #2 */
20, /* 35: TRAP #3 */
20, /* 36: TRAP #4 */
20, /* 37: TRAP #5 */
20, /* 38: TRAP #6 */
20, /* 39: TRAP #7 */
20, /* 40: TRAP #8 */
20, /* 41: TRAP #9 */
20, /* 42: TRAP #10 */
20, /* 43: TRAP #11 */
20, /* 44: TRAP #12 */
20, /* 45: TRAP #13 */
20, /* 46: TRAP #14 */
20, /* 47: TRAP #15 */
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
4, /* 49: FP Inexact Result (unemulated) */
4, /* 50: FP Divide by Zero (unemulated) */
4, /* 51: FP Underflow (unemulated) */
4, /* 52: FP Operand Error (unemulated) */
4, /* 53: FP Overflow (unemulated) */
4, /* 54: FP Signaling NAN (unemulated) */
4, /* 55: FP Unimplemented Data Type (unemulated) */
4, /* 56: MMU Configuration Error (unemulated) */
4, /* 57: MMU Illegal Operation Error (unemulated) */
4, /* 58: MMU Access Level Violation Error (unemulated) */
4, /* 59: RESERVED */
4, /* 60: RESERVED */
4, /* 61: RESERVED */
4, /* 62: RESERVED */
4, /* 63: RESERVED */
/* 64-255: User Defined */
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
}
};
uint8 m68ki_ea_idx_cycle_table[64] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, /* ..01.000 no memory indirect, base NULL */
5, /* ..01..01 memory indirect, base NULL, outer NULL */
7, /* ..01..10 memory indirect, base NULL, outer 16 */
7, /* ..01..11 memory indirect, base NULL, outer 32 */
0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
2, /* ..10.000 no memory indirect, base 16 */
7, /* ..10..01 memory indirect, base 16, outer NULL */
9, /* ..10..10 memory indirect, base 16, outer 16 */
9, /* ..10..11 memory indirect, base 16, outer 32 */
0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
6, /* ..11.000 no memory indirect, base 32 */
11, /* ..11..01 memory indirect, base 32, outer NULL */
13, /* ..11..10 memory indirect, base 32, outer 16 */
13, /* ..11..11 memory indirect, base 32, outer 32 */
0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
};
/* ======================================================================== */
/* =============================== CALLBACKS ============================== */
/* ======================================================================== */
/* Default callbacks used if the callback hasn't been set yet, or if the
* callback is set to NULL
*/
/* Interrupt acknowledge */
static int default_int_ack_callback_data;
static int default_int_ack_callback(int int_level)
{
default_int_ack_callback_data = int_level;
CPU_INT_LEVEL = 0;
return M68K_INT_ACK_AUTOVECTOR;
}
/* Breakpoint acknowledge */
static unsigned int default_bkpt_ack_callback_data;
static void default_bkpt_ack_callback(unsigned int data)
{
default_bkpt_ack_callback_data = data;
}
/* Called when a reset instruction is executed */
static void default_reset_instr_callback(void)
{
}
/* Called when the program counter changed by a large value */
static unsigned int default_pc_changed_callback_data;
static void default_pc_changed_callback(unsigned int new_pc)
{
default_pc_changed_callback_data = new_pc;
}
/* Called every time there's bus activity (read/write to/from memory */
static unsigned int default_set_fc_callback_data;
static void default_set_fc_callback(unsigned int new_fc)
{
default_set_fc_callback_data = new_fc;
}
/* Called every instruction cycle prior to execution */
static void default_instr_hook_callback(void)
{
}
/* ======================================================================== */
/* ================================= API ================================== */
/* ======================================================================== */
/* Access the internals of the CPU */
unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
{
m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
switch(regnum)
{
case M68K_REG_D0: return cpu->dar[0];
case M68K_REG_D1: return cpu->dar[1];
case M68K_REG_D2: return cpu->dar[2];
case M68K_REG_D3: return cpu->dar[3];
case M68K_REG_D4: return cpu->dar[4];
case M68K_REG_D5: return cpu->dar[5];
case M68K_REG_D6: return cpu->dar[6];
case M68K_REG_D7: return cpu->dar[7];
case M68K_REG_A0: return cpu->dar[8];
case M68K_REG_A1: return cpu->dar[9];
case M68K_REG_A2: return cpu->dar[10];
case M68K_REG_A3: return cpu->dar[11];
case M68K_REG_A4: return cpu->dar[12];
case M68K_REG_A5: return cpu->dar[13];
case M68K_REG_A6: return cpu->dar[14];
case M68K_REG_A7: return cpu->dar[15];
case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
case M68K_REG_SR: return cpu->t1_flag |
cpu->t0_flag |
(cpu->s_flag << 11) |
(cpu->m_flag << 11) |
cpu->int_mask |
((cpu->x_flag & XFLAG_SET) >> 4) |
((cpu->n_flag & NFLAG_SET) >> 4) |
((!cpu->not_z_flag) << 2) |
((cpu->v_flag & VFLAG_SET) >> 6) |
((cpu->c_flag & CFLAG_SET) >> 8);
case M68K_REG_SP: return cpu->dar[15];
case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
case M68K_REG_SFC: return cpu->sfc;
case M68K_REG_DFC: return cpu->dfc;
case M68K_REG_VBR: return cpu->vbr;
case M68K_REG_CACR: return cpu->cacr;
case M68K_REG_CAAR: return cpu->caar;
case M68K_REG_PREF_ADDR: return cpu->pref_addr;
case M68K_REG_PREF_DATA: return cpu->pref_data;
case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
case M68K_REG_IR: return cpu->ir;
case M68K_REG_CPU_TYPE:
switch(cpu->cpu_type)
{
case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
}
return M68K_CPU_TYPE_INVALID;
default: return 0;
}
return 0;
}
void m68k_set_reg(m68k_register_t regnum, unsigned int value)
{
switch(regnum)
{
case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
case M68K_REG_SR: m68ki_set_sr(value); return;
case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_USP: if(FLAG_S)
REG_USP = MASK_OUT_ABOVE_32(value);
else
REG_SP = MASK_OUT_ABOVE_32(value);
return;
case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
REG_SP = MASK_OUT_ABOVE_32(value);
else
REG_ISP = MASK_OUT_ABOVE_32(value);
return;
case M68K_REG_MSP: if(FLAG_S && FLAG_M)
REG_SP = MASK_OUT_ABOVE_32(value);
else
REG_MSP = MASK_OUT_ABOVE_32(value);
return;
case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_SFC: REG_SFC = value & 7; return;
case M68K_REG_DFC: REG_DFC = value & 7; return;
case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
default: return;
}
}
/* Set the callbacks */
void m68k_set_int_ack_callback(int (*callback)(int int_level))
{
CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
}
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
{
CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
}
void m68k_set_reset_instr_callback(void (*callback)(void))
{
CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
}
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
{
CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
}
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
{
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
}
void m68k_set_instr_hook_callback(void (*callback)(void))
{
CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
}
#include <stdio.h>
/* Set the CPU type. */
void m68k_set_cpu_type(unsigned int cpu_type)
{
switch(cpu_type)
{
case M68K_CPU_TYPE_68000:
CPU_TYPE = CPU_TYPE_000;
CPU_ADDRESS_MASK = 0x00ffffff;
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
CYC_INSTRUCTION = m68ki_cycles[0];
CYC_EXCEPTION = m68ki_exception_cycle_table[0];
CYC_BCC_NOTAKE_B = -2;
CYC_BCC_NOTAKE_W = 2;
CYC_DBCC_F_NOEXP = -2;
CYC_DBCC_F_EXP = 2;
CYC_SCC_R_FALSE = 2;
CYC_MOVEM_W = 2;
CYC_MOVEM_L = 3;
CYC_SHIFT = 1;
CYC_RESET = 132;
return;
case M68K_CPU_TYPE_68010:
CPU_TYPE = CPU_TYPE_010;
CPU_ADDRESS_MASK = 0x00ffffff;
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
CYC_INSTRUCTION = m68ki_cycles[1];
CYC_EXCEPTION = m68ki_exception_cycle_table[1];
CYC_BCC_NOTAKE_B = -4;
CYC_BCC_NOTAKE_W = 0;
CYC_DBCC_F_NOEXP = 0;
CYC_DBCC_F_EXP = 6;
CYC_SCC_R_FALSE = 0;
CYC_MOVEM_W = 2;
CYC_MOVEM_L = 3;
CYC_SHIFT = 1;
CYC_RESET = 130;
return;
case M68K_CPU_TYPE_68EC020:
CPU_TYPE = CPU_TYPE_EC020;
CPU_ADDRESS_MASK = 0x00ffffff;
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
CYC_INSTRUCTION = m68ki_cycles[2];
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
CYC_BCC_NOTAKE_B = -2;
CYC_BCC_NOTAKE_W = 0;
CYC_DBCC_F_NOEXP = 0;
CYC_DBCC_F_EXP = 4;
CYC_SCC_R_FALSE = 0;
CYC_MOVEM_W = 2;
CYC_MOVEM_L = 2;
CYC_SHIFT = 0;
CYC_RESET = 518;
return;
case M68K_CPU_TYPE_68020:
CPU_TYPE = CPU_TYPE_020;
CPU_ADDRESS_MASK = 0xffffffff;
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
CYC_INSTRUCTION = m68ki_cycles[2];
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
CYC_BCC_NOTAKE_B = -2;
CYC_BCC_NOTAKE_W = 0;
CYC_DBCC_F_NOEXP = 0;
CYC_DBCC_F_EXP = 4;
CYC_SCC_R_FALSE = 0;
CYC_MOVEM_W = 2;
CYC_MOVEM_L = 2;
CYC_SHIFT = 0;
CYC_RESET = 518;
return;
}
}
/* Execute some instructions until we use up num_cycles clock cycles */
/* ASG: removed per-instruction interrupt checks */
int m68k_execute(int num_cycles)
{
/* Make sure we're not stopped */
if(!CPU_STOPPED)
{
/* Set our pool of clock cycles available */
SET_CYCLES(num_cycles);
m68ki_initial_cycles = num_cycles;
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* Return point if we had an address error */
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
/* Main loop. Keep going until we run out of clock cycles */
do
{
/* Set tracing accodring to T1. (T0 is done inside instruction) */
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
/* Set the address space for reads */
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
/* Call external hook to peek at CPU */
m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
/* Record previous program counter */
REG_PPC = REG_PC;
/* Read an instruction and call its handler */
REG_IR = m68ki_read_imm_16();
m68ki_instruction_jump_table[REG_IR]();
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
/* Trace m68k_exception, if necessary */
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
} while(GET_CYCLES() > 0);
/* set previous PC to current PC for the next entry into the loop */
REG_PPC = REG_PC;
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* return how many clocks we used */
return m68ki_initial_cycles - GET_CYCLES();
}
/* We get here if the CPU is stopped or halted */
SET_CYCLES(0);
CPU_INT_CYCLES = 0;
return num_cycles;
}
int m68k_cycles_run(void)
{
return m68ki_initial_cycles - GET_CYCLES();
}
int m68k_cycles_remaining(void)
{
return GET_CYCLES();
}
/* Change the timeslice */
void m68k_modify_timeslice(int cycles)
{
m68ki_initial_cycles += cycles;
ADD_CYCLES(cycles);
}
void m68k_end_timeslice(void)
{
m68ki_initial_cycles = GET_CYCLES();
SET_CYCLES(0);
}
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
/* KS: Modified so that IPL* bits match with mask positions in the SR
* and cleaned out remenants of the interrupt controller.
*/
void m68k_set_irq(unsigned int int_level)
{
uint old_level = CPU_INT_LEVEL;
CPU_INT_LEVEL = int_level << 8;
/* A transition from < 7 to 7 always interrupts (NMI) */
/* Note: Level 7 can also level trigger like a normal IRQ */
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
else
m68ki_check_interrupts(); /* Level triggered (IRQ) */
}
/* Pulse the RESET line on the CPU */
void m68k_pulse_reset(void)
{
static uint emulation_initialized = 0;
/* The first call to this function initializes the opcode handler jump table */
if(!emulation_initialized)
{
m68ki_build_opcode_table();
m68k_set_int_ack_callback(NULL);
m68k_set_bkpt_ack_callback(NULL);
m68k_set_reset_instr_callback(NULL);
m68k_set_pc_changed_callback(NULL);
m68k_set_fc_callback(NULL);
m68k_set_instr_hook_callback(NULL);
emulation_initialized = 1;
}
if(CPU_TYPE == 0) /* KW 990319 */
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
/* Clear all stop levels and eat up all remaining cycles */
CPU_STOPPED = 0;
SET_CYCLES(0);
/* Turn off tracing */
FLAG_T1 = FLAG_T0 = 0;
m68ki_clear_trace();
/* Interrupt mask to level 7 */
FLAG_INT_MASK = 0x0700;
/* Reset VBR */
REG_VBR = 0;
/* Go to supervisor mode */
m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
/* Invalidate the prefetch queue */
#if M68K_EMULATE_PREFETCH
/* Set to arbitrary number since our first fetch is from 0 */
CPU_PREF_ADDR = 0x1000;
#endif /* M68K_EMULATE_PREFETCH */
/* Read the initial stack pointer and program counter */
m68ki_jump(0);
REG_SP = m68ki_read_imm_32();
REG_PC = m68ki_read_imm_32();
m68ki_jump(REG_PC);
}
/* Pulse the HALT line on the CPU */
void m68k_pulse_halt(void)
{
CPU_STOPPED |= STOP_LEVEL_HALT;
}
/* Get and set the current CPU context */
/* This is to allow for multiple CPUs */
unsigned int m68k_context_size()
{
return sizeof(m68ki_cpu_core);
}
unsigned int m68k_get_context(void* dst)
{
if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
return sizeof(m68ki_cpu_core);
}
void m68k_set_context(void* src)
{
if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
}
void m68k_save_context( void (*save_value)(char*, unsigned int))
{
if(!save_value)
return;
save_value("CPU_TYPE" , m68k_get_reg(NULL, M68K_REG_CPU_TYPE));
save_value("D0" , REG_D[0]);
save_value("D1" , REG_D[1]);
save_value("D2" , REG_D[2]);
save_value("D3" , REG_D[3]);
save_value("D4" , REG_D[4]);
save_value("D5" , REG_D[5]);
save_value("D6" , REG_D[6]);
save_value("D7" , REG_D[7]);
save_value("A0" , REG_A[0]);
save_value("A1" , REG_A[1]);
save_value("A2" , REG_A[2]);
save_value("A3" , REG_A[3]);
save_value("A4" , REG_A[4]);
save_value("A5" , REG_A[5]);
save_value("A6" , REG_A[6]);
save_value("A7" , REG_A[7]);
save_value("PPC" , REG_PPC);
save_value("PC" , REG_PC);
save_value("USP" , REG_USP);
save_value("ISP" , REG_ISP);
save_value("MSP" , REG_MSP);
save_value("VBR" , REG_VBR);
save_value("SFC" , REG_SFC);
save_value("DFC" , REG_DFC);
save_value("CACR" , REG_CACR);
save_value("CAAR" , REG_CAAR);
save_value("SR" , m68ki_get_sr());
save_value("INT_LEVEL" , CPU_INT_LEVEL);
save_value("INT_CYCLES", CPU_INT_CYCLES);
save_value("STOPPED" , (CPU_STOPPED & STOP_LEVEL_STOP) != 0);
save_value("HALTED" , (CPU_STOPPED & STOP_LEVEL_HALT) != 0);
save_value("PREF_ADDR" , CPU_PREF_ADDR);
save_value("PREF_DATA" , CPU_PREF_DATA);
}
void m68k_load_context(unsigned int (*load_value)(char*))
{
unsigned int temp;
m68k_set_cpu_type(load_value("CPU_TYPE"));
REG_PPC = load_value("PPC");
REG_PC = load_value("PC");
m68ki_jump(REG_PC);
CPU_INT_LEVEL = 0;
m68ki_set_sr_noint(load_value("SR"));
REG_D[0] = load_value("D0");
REG_D[1] = load_value("D1");
REG_D[2] = load_value("D2");
REG_D[3] = load_value("D3");
REG_D[4] = load_value("D4");
REG_D[5] = load_value("D5");
REG_D[6] = load_value("D6");
REG_D[7] = load_value("D7");
REG_A[0] = load_value("A0");
REG_A[1] = load_value("A1");
REG_A[2] = load_value("A2");
REG_A[3] = load_value("A3");
REG_A[4] = load_value("A4");
REG_A[5] = load_value("A5");
REG_A[6] = load_value("A6");
REG_A[7] = load_value("A7");
REG_USP = load_value("USP");
REG_ISP = load_value("ISP");
REG_MSP = load_value("MSP");
REG_VBR = load_value("VBR");
REG_SFC = load_value("SFC");
REG_DFC = load_value("DFC");
REG_CACR = load_value("CACR");
REG_CAAR = load_value("CAAR");
CPU_INT_LEVEL = load_value("INT_LEVEL");
CPU_INT_CYCLES = load_value("INT_CYCLES");
CPU_STOPPED = 0;
temp = load_value("STOPPED");
if(temp) CPU_STOPPED |= STOP_LEVEL_STOP;
temp = load_value("HALTED");
if(temp) CPU_STOPPED |= STOP_LEVEL_HALT;
CPU_PREF_ADDR = load_value("PREF_ADDR");
CPU_PREF_DATA = load_value("PREF_DATA");
}
/* ======================================================================== */
/* ============================== END OF FILE ============================= */
/* ======================================================================== */

1841
AltairZ80/m68kcpu.h Executable file

File diff suppressed because it is too large Load diff

3443
AltairZ80/m68kdasm.c Executable file

File diff suppressed because it is too large Load diff

11948
AltairZ80/m68kopac.c Normal file

File diff suppressed because it is too large Load diff

13221
AltairZ80/m68kopdm.c Normal file

File diff suppressed because it is too large Load diff

8710
AltairZ80/m68kopnz.c Normal file

File diff suppressed because it is too large Load diff

2093
AltairZ80/m68kops.c Normal file

File diff suppressed because it is too large Load diff

1984
AltairZ80/m68kops.h Normal file

File diff suppressed because it is too large Load diff

543
AltairZ80/m68ksim.c Normal file
View file

@ -0,0 +1,543 @@
/* m68kcpmsim.c: CP/M for Motorola 68000 definitions
Copyright (c) 2014, Peter Schorn
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
PETER SCHORN 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 Peter Schorn shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Peter Schorn.
Based on work by David W. Schultz http://home.earthlink.net/~david.schultz (c) 2014
MC68000 simulation tailored to support CP/M-68K. It includes:
16MB of memory. (Flat, function codes and address space types ignored.)
Console I/O using a MC6850 like serial port with interrupts.
Simulated disk system:
Since the intent is to support CP/M-68K and it does disk I/O in 128 byte
chunks, so will this. Control is via several registers mapped into memory:
Offset Function Description
0 DMA address to read/write data to
4 drive select disk drive
8 read sector sector (128 byte) offset on disk
12 write sector sector (128 byte) offset on disk
16 status read status of operation
Operation is simple: Set the drive and DMA address and then write the
sector number to the sector register. This write triggers the requested
operation. The status of the operation can be determined by reading the
status register.
A zero indicates that no error occured.
Note that these operations invoke read() and write() system calls directly
so that they will alter the image on the hard disk. KEEP BACKUPS!
In addition Linux will buffer the writes so they may note be really complete
for a while. The BIOS flush function invokes a fsync on all open files.
There are two options for booting CPM:
S-records: This loads CPM in two parts. The first is in cpm400.bin which
is created from the srecords in cpm400.sr. The second is in simbios.bin
which contains the BIOS. Both of these files must be binaries and not
srecords.
If you want to alter the bios, rebuild simbios.bin using:
asl simbios.s
p2bin simbios.p
Use altairz80 cpm68k_s to boot.
Boot track: A CPM loader is in the boot track of simulated drive C. 32K of
data is loaded from that file to memory starting at $400.
Use altairz80 cpm68k to boot.
*/
#include "m68k.h"
/* Read/write macros */
#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]
#define READ_WORD(BASE, ADDR) (((BASE)[ADDR] << 8) | \
(BASE)[(ADDR) + 1])
#define READ_LONG(BASE, ADDR) (((BASE)[ADDR] << 24) | \
((BASE)[(ADDR) + 1] << 16) | \
((BASE)[(ADDR) + 2] << 8) | \
(BASE)[(ADDR) + 3])
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[ADDR] = (VAL) & 0xff
#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL) >> 8) & 0xff; \
(BASE)[(ADDR)+1] = (VAL)&0xff
#define WRITE_LONG(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL) >> 24) & 0xff; \
(BASE)[(ADDR) + 1] = ((VAL) >> 16) & 0xff; \
(BASE)[(ADDR) + 2] = ((VAL) >> 8) & 0xff; \
(BASE)[(ADDR) + 3] = (VAL) & 0xff
/* Memory-mapped IO ports */
/* 6850 serial port like thing. Implements a reduced set of functionallity. */
#define MC6850_STAT 0xff1000L // command/status register
#define MC6850_DATA 0xff1002L // receive/transmit data register
/* Memory mapped disk system */
#define DISK_BASE 0xff0000L
#define DISK_SET_DMA (DISK_BASE)
#define DISK_SET_DRIVE (DISK_BASE + 4)
#define DISK_SET_SECTOR (DISK_BASE + 8)
#define DISK_READ (DISK_BASE + 12)
#define DISK_WRITE (DISK_BASE + 16)
#define DISK_STATUS (DISK_BASE + 20)
#define DISK_FLUSH (DISK_BASE + 24)
/* Miscellaneous */
#define M68K_GET_TIME (0xff7ff8) // read long to get time in seconds
#define M68K_STOP_CPU (0xff7ffc) // write long to stop CPU and return to SIMH prompt
/* IRQ connections */
#define IRQ_NMI_DEVICE 7
#define IRQ_MC6850 5
extern uint32 PCX;
/* Prototypes */
static void MC6850_reset(void);
static void m68k_input_device_update(void);
static int nmi_device_ack(void);
static void int_controller_set(uint32 value);
static void int_controller_clear(uint32 value);
/* Data */
static int m68k_MC6850_control = 0; /* MC6850 control register */
static int m68k_MC6850_status = 2; /* MC6850 status register */
static t_stat keyboardCharacter; /* one character buffer */
static t_bool characterAvailable = FALSE; /* buffer initially empty */
static uint32 m68k_int_controller_pending = 0; /* list of pending interrupts */
static uint32 m68k_int_controller_highest_int = 0; /* Highest pending interrupt */
static uint8 m68k_ram[M68K_MAX_RAM + 1]; /* RAM */
/* Interface to HDSK device */
extern void hdsk_prepareRead(void);
extern void hdsk_prepareWrite(void);
extern void hdsk_setSelectedDisk(const int32 disk);
extern void hdsk_setSelectedSector(const int32 sector);
extern void hdsk_setSelectedTrack(const int32 track);
extern void hdsk_setSelectedDMA(const int32 dma);
extern int32 hdsk_getStatus(void);
extern t_bool hdsk_checkParameters(void);
extern int32 hdsk_read(void);
extern int32 hdsk_write(void);
extern int32 hdsk_flush(void);
static uint32 m68k_fc; /* Current function code from CPU */
extern uint32 m68k_registers[M68K_REG_CPU_TYPE + 1];
extern UNIT cpu_unit;
#define M68K_BOOT_LENGTH (32 * 1024) /* size of bootstrap */
#define M68K_BOOT_PC 0x000400 /* initial PC for boot */
#define M68K_BOOT_SP 0xfe0000 /* initial SP for boot */
t_stat m68k_hdsk_boot(const int32 unitno, DEVICE *dptr,
const uint32 verboseMessage, const uint32 hdskNumber) {
UNIT *uptr;
size_t i;
if ((unitno < 0) || (unitno >= hdskNumber))
return SCPE_ARG;
uptr = (dptr -> units) + unitno;
if (((uptr -> flags) & UNIT_ATT) == 0) {
sim_debug(verboseMessage, dptr, "HDSK%d: Boot drive is not attached.\n", unitno);
return SCPE_ARG;
}
if (sim_fseek(uptr -> fileref, 0, SEEK_SET) != 0) {
sim_debug(verboseMessage, dptr, "HDSK%d: Boot error seeking start.\n", unitno);
return SCPE_ARG;
}
i = sim_fread(&m68k_ram[M68K_BOOT_PC], 1, M68K_BOOT_LENGTH, uptr -> fileref);
if (i != M68K_BOOT_LENGTH) {
sim_debug(verboseMessage, dptr,
"HDSK%d: Error: Failed to read %i bytes from boot drive.\n",
unitno, M68K_BOOT_LENGTH);
return SCPE_ARG;
}
// Now put in values for the stack and PC vectors
WRITE_LONG(m68k_ram, 0, M68K_BOOT_SP); // SP
WRITE_LONG(m68k_ram, 4, M68K_BOOT_PC); // PC
m68k_pulse_reset(); // also calls MC6850_reset()
m68k_CPUToView();
return SCPE_OK;
}
void m68k_CPUToView(void) {
uint32 reg;
for (reg = M68K_REG_D0; reg <= M68K_REG_CPU_TYPE; reg++)
m68k_registers[reg] = m68k_get_reg(NULL, reg);
}
void m68k_viewToCPU(void) {
uint32 reg;
for (reg = M68K_REG_D0; reg <= M68K_REG_CPU_TYPE; reg++)
m68k_set_reg(reg, m68k_registers[reg]);
}
t_stat sim_instr_m68k(void) {
t_stat reason = SCPE_OK;
m68k_viewToCPU();
while (TRUE) {
if (sim_interval <= 0) { /* check clock queue */
#if !UNIX_PLATFORM
if ((reason = sim_poll_kbd()) == SCPE_STOP) /* poll on platforms without reliable
signalling */
break;
#endif
if ((reason = sim_process_event()))
break;
m68k_input_device_update();
}
if (sim_brk_summ && sim_brk_test(m68k_get_reg(NULL, M68K_REG_PC), SWMASK('E'))) {
/* breakpoint? */
reason = STOP_IBKPT; /* stop simulation */
break;
}
PCX = m68k_get_reg(NULL, M68K_REG_PC);
sim_interval--;
m68k_execute(1);
if (stop_cpu) {
reason = SCPE_STOP;
break;
}
}
m68k_CPUToView();
return reason;
}
void m68k_clear_memory(void ) {
uint32 i;
for (i = 0; i <= M68K_MAX_RAM; i++)
m68k_ram[i] = 0;
}
void m68k_cpu_reset(void) {
WRITE_LONG(m68k_ram, 0, 0x00006000); // SP
WRITE_LONG(m68k_ram, 4, 0x00000200); // PC
m68k_pulse_reset(); // also calls MC6850_reset()
m68k_CPUToView();
}
/* Implementation for the MC6850 like device
Only those bits of the control register that enable/disable receive and
transmit interrupts are implemented.
In the status register, the Receive Data Register Full, Transmit Data
Register Empty, and IRQ flags are implemented. Although the transmit
data register is always empty.
*/
static void MC6850_reset(void) {
m68k_MC6850_control = 0;
m68k_MC6850_status = 2;
characterAvailable = FALSE;
int_controller_clear(IRQ_MC6850);
}
#define INITIAL_IDLE 100
#define IDLE_SLEEP 20
static uint32 idleCount = INITIAL_IDLE;
static void m68k_input_device_update(void) {
if (characterAvailable) {
m68k_MC6850_status |= 1;
if ((m68k_MC6850_control & 0x80) && !(m68k_MC6850_status & 0x80)) {
int_controller_set(IRQ_MC6850);
m68k_MC6850_status |= 0x80;
}
} else if (--idleCount == 0) {
const t_stat ch = sim_poll_kbd();
idleCount = INITIAL_IDLE;
if (IDLE_SLEEP)
sim_os_ms_sleep(IDLE_SLEEP);
if (ch) {
characterAvailable = TRUE;
keyboardCharacter = ch;
}
}
}
/* wait until character becomes available */
static uint32 MC6850_data_read(void) {
t_stat ch;
int_controller_clear(IRQ_MC6850);
m68k_MC6850_status &= ~0x81; // clear data ready and interrupt flag
if (characterAvailable) {
ch = keyboardCharacter;
characterAvailable = FALSE;
} else
ch = sim_poll_kbd();
while ((ch <= 0) && (!stop_cpu)) {
if (IDLE_SLEEP)
sim_os_ms_sleep(IDLE_SLEEP);
ch = sim_poll_kbd();
}
if (ch == SCPE_STOP)
stop_cpu = TRUE;
return (((ch > 0) && (!stop_cpu)) ? ch & 0xff : 0xff);
}
static int MC6850_status_read() {
return m68k_MC6850_status;
}
/* Implementation for the output device */
static int MC6850_device_ack(void) {
return M68K_INT_ACK_AUTOVECTOR;
}
static void MC6850_data_write(uint32 value) {
sim_putchar(value);
if ((m68k_MC6850_control & 0x60) == 0x20) { // transmit interupt enabled?
int_controller_clear(IRQ_MC6850);
int_controller_set(IRQ_MC6850);
}
}
static void MC6850_control_write(uint32 val) {
m68k_MC6850_control = val;
}
/* Read data from RAM */
unsigned int m68k_cpu_read_byte_raw(unsigned int address) {
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to read byte from non existing memory 0x%08x." NLP,
PCX, address);
return 0xff;
}
return READ_BYTE(m68k_ram, address);
}
unsigned int m68k_cpu_read_byte(unsigned int address) {
switch(address) {
case MC6850_DATA:
return MC6850_data_read();
case MC6850_STAT:
return MC6850_status_read();
default:
break;
}
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to read byte from non existing memory 0x%08x." NLP,
PCX, address);
return 0xff;
}
return READ_BYTE(m68k_ram, address);
}
unsigned int m68k_cpu_read_word(unsigned int address) {
switch(address) {
case DISK_STATUS:
return hdsk_getStatus();
default:
break;
}
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to read word from non existing memory 0x%08x." NLP,
PCX, address);
return 0xffff;
}
return READ_WORD(m68k_ram, address);
}
unsigned int m68k_cpu_read_long(unsigned int address) {
switch(address) {
case DISK_STATUS:
return hdsk_getStatus();
case M68K_GET_TIME:
return time(NULL);
default:
break;
}
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to read long from non existing memory 0x%08x." NLP,
PCX, address);
return 0xffffffff;
}
return READ_LONG(m68k_ram, address);
}
/* Write data to RAM or a device */
void m68k_cpu_write_byte_raw(unsigned int address, unsigned int value) {
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to write byte 0x%02x to non existing memory 0x%08x." NLP,
PCX, value & 0xff, address);
return;
}
WRITE_BYTE(m68k_ram, address, value);
}
void m68k_cpu_write_byte(unsigned int address, unsigned int value) {
switch(address) {
case MC6850_DATA:
MC6850_data_write(value & 0xff);
return;
case MC6850_STAT:
MC6850_control_write(value & 0xff);
return;
default:
break;
}
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to write byte 0x%02x to non existing memory 0x%08x." NLP,
PCX, value & 0xff, address);
return;
}
WRITE_BYTE(m68k_ram, address, value);
}
void m68k_cpu_write_word(unsigned int address, unsigned int value) {
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to write word 0x%04x to non existing memory 0x%08x." NLP,
PCX, value & 0xffff, address);
return;
}
WRITE_WORD(m68k_ram, address, value);
}
void m68k_cpu_write_long(unsigned int address, unsigned int value) {
switch(address) {
case DISK_SET_DRIVE:
hdsk_setSelectedDisk(value);
return;
case DISK_SET_DMA:
hdsk_setSelectedDMA(value);
return;
case DISK_SET_SECTOR:
hdsk_setSelectedSector(value);
return;
case DISK_READ:
hdsk_setSelectedSector(value);
hdsk_setSelectedTrack(0);
hdsk_prepareRead();
if (hdsk_checkParameters())
hdsk_read();
return;
case DISK_WRITE:
hdsk_setSelectedSector(value);
hdsk_setSelectedTrack(0);
hdsk_prepareWrite();
if (hdsk_checkParameters())
hdsk_write();
return;
case DISK_FLUSH:
hdsk_flush();
return;
case M68K_STOP_CPU:
stop_cpu = TRUE;
return;
default:
break;
}
if (address > M68K_MAX_RAM) {
if (cpu_unit.flags & UNIT_CPU_VERBOSE)
printf("M68K: 0x%08x Attempt to write long 0x%08x to non existing memory 0x%08x." NLP,
PCX, value, address);
return;
}
WRITE_LONG(m68k_ram, address, value);
}
/* Called when the CPU pulses the RESET line */
void m68k_cpu_pulse_reset(void) {
MC6850_reset();
}
/* Called when the CPU changes the function code pins */
void m68k_cpu_set_fc(unsigned int fc) {
m68k_fc = fc;
}
/* Called when the CPU acknowledges an interrupt */
int m68k_cpu_irq_ack(int level) {
switch(level) {
case IRQ_NMI_DEVICE:
return nmi_device_ack();
case IRQ_MC6850:
return MC6850_device_ack();
}
return M68K_INT_ACK_SPURIOUS;
}
/* Implementation for the NMI device */
static int nmi_device_ack(void) {
int_controller_clear(IRQ_NMI_DEVICE);
return M68K_INT_ACK_AUTOVECTOR;
}
/* Implementation for the interrupt controller */
static void int_controller_set(uint32 value) {
const uint32 old_pending = m68k_int_controller_pending;
m68k_int_controller_pending |= (1<<value);
if (old_pending != m68k_int_controller_pending && value > m68k_int_controller_highest_int) {
m68k_int_controller_highest_int = value;
m68k_set_irq(m68k_int_controller_highest_int);
}
}
static void int_controller_clear(uint32 value) {
m68k_int_controller_pending &= ~(1<<value);
for (m68k_int_controller_highest_int = 7; m68k_int_controller_highest_int > 0;m68k_int_controller_highest_int--)
if (m68k_int_controller_pending & (1<<m68k_int_controller_highest_int))
break;
m68k_set_irq(m68k_int_controller_highest_int);
}
unsigned int m68k_read_disassembler_16(unsigned int address) {
return m68k_cpu_read_word(address);
}
unsigned int m68k_read_disassembler_32(unsigned int address) {
return m68k_cpu_read_long(address);
}

57
AltairZ80/m68ksim.h Normal file
View file

@ -0,0 +1,57 @@
/* m68kcpmsim.h: CP/M for Motorola 68000 definitions
Copyright (c) 2014, Peter Schorn
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
PETER SCHORN 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 Peter Schorn shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Peter Schorn.
Based on work by David W. Schultz http://home.earthlink.net/~david.schultz (c) 2014
*/
#ifndef M68KSIM__HEADER
#define M68KSIM__HEADER
#include "altairz80_defs.h"
unsigned int m68k_cpu_read_byte(unsigned int address);
unsigned int m68k_cpu_read_byte_raw(unsigned int address);
unsigned int m68k_cpu_read_word(unsigned int address);
unsigned int m68k_cpu_read_long(unsigned int address);
void m68k_cpu_write_byte(unsigned int address, unsigned int value);
void m68k_cpu_write_byte_raw(unsigned int address, unsigned int value);
void m68k_cpu_write_word(unsigned int address, unsigned int value);
void m68k_cpu_write_long(unsigned int address, unsigned int value);
void m68k_cpu_pulse_reset(void);
void m68k_cpu_set_fc(unsigned int fc);
int m68k_cpu_irq_ack(int level);
t_stat sim_instr_m68k(void);
void m68k_cpu_reset(void);
void m68k_clear_memory(void);
void m68k_CPUToView(void);
void m68k_viewToCPU(void);
t_stat m68k_hdsk_boot(const int32 unitno, DEVICE *dptr,
const uint32 verboseMessage, const uint32 hdskNumber);
#define M68K_MAX_RAM 0xffffff // highest address of 16MB of RAM
#define M68K_MAX_RAM_LOG2 24 // 24 bit addresses
#endif /* M68KSIM__HEADER */

View file

@ -59,13 +59,11 @@
#endif #endif
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define STATUS_MSG (1 << 0)
#define SEEK_MSG (1 << 1) #define SEEK_MSG (1 << 1)
#define CMD_MSG (1 << 2) #define CMD_MSG (1 << 2)
#define RD_DATA_MSG (1 << 3) #define RD_DATA_MSG (1 << 3)
#define WR_DATA_MSG (1 << 4) #define WR_DATA_MSG (1 << 4)
#define STATUS_MSG (1 << 5)
#define ORDERS_MSG (1 << 7)
extern uint32 PCX; extern uint32 PCX;
extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc);
@ -150,26 +148,31 @@ static REG mfdc_reg[] = {
{ NULL } { NULL }
}; };
#define MDSK_NAME "Micropolis FD Control MDSK"
static MTAB mfdc_mod[] = { static MTAB mfdc_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
{ UNIT_MFDC_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_membase, &show_membase, NULL, "Sets disk controller base address" },
{ UNIT_MFDC_WLK, UNIT_MFDC_WLK, "WRTLCK", "WRTLCK", NULL }, { UNIT_MFDC_WLK, 0, "WRTENB", "WRTENB",
NULL, NULL, NULL, "Enables " MDSK_NAME "n for writing" },
{ UNIT_MFDC_WLK, UNIT_MFDC_WLK, "WRTLCK", "WRTLCK",
NULL, NULL, NULL, "Locks " MDSK_NAME "n for writing" },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_MFDC_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_MFDC_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " MDSK_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_MFDC_VERBOSE, UNIT_MFDC_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_MFDC_VERBOSE, UNIT_MFDC_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " MDSK_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB mfdc_dt[] = { static DEBTAB mfdc_dt[] = {
{ "ERROR", ERROR_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek activity" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Commands" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Disk read activity" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Disk write activity" },
{ "STATUS", STATUS_MSG },
{ "ORDERS", ORDERS_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -178,8 +181,8 @@ DEVICE mfdc_dev = {
MFDC_MAX_DRIVES, 10, 31, 1, MFDC_MAX_DRIVES, MFDC_MAX_DRIVES, MFDC_MAX_DRIVES, 10, 31, 1, MFDC_MAX_DRIVES, MFDC_MAX_DRIVES,
NULL, NULL, &mfdc_reset, NULL, NULL, &mfdc_reset,
NULL, &mfdc_attach, &mfdc_detach, NULL, &mfdc_attach, &mfdc_detach,
&mfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &mfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
mfdc_dt, NULL, "Micropolis FD Control MDSK" mfdc_dt, NULL, MDSK_NAME
}; };
/* Micropolis FD Control Boot ROM /* Micropolis FD Control Boot ROM

View file

@ -55,13 +55,11 @@
#endif #endif
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define PIO_MSG (1 << 0)
#define PIO_MSG (1 << 1) #define UART_MSG (1 << 1)
#define UART_MSG (1 << 2) #define MPCL_MSG (1 << 2)
#define RTC_MSG (1 << 3) #define ROM_MSG (1 << 3)
#define MPCL_MSG (1 << 4) #define VERBOSE_MSG (1 << 4)
#define ROM_MSG (1 << 5)
#define VERBOSE_MSG (1 << 7)
#define N8VEM_MAX_DRIVES 2 #define N8VEM_MAX_DRIVES 2
@ -86,7 +84,6 @@ extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
int32 (*routine)(const int32, const int32, const int32), uint8 unmap); int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
extern uint32 PCX; extern uint32 PCX;
extern REG *sim_PC;
extern int32 find_unit_index (UNIT *uptr); extern int32 find_unit_index (UNIT *uptr);
static t_stat n8vem_reset(DEVICE *n8vem_dev); static t_stat n8vem_reset(DEVICE *n8vem_dev);
@ -121,29 +118,37 @@ static UNIT n8vem_unit[] = {
}; };
static REG n8vem_reg[] = { static REG n8vem_reg[] = {
{ HRDATA (SAVEROM, save_rom, 1), }, { HRDATAD (SAVEROM, save_rom, 1,
{ HRDATA (SAVERAM, save_ram, 1), }, "When 1, saves the ROM back to file on disk at detach time"), },
{ HRDATA (PIO1A, n8vem_pio1a, 8), }, { HRDATAD (SAVERAM, save_ram, 1,
{ HRDATA (PIO1B, n8vem_pio1b, 8), }, "When 1 save the RAM back to file on disk at detach time"), },
{ HRDATA (PIO1C, n8vem_pio1c, 8), }, { HRDATAD (PIO1A, n8vem_pio1a, 8,
{ HRDATA (PIO1CTRL, n8vem_pio1ctrl, 8), }, "8255 PIO1A IN Port"), },
{ HRDATAD (PIO1B, n8vem_pio1b, 8,
"8255 PIO1B OUT Port"), },
{ HRDATAD (PIO1C, n8vem_pio1c, 8,
"8255 PIO1C IN Port"), },
{ HRDATAD (PIO1CTRL, n8vem_pio1ctrl, 8,
"8255 PIO1 Control Port"), },
{ NULL } { NULL }
}; };
#define N8VEM_NAME "Single-Board Computer N8VEM"
static MTAB n8vem_mod[] = { static MTAB n8vem_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase,
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, NULL, "Sets device base address" },
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase,
NULL, "Sets device I/O address" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB n8vem_dt[] = { static DEBTAB n8vem_dt[] = {
{ "ERROR", ERROR_MSG }, { "PIO", PIO_MSG, "PIP activity"} ,
{ "PIO", PIO_MSG }, { "UART", UART_MSG, "UART activity" },
{ "UART", UART_MSG }, { "ROM", ROM_MSG, "ROM activity" },
{ "RTC", RTC_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "ROM", ROM_MSG },
{ "VERBOSE",VERBOSE_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -152,7 +157,7 @@ DEVICE n8vem_dev = {
N8VEM_MAX_DRIVES, 10, 31, 1, N8VEM_MAX_DRIVES, N8VEM_MAX_DRIVES, N8VEM_MAX_DRIVES, 10, 31, 1, N8VEM_MAX_DRIVES, N8VEM_MAX_DRIVES,
NULL, NULL, &n8vem_reset, NULL, NULL, &n8vem_reset,
&n8vem_boot, &n8vem_attach, &n8vem_detach, &n8vem_boot, &n8vem_attach, &n8vem_detach,
&n8vem_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &n8vem_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
n8vem_dt, NULL, "Single-Board Computer N8VEM" n8vem_dt, NULL, "Single-Board Computer N8VEM"
}; };

View file

@ -59,15 +59,10 @@
#endif #endif
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define STATUS_MSG (1 << 0)
#define SEEK_MSG (1 << 1) #define DRIVE_MSG (1 << 1)
#define CMD_MSG (1 << 2) #define VERBOSE_MSG (1 << 2)
#define RD_DATA_MSG (1 << 3) #define IRQ_MSG (1 << 3)
#define WR_DATA_MSG (1 << 4)
#define STATUS_MSG (1 << 5)
#define DRIVE_MSG (1 << 6)
#define VERBOSE_MSG (1 << 7)
#define IRQ_MSG (1 << 8)
#define CROMFDC_MAX_DRIVES 4 #define CROMFDC_MAX_DRIVES 4
#define CROMFDC_ROM_SIZE (8 * 1024) #define CROMFDC_ROM_SIZE (8 * 1024)
@ -100,13 +95,8 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ
static t_stat cromfdc_svc (UNIT *uptr); static t_stat cromfdc_svc (UNIT *uptr);
extern REG *sim_PC;
extern uint32 PCX; /* external view of PC */ extern uint32 PCX; /* external view of PC */
#define UNIT_V_CROMFDC_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_CROMFDC_WLK (1 << UNIT_V_CROMFDC_WLK)
#define UNIT_V_CROMFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_CROMFDC_VERBOSE (1 << UNIT_V_CROMFDC_VERBOSE)
#define UNIT_V_CROMFDC_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ #define UNIT_V_CROMFDC_ROM (UNIT_V_UF + 2) /* boot ROM enabled */
#define UNIT_CROMFDC_ROM (1 << UNIT_V_CROMFDC_ROM) #define UNIT_CROMFDC_ROM (1 << UNIT_V_CROMFDC_ROM)
#define CROMFDC_CAPACITY (77*1*26*128) /* Default SSSD 8" (IBM 3740) Disk Capacity */ #define CROMFDC_CAPACITY (77*1*26*128) /* Default SSSD 8" (IBM 3740) Disk Capacity */
@ -226,39 +216,40 @@ static UNIT cromfdc_unit[] = {
}; };
static REG cromfdc_reg[] = { static REG cromfdc_reg[] = {
{ HRDATA (DIPSW, dipswitch, 8), }, { HRDATAD (DIPSW, dipswitch, 8,
{ DRDATA (BOOTSTRAP, bootstrap, 2), }, "5-position DIP switch on 64FDC card"), },
{ DRDATA (FDCTYPE, crofdc_type, 8), }, { DRDATAD (BOOTSTRAP, bootstrap, 2,
{ DRDATA (BOOT, crofdc_boot, 10), }, "0 for RDOS 2.52, 1 for RDOS 3.12"), },
{ DRDATA (INHINIT, crofdc_inh_init, 10), }, { DRDATAD (FDCTYPE, crofdc_type, 8,
"Controller type, either 4, 16, or 64 for Cromemco, 50 for CCS-2422"), },
{ DRDATAD (BOOT, crofdc_boot, 10,
"BOOT jumper setting, default is auto-boot"), },
{ DRDATAD (INHINIT, crofdc_inh_init, 10,
"Inhibit Init (Format) switch, default is not inhibited"), },
{ NULL } { NULL }
}; };
#define CROMFDC_NAME "Cromemco 4/16/64 FDC CROMFDC"
static MTAB cromfdc_mod[] = { static MTAB cromfdc_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, &set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
{ UNIT_CROMFDC_WLK, 0, "WRTENB", "WRTENB", NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_CROMFDC_WLK, UNIT_CROMFDC_WLK, "WRTLCK", "WRTLCK", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_CROMFDC_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_CROMFDC_ROM, 0, "NOROM", "NOROM",
/* verbose, show warning messages */ NULL, NULL, NULL, "Disables boot ROM for unit " CROMFDC_NAME "n" },
{ UNIT_CROMFDC_VERBOSE, UNIT_CROMFDC_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_CROMFDC_ROM, UNIT_CROMFDC_ROM, "ROM", "ROM",
{ UNIT_CROMFDC_ROM, 0, "NOROM", "NOROM", NULL }, NULL, NULL, NULL, "Enables boot ROM for unit " CROMFDC_NAME "n" },
{ UNIT_CROMFDC_ROM, UNIT_CROMFDC_ROM, "ROM", "ROM", NULL },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB cromfdc_dt[] = { static DEBTAB cromfdc_dt[] = {
{ "ERROR", ERROR_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "SEEK", SEEK_MSG }, { "DRIVE", DRIVE_MSG, "Drive messages" },
{ "CMD", CMD_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "RDDATA", RD_DATA_MSG }, { "IRQ", IRQ_MSG, "IRQ messages" },
{ "WRDATA", WR_DATA_MSG },
{ "STATUS", STATUS_MSG },
{ "DRIVE", DRIVE_MSG },
{ "VERBOSE",VERBOSE_MSG },
{ "IRQ", IRQ_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -267,8 +258,8 @@ DEVICE cromfdc_dev = {
CROMFDC_MAX_DRIVES, 10, 31, 1, CROMFDC_MAX_DRIVES, CROMFDC_MAX_DRIVES, CROMFDC_MAX_DRIVES, 10, 31, 1, CROMFDC_MAX_DRIVES, CROMFDC_MAX_DRIVES,
NULL, NULL, &cromfdc_reset, NULL, NULL, &cromfdc_reset,
&cromfdc_boot, &wd179x_attach, &wd179x_detach, &cromfdc_boot, &wd179x_attach, &wd179x_detach,
&cromfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &cromfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
cromfdc_dt, NULL, "Cromemco 4/16/64 FDC CROMFDC" cromfdc_dt, NULL, CROMFDC_NAME
}; };
/* This is the CROMFDC RDOS-II ROM. /* This is the CROMFDC RDOS-II ROM.

View file

@ -62,15 +62,9 @@
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define ERROR_MSG (1 << 0)
#define SEEK_MSG (1 << 1) #define DRIVE_MSG (1 << 1)
#define CMD_MSG (1 << 2) #define VERBOSE_MSG (1 << 2)
#define RD_DATA_MSG (1 << 3) #define DMA_MSG (1 << 3)
#define WR_DATA_MSG (1 << 4)
#define STATUS_MSG (1 << 5)
#define DRIVE_MSG (1 << 6)
#define VERBOSE_MSG (1 << 7)
#define IRQ_MSG (1 << 8)
#define DMA_MSG (1 << 9)
#define ADCS6_MAX_DRIVES 4 #define ADCS6_MAX_DRIVES 4
#define ADCS6_ROM_SIZE (2 * 1024) #define ADCS6_ROM_SIZE (2 * 1024)
@ -102,13 +96,8 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ
static t_stat adcs6_svc (UNIT *uptr); static t_stat adcs6_svc (UNIT *uptr);
extern REG *sim_PC;
extern uint32 PCX; /* external view of PC */ extern uint32 PCX; /* external view of PC */
#define UNIT_V_ADCS6_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_ADCS6_WLK (1 << UNIT_V_ADCS6_WLK)
#define UNIT_V_ADCS6_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_ADCS6_VERBOSE (1 << UNIT_V_ADCS6_VERBOSE)
#define UNIT_V_ADCS6_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ #define UNIT_V_ADCS6_ROM (UNIT_V_UF + 2) /* boot ROM enabled */
#define UNIT_ADCS6_ROM (1 << UNIT_V_ADCS6_ROM) #define UNIT_ADCS6_ROM (1 << UNIT_V_ADCS6_ROM)
#define ADCS6_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ #define ADCS6_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
@ -189,36 +178,31 @@ static UNIT adcs6_unit[] = {
}; };
static REG adcs6_reg[] = { static REG adcs6_reg[] = {
{ HRDATA (J7, dipswitch, 8), }, { HRDATAD (J7, dipswitch, 8, "5-position DIP switch on 64FDC card"), },
{ NULL } { NULL }
}; };
#define ADCS6_NAME "ADC Super-Six ADCS6"
static MTAB adcs6_mod[] = { static MTAB adcs6_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, &set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
{ UNIT_ADCS6_WLK, 0, "WRTENB", "WRTENB", NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_ADCS6_WLK, UNIT_ADCS6_WLK, "WRTLCK", "WRTLCK", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_ADCS6_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_ADCS6_ROM, 0, "NOROM", "NOROM",
/* verbose, show warning messages */ NULL, NULL, NULL, "Disables boot ROM for unit " ADCS6_NAME "n" },
{ UNIT_ADCS6_VERBOSE, UNIT_ADCS6_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_ADCS6_ROM, UNIT_ADCS6_ROM, "ROM", "ROM",
{ UNIT_ADCS6_ROM, 0, "NOROM", "NOROM", NULL }, NULL, NULL, NULL, "Enables boot ROM for unit " ADCS6_NAME "n" },
{ UNIT_ADCS6_ROM, UNIT_ADCS6_ROM, "ROM", "ROM", NULL },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB adcs6_dt[] = { static DEBTAB adcs6_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "DRIVE", DRIVE_MSG, "Drive messages" },
{ "CMD", CMD_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "RDDATA", RD_DATA_MSG }, { "DMA", DMA_MSG, "DMA messages" },
{ "WRDATA", WR_DATA_MSG },
{ "STATUS", STATUS_MSG },
{ "DRIVE", DRIVE_MSG },
{ "VERBOSE",VERBOSE_MSG },
{ "IRQ", IRQ_MSG },
{ "DMA", DMA_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -228,7 +212,7 @@ DEVICE adcs6_dev = {
NULL, NULL, &adcs6_reset, NULL, NULL, &adcs6_reset,
&adcs6_boot, &adcs6_attach, &adcs6_detach, &adcs6_boot, &adcs6_attach, &adcs6_detach,
&adcs6_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &adcs6_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
adcs6_dt, NULL, "ADC Super-Six ADCS6" adcs6_dt, NULL, ADCS6_NAME
}; };
/* This is the DIGITEX Monitor version 1.2.A -- 10/06/83 /* This is the DIGITEX Monitor version 1.2.A -- 10/06/83

View file

@ -59,14 +59,11 @@
#endif #endif
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define CMD_MSG (1 << 0)
#define SEEK_MSG (1 << 1) #define RD_DATA_MSG (1 << 1)
#define CMD_MSG (1 << 2) #define STATUS_MSG (1 << 2)
#define RD_DATA_MSG (1 << 3) #define VERBOSE_MSG (1 << 3)
#define WR_DATA_MSG (1 << 4) #define IRQ_MSG (1 << 4)
#define STATUS_MSG (1 << 5)
#define VERBOSE_MSG (1 << 7)
#define IRQ_MSG (1 << 8)
#define DISK1A_MAX_DRIVES 4 #define DISK1A_MAX_DRIVES 4
@ -88,13 +85,8 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ
extern void raise_ss1_interrupt(uint8 intnum); extern void raise_ss1_interrupt(uint8 intnum);
extern REG *sim_PC;
extern uint32 PCX; /* external view of PC */ extern uint32 PCX; /* external view of PC */
#define UNIT_V_DISK1A_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_DISK1A_WLK (1 << UNIT_V_DISK1A_WLK)
#define UNIT_V_DISK1A_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_DISK1A_VERBOSE (1 << UNIT_V_DISK1A_VERBOSE)
#define UNIT_V_DISK1A_ROM (UNIT_V_UF + 2) /* boot ROM enabled */ #define UNIT_V_DISK1A_ROM (UNIT_V_UF + 2) /* boot ROM enabled */
#define UNIT_DISK1A_ROM (1 << UNIT_V_DISK1A_ROM) #define UNIT_DISK1A_ROM (1 << UNIT_V_DISK1A_ROM)
#define DISK1A_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ #define DISK1A_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
@ -127,34 +119,31 @@ static UNIT disk1a_unit[] = {
}; };
static REG disk1a_reg[] = { static REG disk1a_reg[] = {
{ DRDATA (BOOTSTRAP, bootstrap, 10), }, { DRDATAD (BOOTSTRAP, bootstrap, 10, "Bootstrap selector, 0 is default"), },
{ NULL } { NULL }
}; };
#define DISK1A_NAME "Compupro Floppy Controller DISK1A"
static MTAB disk1a_mod[] = { static MTAB disk1a_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, &set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
{ UNIT_DISK1A_WLK, 0, "WRTENB", "WRTENB", NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_DISK1A_WLK, UNIT_DISK1A_WLK, "WRTLCK", "WRTLCK", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
/* quiet, no warning messages */ { UNIT_DISK1A_ROM, 0, "NOROM", "NOROM",
{ UNIT_DISK1A_VERBOSE, 0, "QUIET", "QUIET", NULL }, NULL, NULL, NULL, "Disables boot ROM for unit " DISK1A_NAME "n" },
/* verbose, show warning messages */ { UNIT_DISK1A_ROM, UNIT_DISK1A_ROM, "ROM", "ROM",
{ UNIT_DISK1A_VERBOSE, UNIT_DISK1A_VERBOSE, "VERBOSE", "VERBOSE", NULL }, NULL, NULL, NULL, "Enables boot ROM for unit " DISK1A_NAME "n" },
{ UNIT_DISK1A_ROM, 0, "NOROM", "NOROM", NULL },
{ UNIT_DISK1A_ROM, UNIT_DISK1A_ROM, "ROM", "ROM", NULL },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB disk1a_dt[] = { static DEBTAB disk1a_dt[] = {
{ "ERROR", ERROR_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "SEEK", SEEK_MSG }, { "RDDATA", RD_DATA_MSG, "Read data messages" },
{ "CMD", CMD_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "RDDATA", RD_DATA_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "WRDATA", WR_DATA_MSG }, { "IRQ", IRQ_MSG, "IRQ messages" },
{ "STATUS", STATUS_MSG },
{ "VERBOSE",VERBOSE_MSG },
{ "IRQ", IRQ_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -163,8 +152,8 @@ DEVICE disk1a_dev = {
DISK1A_MAX_DRIVES, 10, 31, 1, DISK1A_MAX_DRIVES, DISK1A_MAX_DRIVES, DISK1A_MAX_DRIVES, 10, 31, 1, DISK1A_MAX_DRIVES, DISK1A_MAX_DRIVES,
NULL, NULL, &disk1a_reset, NULL, NULL, &disk1a_reset,
&disk1a_boot, &disk1a_attach, &disk1a_detach, &disk1a_boot, &disk1a_attach, &disk1a_detach,
&disk1a_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &disk1a_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 9,
disk1a_dt, NULL, "Compupro Floppy Controller DISK1A" disk1a_dt, NULL, DISK1A_NAME
}; };
/* This is the DISK1A Boot ROM. /* This is the DISK1A Boot ROM.

View file

@ -118,7 +118,6 @@ static int32 nsectors = C20MB_NSECTORS;
static int32 sectsize = C20MB_SECTSIZE; static int32 sectsize = C20MB_SECTSIZE;
extern uint32 PCX; extern uint32 PCX;
extern REG *sim_PC;
extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
@ -127,8 +126,6 @@ extern int32 selchan_dma(uint8 *buf, uint32 len);
extern int32 find_unit_index(UNIT *uptr); extern int32 find_unit_index(UNIT *uptr);
extern void raise_ss1_interrupt(uint8 intnum); extern void raise_ss1_interrupt(uint8 intnum);
#define UNIT_V_DISK2_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_DISK2_WLK (1 << UNIT_V_DISK2_WLK)
#define UNIT_V_DISK2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_DISK2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_DISK2_VERBOSE (1 << UNIT_V_DISK2_VERBOSE) #define UNIT_DISK2_VERBOSE (1 << UNIT_V_DISK2_VERBOSE)
#define DISK2_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */ #define DISK2_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */
@ -151,39 +148,50 @@ static UNIT disk2_unit[] = {
}; };
static REG disk2_reg[] = { static REG disk2_reg[] = {
{ DRDATA (NTRACKS, ntracks, 10), }, { DRDATAD (NTRACKS, ntracks, 10,
{ DRDATA (NHEADS, nheads, 8), }, "Number of tracks"), },
{ DRDATA (NSECTORS, nsectors, 8), }, { DRDATAD (NHEADS, nheads, 8,
{ DRDATA (SECTSIZE, sectsize, 11), }, "Number of heads"), },
{ HRDATA (SEL_DRIVE, disk2_info_data.sel_drive, 3), }, { DRDATAD (NSECTORS, nsectors, 8,
{ HRDATA (CYL, disk2_info_data.cyl, 8), }, "Number of sectors per track"), },
{ HRDATA (HEAD, disk2_info_data.head, 8), }, { DRDATAD (SECTSIZE, sectsize, 11,
{ HRDATA (SECTOR, disk2_info_data.sector, 8), }, "Sector size not including pre/postamble"), },
{ HRDATAD (SEL_DRIVE, disk2_info_data.sel_drive, 3,
"Currently selected drive"), },
{ HRDATAD (CYL, disk2_info_data.cyl, 8,
"Cylinder that the current operation is targetting"), },
{ HRDATAD (HEAD, disk2_info_data.head, 8,
"Head that the current operation is targetting"), },
{ HRDATAD (SECTOR, disk2_info_data.sector, 8,
"Sector that the current operation is targetting"), },
{ NULL } { NULL }
}; };
#define DISK2_NAME "Compupro Hard Disk Controller DISK2"
static MTAB disk2_mod[] = { static MTAB disk2_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_DISK2_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_DISK2_WLK, UNIT_DISK2_WLK, "WRTLCK", "WRTLCK", NULL },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_DISK2_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_DISK2_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " DISK2_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_DISK2_VERBOSE, UNIT_DISK2_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_DISK2_VERBOSE, UNIT_DISK2_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " DISK2_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB disk2_dt[] = { static DEBTAB disk2_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "STATUS", STATUS_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "IRQ", IRQ_MSG }, { "IRQ", IRQ_MSG, "IRQ messages" },
{ "VERBOSE",VERBOSE_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ NULL, 0 } { NULL, 0 }
}; };
@ -193,7 +201,7 @@ DEVICE disk2_dev = {
NULL, NULL, &disk2_reset, NULL, NULL, &disk2_reset,
NULL, &disk2_attach, &disk2_detach, NULL, &disk2_attach, &disk2_detach,
&disk2_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &disk2_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
disk2_dt, NULL, "Compupro Hard Disk Controller DISK2" disk2_dt, NULL, DISK2_NAME
}; };
/* Reset routine */ /* Reset routine */

View file

@ -53,10 +53,9 @@
#define CMD_MSG (1 << 2) #define CMD_MSG (1 << 2)
#define RD_DATA_MSG (1 << 3) #define RD_DATA_MSG (1 << 3)
#define WR_DATA_MSG (1 << 4) #define WR_DATA_MSG (1 << 4)
#define STATUS_MSG (1 << 5) #define IRQ_MSG (1 << 5)
#define IRQ_MSG (1 << 6) #define VERBOSE_MSG (1 << 6)
#define VERBOSE_MSG (1 << 7) #define SPECIFY_MSG (1 << 7)
#define SPECIFY_MSG (1 << 8)
#define DISK3_MAX_DRIVES 4 #define DISK3_MAX_DRIVES 4
@ -176,7 +175,6 @@ static int32 nsectors = C20MB_NSECTORS;
static int32 sectsize = C20MB_SECTSIZE; static int32 sectsize = C20MB_SECTSIZE;
extern uint32 PCX; extern uint32 PCX;
extern REG *sim_PC;
extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
@ -188,8 +186,6 @@ extern void raise_ss1_interrupt(uint8 intnum);
extern void PutByteDMA(const uint32 Addr, const uint32 Value); extern void PutByteDMA(const uint32 Addr, const uint32 Value);
extern uint8 GetByteDMA(const uint32 Addr); extern uint8 GetByteDMA(const uint32 Addr);
#define UNIT_V_DISK3_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_DISK3_WLK (1 << UNIT_V_DISK3_WLK)
#define UNIT_V_DISK3_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_DISK3_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_DISK3_VERBOSE (1 << UNIT_V_DISK3_VERBOSE) #define UNIT_DISK3_VERBOSE (1 << UNIT_V_DISK3_VERBOSE)
#define DISK3_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */ #define DISK3_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */
@ -212,42 +208,55 @@ static UNIT disk3_unit[] = {
}; };
static REG disk3_reg[] = { static REG disk3_reg[] = {
{ DRDATA (NTRACKS, ntracks, 10), }, { DRDATAD (NTRACKS, ntracks, 10,
{ DRDATA (NHEADS, nheads, 8), }, "Number of tracks"), },
{ DRDATA (NSECTORS, nsectors, 8), }, { DRDATAD (NHEADS, nheads, 8,
{ DRDATA (SECTSIZE, sectsize, 11), }, "Number of heads"), },
{ HRDATA (SEL_DRIVE, disk3_info_data.sel_drive, 3), }, { DRDATAD (NSECTORS, nsectors, 8,
{ HRDATA (MODE, disk3_info_data.mode, 8), }, "Number of sectors per track"), },
{ HRDATA (RETRIES, disk3_info_data.retries, 8), }, { DRDATAD (SECTSIZE, sectsize, 11,
{ HRDATA (NDRIVES, disk3_info_data.ndrives, 8), }, "Sector size not including pre/postamble"), },
{ HRDATA (LINK_ADDR, disk3_info_data.link_addr, 32), }, { HRDATAD (SEL_DRIVE, disk3_info_data.sel_drive, 3,
{ HRDATA (DMA_ADDR, disk3_info_data.dma_addr, 32), }, "Currently selected drive"), },
{ BRDATA (IOPB, &disk3_info_data.iopb[DISK3_IOPB_CMD], 16, 8, 16), }, { HRDATAD (MODE, disk3_info_data.mode, 8,
"Mode (0xFF=absolute, 0x00=logical)"), },
{ HRDATAD (RETRIES, disk3_info_data.retries, 8,
"Number of retries to attempt"), },
{ HRDATAD (NDRIVES, disk3_info_data.ndrives, 8,
"Number of drives attached to the controller"), },
{ HRDATAD (LINK_ADDR, disk3_info_data.link_addr, 32,
"Link address for next IOPB"), },
{ HRDATAD (DMA_ADDR, disk3_info_data.dma_addr, 32,
"DMA address for the current IOPB"), },
{ BRDATAD (IOPB, &disk3_info_data.iopb[DISK3_IOPB_CMD], 16, 8, 16,
"IOPB command register"), } ,
{ NULL } { NULL }
}; };
#define DISK3_NAME "Compupro ST-506 Disk Controller DISK3"
static MTAB disk3_mod[] = { static MTAB disk3_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_DISK3_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_DISK3_WLK, UNIT_DISK3_WLK, "WRTLCK", "WRTLCK", NULL },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_DISK3_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_DISK3_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " DISK3_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_DISK3_VERBOSE, UNIT_DISK3_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_DISK3_VERBOSE, UNIT_DISK3_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " DISK3_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB disk3_dt[] = { static DEBTAB disk3_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "STATUS", STATUS_MSG }, { "IRQ", IRQ_MSG, "IRQ messages" },
{ "IRQ", IRQ_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "VERBOSE",VERBOSE_MSG }, { "SPECIFY", SPECIFY_MSG, "Specify messages" },
{ "SPECIFY",SPECIFY_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -257,7 +266,7 @@ DEVICE disk3_dev = {
NULL, NULL, &disk3_reset, NULL, NULL, &disk3_reset,
NULL, &disk3_attach, &disk3_detach, NULL, &disk3_attach, &disk3_detach,
&disk3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &disk3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
disk3_dt, NULL, "Compupro ST-506 Disk Controller DISK3" disk3_dt, NULL, DISK3_NAME
}; };
/* Reset routine */ /* Reset routine */

View file

@ -31,8 +31,6 @@
#include "altairz80_defs.h" #include "altairz80_defs.h"
#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
#define UNIT_V_DSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_DSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_DSK_VERBOSE (1 << UNIT_V_DSK_VERBOSE) #define UNIT_DSK_VERBOSE (1 << UNIT_V_DSK_VERBOSE)
#define DSK_SECTSIZE 137 /* size of sector */ #define DSK_SECTSIZE 137 /* size of sector */
@ -60,7 +58,6 @@ extern uint32 PCX;
current_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */ current_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */
static int32 current_disk = NUM_OF_DSK; static int32 current_disk = NUM_OF_DSK;
static int32 warnLevelDSK = 3; static int32 warnLevelDSK = 3;
static int32 warnLock [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static int32 warnAttached [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; static int32 warnAttached [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static int32 warnDSK11 = 0; static int32 warnDSK11 = 0;
@ -84,23 +81,29 @@ static UNIT fif_unit[] = {
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) } { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }
}; };
#define FIF_NAME "IMSAI FIF"
static REG fif_reg[] = { static REG fif_reg[] = {
{ DRDATA (DISK, current_disk, 4) }, { DRDATAD (DISK, current_disk, 4,
{ DRDATA (DSKWL, warnLevelDSK, 32) }, "Current selected disk") },
{ BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, { DRDATAD (DSKWL, warnLevelDSK, 32,
{ BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, "Warn level register") },
{ DRDATA (WARNDSK11, warnDSK11, 4), REG_RO }, { BRDATAD (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK,
"Count for selection of unattached disk register array"), REG_CIRC + REG_RO },
{ DRDATAD (WARNDSK11, warnDSK11, 4,
"Count of IN/OUT(9) on unattached disk register"), REG_RO },
{ NULL } { NULL }
}; };
static MTAB fif_mod[] = { static MTAB fif_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_DSK_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_DSK_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " FIF_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_DSK_VERBOSE, UNIT_DSK_VERBOSE, "VERBOSE", "VERBOSE", &fif_set_verbose }, { UNIT_DSK_VERBOSE, UNIT_DSK_VERBOSE, "VERBOSE", "VERBOSE",
&fif_set_verbose, NULL, NULL, "Verbose messages for unit " FIF_NAME "n" },
{ 0 } { 0 }
}; };
@ -110,15 +113,13 @@ DEVICE fif_dev = {
NULL, NULL, &fif_reset, NULL, NULL, &fif_reset,
NULL, NULL, NULL, NULL, NULL, NULL,
&fif_info_data, (DEV_DISABLE | DEV_DIS), 0, &fif_info_data, (DEV_DISABLE | DEV_DIS), 0,
NULL, NULL, "IMSAI FIF" NULL, NULL, FIF_NAME
}; };
static void resetDSKWarningFlags(void) { static void resetDSKWarningFlags(void) {
int32 i; int32 i;
for (i = 0; i < NUM_OF_DSK; i++) { for (i = 0; i < NUM_OF_DSK; i++)
warnLock[i] = 0;
warnAttached[i] = 0; warnAttached[i] = 0;
}
warnDSK11 = 0; warnDSK11 = 0;
} }

View file

@ -56,8 +56,7 @@
#define CMD_MSG (1 << 2) #define CMD_MSG (1 << 2)
#define RD_DATA_MSG (1 << 3) #define RD_DATA_MSG (1 << 3)
#define WR_DATA_MSG (1 << 4) #define WR_DATA_MSG (1 << 4)
#define STATUS_MSG (1 << 5) #define VERBOSE_MSG (1 << 5)
#define VERBOSE_MSG (1 << 7)
#define HDC1001_MAX_DRIVES 4 #define HDC1001_MAX_DRIVES 4
@ -96,7 +95,6 @@ static HDC1001_INFO hdc1001_info_data = { { 0x0, 0, 0xC8, 8 } };
static HDC1001_INFO *hdc1001_info = &hdc1001_info_data; static HDC1001_INFO *hdc1001_info = &hdc1001_info_data;
extern uint32 PCX; extern uint32 PCX;
extern REG *sim_PC;
extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc); extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc); extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
@ -107,8 +105,6 @@ extern int32 find_unit_index(UNIT *uptr);
extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value); extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value);
extern uint8 GetBYTEWrapper(const uint32 Addr); extern uint8 GetBYTEWrapper(const uint32 Addr);
#define UNIT_V_HDC1001_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_HDC1001_WLK (1 << UNIT_V_HDC1001_WLK)
#define UNIT_V_HDC1001_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_HDC1001_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_HDC1001_VERBOSE (1 << UNIT_V_HDC1001_VERBOSE) #define UNIT_HDC1001_VERBOSE (1 << UNIT_V_HDC1001_VERBOSE)
#define HDC1001_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ #define HDC1001_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
@ -133,26 +129,28 @@ static REG hdc1001_reg[] = {
{ NULL } { NULL }
}; };
#define HDC1001_NAME "ADC Hard Disk Controller HDC1001"
static MTAB hdc1001_mod[] = { static MTAB hdc1001_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_HDC1001_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_HDC1001_WLK, UNIT_HDC1001_WLK, "WRTLCK", "WRTLCK", NULL },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_HDC1001_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_HDC1001_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " HDC1001_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_HDC1001_VERBOSE, UNIT_HDC1001_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_HDC1001_VERBOSE, UNIT_HDC1001_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " HDC1001_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB hdc1001_dt[] = { static DEBTAB hdc1001_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "STATUS", STATUS_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "VERBOSE",VERBOSE_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -162,7 +160,7 @@ DEVICE hdc1001_dev = {
NULL, NULL, &hdc1001_reset, NULL, NULL, &hdc1001_reset,
NULL, &hdc1001_attach, &hdc1001_detach, NULL, &hdc1001_attach, &hdc1001_detach,
&hdc1001_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &hdc1001_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
hdc1001_dt, NULL, "ADC Hard Disk Controller HDC1001" hdc1001_dt, NULL, HDC1001_NAME
}; };
/* Reset routine */ /* Reset routine */

View file

@ -58,11 +58,10 @@
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define ERROR_MSG (1 << 0)
#define TRACE_MSG (1 << 1) #define RXIRQ_MSG (1 << 1)
#define RXIRQ_MSG (1 << 2) #define TXIRQ_MSG (1 << 2)
#define TXIRQ_MSG (1 << 3) #define UART_MSG (1 << 3)
#define UART_MSG (1 << 4) #define USER_MSG (1 << 4)
#define USER_MSG (1 << 5)
#define IF3_MAX_BOARDS 4 #define IF3_MAX_BOARDS 4
@ -110,30 +109,34 @@ static uint8 if3_risr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 };
static uint8 if3_tisr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 }; static uint8 if3_tisr[IF3_MAX_BOARDS] = { 0, 0, 0, 0 };
static REG if3_reg[] = { static REG if3_reg[] = {
{ HRDATA (USER, if3_user, 3), }, { HRDATAD (USER, if3_user, 3, "IF3 user register"), },
{ HRDATA (BOARD, if3_board, 2), }, { HRDATAD (BOARD, if3_board, 2, "IF3 board register"), },
{ BRDATA (RIMR, &if3_rimr[0], 16, 8, 4), }, { BRDATAD (RIMR, &if3_rimr[0], 16, 8, 4, "IF3 RIMR register array"), },
{ BRDATA (RISR, &if3_risr[0], 16, 8, 4), }, { BRDATAD (RISR, &if3_risr[0], 16, 8, 4, "IF3 RISR register array"), },
{ BRDATA (TIMR, &if3_timr[0], 16, 8, 4), }, { BRDATAD (TIMR, &if3_timr[0], 16, 8, 4, "IF3 TIMR register array"), },
{ BRDATA (TISR, &if3_tisr[0], 16, 8, 4), }, { BRDATAD (TISR, &if3_tisr[0], 16, 8, 4, "IF3 TISR register array"), },
{ NULL } { NULL }
}; };
#define IF3_NAME "Compupro Interfacer 3 IF3"
static MTAB if3_mod[] = { static MTAB if3_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_IF3_CONNECT, UNIT_IF3_CONNECT,"INSTALLED", "INSTALLED", &set_if3_connect, NULL, NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_IF3_CONNECT, 0, "UNINSTALLED","UNINSTALLED", &set_if3_connect, NULL, NULL }, { UNIT_IF3_CONNECT, UNIT_IF3_CONNECT,"INSTALLED", "INSTALLED",
&set_if3_connect, NULL, NULL, "Installs board for unit " IF3_NAME "n" },
{ UNIT_IF3_CONNECT, 0, "UNINSTALLED","UNINSTALLED",
&set_if3_connect, NULL, NULL, "Uninstalls board for unit " IF3_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB if3_dt[] = { static DEBTAB if3_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "TRACE", TRACE_MSG }, { "RXIRQ", RXIRQ_MSG, "RX IRQ messages" },
{ "RXIRQ", RXIRQ_MSG }, { "TXIRQ", TXIRQ_MSG, "TX IRQ messages" },
{ "TXIRQ", TXIRQ_MSG }, { "UART", UART_MSG, "UART messages" },
{ "UART", UART_MSG }, { "USER", USER_MSG, "User messages" },
{ "USER", USER_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -143,7 +146,7 @@ DEVICE if3_dev = {
NULL, NULL, &if3_reset, NULL, NULL, &if3_reset,
NULL, NULL, NULL, NULL, NULL, NULL,
&if3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0, &if3_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
if3_dt, NULL, "Compupro Interfacer 3 IF3" if3_dt, NULL, IF3_NAME
}; };
static t_stat set_if3_connect(UNIT *uptr, int32 val, char *cptr, void *desc) static t_stat set_if3_connect(UNIT *uptr, int32 val, char *cptr, void *desc)

View file

@ -54,11 +54,10 @@
#endif #endif
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define SEEK_MSG (1 << 0)
#define SEEK_MSG (1 << 1) #define RD_DATA_MSG (1 << 1)
#define RD_DATA_MSG (1 << 3) #define WR_DATA_MSG (1 << 2)
#define WR_DATA_MSG (1 << 4) #define VERBOSE_MSG (1 << 3)
#define VERBOSE_MSG (1 << 7)
#define MDRIVEH_MAX_DRIVES 8 #define MDRIVEH_MAX_DRIVES 8
@ -78,8 +77,6 @@ extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
int32 (*routine)(const int32, const int32, const int32), uint8 unmap); int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
extern REG *sim_PC;
#define UNIT_V_MDRIVEH_WLK (UNIT_V_UF + 0) /* write locked */ #define UNIT_V_MDRIVEH_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_MDRIVEH_WLK (1 << UNIT_V_MDRIVEH_WLK) #define UNIT_MDRIVEH_WLK (1 << UNIT_V_MDRIVEH_WLK)
#define UNIT_V_MDRIVEH_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_MDRIVEH_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
@ -107,24 +104,32 @@ static REG mdriveh_reg[] = {
{ NULL } { NULL }
}; };
#define MDRIVEH_NAME "Compupro Memory Drive MDRIVEH"
static MTAB mdriveh_mod[] = { static MTAB mdriveh_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_MDRIVEH_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_MDRIVEH_WLK, UNIT_MDRIVEH_WLK, "WRTLCK", "WRTLCK", NULL }, { UNIT_MDRIVEH_WLK, 0, "WRTENB", "WRTENB",
NULL, NULL, NULL,
"Enables " MDRIVEH_NAME "n for writing" },
{ UNIT_MDRIVEH_WLK, UNIT_MDRIVEH_WLK, "WRTLCK", "WRTLCK",
NULL, NULL, NULL,
"Locks " MDRIVEH_NAME "n for writing" },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_MDRIVEH_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_MDRIVEH_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " MDRIVEH_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_MDRIVEH_VERBOSE, UNIT_MDRIVEH_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_MDRIVEH_VERBOSE, UNIT_MDRIVEH_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " MDRIVEH_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB mdriveh_dt[] = { static DEBTAB mdriveh_dt[] = {
{ "ERROR", ERROR_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "SEEK", SEEK_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "RDDATA", RD_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "WRDATA", WR_DATA_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "VERBOSE",VERBOSE_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -133,8 +138,8 @@ DEVICE mdriveh_dev = {
MDRIVEH_MAX_DRIVES, 10, 31, 1, MDRIVEH_MAX_DRIVES, MDRIVEH_MAX_DRIVES, MDRIVEH_MAX_DRIVES, 10, 31, 1, MDRIVEH_MAX_DRIVES, MDRIVEH_MAX_DRIVES,
NULL, NULL, &mdriveh_reset, NULL, NULL, &mdriveh_reset,
NULL, NULL, NULL, NULL, NULL, NULL,
&mdriveh_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &mdriveh_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
mdriveh_dt, NULL, "Compupro Memory Drive MDRIVEH" mdriveh_dt, NULL, MDRIVEH_NAME
}; };

View file

@ -62,16 +62,14 @@
#define WR_DATA_MSG (1 << 4) #define WR_DATA_MSG (1 << 4)
#define STATUS_MSG (1 << 5) #define STATUS_MSG (1 << 5)
#define ORDERS_MSG (1 << 6) #define ORDERS_MSG (1 << 6)
#define VERBOSE_MSG (1 << 7) #define RD_DATA_DETAIL_MSG (1 << 7)
#define RD_DATA_DETAIL_MSG (1 << 8) #define WR_DATA_DETAIL_MSG (1 << 8)
#define WR_DATA_DETAIL_MSG (1 << 9)
extern uint32 PCX; extern uint32 PCX;
extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc); extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc);
extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc); extern t_stat show_membase(FILE *st, UNIT *uptr, int32 val, void *desc);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
int32 (*routine)(const int32, const int32, const int32), uint8 unmap); int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
extern REG *sim_PC;
#define MDSAD_MAX_DRIVES 4 #define MDSAD_MAX_DRIVES 4
#define MDSAD_SECTOR_LEN 512 #define MDSAD_SECTOR_LEN 512
@ -156,8 +154,6 @@ static MDSAD_INFO *mdsad_info = &mdsad_info_data;
static SECTOR_FORMAT sdata; static SECTOR_FORMAT sdata;
#define UNIT_V_MDSAD_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_MDSAD_WLK (1 << UNIT_V_MDSAD_WLK)
#define UNIT_V_MDSAD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_MDSAD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_MDSAD_VERBOSE (1 << UNIT_V_MDSAD_VERBOSE) #define UNIT_MDSAD_VERBOSE (1 << UNIT_V_MDSAD_VERBOSE)
#define MDSAD_CAPACITY (70*10*MDSAD_SECTOR_LEN) /* Default North Star Disk Capacity */ #define MDSAD_CAPACITY (70*10*MDSAD_SECTOR_LEN) /* Default North Star Disk Capacity */
@ -232,29 +228,31 @@ static REG mdsad_reg[] = {
{ NULL } { NULL }
}; };
#define MDSAD_NAME "North Star Floppy Controller MDSAD"
static MTAB mdsad_mod[] = { static MTAB mdsad_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
{ UNIT_MDSAD_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
{ UNIT_MDSAD_WLK, UNIT_MDSAD_WLK, "WRTLCK", "WRTLCK", NULL },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_MDSAD_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_MDSAD_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " MDSAD_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_MDSAD_VERBOSE, UNIT_MDSAD_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_MDSAD_VERBOSE, UNIT_MDSAD_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " MDSAD_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB mdsad_dt[] = { static DEBTAB mdsad_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "STATUS", STATUS_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "ORDERS", ORDERS_MSG }, { "ORDERS", ORDERS_MSG, "Orders messages" },
{ "RDDETAIL", RD_DATA_DETAIL_MSG }, { "RDDETAIL", RD_DATA_DETAIL_MSG, "Read detail messages" },
{ "WRDETAIL", WR_DATA_DETAIL_MSG }, { "WRDETAIL", WR_DATA_DETAIL_MSG, "Write detail messags" },
{ "VERBOSE",VERBOSE_MSG },
{ NULL, 0 } { NULL, 0 }
}; };

View file

@ -54,13 +54,9 @@
#endif #endif
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define UART_MSG (1 << 0)
#define PIO_MSG (1 << 1) #define ROM_MSG (1 << 1)
#define UART_MSG (1 << 2) #define VERBOSE_MSG (1 << 2)
#define RTC_MSG (1 << 3)
#define ROM_MSG (1 << 5)
#define VERBOSE_MSG (1 << 7)
#define IRQ_MSG (1 << 8)
#define SCP300F_MAX_DRIVES 1 #define SCP300F_MAX_DRIVES 1
#define SCP300F_ROM_SIZE (2048) #define SCP300F_ROM_SIZE (2048)
@ -69,9 +65,6 @@
#define SCP300F_IO_SIZE (16) #define SCP300F_IO_SIZE (16)
#define SCP300F_IO_MASK (SCP300F_IO_SIZE - 1) #define SCP300F_IO_MASK (SCP300F_IO_SIZE - 1)
#define UNIT_V_SCP300F_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_SCP300F_VERBOSE (1 << UNIT_V_SCP300F_VERBOSE)
typedef struct { typedef struct {
PNP_INFO pnp; /* Plug and Play */ PNP_INFO pnp; /* Plug and Play */
uint8 *ram; uint8 *ram;
@ -106,29 +99,23 @@ static UNIT scp300f_unit[] = {
}; };
static REG scp300f_reg[] = { static REG scp300f_reg[] = {
{ HRDATA (SR, scp300f_sr, 8), }, { HRDATAD (SR, scp300f_sr, 8, "Sense switch register, 0=monitor prompt, 1=disk boot"), },
{ NULL } { NULL }
}; };
static MTAB scp300f_mod[] = { static MTAB scp300f_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, &set_membase, &show_membase, NULL, "Sets support module memory base address" },
/* quiet, no warning messages */ { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_SCP300F_VERBOSE, 0, "QUIET", "QUIET", NULL }, &set_iobase, &show_iobase, NULL, "Sets support module I/O base address" },
/* verbose, show warning messages */
{ UNIT_SCP300F_VERBOSE, UNIT_SCP300F_VERBOSE, "VERBOSE", "VERBOSE", NULL },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB scp300f_dt[] = { static DEBTAB scp300f_dt[] = {
{ "ERROR", ERROR_MSG }, { "UART", UART_MSG, "UART messages" },
{ "PIO", PIO_MSG }, { "ROM", ROM_MSG, "ROM messages" },
{ "UART", UART_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "RTC", RTC_MSG },
{ "ROM", ROM_MSG },
{ "VERBOSE",VERBOSE_MSG },
{ "IRQ", IRQ_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -138,7 +125,7 @@ DEVICE scp300f_dev = {
SCP300F_MAX_DRIVES, 10, 31, 1, SCP300F_MAX_DRIVES, SCP300F_MAX_DRIVES, SCP300F_MAX_DRIVES, 10, 31, 1, SCP300F_MAX_DRIVES, SCP300F_MAX_DRIVES,
NULL, NULL, &scp300f_reset, NULL, NULL, &scp300f_reset,
NULL, NULL, NULL, NULL, NULL, NULL,
&scp300f_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &scp300f_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
scp300f_dt, NULL, "SCP Support Board SCP300F" scp300f_dt, NULL, "SCP Support Board SCP300F"
}; };

View file

@ -54,15 +54,11 @@
#endif #endif
/* Debug flags */ /* Debug flags */
#define ERROR_MSG (1 << 0) #define VERBOSE_MSG (1 << 0)
#define VERBOSE_MSG (1 << 1) #define DMA_MSG (1 << 1)
#define DMA_MSG (1 << 2)
#define SELCHAN_MAX_DRIVES 1 #define SELCHAN_MAX_DRIVES 1
#define UNIT_V_SELCHAN_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_SELCHAN_VERBOSE (1 << UNIT_V_SELCHAN_VERBOSE)
typedef struct { typedef struct {
PNP_INFO pnp; /* Plug and Play */ PNP_INFO pnp; /* Plug and Play */
uint32 selchan; /* Selector Channel Register */ uint32 selchan; /* Selector Channel Register */
@ -95,25 +91,21 @@ static UNIT selchan_unit[] = {
}; };
static REG selchan_reg[] = { static REG selchan_reg[] = {
{ HRDATA (DMA_MODE, selchan_info_data.dma_mode, 8), }, { HRDATAD (DMA_MODE, selchan_info_data.dma_mode, 8, "DMA mode register"), },
{ HRDATA (DMA_ADDR, selchan_info_data.dma_addr, 24), }, { HRDATAD (DMA_ADDR, selchan_info_data.dma_addr, 24, "DMA transfer address register"), },
{ NULL } { NULL }
}; };
static MTAB selchan_mod[] = { static MTAB selchan_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL,
/* quiet, no warning messages */ "Sets disk controller I/O base address" },
{ UNIT_SELCHAN_VERBOSE, 0, "QUIET", "QUIET", NULL },
/* verbose, show warning messages */
{ UNIT_SELCHAN_VERBOSE, UNIT_SELCHAN_VERBOSE, "VERBOSE", "VERBOSE", NULL },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB selchan_dt[] = { static DEBTAB selchan_dt[] = {
{ "ERROR", ERROR_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ "VERBOSE",VERBOSE_MSG }, { "DMA", DMA_MSG, "DMA messages" },
{ "DMA", DMA_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -122,7 +114,7 @@ DEVICE selchan_dev = {
SELCHAN_MAX_DRIVES, 10, 31, 1, SELCHAN_MAX_DRIVES, SELCHAN_MAX_DRIVES, SELCHAN_MAX_DRIVES, 10, 31, 1, SELCHAN_MAX_DRIVES, SELCHAN_MAX_DRIVES,
NULL, NULL, &selchan_reset, NULL, NULL, &selchan_reset,
NULL, NULL, NULL, NULL, NULL, NULL,
&selchan_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &selchan_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
selchan_dt, NULL, "Compupro Selector Channel SELCHAN" selchan_dt, NULL, "Compupro Selector Channel SELCHAN"
}; };

View file

@ -177,46 +177,47 @@ static UNIT ss1_unit[] = {
}; };
static REG ss1_reg[] = { static REG ss1_reg[] = {
{ HRDATA (MPIC_IMR, ss1_pic[MASTER_PIC].IMR, 8), }, { HRDATAD (MPIC_IMR, ss1_pic[MASTER_PIC].IMR, 8, "Master IMR register"), },
{ HRDATA (MPIC_IRR, ss1_pic[MASTER_PIC].IRR, 8), }, { HRDATAD (MPIC_IRR, ss1_pic[MASTER_PIC].IRR, 8, "Master IRR register"), },
{ HRDATA (MPIC_ISR, ss1_pic[MASTER_PIC].ISR, 8), }, { HRDATAD (MPIC_ISR, ss1_pic[MASTER_PIC].ISR, 8, "Master ISR register"), },
{ HRDATA (MPIC_OCW2, ss1_pic[MASTER_PIC].OCW2, 8), }, { HRDATAD (MPIC_OCW2, ss1_pic[MASTER_PIC].OCW2, 8, "Master OCW2 register"), },
{ HRDATA (MPIC_OCW3, ss1_pic[MASTER_PIC].OCW3, 8), }, { HRDATAD (MPIC_OCW3, ss1_pic[MASTER_PIC].OCW3, 8, "Master OCW3 register"), },
{ HRDATA (SPIC_IMR, ss1_pic[SLAVE_PIC].IMR, 8), }, { HRDATAD (SPIC_IMR, ss1_pic[SLAVE_PIC].IMR, 8, "Slave IMR register"), },
{ HRDATA (SPIC_IRR, ss1_pic[SLAVE_PIC].IRR, 8), }, { HRDATAD (SPIC_IRR, ss1_pic[SLAVE_PIC].IRR, 8, "Slave IRR register"), },
{ HRDATA (SPIC_ISR, ss1_pic[SLAVE_PIC].ISR, 8), }, { HRDATAD (SPIC_ISR, ss1_pic[SLAVE_PIC].ISR, 8, "Slave ISR register"), },
{ HRDATA (SPIC_OCW2, ss1_pic[SLAVE_PIC].OCW2, 8), }, { HRDATAD (SPIC_OCW2, ss1_pic[SLAVE_PIC].OCW2, 8, "Slave OCW2 register"), },
{ HRDATA (SPIC_OCW3, ss1_pic[SLAVE_PIC].OCW3, 8), }, { HRDATAD (SPIC_OCW3, ss1_pic[SLAVE_PIC].OCW3, 8, "Slave OCW3 register"), },
{ HRDATA (T0_MODE, ss1_tc[0].mode, 3), }, { HRDATAD (T0_MODE, ss1_tc[0].mode, 3, "Timer 0 mode register"), },
{ HRDATA (T0_COUNT, ss1_tc[0].count, 16), }, { HRDATAD (T0_COUNT, ss1_tc[0].count, 16, "Timer 0 count register"), },
{ HRDATA (T1_MODE, ss1_tc[1].mode, 3), }, { HRDATAD (T1_MODE, ss1_tc[1].mode, 3, "Timer 1 mode register"), },
{ HRDATA (T1_COUNT, ss1_tc[1].count, 16), }, { HRDATAD (T1_COUNT, ss1_tc[1].count, 16, "Timer 1 count register"), },
{ HRDATA (T2_MODE, ss1_tc[2].mode, 3), }, { HRDATAD (T2_MODE, ss1_tc[2].mode, 3, "Timer 2 mode register"), },
{ HRDATA (T2_COUNT, ss1_tc[2].count, 16), }, { HRDATAD (T2_COUNT, ss1_tc[2].count, 16, "Timer 2 count register"), },
{ HRDATA (RTC_DIGIT, ss1_rtc[0].digit_sel, 4), }, { HRDATAD (RTC_DIGIT, ss1_rtc[0].digit_sel, 4, "Digit selector register"), },
{ HRDATA (RTC_FLAGS, ss1_rtc[0].flags, 4), }, { HRDATAD (RTC_FLAGS, ss1_rtc[0].flags, 4, "Flags register"), },
{ NULL } { NULL }
}; };
static MTAB ss1_mod[] = { static MTAB ss1_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
&set_iobase, &show_iobase, NULL, "Sets system support module base address" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB ss1_dt[] = { static DEBTAB ss1_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "TRACE", TRACE_MSG }, { "TRACE", TRACE_MSG, "Trace messages" },
{ "PIC", PIC_MSG }, { "PIC", PIC_MSG, "PIC messages" },
{ "TC", TC_MSG }, { "TC", TC_MSG, "TC messages" },
{ "RTC", RTC_MSG }, { "RTC", RTC_MSG, "RTC messages" },
{ "MATH", MATH_MSG }, { "MATH", MATH_MSG, "Math messages" },
{ "UART", UART_MSG }, { "UART", UART_MSG, "UART messages" },
{ "IRQ", IRQ_MSG }, { "IRQ", IRQ_MSG, "IRQ messages" },
{ NULL, 0 } { NULL, 0 }
}; };

View file

@ -65,7 +65,6 @@
#define RD_DATA_MSG (1 << 3) #define RD_DATA_MSG (1 << 3)
#define WR_DATA_MSG (1 << 4) #define WR_DATA_MSG (1 << 4)
#define STATUS_MSG (1 << 5) #define STATUS_MSG (1 << 5)
#define ORDERS_MSG (1 << 7)
static void VFDHD_Command(void); static void VFDHD_Command(void);
@ -141,8 +140,6 @@ extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
int32 (*routine)(const int32, const int32, const int32), uint8 unmap); int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
#define UNIT_V_VFDHD_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_VFDHD_WLK (1 << UNIT_V_VFDHD_WLK)
#define UNIT_V_VFDHD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ #define UNIT_V_VFDHD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
#define UNIT_VFDHD_VERBOSE (1 << UNIT_V_VFDHD_VERBOSE) #define UNIT_VFDHD_VERBOSE (1 << UNIT_V_VFDHD_VERBOSE)
#define VFDHD_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */ #define VFDHD_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
@ -166,30 +163,32 @@ static UNIT vfdhd_unit[] = {
}; };
static REG vfdhd_reg[] = { static REG vfdhd_reg[] = {
{ DRDATA (HDSIZE, hdSize, 10), }, { DRDATAD (HDSIZE, hdSize, 10, "Size register"), },
{ NULL } { NULL }
}; };
#define VFDHD_NAME "Vector Graphic FD-HD Controller VFDHD"
static MTAB vfdhd_mod[] = { static MTAB vfdhd_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_VFDHD_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_VFDHD_WLK, UNIT_VFDHD_WLK, "WRTLCK", "WRTLCK", NULL },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_VFDHD_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_VFDHD_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " VFDHD_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_VFDHD_VERBOSE, UNIT_VFDHD_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_VFDHD_VERBOSE, UNIT_VFDHD_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " VFDHD_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB vfdhd_dt[] = { static DEBTAB vfdhd_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "STATUS", STATUS_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "ORDERS", ORDERS_MSG },
{ NULL, 0 } { NULL, 0 }
}; };
@ -199,7 +198,7 @@ DEVICE vfdhd_dev = {
NULL, NULL, &vfdhd_reset, NULL, NULL, &vfdhd_reset,
NULL, &vfdhd_attach, &vfdhd_detach, NULL, &vfdhd_attach, &vfdhd_detach,
&vfdhd_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &vfdhd_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
vfdhd_dt, NULL, "Vector Graphic FD-HD Controller VFDHD" vfdhd_dt, NULL, VFDHD_NAME
}; };
/* Reset routine */ /* Reset routine */

View file

@ -208,27 +208,34 @@ static UNIT wd179x_unit[] = {
{ UDATA (&wd179x_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, WD179X_CAPACITY), 58200 } { UDATA (&wd179x_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, WD179X_CAPACITY), 58200 }
}; };
#define WD179X_NAME "Western Digital FDC Core WD179X"
static MTAB wd179x_mod[] = { static MTAB wd179x_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL }, { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
{ UNIT_WD179X_WLK, 0, "WRTENB", "WRTENB", NULL }, &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
{ UNIT_WD179X_WLK, UNIT_WD179X_WLK, "WRTLCK", "WRTLCK", NULL }, { UNIT_WD179X_WLK, 0, "WRTENB", "WRTENB",
NULL, NULL, NULL, "Enables " WD179X_NAME "n for writing" },
{ UNIT_WD179X_WLK, UNIT_WD179X_WLK, "WRTLCK", "WRTLCK",
NULL, NULL, NULL, "Locks " WD179X_NAME "n for writing" },
/* quiet, no warning messages */ /* quiet, no warning messages */
{ UNIT_WD179X_VERBOSE, 0, "QUIET", "QUIET", NULL }, { UNIT_WD179X_VERBOSE, 0, "QUIET", "QUIET",
NULL, NULL, NULL, "No verbose messages for unit " WD179X_NAME "n" },
/* verbose, show warning messages */ /* verbose, show warning messages */
{ UNIT_WD179X_VERBOSE, UNIT_WD179X_VERBOSE, "VERBOSE", "VERBOSE", NULL }, { UNIT_WD179X_VERBOSE, UNIT_WD179X_VERBOSE, "VERBOSE", "VERBOSE",
NULL, NULL, NULL, "Verbose messages for unit " WD179X_NAME "n" },
{ 0 } { 0 }
}; };
/* Debug Flags */ /* Debug Flags */
static DEBTAB wd179x_dt[] = { static DEBTAB wd179x_dt[] = {
{ "ERROR", ERROR_MSG }, { "ERROR", ERROR_MSG, "Error messages" },
{ "SEEK", SEEK_MSG }, { "SEEK", SEEK_MSG, "Seek messages" },
{ "CMD", CMD_MSG }, { "CMD", CMD_MSG, "Command messages" },
{ "RDDATA", RD_DATA_MSG }, { "READ", RD_DATA_MSG, "Read messages" },
{ "WRDATA", WR_DATA_MSG }, { "WRITE", WR_DATA_MSG, "Write messages" },
{ "STATUS", STATUS_MSG }, { "STATUS", STATUS_MSG, "Status messages" },
{ "FMT", FMT_MSG }, { "FMT", FMT_MSG, "Format messages" },
{ "VERBOSE",VERBOSE_MSG }, { "VERBOSE", VERBOSE_MSG, "Verbose messages" },
{ NULL, 0 } { NULL, 0 }
}; };
@ -238,7 +245,7 @@ DEVICE wd179x_dev = {
NULL, NULL, &wd179x_reset, NULL, NULL, &wd179x_reset,
NULL, &wd179x_attach, &wd179x_detach, NULL, &wd179x_attach, &wd179x_detach,
&wd179x_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, &wd179x_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
wd179x_dt, NULL, "Western Digital FDC Core WD179X" wd179x_dt, NULL, WD179X_NAME
}; };
/* Unit service routine */ /* Unit service routine */

View file

@ -201,6 +201,41 @@
RelativePath="..\AltairZ80\altairz80_mhdsk.c" RelativePath="..\AltairZ80\altairz80_mhdsk.c"
> >
</File> </File>
<File
RelativePath="..\AltairZ80\m68kcpu.c"
>
</File>
<File
RelativePath="..\AltairZ80\m68kdasm.c"
>
</File>
<File
RelativePath="..\AltairZ80\m68kopac.c"
>
</File>
<File
RelativePath="..\AltairZ80\m68kopdm.c"
>
</File>
<File
RelativePath="..\AltairZ80\m68kopnz.c"
>
</File>
<File
RelativePath="..\AltairZ80\m68kops.c"
>
</File>
<File
RelativePath="..\AltairZ80\m68ksim.c"
>
</File>
<File <File
RelativePath="..\AltairZ80\altairz80_net.c" RelativePath="..\AltairZ80\altairz80_net.c"
> >

View file

@ -330,7 +330,10 @@ ALTAIRZ80_SOURCE2 = $(ALTAIRZ80_DIR)S100_DISK1A.C,$(ALTAIRZ80_DIR)S100_DISK2.C,\
$(ALTAIRZ80_DIR)S100_SCP300F.C,$(ALTAIRZ80_DIR)SIM_IMD.C,\ $(ALTAIRZ80_DIR)S100_SCP300F.C,$(ALTAIRZ80_DIR)SIM_IMD.C,\
$(ALTAIRZ80_DIR)WD179X.C,$(ALTAIRZ80_DIR)S100_DISK3.C,\ $(ALTAIRZ80_DIR)WD179X.C,$(ALTAIRZ80_DIR)S100_DISK3.C,\
$(ALTAIRZ80_DIR)S100_ADCS6.C,$(ALTAIRZ80_DIR)S100_HDC1001.C,\ $(ALTAIRZ80_DIR)S100_ADCS6.C,$(ALTAIRZ80_DIR)S100_HDC1001.C,\
$(ALTAIRZ80_DIR)S100_IF3.C,$(ALTAIRZ80_DIR)ALTAIRZ80_MHDSK.C $(ALTAIRZ80_DIR)S100_IF3.C,$(ALTAIRZ80_DIR)ALTAIRZ80_MHDSK.C,\
$(ALTAIRZ80_DIR)M68KCPU.C,$(ALTAIRZ80_DIR)M68KDASM.C,\
$(ALTAIRZ80_DIR)M68KOPAC.C,$(ALTAIRZ80_DIR)M68KOPDM.C,\
$(ALTAIRZ80_DIR)M68KOPNZ.C,$(ALTAIRZ80_DIR)M68KOPS.C,$(ALTAIRZ80_DIR)M68KSIM.C
ALTAIRZ80_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEF=($(CC_DEFS)) ALTAIRZ80_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEF=($(CC_DEFS))
# #

View file

@ -1021,7 +1021,10 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \ ${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \
${ALTAIRZ80D}/s100_scp300f.c ${ALTAIRZ80D}/sim_imd.c \ ${ALTAIRZ80D}/s100_scp300f.c ${ALTAIRZ80D}/sim_imd.c \
${ALTAIRZ80D}/wd179x.c ${ALTAIRZ80D}/s100_hdc1001.c \ ${ALTAIRZ80D}/wd179x.c ${ALTAIRZ80D}/s100_hdc1001.c \
${ALTAIRZ80D}/s100_if3.c ${ALTAIRZ80D}/s100_adcs6.c ${ALTAIRZ80D}/s100_if3.c ${ALTAIRZ80D}/s100_adcs6.c \
${ALTAIRZ80D}/m68kcpu.c ${ALTAIRZ80D}/m68kdasm.c \
${ALTAIRZ80D}/m68kopac.c ${ALTAIRZ80D}/m68kopdm.c \
${ALTAIRZ80D}/m68kopnz.c ${ALTAIRZ80D}/m68kops.c ${ALTAIRZ80D}/m68ksim.c
ALTAIRZ80_OPT = -I ${ALTAIRZ80D} ALTAIRZ80_OPT = -I ${ALTAIRZ80D}