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:
parent
709016c356
commit
589aca19f4
43 changed files with 46967 additions and 1095 deletions
|
@ -27,7 +27,8 @@
|
|||
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>
|
||||
#define SWITCHCPU_DEFAULT 0xfd
|
||||
|
||||
|
@ -183,7 +184,7 @@ void out(const uint32 Port, const uint32 Value);
|
|||
uint32 in(const uint32 Port);
|
||||
void altairz80_init(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);
|
||||
void PutBYTEWrapper(const uint32 Addr, const uint32 Value);
|
||||
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 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 */
|
||||
struct idev {
|
||||
int32 (*routine)(const int32, const int32, const int32);
|
||||
|
@ -262,107 +266,275 @@ struct idev {
|
|||
static int32 switcherPort = SWITCHCPU_DEFAULT;
|
||||
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[] = {
|
||||
{ HRDATA (AF, AF_S, 16) },
|
||||
{ HRDATA (BC, BC_S, 16) },
|
||||
{ HRDATA (DE, DE_S, 16) },
|
||||
{ HRDATA (HL, HL_S, 16) },
|
||||
{ HRDATA (IX, IX_S, 16) },
|
||||
{ HRDATA (IY, IY_S, 16) },
|
||||
{ HRDATA (PC, PC_S, 16 + MAXBANKSLOG2) }, /* 8080 / Z80 PC [6] */
|
||||
{ HRDATA (PCX, PCX_S, 16 + MAXBANKSLOG2) }, /* 8086 PC [7] */
|
||||
{ HRDATA (SP, SP_S, 16) },
|
||||
{ HRDATA (AF1, AF1_S, 16) },
|
||||
{ HRDATA (BC1, BC1_S, 16) },
|
||||
{ HRDATA (DE1, DE1_S, 16) },
|
||||
{ HRDATA (HL1, HL1_S, 16) },
|
||||
{ GRDATA (IFF, IFF_S, 2, 2, 0) },
|
||||
{ FLDATA (IR, IR_S, 8) },
|
||||
{ HRDATA (AX, AX_S, 16) }, /* 8086 */
|
||||
{ GRDATA (AL, AX_S, 16, 8, 0) }, /* 8086, low 8 bits of AX */
|
||||
{ GRDATA (AH, AX_S, 16, 8, 8) }, /* 8086, high 8 bits of AX */
|
||||
{ HRDATA (BX, BX_S, 16) }, /* 8086 */
|
||||
{ GRDATA (BL, BX_S, 16, 8, 0) }, /* 8086, low 8 bits of BX */
|
||||
{ GRDATA (BH, BX_S, 16, 8, 8) }, /* 8086, high 8 bits of BX */
|
||||
{ HRDATA (CX, CX_S, 16) }, /* 8086 */
|
||||
{ GRDATA (CL, CX_S, 16, 8, 0) }, /* 8086, low 8 bits of CX */
|
||||
{ GRDATA (CH, CX_S, 16, 8, 8) }, /* 8086, high 8 bits of CX */
|
||||
{ HRDATA (DX, DX_S, 16) }, /* 8086 */
|
||||
{ GRDATA (DL, DX_S, 16, 8, 0) }, /* 8086, low 8 bits of DX */
|
||||
{ GRDATA (DH, DX_S, 16, 8, 8) }, /* 8086, high 8 bits of DX */
|
||||
{ HRDATA (SPX, SPX_S, 16) }, /* 8086 */
|
||||
{ HRDATA (BP, BP_S, 16) }, /* 8086, Base Pointer */
|
||||
{ HRDATA (SI, SI_S, 16) }, /* 8086, Source Index */
|
||||
{ HRDATA (DI, DI_S, 16) }, /* 8086, Destination Index */
|
||||
{ HRDATA (CS, CS_S, 16) }, /* 8086, Code Segment */
|
||||
{ HRDATA (DS, DS_S, 16) }, /* 8086, Data Segment */
|
||||
{ HRDATA (ES, ES_S, 16) }, /* 8086, Extra Segment */
|
||||
{ HRDATA (SS, SS_S, 16) }, /* 8086, Stack Segment */
|
||||
{ HRDATA (FLAGS, FLAGS_S, 16) }, /* 8086, FLAGS */
|
||||
{ HRDATA (IP, IP_S, 16), REG_RO }, /* 8086, set via PC */
|
||||
{ FLDATA (OPSTOP, cpu_unit.flags, UNIT_CPU_V_OPSTOP), REG_HRO },
|
||||
{ HRDATA (SR, SR, 8) },
|
||||
{ HRDATA (BANK, bankSelect, MAXBANKSLOG2) },
|
||||
{ HRDATA (COMMON, common, 32) },
|
||||
{ HRDATA (SWITCHERPORT, switcherPort, 8), },
|
||||
{ DRDATA (CLOCK, clockFrequency, 32) },
|
||||
{ DRDATA (SLICE, sliceLength, 16) },
|
||||
{ DRDATA (TSTATES, executedTStates, 32), REG_RO },
|
||||
{ HRDATA (CAPACITY, cpu_unit.capac, 32), REG_RO },
|
||||
{ HRDATA (PREVCAP, previousCapacity, 32), REG_RO },
|
||||
{ BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO + REG_CIRC },
|
||||
{ DRDATA (PCQP, pcq_p, PCQ_SIZE_LOG2), REG_HRO },
|
||||
{ HRDATA (WRU, sim_int_char, 8) },
|
||||
// 8080 and Z80 registers
|
||||
{ HRDATAD (AF, AF_S, 16, "8080 / Z80 Accumulator Flag register")
|
||||
}, /* 0 */
|
||||
{ HRDATAD (BC, BC_S, 16, "8080 / Z80 BC register")
|
||||
}, /* 1 */
|
||||
{ HRDATAD (DE, DE_S, 16, "8080 / Z80 DE register")
|
||||
}, /* 2 */
|
||||
{ HRDATAD (HL, HL_S, 16, "8080 / Z80 HL register")
|
||||
}, /* 3 */
|
||||
{ HRDATAD (PC, PC_S, 16 + MAXBANKSLOG2, "8080 / Z80 Program Counter register")
|
||||
}, /* 4 8080 / Z80 */
|
||||
{ HRDATAD (SP, SP_S, 16, "8080 / Z80 Stack Pointer register")
|
||||
}, /* 5 */
|
||||
|
||||
// Z80 registers
|
||||
{ HRDATAD (IX, IX_S, 16, "Z80 IX register")
|
||||
}, /* 8 */
|
||||
{ HRDATAD (IY, IY_S, 16, "Z80 IY register")
|
||||
}, /* 9 */
|
||||
{ HRDATAD (AF1, AF1_S, 16, "Z80 Alternate Accumulator Flag register")
|
||||
}, /* 10 */
|
||||
{ HRDATAD (BC1, BC1_S, 16, "Z80 Alternate BC register")
|
||||
}, /* 11 */
|
||||
{ HRDATAD (DE1, DE1_S, 16, "Z80 Alternate DE register")
|
||||
}, /* 12 */
|
||||
{ HRDATAD (HL1, HL1_S, 16, "Z80 Alternate HL register")
|
||||
}, /* 13 */
|
||||
{ GRDATAD (IFF, IFF_S, 2, 2, 0, "Z80 Interrupt Flip Flop register")
|
||||
}, /* 6 */
|
||||
{ FLDATAD (IR, IR_S, 8, "8Z80 Interrupt (upper) / Refresh (lower) register")
|
||||
}, /* 7 */
|
||||
|
||||
// 8086 registers
|
||||
{ HRDATAD (AX, AX_S, 16, "8086 AX register")
|
||||
}, /* 14 8086 */
|
||||
{ GRDATAD (AL, AX_S, 16, 8, 0, "8086 low bits of AX register")
|
||||
}, /* 15 8086, low 8 bits of AX */
|
||||
{ GRDATAD (AH, AX_S, 16, 8, 8, "8086 high bits of AX register")
|
||||
}, /* 16 8086, high 8 bits of AX */
|
||||
{ HRDATAD (BX, BX_S, 16, "8086 BX register")
|
||||
}, /* 17 8086 */
|
||||
{ GRDATAD (BL, BX_S, 16, 8, 0, "8086 low bits of BX register")
|
||||
}, /* 18 8086, low 8 bits of BX */
|
||||
{ GRDATAD (BH, BX_S, 16, 8, 8, "8086 high bits of BX register")
|
||||
}, /* 19 8086, high 8 bits of BX */
|
||||
{ HRDATAD (CX, CX_S, 16, "8086 CX register")
|
||||
}, /* 20 8086 */
|
||||
{ GRDATAD (CL, CX_S, 16, 8, 0, "8086 low bits of CX register")
|
||||
}, /* 21 8086, low 8 bits of CX */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
static MTAB cpu_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_8080, NULL, "8080", &cpu_set_chiptype },
|
||||
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_Z80, NULL, "Z80", &cpu_set_chiptype },
|
||||
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_8086, NULL, "8086", &cpu_set_chiptype },
|
||||
{ UNIT_CPU_OPSTOP, UNIT_CPU_OPSTOP, "ITRAP", "ITRAP", NULL, &chip_show },
|
||||
{ UNIT_CPU_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL, &chip_show },
|
||||
{ UNIT_CPU_STOPONHALT, UNIT_CPU_STOPONHALT,"STOPONHALT", "STOPONHALT", NULL },
|
||||
{ UNIT_CPU_STOPONHALT, 0, "LOOPONHALT", "LOOPONHALT", NULL },
|
||||
{ UNIT_CPU_BANKED, UNIT_CPU_BANKED, "BANKED", "BANKED", &cpu_set_banked },
|
||||
{ UNIT_CPU_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked },
|
||||
{ UNIT_CPU_ALTAIRROM, UNIT_CPU_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom },
|
||||
{ UNIT_CPU_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", &cpu_set_noaltairrom},
|
||||
{ UNIT_CPU_VERBOSE, UNIT_CPU_VERBOSE, "VERBOSE", "VERBOSE", NULL, &cpu_show },
|
||||
{ UNIT_CPU_VERBOSE, 0, "QUIET", "QUIET", NULL },
|
||||
{ MTAB_VDV, 0, NULL, "CLEARMEMORY", &cpu_clear_command },
|
||||
{ UNIT_CPU_MMU, UNIT_CPU_MMU, "MMU", "MMU", NULL },
|
||||
{ UNIT_CPU_MMU, 0, "NOMMU", "NOMMU", &cpu_set_nommu },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "MEMORY", &cpu_set_memory },
|
||||
{ UNIT_CPU_SWITCHER, UNIT_CPU_SWITCHER, "SWITCHER", "SWITCHER", &cpu_set_switcher, &cpu_show_switcher },
|
||||
{ UNIT_CPU_SWITCHER, 0, "NOSWITCHER", "NOSWITCHER", &cpu_reset_switcher, &cpu_show_switcher },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "AZ80", &cpu_set_ramtype },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "HRAM", &cpu_set_ramtype },
|
||||
{ MTAB_XTD | MTAB_VDV, 2, NULL, "VRAM", &cpu_set_ramtype },
|
||||
{ MTAB_XTD | MTAB_VDV, 3, NULL, "CRAM", &cpu_set_ramtype },
|
||||
{ MTAB_VDV, 4, NULL, "4KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 8, NULL, "8KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 12, NULL, "12KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 16, NULL, "16KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 20, NULL, "20KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 24, NULL, "24KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 28, NULL, "28KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 32, NULL, "32KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 36, NULL, "36KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 40, NULL, "40KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 44, NULL, "44KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 48, NULL, "48KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 52, NULL, "52KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 56, NULL, "56KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 60, NULL, "60KB", &cpu_set_size },
|
||||
{ MTAB_VDV, 64, NULL, "64KB", &cpu_set_size },
|
||||
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_8080, NULL, "8080", &cpu_set_chiptype,
|
||||
NULL, NULL, "Chooses 8080 CPU"},
|
||||
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_Z80, NULL, "Z80", &cpu_set_chiptype,
|
||||
NULL, NULL, "Chooses Z80 CPU" },
|
||||
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_8086, NULL, "8086", &cpu_set_chiptype,
|
||||
NULL, NULL, "Chooses 8086 CPU" },
|
||||
{ MTAB_XTD | MTAB_VDV, CHIP_TYPE_M68K, NULL, "M68K", &cpu_set_chiptype,
|
||||
NULL, NULL, "Chooses M68K CPU" },
|
||||
{ UNIT_CPU_OPSTOP, UNIT_CPU_OPSTOP, "ITRAP", "ITRAP", NULL, &chip_show,
|
||||
NULL, "Stop on illegal instruction" },
|
||||
{ UNIT_CPU_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL, &chip_show,
|
||||
NULL, "Do not stop on illegal instruction" },
|
||||
{ UNIT_CPU_STOPONHALT, UNIT_CPU_STOPONHALT,"STOPONHALT", "STOPONHALT", NULL,
|
||||
NULL, NULL, "Stop on halt instruction" },
|
||||
{ UNIT_CPU_STOPONHALT, 0, "LOOPONHALT", "LOOPONHALT", NULL,
|
||||
NULL, NULL, "Enter loop on halt instruction" },
|
||||
{ UNIT_CPU_BANKED, UNIT_CPU_BANKED, "BANKED", "BANKED", &cpu_set_banked,
|
||||
NULL, NULL, "Enable banked memory for 8080 / Z80" },
|
||||
{ UNIT_CPU_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked,
|
||||
NULL, NULL, "Disable banked memory for 8080 / Z80" },
|
||||
{ UNIT_CPU_ALTAIRROM, UNIT_CPU_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom,
|
||||
NULL, NULL, "Enable Altair ROM for 8080 / Z80" },
|
||||
{ UNIT_CPU_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", &cpu_set_noaltairrom,
|
||||
NULL, NULL, "Disable Altair ROM for 8080 / Z80"},
|
||||
{ UNIT_CPU_VERBOSE, UNIT_CPU_VERBOSE, "VERBOSE", "VERBOSE", NULL, &cpu_show,
|
||||
NULL, "Enable verbose messages" },
|
||||
{ UNIT_CPU_VERBOSE, 0, "QUIET", "QUIET", NULL, NULL,
|
||||
NULL, "Disable verbose messages" },
|
||||
{ MTAB_VDV, 0, NULL, "CLEARMEMORY", &cpu_clear_command,
|
||||
NULL, NULL, "Clears the RAM" },
|
||||
{ UNIT_CPU_MMU, UNIT_CPU_MMU, "MMU", "MMU", NULL, NULL,
|
||||
NULL, "Enable the Memory Management Unit for 8080 / Z80" },
|
||||
{ UNIT_CPU_MMU, 0, "NOMMU", "NOMMU", &cpu_set_nommu,
|
||||
NULL, NULL, "Disable the Memory Management Unit for 8080 / Z80" },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "MEMORY", &cpu_set_memory,
|
||||
NULL, NULL, "Sets the RAM size for 8080 / Z80 / 8086" },
|
||||
{ UNIT_CPU_SWITCHER, UNIT_CPU_SWITCHER, "SWITCHER", "SWITCHER", &cpu_set_switcher, &cpu_show_switcher,
|
||||
NULL, "Sets CPU switcher port for 8080 / Z80 / 8086" },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB cpu_dt[] = {
|
||||
{ "LOG_IN", IN_MSG },
|
||||
{ "LOG_OUT", OUT_MSG },
|
||||
{ "LOG_IN", IN_MSG, "Log IN operations" },
|
||||
{ "LOG_OUT", OUT_MSG, "Log OUT operations" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -449,7 +621,7 @@ static struct idev dev_table[256] = {
|
|||
static int32 ramtype = 0;
|
||||
#define MAX_RAM_TYPE 3
|
||||
|
||||
int32 chiptype = CHIP_TYPE_8080;
|
||||
ChipType chiptype = CHIP_TYPE_8080;
|
||||
|
||||
void out(const uint32 Port, const uint32 Value) {
|
||||
if ((cpu_dev.dctrl & OUT_MSG) && sim_deb) {
|
||||
|
@ -1555,9 +1727,9 @@ static void altairz80_print_tables(void) {
|
|||
#define LOG2PAGESIZE 8
|
||||
#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
|
||||
isRAM isEmpty routine code
|
||||
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 isEmpty;
|
||||
int32 (*routine)(const int32, const int32, const int32);
|
||||
};
|
||||
|
||||
typedef struct mdev MDEV;
|
||||
} MDEV;
|
||||
|
||||
static MDEV ROM_PAGE = {FALSE, FALSE, NULL}; /* this makes a page ROM */
|
||||
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 */
|
||||
|
||||
t_stat sim_instr (void) {
|
||||
uint32 i;
|
||||
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 {
|
||||
result = (chiptype == CHIP_TYPE_8086) ? sim_instr_8086() : sim_instr_mmu();
|
||||
} while (switch_cpu_now == FALSE);
|
||||
else {
|
||||
uint32 i;
|
||||
for (i = 0; i < MAXBANKSIZE; i++)
|
||||
MOPT[i] = M[i];
|
||||
result = sim_instr_nommu();
|
||||
|
@ -6350,6 +6522,7 @@ static t_stat cpu_reset(DEVICE *dptr) {
|
|||
IFF_S = 3;
|
||||
setBankSelect(0);
|
||||
cpu8086reset();
|
||||
m68k_cpu_reset();
|
||||
sim_brk_types = (SWMASK('E') | SWMASK('I') | SWMASK('M'));
|
||||
sim_brk_dflt = SWMASK('E');
|
||||
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_addr returns[2] = {0, 0};
|
||||
if (chiptype == 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;
|
||||
}
|
||||
} else { // 8080 or Z80
|
||||
switch (chiptype) {
|
||||
case CHIP_TYPE_8080:
|
||||
case CHIP_TYPE_Z80:
|
||||
switch (GetBYTE(PC_S)) {
|
||||
case 0xc4: /* CALL NZ,nnnn */
|
||||
case 0xcc: /* CALL Z,nnnn */
|
||||
|
@ -6393,10 +6557,42 @@ static t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs) {
|
|||
default:
|
||||
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;
|
||||
if (addr & (PAGESIZE - 1))
|
||||
return SCPE_IERR;
|
||||
|
@ -6410,83 +6606,126 @@ t_stat install_bootrom(int32 bootrom[], int32 size, int32 addr, int32 makeROM) {
|
|||
|
||||
/* memory examine */
|
||||
static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) {
|
||||
int32 oldBankSelect;
|
||||
if (chiptype == CHIP_TYPE_8086)
|
||||
*vptr = GetBYTEExtended(addr);
|
||||
else {
|
||||
oldBankSelect = getBankSelect();
|
||||
switch (chiptype) {
|
||||
case CHIP_TYPE_8080:
|
||||
case CHIP_TYPE_Z80: {
|
||||
const int32 oldBankSelect = getBankSelect();
|
||||
setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK);
|
||||
*vptr = GetBYTE(addr & ADDRMASK);
|
||||
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;
|
||||
}
|
||||
|
||||
/* memory deposit */
|
||||
static t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) {
|
||||
int32 oldBankSelect;
|
||||
if (chiptype == CHIP_TYPE_8086)
|
||||
PutBYTEExtended(addr, val);
|
||||
else {
|
||||
oldBankSelect = getBankSelect();
|
||||
switch (chiptype) {
|
||||
case CHIP_TYPE_8080:
|
||||
case CHIP_TYPE_Z80: {
|
||||
const int32 oldBankSelect = getBankSelect();
|
||||
setBankSelect((addr >> MAXBANKSIZELOG2) & BANKMASK);
|
||||
PutBYTE(addr & ADDRMASK, val);
|
||||
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;
|
||||
}
|
||||
|
||||
struct cpuflag {
|
||||
int32 mask; /* bit mask within CPU status register */
|
||||
char name; /* character to print if flag is set */
|
||||
};
|
||||
typedef struct cpuflag CPUFLAG;
|
||||
typedef struct {
|
||||
uint32 mask; /* bit mask within CPU status register */
|
||||
const char* flagName; /* string to print if flag is set */
|
||||
} CPUFLAG;
|
||||
|
||||
static CPUFLAG cpuflags8086[] = {
|
||||
{1 << 11, 'O'},
|
||||
{1 << 10, 'D'},
|
||||
{1 << 9, 'I'},
|
||||
{1 << 8, 'T'},
|
||||
{1 << 7, 'S'},
|
||||
{1 << 6, 'Z'},
|
||||
{1 << 4, 'A'},
|
||||
{1 << 2, 'P'},
|
||||
{1 << 0, 'C'},
|
||||
const static CPUFLAG cpuflags8080[] = {
|
||||
{1 << 7, "S"},
|
||||
{1 << 6, "Z"},
|
||||
{1 << 4, "A"},
|
||||
{1 << 3, "P"},
|
||||
{1 << 1, "N"},
|
||||
{1 << 0, "C"},
|
||||
{0, 0} /* last mask must be 0 */
|
||||
};
|
||||
|
||||
static CPUFLAG cpuflags8080[] = {
|
||||
{1 << 7, 'S'},
|
||||
{1 << 6, 'Z'},
|
||||
{1 << 4, 'A'},
|
||||
{1 << 3, 'P'},
|
||||
{1 << 1, 'N'},
|
||||
{1 << 0, 'C'},
|
||||
const static CPUFLAG cpuflagsZ80[] = {
|
||||
{1 << 7, "S"},
|
||||
{1 << 6, "Z"},
|
||||
{1 << 4, "A"},
|
||||
{1 << 3, "V"},
|
||||
{1 << 1, "N"},
|
||||
{1 << 0, "C"},
|
||||
{0, 0} /* last mask must be 0 */
|
||||
};
|
||||
|
||||
static CPUFLAG cpuflagsZ80[] = {
|
||||
{1 << 7, 'S'},
|
||||
{1 << 6, 'Z'},
|
||||
{1 << 4, 'A'},
|
||||
{1 << 3, 'V'},
|
||||
{1 << 1, 'N'},
|
||||
{1 << 0, 'C'},
|
||||
const static CPUFLAG cpuflags8086[] = {
|
||||
{1 << 11, "O"},
|
||||
{1 << 10, "D"},
|
||||
{1 << 9, "I"},
|
||||
{1 << 8, "T"},
|
||||
{1 << 7, "S"},
|
||||
{1 << 6, "Z"},
|
||||
{1 << 4, "A"},
|
||||
{1 << 2, "P"},
|
||||
{1 << 0, "C"},
|
||||
{0, 0} /* last mask must be 0 */
|
||||
};
|
||||
|
||||
/* needs to be set for each chiptype <= MAX_CHIP_TYPE */
|
||||
static char *chipTypeToString[] = { "8080", "Z80", "8086" };
|
||||
static int32 *flagregister[] = { &AF_S, &AF_S, &FLAGS_S };
|
||||
static CPUFLAG *cpuflags[] = { cpuflags8080, cpuflagsZ80, cpuflags8086 };
|
||||
const static CPUFLAG cpuflagsM68K[] = {
|
||||
{1 << 15, "T1"}, /* Trace Enable T1 */
|
||||
{1 << 14, "T0"}, /* Trace Enable T0 */
|
||||
{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 */
|
||||
static char *ramTypeToString[] = { "AZ80", "HRAM", "VRAM", "CRAM" };
|
||||
|
||||
static t_stat chip_show(FILE *st, UNIT *uptr, int32 val, void *desc) {
|
||||
fprintf(st, cpu_unit.flags & UNIT_CPU_OPSTOP ? "ITRAP, " : "NOITRAP, ");
|
||||
if (chiptype <= MAX_CHIP_TYPE)
|
||||
fprintf(st, "%s", chipTypeToString[chiptype]);
|
||||
if (chiptype < NUM_CHIP_TYPE)
|
||||
fprintf(st, "%s", cpu_mod[chiptype].mstring);
|
||||
fprintf(st, ", ");
|
||||
if (ramtype <= MAX_RAM_TYPE)
|
||||
fprintf(st, "%s", ramTypeToString[ramtype]);
|
||||
|
@ -6498,7 +6737,9 @@ static t_stat cpu_show(FILE *st, UNIT *uptr, int32 val, void *desc) {
|
|||
MDEV m;
|
||||
maxBanks = ((cpu_unit.flags & UNIT_CPU_BANKED) ||
|
||||
(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++)
|
||||
fprintf(st, "0123456789ABCDEF");
|
||||
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, "]");
|
||||
if (chiptype <= MAX_CHIP_TYPE) {
|
||||
}
|
||||
if (chiptype < NUM_CHIP_TYPE) {
|
||||
first = TRUE;
|
||||
/* show verbose CPU flags */
|
||||
for (i = 0; cpuflags[chiptype][i].mask; i++)
|
||||
if (*flagregister[chiptype] & cpuflags[chiptype][i].mask) {
|
||||
if (first) {
|
||||
first = FALSE;
|
||||
fprintf(st, " ");
|
||||
fprintf(st, "\nFlags");
|
||||
}
|
||||
fprintf(st, "%c", cpuflags[chiptype][i].name);
|
||||
fprintf(st, " %s", cpuflags[chiptype][i].flagName);
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
|
@ -6551,6 +6793,7 @@ static void cpu_clear(void) {
|
|||
mmu_table[i] = EMPTY_PAGE;
|
||||
if (cpu_unit.flags & UNIT_CPU_ALTAIRROM)
|
||||
install_ALTAIRbootROM();
|
||||
m68k_clear_memory();
|
||||
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) {
|
||||
extern REG *sim_PC;
|
||||
if ((chiptype == value) || (chiptype > MAX_CHIP_TYPE))
|
||||
static void cpu_set_chiptype_short(const int32 value) {
|
||||
if ((chiptype == value) || (chiptype >= NUM_CHIP_TYPE))
|
||||
return; /* nothing to do */
|
||||
if (((chiptype == CHIP_TYPE_8080) && (value == CHIP_TYPE_Z80)) ||
|
||||
((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;
|
||||
}
|
||||
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)
|
||||
previousCapacity = MEMORYSIZE;
|
||||
MEMORYSIZE = MAXMEMORY;
|
||||
cpu_unit.flags &= ~(UNIT_CPU_BANKED | UNIT_CPU_ALTAIRROM);
|
||||
cpu_unit.flags |= UNIT_CPU_MMU;
|
||||
cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2;
|
||||
if (need_cpu_clear)
|
||||
cpu_clear();
|
||||
sim_PC = &cpu_reg[7];
|
||||
}
|
||||
else if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) {
|
||||
MEMORYSIZE = previousCapacity;
|
||||
cpu_dev.awidth = MAXBANKSIZELOG2;
|
||||
if (need_cpu_clear)
|
||||
cpu_clear();
|
||||
sim_PC = &cpu_reg[6];
|
||||
sim_PC = &cpu_reg[CPU_INDEX_8086];
|
||||
break;
|
||||
|
||||
case CHIP_TYPE_M68K:
|
||||
MEMORYSIZE = M68K_MAX_RAM + 1;
|
||||
cpu_dev.awidth = M68K_MAX_RAM_LOG2;
|
||||
sim_PC = &cpu_reg[CPU_INDEX_M68K];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -6758,7 +7010,7 @@ static int32 switchcpu_io(const int32 port, const int32 io, const int32 data) {
|
|||
break;
|
||||
}
|
||||
|
||||
cpu_set_chiptype_short(new_chiptype, FALSE);
|
||||
cpu_set_chiptype_short(new_chiptype);
|
||||
return(0xFF); /* Return High-Z Data */
|
||||
} else {
|
||||
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 */
|
||||
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;
|
||||
size <<= KBLOG2;
|
||||
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"
|
||||
|
||||
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) {
|
||||
int32 i;
|
||||
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;
|
||||
MDEV m;
|
||||
char gbuf[CBUFSIZE];
|
||||
if (chiptype == CHIP_TYPE_M68K)
|
||||
return sim_load_m68k(fileref, cptr, fnam, flag);
|
||||
if (flag) {
|
||||
result = get_range(NULL, cptr, &lo, &hi, 16, ADDRMASKEXTENDED, 0);
|
||||
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)
|
||||
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 {
|
||||
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;
|
||||
if (cptr == result)
|
||||
return SCPE_ARG;
|
||||
while (isspace(*result)) result++;
|
||||
while (isspace(*result))
|
||||
result++;
|
||||
get_glyph(result, gbuf, 0);
|
||||
if (strcmp(gbuf, "ROM") == 0)
|
||||
makeROM = TRUE;
|
||||
|
@ -6981,6 +7277,6 @@ void cpu_raise_interrupt(uint32 irq) {
|
|||
cpu8086_intr(irq);
|
||||
} else if (cpu_unit.flags & UNIT_CPU_VERBOSE) {
|
||||
printf("Interrupts not fully supported for chiptype: %s\n",
|
||||
(chiptype <= MAX_CHIP_TYPE) ? chipTypeToString[chiptype] : "????");
|
||||
(chiptype < NUM_CHIP_TYPE) ? cpu_mod[chiptype].mstring : "????");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
Based on work by Charles E Owen (c) 1997
|
||||
*/
|
||||
|
||||
#ifndef ALTAIRZ80_DEFS_H_
|
||||
#define ALTAIRZ80_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator definitions */
|
||||
|
||||
#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_2 0xb4 /* LD a,80h | <unitno> */
|
||||
|
||||
#define CHIP_TYPE_8080 0
|
||||
#define CHIP_TYPE_Z80 1
|
||||
#define CHIP_TYPE_8086 2
|
||||
#define MAX_CHIP_TYPE CHIP_TYPE_8086
|
||||
#define CPU_INDEX_8080 4 /* index of default PC register */
|
||||
|
||||
typedef enum {
|
||||
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 */
|
||||
#define STOP_HALT 0 /* HALT */
|
||||
|
@ -81,7 +89,7 @@
|
|||
#define UNIX_PLATFORM 0
|
||||
#endif
|
||||
|
||||
#define ADDRESS_FORMAT "[0x%05x]"
|
||||
#define ADDRESS_FORMAT "[0x%08x]"
|
||||
|
||||
/* use NLP for new line printing while the simulation is running */
|
||||
#if UNIX_PLATFORM
|
||||
|
@ -100,3 +108,5 @@ typedef struct {
|
|||
uint32 io_base; /* I/O Base Address */
|
||||
uint32 io_size; /* I/O Address Space requirement */
|
||||
} PNP_INFO;
|
||||
|
||||
#endif
|
||||
|
|
Binary file not shown.
|
@ -106,6 +106,11 @@
|
|||
T = Sector True, is a 1 when the sector is positioned to read or
|
||||
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"
|
||||
|
@ -131,21 +136,26 @@
|
|||
#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1)
|
||||
#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 dsk11(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_reset(DEVICE *dptr);
|
||||
static t_stat dsk_attach(UNIT *uptr, char *cptr);
|
||||
|
||||
extern REG *sim_PC;
|
||||
extern UNIT cpu_unit;
|
||||
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,
|
||||
int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
|
||||
void install_ALTAIRbootROM(void);
|
||||
extern int32 find_unit_index(UNIT *uptr);
|
||||
|
||||
/* 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_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 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,
|
||||
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 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 */
|
||||
int32 bootrom_dsk[BOOTROM_SIZE_DSK] = {
|
||||
0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */
|
||||
|
@ -229,40 +278,62 @@ static UNIT dsk_unit[] = {
|
|||
};
|
||||
|
||||
static REG dsk_reg[] = {
|
||||
{ DRDATA (DISK, current_disk, 4) },
|
||||
{ BRDATA (CURTRACK, current_track, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ BRDATA (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ BRDATA (CURBYTE, current_byte, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ BRDATA (CURFLAG, current_flag, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ BRDATA (TRACKS, tracks, 10, 8, NUM_OF_DSK), REG_CIRC },
|
||||
{ DRDATA (IN9COUNT, in9_count, 4), REG_RO },
|
||||
{ DRDATA (IN9MESSAGE, in9_message, 4), REG_RO },
|
||||
{ DRDATA (DIRTY, dirty, 4), REG_RO },
|
||||
{ DRDATA (DSKWL, warnLevelDSK, 32) },
|
||||
{ BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ DRDATA (WARNDSK10, warnDSK10, 4), REG_RO },
|
||||
{ DRDATA (WARNDSK11, warnDSK11, 4), REG_RO },
|
||||
{ DRDATA (WARNDSK12, warnDSK12, 4), REG_RO },
|
||||
{ BRDATA (DISKBUFFER, dskbuf, 10, 8, DSK_SECTSIZE), REG_CIRC + REG_RO },
|
||||
{ DRDATAD (DISK, current_disk, 4,
|
||||
"Selected disk register"), },
|
||||
{ BRDATAD (CURTRACK, current_track, 10, 32, NUM_OF_DSK,
|
||||
"Selected track register array"), REG_CIRC + REG_RO },
|
||||
{ BRDATAD (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK,
|
||||
"Selected sector register array"), REG_CIRC + REG_RO },
|
||||
{ BRDATAD (CURBYTE, current_byte, 10, 32, NUM_OF_DSK,
|
||||
"Current byte register arrayr"), REG_CIRC + REG_RO },
|
||||
{ BRDATAD (CURFLAG, current_flag, 10, 32, NUM_OF_DSK,
|
||||
"Current flag register array"), REG_CIRC + REG_RO },
|
||||
{ BRDATAD (TRACKS, tracks, 10, 8, NUM_OF_DSK,
|
||||
"Number of tracks register array"), REG_CIRC },
|
||||
{ BRDATAD (SECTPERTRACK,sectors_per_track, 10, 8, NUM_OF_DSK,
|
||||
"Number of sectors per track register array"), REG_CIRC },
|
||||
{ DRDATAD (IN9COUNT, in9_count, 4,
|
||||
"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 }
|
||||
};
|
||||
|
||||
#define DSK_NAME "Altair Floppy Disk DSK"
|
||||
|
||||
static MTAB dsk_mod[] = {
|
||||
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL, NULL, 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB dsk_dt[] = {
|
||||
{ "IN", IN_MSG },
|
||||
{ "OUT", OUT_MSG },
|
||||
{ "READ", READ_MSG },
|
||||
{ "WRITE", WRITE_MSG },
|
||||
{ "SECTOR_STUCK", SECTOR_STUCK_MSG },
|
||||
{ "TRACK_STUCK", TRACK_STUCK_MSG },
|
||||
{ "VERBOSE", VERBOSE_MSG },
|
||||
{ "IN", IN_MSG, "IN operations" },
|
||||
{ "OUT", OUT_MSG, "OUT operations" },
|
||||
{ "READ", READ_MSG, "Read operations" },
|
||||
{ "WRITE", WRITE_MSG, "Write operations" },
|
||||
{ "SECTOR_STUCK", SECTOR_STUCK_MSG, "Sector stuck" },
|
||||
{ "TRACK_STUCK", TRACK_STUCK_MSG, "Track stuck" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -270,9 +341,9 @@ DEVICE dsk_dev = {
|
|||
"DSK", dsk_unit, dsk_reg, dsk_mod,
|
||||
NUM_OF_DSK, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dsk_reset,
|
||||
&dsk_boot, NULL, NULL,
|
||||
&dsk_boot, &dsk_attach, NULL,
|
||||
NULL, (DEV_DISABLE | DEV_DEBUG), 0,
|
||||
dsk_dt, NULL, "Altair Floppy Disk DSK"
|
||||
dsk_dt, NULL, DSK_NAME
|
||||
};
|
||||
|
||||
static char* selectInOut(const int32 io) {
|
||||
|
@ -291,7 +362,6 @@ static t_stat dsk_reset(DEVICE *dptr) {
|
|||
current_sector[i] = 0;
|
||||
current_byte[i] = 0;
|
||||
current_flag[i] = 0;
|
||||
tracks[i] = MAX_TRACKS;
|
||||
}
|
||||
warnDSK10 = 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);
|
||||
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) {
|
||||
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) {
|
||||
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 */
|
||||
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_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 */
|
||||
}
|
||||
}
|
||||
*((int32 *) sim_PC->loc) = ALTAIR_ROM_LOW;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -465,7 +564,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
|
|||
writebuf();
|
||||
if (current_flag[current_disk] & 0x04) { /* head loaded? */
|
||||
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_byte[current_disk] = 0xff;
|
||||
return (((current_sector[current_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
Contains code from Howard M. Harte for defining and changing disk geometry.
|
||||
*/
|
||||
|
||||
#include "altairz80_defs.h"
|
||||
#include "m68k.h"
|
||||
#include <assert.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_FORMAT_TYPE u6 /* Disk Format Type */
|
||||
#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_ERROR 1 /* indicates to CP/M an error condition */
|
||||
#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
|
||||
|
||||
extern uint32 PCX;
|
||||
extern REG *sim_PC;
|
||||
extern UNIT cpu_unit;
|
||||
extern ChipType chiptype;
|
||||
|
||||
extern void install_ALTAIRbootROM(void);
|
||||
extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value);
|
||||
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 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);
|
||||
|
@ -94,11 +94,40 @@ static int32 selectedDisk;
|
|||
static int32 selectedSector;
|
||||
static int32 selectedTrack;
|
||||
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 {
|
||||
char name[DPB_NAME_LENGTH + 1]; /* name of CP/M disk parameter block */
|
||||
t_addr capac; /* capacity */
|
||||
uint16 spt; /* sectors per track */
|
||||
uint32 spt; /* sectors per track */
|
||||
uint8 bsh; /* data allocation block shift factor */
|
||||
uint8 blm; /* data allocation block mask */
|
||||
uint8 exm; /* extent mask */
|
||||
|
@ -163,6 +192,9 @@ static DPB dpb[] = {
|
|||
{ "HDSK", HDSK_CAPACITY, 32, 0x05, 0x1F, 0x01, 0x07f9, 0x03FF,
|
||||
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,
|
||||
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) },
|
||||
};
|
||||
static DISK_INFO* hdsk_imd[HDSK_NUMBER];
|
||||
|
||||
static REG hdsk_reg[] = {
|
||||
{ DRDATA (HDCMD, hdskLastCommand, 32), REG_RO },
|
||||
{ DRDATA (HDPOS, hdskCommandPosition, 32), REG_RO },
|
||||
{ DRDATA (HDDSK, selectedDisk, 32), REG_RO },
|
||||
{ DRDATA (HDSEC, selectedSector, 32), REG_RO },
|
||||
{ DRDATA (HDTRK, selectedTrack, 32), REG_RO },
|
||||
{ DRDATA (HDDMA, selectedDMA, 32), REG_RO },
|
||||
{ DRDATAD (HDCMD, hdskLastCommand, 32, "Last command"),
|
||||
REG_RO },
|
||||
{ DRDATAD (HDPOS, hdskCommandPosition, 32, "Commmand position"),
|
||||
REG_RO },
|
||||
{ DRDATAD (HDDSK, selectedDisk, 32, "Selected disk"),
|
||||
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 }
|
||||
};
|
||||
|
||||
#define HDSK_NAME "Hard Disk HDSK"
|
||||
|
||||
static MTAB hdsk_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", &set_format, &show_format, NULL },
|
||||
{ UNIT_HDSK_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_HDSK_WLK, UNIT_HDSK_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "GEOM", "GEOM", &set_geom, &show_geom, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Defines the I/O port assignment for device " HDSK_NAME },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&set_format, &show_format, NULL, "Defines the format for unit " HDSK_NAME "n" },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB hdsk_dt[] = {
|
||||
{ "READ", READ_MSG },
|
||||
{ "WRITE", WRITE_MSG },
|
||||
{ "VERBOSE", VERBOSE_MSG },
|
||||
{ "READ", READ_MSG, "Disk read activity" },
|
||||
{ "WRITE", WRITE_MSG, "Disk write activity" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "All disk activity" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
DEVICE hdsk_dev = {
|
||||
"HDSK", hdsk_unit, hdsk_reg, hdsk_mod,
|
||||
8, 10, 31, 1, 8, 8,
|
||||
HDSK_NUMBER, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &hdsk_reset,
|
||||
&hdsk_boot, &hdsk_attach, &hdsk_detach,
|
||||
&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) {
|
||||
t_bool installSuccessful;
|
||||
if (chiptype == CHIP_TYPE_M68K)
|
||||
return m68k_hdsk_boot(unitno, dptr, VERBOSE_MSG, HDSK_NUMBER);
|
||||
if (MEMORYSIZE < 24 * KB) {
|
||||
printf("Need at least 24KB RAM to boot from hard disk.\n");
|
||||
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 */
|
||||
static int32 checkParameters(void) {
|
||||
t_bool hdsk_checkParameters(void) {
|
||||
UNIT *uptr;
|
||||
if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) {
|
||||
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)) {
|
||||
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);
|
||||
selectedSector = 0;
|
||||
}
|
||||
|
@ -694,23 +748,36 @@ static int32 checkParameters(void) {
|
|||
selectedDisk, PCX, selectedTrack, uptr -> HDSK_NUMBER_OF_TRACKS);
|
||||
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;
|
||||
if (hdskLastCommand == HDSK_READ) {
|
||||
sim_debug(READ_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT
|
||||
" Read Track=%04d Sector=%02d Len=%04d DMA=%04x\n",
|
||||
selectedDisk, PCX, selectedTrack, selectedSector, uptr -> HDSK_SECTOR_SIZE, selectedDMA);
|
||||
" Read Track=%04d Sector=%06d Len=%04d DMA=%08x\n",
|
||||
selectedDisk, PCX, selectedTrack, selectedSector,
|
||||
uptr -> HDSK_SECTOR_SIZE, selectedDMA);
|
||||
}
|
||||
if (hdskLastCommand == HDSK_WRITE) {
|
||||
sim_debug(WRITE_MSG, &hdsk_dev, "HDSK%d " ADDRESS_FORMAT
|
||||
" Write Track=%04d Sector=%02d Len=%04d DMA=%04x\n",
|
||||
selectedDisk, PCX, selectedTrack, selectedSector, uptr -> HDSK_SECTOR_SIZE, selectedDMA);
|
||||
" Write Track=%04d Sector=%06d Len=%04d DMA=%08x\n",
|
||||
selectedDisk, PCX, selectedTrack, selectedSector,
|
||||
uptr -> HDSK_SECTOR_SIZE, selectedDMA);
|
||||
}
|
||||
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) {
|
||||
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
||||
assert(uptr != NULL);
|
||||
int32 hostSector = (dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ?
|
||||
selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector];
|
||||
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) +
|
||||
dpb[uptr -> HDSK_FORMAT_TYPE].offset, SEEK_SET)) {
|
||||
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);
|
||||
return CPM_ERROR;
|
||||
}
|
||||
|
@ -728,8 +795,8 @@ static int32 doSeek(void) {
|
|||
|
||||
static uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */
|
||||
|
||||
/* pre-condition: checkParameters has been executed to repair any faulty parameters */
|
||||
static int32 doRead(void) {
|
||||
/* pre-condition: hdsk_checkParameters has been executed to repair any faulty parameters */
|
||||
int32 hdsk_read(void) {
|
||||
int32 i;
|
||||
t_stat result;
|
||||
DISK_INFO *thisDisk;
|
||||
|
@ -761,30 +828,39 @@ static int32 doRead(void) {
|
|||
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
|
||||
hdskbuf[i] = CPM_EMPTY;
|
||||
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);
|
||||
return CPM_ERROR;
|
||||
hdskStatus = CPM_ERROR;
|
||||
return hdskStatus;
|
||||
}
|
||||
} else {
|
||||
if (doSeek())
|
||||
return CPM_ERROR;
|
||||
if (doSeek()) {
|
||||
hdskStatus = CPM_ERROR;
|
||||
return hdskStatus;
|
||||
}
|
||||
|
||||
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++)
|
||||
hdskbuf[i] = CPM_EMPTY;
|
||||
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);
|
||||
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++)
|
||||
PutBYTEWrapper(selectedDMA + i, hdskbuf[i]);
|
||||
return CPM_OK;
|
||||
hdskStatus = CPM_OK;
|
||||
return hdskStatus;
|
||||
}
|
||||
|
||||
/* pre-condition: checkParameters has been executed to repair any faulty parameters */
|
||||
static int32 doWrite(void) {
|
||||
/* pre-condition: hdsk_checkParameters has been executed to repair any faulty parameters */
|
||||
int32 hdsk_write(void) {
|
||||
int32 i;
|
||||
t_stat result;
|
||||
DISK_INFO *thisDisk;
|
||||
|
@ -797,9 +873,13 @@ static int32 doWrite(void) {
|
|||
size_t rtn;
|
||||
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
||||
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++)
|
||||
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
|
||||
if (is_imd(uptr)) {
|
||||
thisDisk = hdsk_imd[selectedDisk];
|
||||
hostSector = ((dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ?
|
||||
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);
|
||||
if (result != SCPE_OK) {
|
||||
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);
|
||||
return CPM_ERROR;
|
||||
hdskStatus = CPM_ERROR;
|
||||
return hdskStatus;
|
||||
}
|
||||
} else {
|
||||
if (doSeek())
|
||||
return CPM_ERROR;
|
||||
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
|
||||
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
|
||||
if (doSeek()) {
|
||||
hdskStatus = CPM_ERROR;
|
||||
return hdskStatus;
|
||||
}
|
||||
rtn = sim_fwrite(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref);
|
||||
if (rtn != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
|
||||
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);
|
||||
return CPM_ERROR;
|
||||
hdskStatus = CPM_ERROR;
|
||||
return hdskStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
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);
|
||||
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
|
||||
|
@ -850,7 +952,7 @@ static uint8 parameterBlock[PARAMETER_BLOCK_SIZE];
|
|||
|
||||
static int32 hdsk_in(const int32 port) {
|
||||
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;
|
||||
hdskCommandPosition = 0;
|
||||
return result;
|
||||
|
|
|
@ -71,7 +71,7 @@ extern uint32 PCX;
|
|||
#define BOOTROM_SIZE_MHDSK 256
|
||||
#define MHDSK_BOOT_ADDRESS 0xfc00
|
||||
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.
|
||||
|
||||
|
@ -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) }};
|
||||
|
||||
#define MHDSK_NAME "MITS Hard Disk MHDSK"
|
||||
|
||||
static MTAB dsk_mod[] = {
|
||||
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL, NULL, 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB mhdsk_dt[] = {
|
||||
{ "READ", READ_MSG },
|
||||
{ "WRITE", WRITE_MSG },
|
||||
{ "VERBOSE", VERBOSE_MSG },
|
||||
{ "READ", READ_MSG, "Read messages" },
|
||||
{ "WRITE", WRITE_MSG, "Write messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -198,7 +202,7 @@ DEVICE mhdsk_dev = {
|
|||
NULL, NULL, &dsk_reset,
|
||||
&mhdsk_boot, NULL, NULL,
|
||||
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] = {
|
||||
|
|
|
@ -84,22 +84,24 @@ static UNIT net_unit = {
|
|||
};
|
||||
|
||||
static REG net_reg[] = {
|
||||
{ DRDATA (POLL, net_unit.wait, 32) },
|
||||
{ DRDATAD (POLL, net_unit.wait, 32, "Polling interval") },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static MTAB net_mod[] = {
|
||||
{ UNIT_SERVER, 0, "CLIENT", "CLIENT", &set_net}, /* machine is a client */
|
||||
{ UNIT_SERVER, UNIT_SERVER, "SERVER", "SERVER", &set_net}, /* machine is a server */
|
||||
{ UNIT_SERVER, 0, "CLIENT", "CLIENT", &set_net, NULL, NULL,
|
||||
"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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB net_dt[] = {
|
||||
{ "ACCEPT", ACCEPT_MSG },
|
||||
{ "DROP", DROP_MSG },
|
||||
{ "IN", IN_MSG },
|
||||
{ "OUT", OUT_MSG },
|
||||
{ "ACCEPT", ACCEPT_MSG, "Accept messages" },
|
||||
{ "DROP", DROP_MSG, "Drop messages" },
|
||||
{ "IN", IN_MSG, "Incoming messages" },
|
||||
{ "OUT", OUT_MSG, "Outgoing messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -172,11 +172,11 @@ extern volatile int32 stop_cpu;
|
|||
|
||||
/* Debug Flags */
|
||||
static DEBTAB generic_dt[] = {
|
||||
{ "IN", IN_MSG },
|
||||
{ "OUT", OUT_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "VERBOSE", VERBOSE_MSG },
|
||||
{ "BUFFEREMPTY", BUFFER_EMPTY_MSG },
|
||||
{ "IN", IN_MSG, "IN messages" },
|
||||
{ "OUT", OUT_MSG, "OUT messages" },
|
||||
{ "CMD", CMD_MSG, "Commands" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ "BUFFEREMPTY", BUFFER_EMPTY_MSG, "IN for empty buffer" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -279,40 +279,71 @@ static UNIT sio_unit = {
|
|||
};
|
||||
|
||||
static REG sio_reg[] = {
|
||||
{ DRDATA (SIOWLEV, warnLevelSIO, 32) },
|
||||
{ DRDATA (WRNUPTP, warnUnattachedPTP, 32) },
|
||||
{ DRDATA (WRNUPTR, warnUnattachedPTR, 32) },
|
||||
{ DRDATA (WRNPTRE, warnPTREOF, 32) },
|
||||
{ DRDATA (WRUPORT, warnUnassignedPort, 32) },
|
||||
{ HRDATA (FILEATT, sio_unit.u4, 8), REG_RO }, /* TRUE iff terminal input is attached to a file */
|
||||
{ HRDATA (TSTATUS, sio_unit.u3, 8) }, /* TRUE iff a character available in sio_unit.buf */
|
||||
{ DRDATA (TBUFFER, sio_unit.buf, 8) }, /* input buffer for one character */
|
||||
{ DRDATA (KEYBDI, keyboardInterrupt, 3), REG_RO },
|
||||
{ HRDATA (KEYBDH, keyboardInterruptHandler, 16) },
|
||||
{ DRDATAD (SIOWLEV, warnLevelSIO, 32,
|
||||
"Warn level SIO register") },
|
||||
{ DRDATAD (WRNUPTP, warnUnattachedPTP, 32,
|
||||
"Counter for unattached PTP access") },
|
||||
{ DRDATAD (WRNUPTR, warnUnattachedPTR, 32,
|
||||
"Counter for unattached PTR access") },
|
||||
{ DRDATAD (WRNPTRE, warnPTREOF, 32,
|
||||
"Counter for EOF reached for PTR") },
|
||||
{ DRDATAD (WRUPORT, warnUnassignedPort, 32,
|
||||
"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 }
|
||||
};
|
||||
|
||||
static MTAB sio_mod[] = {
|
||||
{ UNIT_SIO_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */
|
||||
{ UNIT_SIO_ANSI, UNIT_SIO_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */
|
||||
{ UNIT_SIO_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */
|
||||
{ UNIT_SIO_UPPER, UNIT_SIO_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */
|
||||
{ UNIT_SIO_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */
|
||||
{ UNIT_SIO_BS, UNIT_SIO_BS, "DEL", "DEL", NULL }, /* map backspace to delete */
|
||||
{ UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */
|
||||
{ UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||
/* verbose, display warning messages */
|
||||
{ UNIT_SIO_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */
|
||||
{ UNIT_SIO_MAP, UNIT_SIO_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */
|
||||
{ UNIT_SIO_BELL, 0, "BELL", "BELL", NULL }, /* enable bell character */
|
||||
{ UNIT_SIO_BELL, UNIT_SIO_BELL, "NOBELL", "NOBELL", NULL }, /* suppress ringing the bell */
|
||||
{ UNIT_SIO_SLEEP, 0, "NOSLEEP", "NOSLEEP", NULL }, /* no sleep after keyboard status check */
|
||||
{ UNIT_SIO_SLEEP, UNIT_SIO_SLEEP, "SLEEP", "SLEEP", NULL }, /* sleep after keyboard status check */
|
||||
{ UNIT_SIO_ANSI, 0, "TTY", "TTY", NULL, NULL, NULL,
|
||||
"Do not touch bit 8 of console output"}, /* keep bit 8 as is for output */
|
||||
{ UNIT_SIO_ANSI, UNIT_SIO_ANSI, "ANSI", "ANSI", NULL, NULL, NULL,
|
||||
"Set bit 8 of console output to 0"}, /* set bit 8 to 0 before output */
|
||||
{ UNIT_SIO_UPPER, 0, "ALL", "ALL", NULL, NULL, NULL,
|
||||
"Console input remains unchanged" }, /* do not change case of input characters */
|
||||
{ UNIT_SIO_UPPER, UNIT_SIO_UPPER, "UPPER", "UPPER", NULL, NULL, NULL,
|
||||
"Convert console input to upper case" }, /* change input characters to upper case */
|
||||
{ UNIT_SIO_BS, 0, "BS", "BS", NULL, NULL, NULL,
|
||||
"Map delete to backspace" }, /* map delete to backspace */
|
||||
{ UNIT_SIO_BS, UNIT_SIO_BS, "DEL", "DEL", NULL, NULL, NULL,
|
||||
"Map backspace to delete" }, /* map backspace to delete */
|
||||
{ UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL, NULL, NULL,
|
||||
"Do not display SIO error messages" }, /* quiet, no error messages */
|
||||
{ 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 */
|
||||
{ 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 */
|
||||
{ UNIT_SIO_INTERRUPT, UNIT_SIO_INTERRUPT, "INTERRUPT","INTERRUPT",&sio_dev_set_interrupton },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "PORT", "PORT", &sio_dev_set_port, &sio_dev_show_port },
|
||||
{ UNIT_SIO_INTERRUPT, UNIT_SIO_INTERRUPT, "INTERRUPT", "INTERRUPT",
|
||||
&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 }
|
||||
};
|
||||
|
||||
|
@ -334,7 +365,7 @@ static UNIT ptr_unit = {
|
|||
};
|
||||
|
||||
static REG ptr_reg[] = {
|
||||
{ HRDATA (STAT, ptr_unit.u3, 8) },
|
||||
{ HRDATAD (STAT, ptr_unit.u3, 8, "Status register") },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -367,43 +398,70 @@ static UNIT simh_unit = {
|
|||
};
|
||||
|
||||
static REG simh_reg[] = {
|
||||
{ DRDATA (CZD, ClockZSDOSDelta, 32) },
|
||||
{ DRDATA (SCZP, setClockZSDOSPos, 8), REG_RO },
|
||||
{ HRDATA (SCZA, setClockZSDOSAdr, 16), REG_RO },
|
||||
{ DRDATA (GCZP, getClockZSDOSPos, 8), REG_RO },
|
||||
{ DRDATAD (CZD, ClockZSDOSDelta, 32,
|
||||
"ZSDOS Clock - Delta between real clock and AltairZ80 clock") },
|
||||
{ DRDATAD (SCZP, setClockZSDOSPos, 8,
|
||||
"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) },
|
||||
{ DRDATA (SC3DP, setClockCPM3Pos, 8), REG_RO },
|
||||
{ HRDATA (SC3DA, setClockCPM3Adr, 16), REG_RO },
|
||||
{ DRDATA (GC3DP, getClockCPM3Pos, 8), REG_RO },
|
||||
{ DRDATA (D3DO, daysCPM3SinceOrg, 32), REG_RO },
|
||||
{ DRDATAD (CC3D, ClockCPM3Delta, 32,
|
||||
"CP/M 3 Clock - Delta between real clock and AltairZ80 clock") },
|
||||
{ DRDATAD (SC3DP, setClockCPM3Pos, 8,
|
||||
"CP/M 3 Clock - Status register for receiving address of parameter block"), 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 },
|
||||
{ DRDATA (TIMI, timerInterrupt, 3) },
|
||||
{ HRDATA (TIMH, timerInterruptHandler, 16) },
|
||||
{ DRDATA (STIAP, setTimerInterruptAdrPos,8), REG_RO },
|
||||
{ DRDATA (TIMD, timerDelta, 32) },
|
||||
{ DRDATA (STDP, setTimerDeltaPos, 8), REG_RO },
|
||||
{ DRDATA (SLEEP, SIMHSleep, 32) },
|
||||
{ DRDATA (VOSLP, sleepAllowedStart, 32) },
|
||||
{ DRDATAD (TOFNI, timeOfNextInterrupt, 32,
|
||||
"Time when next interrupt is scheduled"), REG_RO },
|
||||
{ DRDATAD (TIMI, timerInterrupt, 3,
|
||||
"BOOL - determines whether a timer interrupt is pending") },
|
||||
{ HRDATAD (TIMH, timerInterruptHandler, 16,
|
||||
"Address of timer interrupt handling routine") },
|
||||
{ DRDATAD (STIAP, setTimerInterruptAdrPos,8,
|
||||
"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 },
|
||||
{ DRDATA (STPOS, getStopWatchDeltaPos, 8), REG_RO },
|
||||
{ DRDATA (STPNW, stopWatchNow, 32), REG_RO },
|
||||
{ DRDATA (MTSP, markTimeSP, 8), REG_RO },
|
||||
{ DRDATAD (STPDT, stopWatchDelta, 32,
|
||||
"Elapsed time of stop watch"), REG_RO },
|
||||
{ DRDATAD (STPOS, getStopWatchDeltaPos, 8,
|
||||
"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 },
|
||||
{ DRDATA (LCPMS, lastCPMStatus, 8), REG_RO },
|
||||
{ DRDATA (LCMD, lastCommand, 8), REG_RO },
|
||||
{ DRDATA (CPOS, getCommonPos, 8), REG_RO },
|
||||
{ DRDATAD (VPOS, versionPos, 8,
|
||||
"Status register for sending version information"), REG_RO },
|
||||
{ DRDATAD (LCPMS, lastCPMStatus, 8,
|
||||
"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 }
|
||||
};
|
||||
|
||||
static MTAB simh_mod[] = {
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
|
@ -1191,7 +1249,6 @@ static t_stat simh_dev_reset(DEVICE *dptr) {
|
|||
free(urlResult);
|
||||
urlResult = NULL;
|
||||
}
|
||||
if (simh_unit.flags & UNIT_SIMH_TIMERON)
|
||||
simh_dev_set_timeron(NULL, 0, NULL, NULL);
|
||||
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) {
|
||||
if (rtc_avail) {
|
||||
timeOfNextInterrupt = sim_os_msec() + timerDelta;
|
||||
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) {
|
||||
timerInterrupt = FALSE;
|
||||
if (rtc_avail)
|
||||
sim_cancel(&simh_unit);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat simh_svc(UNIT *uptr) {
|
||||
if (simh_unit.flags & UNIT_SIMH_TIMERON) {
|
||||
uint32 now = sim_os_msec();
|
||||
if (now >= timeOfNextInterrupt) {
|
||||
timerInterrupt = TRUE;
|
||||
|
@ -1236,7 +1288,7 @@ static t_stat simh_svc(UNIT *uptr) {
|
|||
}
|
||||
}
|
||||
/* post condition: now < timeOfNextInterrupt */
|
||||
if (simh_unit.flags & UNIT_SIMH_TIMERON)
|
||||
}
|
||||
sim_activate(&simh_unit, simh_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
03/27/14 -- MWD Add MITS Hard Disk device (mhdsk_dev)
|
||||
*/
|
||||
|
||||
#include "m68k.h"
|
||||
#include <ctype.h>
|
||||
#include "altairz80_defs.h"
|
||||
|
||||
#define SIM_EMAX 6
|
||||
|
||||
|
@ -72,10 +72,6 @@ extern DEVICE wdi2_dev;
|
|||
|
||||
extern DEVICE scp300f_dev;
|
||||
|
||||
#ifdef USE_FPC
|
||||
extern DEVICE fpc_dev;
|
||||
#endif /* USE_FPC */
|
||||
|
||||
extern int32 chiptype;
|
||||
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)";
|
||||
REG *sim_PC = &cpu_reg[6];
|
||||
REG *sim_PC = &cpu_reg[CPU_INDEX_8080];
|
||||
int32 sim_emax = SIM_EMAX;
|
||||
DEVICE *sim_devices[] = {
|
||||
/* AltairZ80 Devices */
|
||||
|
@ -380,6 +376,7 @@ static void printHex4(char* string, const uint32 value) {
|
|||
addr = current PC
|
||||
Outputs:
|
||||
*S = output text
|
||||
return = length of instruction in bytes
|
||||
|
||||
DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997
|
||||
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) {
|
||||
char disasm_result[128];
|
||||
int32 ch = val[0] & 0x7f;
|
||||
long r;
|
||||
long r = 1;
|
||||
unsigned char vals[SIM_EMAX];
|
||||
int32 i;
|
||||
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')))
|
||||
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++)
|
||||
vals[i] = val[i] & 0xff;
|
||||
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);
|
||||
return 1 - r;
|
||||
}
|
||||
|
@ -769,14 +779,19 @@ static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *co
|
|||
status = error status
|
||||
*/
|
||||
t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) {
|
||||
static t_bool symbolicInputNotImplementedMessage = FALSE;
|
||||
#define NO_SYMBOLIC_INPUT_MESSAGE "Symbolic input is not supported for the 8086.\n"
|
||||
if (chiptype == CHIP_TYPE_8086) {
|
||||
if (!symbolicInputNotImplementedMessage) {
|
||||
printf(NO_SYMBOLIC_INPUT_MESSAGE);
|
||||
if (sim_log)
|
||||
fprintf(sim_log, NO_SYMBOLIC_INPUT_MESSAGE);
|
||||
symbolicInputNotImplementedMessage = TRUE;
|
||||
static t_bool symbolicInputNotImplementedMessage8086 = FALSE;
|
||||
static t_bool symbolicInputNotImplementedMessageM68K = FALSE;
|
||||
if ((sw & (SWMASK('M'))) && (chiptype == CHIP_TYPE_8086)) {
|
||||
if (!symbolicInputNotImplementedMessage8086) {
|
||||
sim_printf("Symbolic input is not supported for the 8086.\n");
|
||||
symbolicInputNotImplementedMessage8086 = 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;
|
||||
}
|
||||
|
|
|
@ -88,11 +88,15 @@ static UNIT fw2_unit[] = {
|
|||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, FW2_CAPACITY) }
|
||||
};
|
||||
|
||||
#define FWII_NAME "Vector Graphic Flashwriter 2 FWII"
|
||||
|
||||
static MTAB fw2_mod[] = {
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
|
@ -102,7 +106,7 @@ DEVICE fw2_dev = {
|
|||
NULL, NULL, NULL,
|
||||
NULL, &fw2_attach, &fw2_detach,
|
||||
NULL, (DEV_DISABLE | DEV_DIS), 0,
|
||||
NULL, NULL, "Vector Graphic Flashwriter 2 FWII"
|
||||
NULL, NULL, FWII_NAME
|
||||
};
|
||||
|
||||
/* Attach routine */
|
||||
|
|
|
@ -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 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_I8272_VERBOSE (1 << UNIT_V_I8272_VERBOSE)
|
||||
#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) }
|
||||
};
|
||||
|
||||
#define I8272_NAME "Intel/NEC(765) FDC Core I8272"
|
||||
|
||||
static MTAB i8272_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_I8272_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_I8272_WLK, UNIT_I8272_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB i8272_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "FMT", FMT_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ "FMT", FMT_MSG, "Format messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ "IRQ", IRQ_MSG, "IRQ messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -222,7 +223,7 @@ DEVICE i8272_dev = {
|
|||
NULL, NULL, &i8272_reset,
|
||||
NULL, &i8272_attach, &i8272_detach,
|
||||
&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);
|
||||
|
|
339
AltairZ80/m68k.h
Executable file
339
AltairZ80/m68k.h
Executable 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
193
AltairZ80/m68kconf.h
Normal 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
894
AltairZ80/m68kcpu.c
Executable 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
1841
AltairZ80/m68kcpu.h
Executable file
File diff suppressed because it is too large
Load diff
3443
AltairZ80/m68kdasm.c
Executable file
3443
AltairZ80/m68kdasm.c
Executable file
File diff suppressed because it is too large
Load diff
11948
AltairZ80/m68kopac.c
Normal file
11948
AltairZ80/m68kopac.c
Normal file
File diff suppressed because it is too large
Load diff
13221
AltairZ80/m68kopdm.c
Normal file
13221
AltairZ80/m68kopdm.c
Normal file
File diff suppressed because it is too large
Load diff
8710
AltairZ80/m68kopnz.c
Normal file
8710
AltairZ80/m68kopnz.c
Normal file
File diff suppressed because it is too large
Load diff
2093
AltairZ80/m68kops.c
Normal file
2093
AltairZ80/m68kops.c
Normal file
File diff suppressed because it is too large
Load diff
1984
AltairZ80/m68kops.h
Normal file
1984
AltairZ80/m68kops.h
Normal file
File diff suppressed because it is too large
Load diff
543
AltairZ80/m68ksim.c
Normal file
543
AltairZ80/m68ksim.c
Normal 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
57
AltairZ80/m68ksim.h
Normal 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 */
|
|
@ -59,13 +59,11 @@
|
|||
#endif
|
||||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define STATUS_MSG (1 << 0)
|
||||
#define SEEK_MSG (1 << 1)
|
||||
#define CMD_MSG (1 << 2)
|
||||
#define RD_DATA_MSG (1 << 3)
|
||||
#define WR_DATA_MSG (1 << 4)
|
||||
#define STATUS_MSG (1 << 5)
|
||||
#define ORDERS_MSG (1 << 7)
|
||||
|
||||
extern uint32 PCX;
|
||||
extern t_stat set_membase(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
@ -150,26 +148,31 @@ static REG mfdc_reg[] = {
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
#define MDSK_NAME "Micropolis FD Control MDSK"
|
||||
|
||||
static MTAB mfdc_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL },
|
||||
{ UNIT_MFDC_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_MFDC_WLK, UNIT_MFDC_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
|
||||
&set_membase, &show_membase, NULL, "Sets disk controller base address" },
|
||||
{ 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 */
|
||||
{ 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB mfdc_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "ORDERS", ORDERS_MSG },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek activity" },
|
||||
{ "CMD", CMD_MSG, "Commands" },
|
||||
{ "READ", RD_DATA_MSG, "Disk read activity" },
|
||||
{ "WRITE", WR_DATA_MSG, "Disk write activity" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -178,8 +181,8 @@ DEVICE mfdc_dev = {
|
|||
MFDC_MAX_DRIVES, 10, 31, 1, MFDC_MAX_DRIVES, MFDC_MAX_DRIVES,
|
||||
NULL, NULL, &mfdc_reset,
|
||||
NULL, &mfdc_attach, &mfdc_detach,
|
||||
&mfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
|
||||
mfdc_dt, NULL, "Micropolis FD Control MDSK"
|
||||
&mfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
|
||||
mfdc_dt, NULL, MDSK_NAME
|
||||
};
|
||||
|
||||
/* Micropolis FD Control Boot ROM
|
||||
|
|
|
@ -55,13 +55,11 @@
|
|||
#endif
|
||||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define PIO_MSG (1 << 1)
|
||||
#define UART_MSG (1 << 2)
|
||||
#define RTC_MSG (1 << 3)
|
||||
#define MPCL_MSG (1 << 4)
|
||||
#define ROM_MSG (1 << 5)
|
||||
#define VERBOSE_MSG (1 << 7)
|
||||
#define PIO_MSG (1 << 0)
|
||||
#define UART_MSG (1 << 1)
|
||||
#define MPCL_MSG (1 << 2)
|
||||
#define ROM_MSG (1 << 3)
|
||||
#define VERBOSE_MSG (1 << 4)
|
||||
|
||||
#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,
|
||||
int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
|
||||
extern uint32 PCX;
|
||||
extern REG *sim_PC;
|
||||
extern int32 find_unit_index (UNIT *uptr);
|
||||
|
||||
static t_stat n8vem_reset(DEVICE *n8vem_dev);
|
||||
|
@ -121,29 +118,37 @@ static UNIT n8vem_unit[] = {
|
|||
};
|
||||
|
||||
static REG n8vem_reg[] = {
|
||||
{ HRDATA (SAVEROM, save_rom, 1), },
|
||||
{ HRDATA (SAVERAM, save_ram, 1), },
|
||||
{ HRDATA (PIO1A, n8vem_pio1a, 8), },
|
||||
{ HRDATA (PIO1B, n8vem_pio1b, 8), },
|
||||
{ HRDATA (PIO1C, n8vem_pio1c, 8), },
|
||||
{ HRDATA (PIO1CTRL, n8vem_pio1ctrl, 8), },
|
||||
{ HRDATAD (SAVEROM, save_rom, 1,
|
||||
"When 1, saves the ROM back to file on disk at detach time"), },
|
||||
{ HRDATAD (SAVERAM, save_ram, 1,
|
||||
"When 1 save the RAM back to file on disk at detach time"), },
|
||||
{ HRDATAD (PIO1A, n8vem_pio1a, 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 }
|
||||
};
|
||||
|
||||
#define N8VEM_NAME "Single-Board Computer N8VEM"
|
||||
|
||||
static MTAB n8vem_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase,
|
||||
NULL, "Sets device base address" },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase,
|
||||
NULL, "Sets device I/O address" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB n8vem_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "PIO", PIO_MSG },
|
||||
{ "UART", UART_MSG },
|
||||
{ "RTC", RTC_MSG },
|
||||
{ "ROM", ROM_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "PIO", PIO_MSG, "PIP activity"} ,
|
||||
{ "UART", UART_MSG, "UART activity" },
|
||||
{ "ROM", ROM_MSG, "ROM activity" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -152,7 +157,7 @@ DEVICE n8vem_dev = {
|
|||
N8VEM_MAX_DRIVES, 10, 31, 1, N8VEM_MAX_DRIVES, N8VEM_MAX_DRIVES,
|
||||
NULL, NULL, &n8vem_reset,
|
||||
&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"
|
||||
};
|
||||
|
||||
|
|
|
@ -59,15 +59,10 @@
|
|||
#endif
|
||||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define SEEK_MSG (1 << 1)
|
||||
#define CMD_MSG (1 << 2)
|
||||
#define RD_DATA_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 STATUS_MSG (1 << 0)
|
||||
#define DRIVE_MSG (1 << 1)
|
||||
#define VERBOSE_MSG (1 << 2)
|
||||
#define IRQ_MSG (1 << 3)
|
||||
|
||||
#define CROMFDC_MAX_DRIVES 4
|
||||
#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);
|
||||
|
||||
extern REG *sim_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_CROMFDC_ROM (1 << UNIT_V_CROMFDC_ROM)
|
||||
#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[] = {
|
||||
{ HRDATA (DIPSW, dipswitch, 8), },
|
||||
{ DRDATA (BOOTSTRAP, bootstrap, 2), },
|
||||
{ DRDATA (FDCTYPE, crofdc_type, 8), },
|
||||
{ DRDATA (BOOT, crofdc_boot, 10), },
|
||||
{ DRDATA (INHINIT, crofdc_inh_init, 10), },
|
||||
{ HRDATAD (DIPSW, dipswitch, 8,
|
||||
"5-position DIP switch on 64FDC card"), },
|
||||
{ DRDATAD (BOOTSTRAP, bootstrap, 2,
|
||||
"0 for RDOS 2.52, 1 for RDOS 3.12"), },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
#define CROMFDC_NAME "Cromemco 4/16/64 FDC CROMFDC"
|
||||
|
||||
static MTAB cromfdc_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_CROMFDC_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_CROMFDC_WLK, UNIT_CROMFDC_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
|
||||
&set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* quiet, no warning messages */
|
||||
{ UNIT_CROMFDC_VERBOSE, 0, "QUIET", "QUIET", NULL },
|
||||
/* verbose, show warning messages */
|
||||
{ UNIT_CROMFDC_VERBOSE, UNIT_CROMFDC_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||
{ UNIT_CROMFDC_ROM, 0, "NOROM", "NOROM", NULL },
|
||||
{ UNIT_CROMFDC_ROM, UNIT_CROMFDC_ROM, "ROM", "ROM", NULL },
|
||||
{ UNIT_CROMFDC_ROM, 0, "NOROM", "NOROM",
|
||||
NULL, NULL, NULL, "Disables boot ROM for unit " CROMFDC_NAME "n" },
|
||||
{ UNIT_CROMFDC_ROM, UNIT_CROMFDC_ROM, "ROM", "ROM",
|
||||
NULL, NULL, NULL, "Enables boot ROM for unit " CROMFDC_NAME "n" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB cromfdc_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "DRIVE", DRIVE_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ "DRIVE", DRIVE_MSG, "Drive messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ "IRQ", IRQ_MSG, "IRQ messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -267,8 +258,8 @@ DEVICE cromfdc_dev = {
|
|||
CROMFDC_MAX_DRIVES, 10, 31, 1, CROMFDC_MAX_DRIVES, CROMFDC_MAX_DRIVES,
|
||||
NULL, NULL, &cromfdc_reset,
|
||||
&cromfdc_boot, &wd179x_attach, &wd179x_detach,
|
||||
&cromfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
|
||||
cromfdc_dt, NULL, "Cromemco 4/16/64 FDC CROMFDC"
|
||||
&cromfdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
|
||||
cromfdc_dt, NULL, CROMFDC_NAME
|
||||
};
|
||||
|
||||
/* This is the CROMFDC RDOS-II ROM.
|
||||
|
|
|
@ -62,15 +62,9 @@
|
|||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define SEEK_MSG (1 << 1)
|
||||
#define CMD_MSG (1 << 2)
|
||||
#define RD_DATA_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 DRIVE_MSG (1 << 1)
|
||||
#define VERBOSE_MSG (1 << 2)
|
||||
#define DMA_MSG (1 << 3)
|
||||
|
||||
#define ADCS6_MAX_DRIVES 4
|
||||
#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);
|
||||
|
||||
extern REG *sim_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_ADCS6_ROM (1 << UNIT_V_ADCS6_ROM)
|
||||
#define ADCS6_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||
|
@ -189,36 +178,31 @@ static UNIT adcs6_unit[] = {
|
|||
};
|
||||
|
||||
static REG adcs6_reg[] = {
|
||||
{ HRDATA (J7, dipswitch, 8), },
|
||||
{ HRDATAD (J7, dipswitch, 8, "5-position DIP switch on 64FDC card"), },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
#define ADCS6_NAME "ADC Super-Six ADCS6"
|
||||
|
||||
static MTAB adcs6_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_ADCS6_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_ADCS6_WLK, UNIT_ADCS6_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
|
||||
&set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* quiet, no warning messages */
|
||||
{ UNIT_ADCS6_VERBOSE, 0, "QUIET", "QUIET", NULL },
|
||||
/* verbose, show warning messages */
|
||||
{ UNIT_ADCS6_VERBOSE, UNIT_ADCS6_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||
{ UNIT_ADCS6_ROM, 0, "NOROM", "NOROM", NULL },
|
||||
{ UNIT_ADCS6_ROM, UNIT_ADCS6_ROM, "ROM", "ROM", NULL },
|
||||
{ UNIT_ADCS6_ROM, 0, "NOROM", "NOROM",
|
||||
NULL, NULL, NULL, "Disables boot ROM for unit " ADCS6_NAME "n" },
|
||||
{ UNIT_ADCS6_ROM, UNIT_ADCS6_ROM, "ROM", "ROM",
|
||||
NULL, NULL, NULL, "Enables boot ROM for unit " ADCS6_NAME "n" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB adcs6_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "DRIVE", DRIVE_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "DMA", DMA_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "DRIVE", DRIVE_MSG, "Drive messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ "DMA", DMA_MSG, "DMA messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -228,7 +212,7 @@ DEVICE adcs6_dev = {
|
|||
NULL, NULL, &adcs6_reset,
|
||||
&adcs6_boot, &adcs6_attach, &adcs6_detach,
|
||||
&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
|
||||
|
|
|
@ -59,14 +59,11 @@
|
|||
#endif
|
||||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define SEEK_MSG (1 << 1)
|
||||
#define CMD_MSG (1 << 2)
|
||||
#define RD_DATA_MSG (1 << 3)
|
||||
#define WR_DATA_MSG (1 << 4)
|
||||
#define STATUS_MSG (1 << 5)
|
||||
#define VERBOSE_MSG (1 << 7)
|
||||
#define IRQ_MSG (1 << 8)
|
||||
#define CMD_MSG (1 << 0)
|
||||
#define RD_DATA_MSG (1 << 1)
|
||||
#define STATUS_MSG (1 << 2)
|
||||
#define VERBOSE_MSG (1 << 3)
|
||||
#define IRQ_MSG (1 << 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 REG *sim_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_DISK1A_ROM (1 << UNIT_V_DISK1A_ROM)
|
||||
#define DISK1A_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||
|
@ -127,34 +119,31 @@ static UNIT disk1a_unit[] = {
|
|||
};
|
||||
|
||||
static REG disk1a_reg[] = {
|
||||
{ DRDATA (BOOTSTRAP, bootstrap, 10), },
|
||||
{ DRDATAD (BOOTSTRAP, bootstrap, 10, "Bootstrap selector, 0 is default"), },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
#define DISK1A_NAME "Compupro Floppy Controller DISK1A"
|
||||
|
||||
static MTAB disk1a_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_DISK1A_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_DISK1A_WLK, UNIT_DISK1A_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
/* quiet, no warning messages */
|
||||
{ UNIT_DISK1A_VERBOSE, 0, "QUIET", "QUIET", NULL },
|
||||
/* verbose, show warning messages */
|
||||
{ UNIT_DISK1A_VERBOSE, UNIT_DISK1A_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||
{ UNIT_DISK1A_ROM, 0, "NOROM", "NOROM", NULL },
|
||||
{ UNIT_DISK1A_ROM, UNIT_DISK1A_ROM, "ROM", "ROM", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
|
||||
&set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
{ UNIT_DISK1A_ROM, 0, "NOROM", "NOROM",
|
||||
NULL, NULL, NULL, "Disables boot ROM for unit " DISK1A_NAME "n" },
|
||||
{ UNIT_DISK1A_ROM, UNIT_DISK1A_ROM, "ROM", "ROM",
|
||||
NULL, NULL, NULL, "Enables boot ROM for unit " DISK1A_NAME "n" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB disk1a_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "RDDATA", RD_DATA_MSG, "Read data messages" },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ "IRQ", IRQ_MSG, "IRQ messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -163,8 +152,8 @@ DEVICE disk1a_dev = {
|
|||
DISK1A_MAX_DRIVES, 10, 31, 1, DISK1A_MAX_DRIVES, DISK1A_MAX_DRIVES,
|
||||
NULL, NULL, &disk1a_reset,
|
||||
&disk1a_boot, &disk1a_attach, &disk1a_detach,
|
||||
&disk1a_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
|
||||
disk1a_dt, NULL, "Compupro Floppy Controller DISK1A"
|
||||
&disk1a_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 9,
|
||||
disk1a_dt, NULL, DISK1A_NAME
|
||||
};
|
||||
|
||||
/* This is the DISK1A Boot ROM.
|
||||
|
|
|
@ -118,7 +118,6 @@ static int32 nsectors = C20MB_NSECTORS;
|
|||
static int32 sectsize = C20MB_SECTSIZE;
|
||||
|
||||
extern uint32 PCX;
|
||||
extern REG *sim_PC;
|
||||
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 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 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_DISK2_VERBOSE (1 << UNIT_V_DISK2_VERBOSE)
|
||||
#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[] = {
|
||||
{ DRDATA (NTRACKS, ntracks, 10), },
|
||||
{ DRDATA (NHEADS, nheads, 8), },
|
||||
{ DRDATA (NSECTORS, nsectors, 8), },
|
||||
{ DRDATA (SECTSIZE, sectsize, 11), },
|
||||
{ HRDATA (SEL_DRIVE, disk2_info_data.sel_drive, 3), },
|
||||
{ HRDATA (CYL, disk2_info_data.cyl, 8), },
|
||||
{ HRDATA (HEAD, disk2_info_data.head, 8), },
|
||||
{ HRDATA (SECTOR, disk2_info_data.sector, 8), },
|
||||
{ DRDATAD (NTRACKS, ntracks, 10,
|
||||
"Number of tracks"), },
|
||||
{ DRDATAD (NHEADS, nheads, 8,
|
||||
"Number of heads"), },
|
||||
{ DRDATAD (NSECTORS, nsectors, 8,
|
||||
"Number of sectors per track"), },
|
||||
{ DRDATAD (SECTSIZE, sectsize, 11,
|
||||
"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 }
|
||||
};
|
||||
|
||||
#define DISK2_NAME "Compupro Hard Disk Controller DISK2"
|
||||
|
||||
static MTAB disk2_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_DISK2_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_DISK2_WLK, UNIT_DISK2_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB disk2_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ "IRQ", IRQ_MSG, "IRQ messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -193,7 +201,7 @@ DEVICE disk2_dev = {
|
|||
NULL, NULL, &disk2_reset,
|
||||
NULL, &disk2_attach, &disk2_detach,
|
||||
&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 */
|
||||
|
|
|
@ -53,10 +53,9 @@
|
|||
#define CMD_MSG (1 << 2)
|
||||
#define RD_DATA_MSG (1 << 3)
|
||||
#define WR_DATA_MSG (1 << 4)
|
||||
#define STATUS_MSG (1 << 5)
|
||||
#define IRQ_MSG (1 << 6)
|
||||
#define VERBOSE_MSG (1 << 7)
|
||||
#define SPECIFY_MSG (1 << 8)
|
||||
#define IRQ_MSG (1 << 5)
|
||||
#define VERBOSE_MSG (1 << 6)
|
||||
#define SPECIFY_MSG (1 << 7)
|
||||
|
||||
#define DISK3_MAX_DRIVES 4
|
||||
|
||||
|
@ -176,7 +175,6 @@ static int32 nsectors = C20MB_NSECTORS;
|
|||
static int32 sectsize = C20MB_SECTSIZE;
|
||||
|
||||
extern uint32 PCX;
|
||||
extern REG *sim_PC;
|
||||
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 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 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_DISK3_VERBOSE (1 << UNIT_V_DISK3_VERBOSE)
|
||||
#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[] = {
|
||||
{ DRDATA (NTRACKS, ntracks, 10), },
|
||||
{ DRDATA (NHEADS, nheads, 8), },
|
||||
{ DRDATA (NSECTORS, nsectors, 8), },
|
||||
{ DRDATA (SECTSIZE, sectsize, 11), },
|
||||
{ HRDATA (SEL_DRIVE, disk3_info_data.sel_drive, 3), },
|
||||
{ HRDATA (MODE, disk3_info_data.mode, 8), },
|
||||
{ HRDATA (RETRIES, disk3_info_data.retries, 8), },
|
||||
{ HRDATA (NDRIVES, disk3_info_data.ndrives, 8), },
|
||||
{ HRDATA (LINK_ADDR, disk3_info_data.link_addr, 32), },
|
||||
{ HRDATA (DMA_ADDR, disk3_info_data.dma_addr, 32), },
|
||||
{ BRDATA (IOPB, &disk3_info_data.iopb[DISK3_IOPB_CMD], 16, 8, 16), },
|
||||
{ DRDATAD (NTRACKS, ntracks, 10,
|
||||
"Number of tracks"), },
|
||||
{ DRDATAD (NHEADS, nheads, 8,
|
||||
"Number of heads"), },
|
||||
{ DRDATAD (NSECTORS, nsectors, 8,
|
||||
"Number of sectors per track"), },
|
||||
{ DRDATAD (SECTSIZE, sectsize, 11,
|
||||
"Sector size not including pre/postamble"), },
|
||||
{ HRDATAD (SEL_DRIVE, disk3_info_data.sel_drive, 3,
|
||||
"Currently selected drive"), },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
#define DISK3_NAME "Compupro ST-506 Disk Controller DISK3"
|
||||
|
||||
static MTAB disk3_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_DISK3_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_DISK3_WLK, UNIT_DISK3_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB disk3_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "SPECIFY",SPECIFY_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "IRQ", IRQ_MSG, "IRQ messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ "SPECIFY", SPECIFY_MSG, "Specify messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -257,7 +266,7 @@ DEVICE disk3_dev = {
|
|||
NULL, NULL, &disk3_reset,
|
||||
NULL, &disk3_attach, &disk3_detach,
|
||||
&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 */
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
#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_DSK_VERBOSE (1 << UNIT_V_DSK_VERBOSE)
|
||||
#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 */
|
||||
static int32 current_disk = NUM_OF_DSK;
|
||||
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 warnDSK11 = 0;
|
||||
|
||||
|
@ -84,23 +81,29 @@ static UNIT fif_unit[] = {
|
|||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }
|
||||
};
|
||||
|
||||
#define FIF_NAME "IMSAI FIF"
|
||||
|
||||
static REG fif_reg[] = {
|
||||
{ DRDATA (DISK, current_disk, 4) },
|
||||
{ DRDATA (DSKWL, warnLevelDSK, 32) },
|
||||
{ BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
|
||||
{ DRDATA (WARNDSK11, warnDSK11, 4), REG_RO },
|
||||
{ DRDATAD (DISK, current_disk, 4,
|
||||
"Current selected disk") },
|
||||
{ DRDATAD (DSKWL, warnLevelDSK, 32,
|
||||
"Warn level register") },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
static MTAB fif_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_DSK_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_DSK_WLK, UNIT_DSK_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
|
@ -110,15 +113,13 @@ DEVICE fif_dev = {
|
|||
NULL, NULL, &fif_reset,
|
||||
NULL, NULL, NULL,
|
||||
&fif_info_data, (DEV_DISABLE | DEV_DIS), 0,
|
||||
NULL, NULL, "IMSAI FIF"
|
||||
NULL, NULL, FIF_NAME
|
||||
};
|
||||
|
||||
static void resetDSKWarningFlags(void) {
|
||||
int32 i;
|
||||
for (i = 0; i < NUM_OF_DSK; i++) {
|
||||
warnLock[i] = 0;
|
||||
for (i = 0; i < NUM_OF_DSK; i++)
|
||||
warnAttached[i] = 0;
|
||||
}
|
||||
warnDSK11 = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,7 @@
|
|||
#define CMD_MSG (1 << 2)
|
||||
#define RD_DATA_MSG (1 << 3)
|
||||
#define WR_DATA_MSG (1 << 4)
|
||||
#define STATUS_MSG (1 << 5)
|
||||
#define VERBOSE_MSG (1 << 7)
|
||||
#define VERBOSE_MSG (1 << 5)
|
||||
|
||||
#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;
|
||||
|
||||
extern uint32 PCX;
|
||||
extern REG *sim_PC;
|
||||
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 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 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_HDC1001_VERBOSE (1 << UNIT_V_HDC1001_VERBOSE)
|
||||
#define HDC1001_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||
|
@ -133,26 +129,28 @@ static REG hdc1001_reg[] = {
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
#define HDC1001_NAME "ADC Hard Disk Controller HDC1001"
|
||||
|
||||
static MTAB hdc1001_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_HDC1001_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_HDC1001_WLK, UNIT_HDC1001_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB hdc1001_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -162,7 +160,7 @@ DEVICE hdc1001_dev = {
|
|||
NULL, NULL, &hdc1001_reset,
|
||||
NULL, &hdc1001_attach, &hdc1001_detach,
|
||||
&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 */
|
||||
|
|
|
@ -58,11 +58,10 @@
|
|||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define TRACE_MSG (1 << 1)
|
||||
#define RXIRQ_MSG (1 << 2)
|
||||
#define TXIRQ_MSG (1 << 3)
|
||||
#define UART_MSG (1 << 4)
|
||||
#define USER_MSG (1 << 5)
|
||||
#define RXIRQ_MSG (1 << 1)
|
||||
#define TXIRQ_MSG (1 << 2)
|
||||
#define UART_MSG (1 << 3)
|
||||
#define USER_MSG (1 << 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 REG if3_reg[] = {
|
||||
{ HRDATA (USER, if3_user, 3), },
|
||||
{ HRDATA (BOARD, if3_board, 2), },
|
||||
{ BRDATA (RIMR, &if3_rimr[0], 16, 8, 4), },
|
||||
{ BRDATA (RISR, &if3_risr[0], 16, 8, 4), },
|
||||
{ BRDATA (TIMR, &if3_timr[0], 16, 8, 4), },
|
||||
{ BRDATA (TISR, &if3_tisr[0], 16, 8, 4), },
|
||||
{ HRDATAD (USER, if3_user, 3, "IF3 user register"), },
|
||||
{ HRDATAD (BOARD, if3_board, 2, "IF3 board register"), },
|
||||
{ BRDATAD (RIMR, &if3_rimr[0], 16, 8, 4, "IF3 RIMR register array"), },
|
||||
{ BRDATAD (RISR, &if3_risr[0], 16, 8, 4, "IF3 RISR register array"), },
|
||||
{ BRDATAD (TIMR, &if3_timr[0], 16, 8, 4, "IF3 TIMR register array"), },
|
||||
{ BRDATAD (TISR, &if3_tisr[0], 16, 8, 4, "IF3 TISR register array"), },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
#define IF3_NAME "Compupro Interfacer 3 IF3"
|
||||
|
||||
static MTAB if3_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_IF3_CONNECT, UNIT_IF3_CONNECT,"INSTALLED", "INSTALLED", &set_if3_connect, NULL, NULL },
|
||||
{ UNIT_IF3_CONNECT, 0, "UNINSTALLED","UNINSTALLED", &set_if3_connect, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB if3_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "TRACE", TRACE_MSG },
|
||||
{ "RXIRQ", RXIRQ_MSG },
|
||||
{ "TXIRQ", TXIRQ_MSG },
|
||||
{ "UART", UART_MSG },
|
||||
{ "USER", USER_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "RXIRQ", RXIRQ_MSG, "RX IRQ messages" },
|
||||
{ "TXIRQ", TXIRQ_MSG, "TX IRQ messages" },
|
||||
{ "UART", UART_MSG, "UART messages" },
|
||||
{ "USER", USER_MSG, "User messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -143,7 +146,7 @@ DEVICE if3_dev = {
|
|||
NULL, NULL, &if3_reset,
|
||||
NULL, NULL, NULL,
|
||||
&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)
|
||||
|
|
|
@ -54,11 +54,10 @@
|
|||
#endif
|
||||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define SEEK_MSG (1 << 1)
|
||||
#define RD_DATA_MSG (1 << 3)
|
||||
#define WR_DATA_MSG (1 << 4)
|
||||
#define VERBOSE_MSG (1 << 7)
|
||||
#define SEEK_MSG (1 << 0)
|
||||
#define RD_DATA_MSG (1 << 1)
|
||||
#define WR_DATA_MSG (1 << 2)
|
||||
#define VERBOSE_MSG (1 << 3)
|
||||
|
||||
#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,
|
||||
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_MDRIVEH_WLK (1 << UNIT_V_MDRIVEH_WLK)
|
||||
#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 }
|
||||
};
|
||||
|
||||
#define MDRIVEH_NAME "Compupro Memory Drive MDRIVEH"
|
||||
|
||||
static MTAB mdriveh_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_MDRIVEH_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_MDRIVEH_WLK, UNIT_MDRIVEH_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
{ 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 */
|
||||
{ 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB mdriveh_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -133,8 +138,8 @@ DEVICE mdriveh_dev = {
|
|||
MDRIVEH_MAX_DRIVES, 10, 31, 1, MDRIVEH_MAX_DRIVES, MDRIVEH_MAX_DRIVES,
|
||||
NULL, NULL, &mdriveh_reset,
|
||||
NULL, NULL, NULL,
|
||||
&mdriveh_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG,
|
||||
mdriveh_dt, NULL, "Compupro Memory Drive MDRIVEH"
|
||||
&mdriveh_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0,
|
||||
mdriveh_dt, NULL, MDRIVEH_NAME
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -62,16 +62,14 @@
|
|||
#define WR_DATA_MSG (1 << 4)
|
||||
#define STATUS_MSG (1 << 5)
|
||||
#define ORDERS_MSG (1 << 6)
|
||||
#define VERBOSE_MSG (1 << 7)
|
||||
#define RD_DATA_DETAIL_MSG (1 << 8)
|
||||
#define WR_DATA_DETAIL_MSG (1 << 9)
|
||||
#define RD_DATA_DETAIL_MSG (1 << 7)
|
||||
#define WR_DATA_DETAIL_MSG (1 << 8)
|
||||
|
||||
extern uint32 PCX;
|
||||
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 uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
||||
int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
|
||||
extern REG *sim_PC;
|
||||
|
||||
#define MDSAD_MAX_DRIVES 4
|
||||
#define MDSAD_SECTOR_LEN 512
|
||||
|
@ -156,8 +154,6 @@ static MDSAD_INFO *mdsad_info = &mdsad_info_data;
|
|||
|
||||
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_MDSAD_VERBOSE (1 << UNIT_V_MDSAD_VERBOSE)
|
||||
#define MDSAD_CAPACITY (70*10*MDSAD_SECTOR_LEN) /* Default North Star Disk Capacity */
|
||||
|
@ -232,29 +228,31 @@ static REG mdsad_reg[] = {
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
#define MDSAD_NAME "North Star Floppy Controller MDSAD"
|
||||
|
||||
static MTAB mdsad_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL },
|
||||
{ UNIT_MDSAD_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_MDSAD_WLK, UNIT_MDSAD_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
|
||||
&set_membase, &show_membase, NULL, "Sets disk controller memory base address" },
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB mdsad_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "ORDERS", ORDERS_MSG },
|
||||
{ "RDDETAIL", RD_DATA_DETAIL_MSG },
|
||||
{ "WRDETAIL", WR_DATA_DETAIL_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ "ORDERS", ORDERS_MSG, "Orders messages" },
|
||||
{ "RDDETAIL", RD_DATA_DETAIL_MSG, "Read detail messages" },
|
||||
{ "WRDETAIL", WR_DATA_DETAIL_MSG, "Write detail messags" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -54,13 +54,9 @@
|
|||
#endif
|
||||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define PIO_MSG (1 << 1)
|
||||
#define UART_MSG (1 << 2)
|
||||
#define RTC_MSG (1 << 3)
|
||||
#define ROM_MSG (1 << 5)
|
||||
#define VERBOSE_MSG (1 << 7)
|
||||
#define IRQ_MSG (1 << 8)
|
||||
#define UART_MSG (1 << 0)
|
||||
#define ROM_MSG (1 << 1)
|
||||
#define VERBOSE_MSG (1 << 2)
|
||||
|
||||
#define SCP300F_MAX_DRIVES 1
|
||||
#define SCP300F_ROM_SIZE (2048)
|
||||
|
@ -69,9 +65,6 @@
|
|||
#define SCP300F_IO_SIZE (16)
|
||||
#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 {
|
||||
PNP_INFO pnp; /* Plug and Play */
|
||||
uint8 *ram;
|
||||
|
@ -106,29 +99,23 @@ static UNIT scp300f_unit[] = {
|
|||
};
|
||||
|
||||
static REG scp300f_reg[] = {
|
||||
{ HRDATA (SR, scp300f_sr, 8), },
|
||||
{ HRDATAD (SR, scp300f_sr, 8, "Sense switch register, 0=monitor prompt, 1=disk boot"), },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static MTAB scp300f_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE", &set_membase, &show_membase, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
/* quiet, no warning messages */
|
||||
{ UNIT_SCP300F_VERBOSE, 0, "QUIET", "QUIET", NULL },
|
||||
/* verbose, show warning messages */
|
||||
{ UNIT_SCP300F_VERBOSE, UNIT_SCP300F_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "MEMBASE", "MEMBASE",
|
||||
&set_membase, &show_membase, NULL, "Sets support module memory base address" },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets support module I/O base address" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB scp300f_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "PIO", PIO_MSG },
|
||||
{ "UART", UART_MSG },
|
||||
{ "RTC", RTC_MSG },
|
||||
{ "ROM", ROM_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "UART", UART_MSG, "UART messages" },
|
||||
{ "ROM", ROM_MSG, "ROM messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -138,7 +125,7 @@ DEVICE scp300f_dev = {
|
|||
SCP300F_MAX_DRIVES, 10, 31, 1, SCP300F_MAX_DRIVES, SCP300F_MAX_DRIVES,
|
||||
NULL, NULL, &scp300f_reset,
|
||||
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"
|
||||
};
|
||||
|
||||
|
|
|
@ -54,15 +54,11 @@
|
|||
#endif
|
||||
|
||||
/* Debug flags */
|
||||
#define ERROR_MSG (1 << 0)
|
||||
#define VERBOSE_MSG (1 << 1)
|
||||
#define DMA_MSG (1 << 2)
|
||||
#define VERBOSE_MSG (1 << 0)
|
||||
#define DMA_MSG (1 << 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 {
|
||||
PNP_INFO pnp; /* Plug and Play */
|
||||
uint32 selchan; /* Selector Channel Register */
|
||||
|
@ -95,25 +91,21 @@ static UNIT selchan_unit[] = {
|
|||
};
|
||||
|
||||
static REG selchan_reg[] = {
|
||||
{ HRDATA (DMA_MODE, selchan_info_data.dma_mode, 8), },
|
||||
{ HRDATA (DMA_ADDR, selchan_info_data.dma_addr, 24), },
|
||||
{ HRDATAD (DMA_MODE, selchan_info_data.dma_mode, 8, "DMA mode register"), },
|
||||
{ HRDATAD (DMA_ADDR, selchan_info_data.dma_addr, 24, "DMA transfer address register"), },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static MTAB selchan_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
/* quiet, no warning messages */
|
||||
{ UNIT_SELCHAN_VERBOSE, 0, "QUIET", "QUIET", NULL },
|
||||
/* verbose, show warning messages */
|
||||
{ UNIT_SELCHAN_VERBOSE, UNIT_SELCHAN_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL,
|
||||
"Sets disk controller I/O base address" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB selchan_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "DMA", DMA_MSG },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ "DMA", DMA_MSG, "DMA messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -122,7 +114,7 @@ DEVICE selchan_dev = {
|
|||
SELCHAN_MAX_DRIVES, 10, 31, 1, SELCHAN_MAX_DRIVES, SELCHAN_MAX_DRIVES,
|
||||
NULL, NULL, &selchan_reset,
|
||||
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"
|
||||
};
|
||||
|
||||
|
|
|
@ -177,46 +177,47 @@ static UNIT ss1_unit[] = {
|
|||
};
|
||||
|
||||
static REG ss1_reg[] = {
|
||||
{ HRDATA (MPIC_IMR, ss1_pic[MASTER_PIC].IMR, 8), },
|
||||
{ HRDATA (MPIC_IRR, ss1_pic[MASTER_PIC].IRR, 8), },
|
||||
{ HRDATA (MPIC_ISR, ss1_pic[MASTER_PIC].ISR, 8), },
|
||||
{ HRDATA (MPIC_OCW2, ss1_pic[MASTER_PIC].OCW2, 8), },
|
||||
{ HRDATA (MPIC_OCW3, ss1_pic[MASTER_PIC].OCW3, 8), },
|
||||
{ HRDATAD (MPIC_IMR, ss1_pic[MASTER_PIC].IMR, 8, "Master IMR register"), },
|
||||
{ HRDATAD (MPIC_IRR, ss1_pic[MASTER_PIC].IRR, 8, "Master IRR register"), },
|
||||
{ HRDATAD (MPIC_ISR, ss1_pic[MASTER_PIC].ISR, 8, "Master ISR register"), },
|
||||
{ HRDATAD (MPIC_OCW2, ss1_pic[MASTER_PIC].OCW2, 8, "Master OCW2 register"), },
|
||||
{ HRDATAD (MPIC_OCW3, ss1_pic[MASTER_PIC].OCW3, 8, "Master OCW3 register"), },
|
||||
|
||||
{ HRDATA (SPIC_IMR, ss1_pic[SLAVE_PIC].IMR, 8), },
|
||||
{ HRDATA (SPIC_IRR, ss1_pic[SLAVE_PIC].IRR, 8), },
|
||||
{ HRDATA (SPIC_ISR, ss1_pic[SLAVE_PIC].ISR, 8), },
|
||||
{ HRDATA (SPIC_OCW2, ss1_pic[SLAVE_PIC].OCW2, 8), },
|
||||
{ HRDATA (SPIC_OCW3, ss1_pic[SLAVE_PIC].OCW3, 8), },
|
||||
{ HRDATAD (SPIC_IMR, ss1_pic[SLAVE_PIC].IMR, 8, "Slave IMR register"), },
|
||||
{ HRDATAD (SPIC_IRR, ss1_pic[SLAVE_PIC].IRR, 8, "Slave IRR register"), },
|
||||
{ HRDATAD (SPIC_ISR, ss1_pic[SLAVE_PIC].ISR, 8, "Slave ISR register"), },
|
||||
{ HRDATAD (SPIC_OCW2, ss1_pic[SLAVE_PIC].OCW2, 8, "Slave OCW2 register"), },
|
||||
{ HRDATAD (SPIC_OCW3, ss1_pic[SLAVE_PIC].OCW3, 8, "Slave OCW3 register"), },
|
||||
|
||||
{ HRDATA (T0_MODE, ss1_tc[0].mode, 3), },
|
||||
{ HRDATA (T0_COUNT, ss1_tc[0].count, 16), },
|
||||
{ HRDATA (T1_MODE, ss1_tc[1].mode, 3), },
|
||||
{ HRDATA (T1_COUNT, ss1_tc[1].count, 16), },
|
||||
{ HRDATA (T2_MODE, ss1_tc[2].mode, 3), },
|
||||
{ HRDATA (T2_COUNT, ss1_tc[2].count, 16), },
|
||||
{ HRDATAD (T0_MODE, ss1_tc[0].mode, 3, "Timer 0 mode register"), },
|
||||
{ HRDATAD (T0_COUNT, ss1_tc[0].count, 16, "Timer 0 count register"), },
|
||||
{ HRDATAD (T1_MODE, ss1_tc[1].mode, 3, "Timer 1 mode register"), },
|
||||
{ HRDATAD (T1_COUNT, ss1_tc[1].count, 16, "Timer 1 count register"), },
|
||||
{ HRDATAD (T2_MODE, ss1_tc[2].mode, 3, "Timer 2 mode register"), },
|
||||
{ HRDATAD (T2_COUNT, ss1_tc[2].count, 16, "Timer 2 count register"), },
|
||||
|
||||
{ HRDATA (RTC_DIGIT, ss1_rtc[0].digit_sel, 4), },
|
||||
{ HRDATA (RTC_FLAGS, ss1_rtc[0].flags, 4), },
|
||||
{ HRDATAD (RTC_DIGIT, ss1_rtc[0].digit_sel, 4, "Digit selector register"), },
|
||||
{ HRDATAD (RTC_FLAGS, ss1_rtc[0].flags, 4, "Flags register"), },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB ss1_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "TRACE", TRACE_MSG },
|
||||
{ "PIC", PIC_MSG },
|
||||
{ "TC", TC_MSG },
|
||||
{ "RTC", RTC_MSG },
|
||||
{ "MATH", MATH_MSG },
|
||||
{ "UART", UART_MSG },
|
||||
{ "IRQ", IRQ_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "TRACE", TRACE_MSG, "Trace messages" },
|
||||
{ "PIC", PIC_MSG, "PIC messages" },
|
||||
{ "TC", TC_MSG, "TC messages" },
|
||||
{ "RTC", RTC_MSG, "RTC messages" },
|
||||
{ "MATH", MATH_MSG, "Math messages" },
|
||||
{ "UART", UART_MSG, "UART messages" },
|
||||
{ "IRQ", IRQ_MSG, "IRQ messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
#define RD_DATA_MSG (1 << 3)
|
||||
#define WR_DATA_MSG (1 << 4)
|
||||
#define STATUS_MSG (1 << 5)
|
||||
#define ORDERS_MSG (1 << 7)
|
||||
|
||||
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,
|
||||
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_VFDHD_VERBOSE (1 << UNIT_V_VFDHD_VERBOSE)
|
||||
#define VFDHD_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||
|
@ -166,30 +163,32 @@ static UNIT vfdhd_unit[] = {
|
|||
};
|
||||
|
||||
static REG vfdhd_reg[] = {
|
||||
{ DRDATA (HDSIZE, hdSize, 10), },
|
||||
{ DRDATAD (HDSIZE, hdSize, 10, "Size register"), },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
#define VFDHD_NAME "Vector Graphic FD-HD Controller VFDHD"
|
||||
|
||||
static MTAB vfdhd_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_VFDHD_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_VFDHD_WLK, UNIT_VFDHD_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
/* 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB vfdhd_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "ORDERS", ORDERS_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -199,7 +198,7 @@ DEVICE vfdhd_dev = {
|
|||
NULL, NULL, &vfdhd_reset,
|
||||
NULL, &vfdhd_attach, &vfdhd_detach,
|
||||
&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 */
|
||||
|
|
|
@ -208,27 +208,34 @@ static UNIT wd179x_unit[] = {
|
|||
{ 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[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },
|
||||
{ UNIT_WD179X_WLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_WD179X_WLK, UNIT_WD179X_WLK, "WRTLCK", "WRTLCK", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE",
|
||||
&set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" },
|
||||
{ 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 */
|
||||
{ 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 */
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/* Debug Flags */
|
||||
static DEBTAB wd179x_dt[] = {
|
||||
{ "ERROR", ERROR_MSG },
|
||||
{ "SEEK", SEEK_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "RDDATA", RD_DATA_MSG },
|
||||
{ "WRDATA", WR_DATA_MSG },
|
||||
{ "STATUS", STATUS_MSG },
|
||||
{ "FMT", FMT_MSG },
|
||||
{ "VERBOSE",VERBOSE_MSG },
|
||||
{ "ERROR", ERROR_MSG, "Error messages" },
|
||||
{ "SEEK", SEEK_MSG, "Seek messages" },
|
||||
{ "CMD", CMD_MSG, "Command messages" },
|
||||
{ "READ", RD_DATA_MSG, "Read messages" },
|
||||
{ "WRITE", WR_DATA_MSG, "Write messages" },
|
||||
{ "STATUS", STATUS_MSG, "Status messages" },
|
||||
{ "FMT", FMT_MSG, "Format messages" },
|
||||
{ "VERBOSE", VERBOSE_MSG, "Verbose messages" },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -238,7 +245,7 @@ DEVICE wd179x_dev = {
|
|||
NULL, NULL, &wd179x_reset,
|
||||
NULL, &wd179x_attach, &wd179x_detach,
|
||||
&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 */
|
||||
|
|
|
@ -201,6 +201,41 @@
|
|||
RelativePath="..\AltairZ80\altairz80_mhdsk.c"
|
||||
>
|
||||
</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
|
||||
RelativePath="..\AltairZ80\altairz80_net.c"
|
||||
>
|
||||
|
|
|
@ -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)WD179X.C,$(ALTAIRZ80_DIR)S100_DISK3.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))
|
||||
|
||||
#
|
||||
|
|
5
makefile
5
makefile
|
@ -1021,7 +1021,10 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
|
|||
${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \
|
||||
${ALTAIRZ80D}/s100_scp300f.c ${ALTAIRZ80D}/sim_imd.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}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue