Notes For V3.8
The makefile now works for Linux and most Unix's. However, for Solaris and MacOS, you must first export the OSTYPE environment variable: > export OSTYPE > make Otherwise, you will get build errors. 1. New Features 1.1 3.8-0 1.1.1 SCP and Libraries - BREAK, NOBREAK, and SHOW BREAK with no argument will set, clear, and show (respectively) a breakpoint at the current PC. 1.1.2 GRI - Added support for the GRI-99 processor. 1.1.3 HP2100 - Added support for the BACI terminal interface. - Added support for RTE OS/VMA/EMA, SIGNAL, VIS firmware extensions. 1.1.4 Nova - Added support for 64KW memory (implemented in third-party CPU's). 1.1.5 PDP-11 - Added support for DC11, RC11, KE11A, KG11A. - Added modem control support for DL11. - Added ASCII character support for all 8b devices. 1.2 3.8-1 1.2.1 SCP and libraries - Added capability to set line connection order for terminal multiplexers. 1.2.2 HP2100 - Added support for 12620A/12936A privileged interrupt fence. - Added support for 12792C eight-channel asynchronous multiplexer. 1.3 3.8-2 1.3.1 1401 - Added "no rewind" option to magtape boot. 1.3.2 PDP-11 - Added RD32 support to RQ - Added debug support to RL 1.3.3 PDP-8 - Added FPP support (many thanks to Rick Murphy for debugging the code) 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h.
This commit is contained in:
parent
9c4779c061
commit
35eac703c3
55 changed files with 4948 additions and 760 deletions
|
@ -1,7 +1,7 @@
|
||||||
Notes For V3.8
|
Notes For V3.8
|
||||||
|
|
||||||
|
|
||||||
The makefile now works for Linux and most Unix's. Howevr, for Solaris
|
The makefile now works for Linux and most Unix's. However, for Solaris
|
||||||
and MacOS, you must first export the OSTYPE environment variable:
|
and MacOS, you must first export the OSTYPE environment variable:
|
||||||
|
|
||||||
> export OSTYPE
|
> export OSTYPE
|
||||||
|
@ -49,6 +49,21 @@ Otherwise, you will get build errors.
|
||||||
- Added support for 12620A/12936A privileged interrupt fence.
|
- Added support for 12620A/12936A privileged interrupt fence.
|
||||||
- Added support for 12792C eight-channel asynchronous multiplexer.
|
- Added support for 12792C eight-channel asynchronous multiplexer.
|
||||||
|
|
||||||
|
1.3 3.8-2
|
||||||
|
|
||||||
|
1.3.1 1401
|
||||||
|
|
||||||
|
- Added "no rewind" option to magtape boot.
|
||||||
|
|
||||||
|
1.3.2 PDP-11
|
||||||
|
|
||||||
|
- Added RD32 support to RQ
|
||||||
|
- Added debug support to RL
|
||||||
|
|
||||||
|
1.3.3 PDP-8
|
||||||
|
|
||||||
|
- Added FPP support (many thanks to Rick Murphy for debugging the code)
|
||||||
|
|
||||||
|
|
||||||
2. Bugs Fixed
|
2. Bugs Fixed
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altair_dsk.c: MITS Altair 88-DISK Simulator
|
/* altair_dsk.c: MITS Altair 88-DISK Simulator
|
||||||
|
|
||||||
Copyright (c) 1997-2005, Charles E. Owen
|
Copyright (c) 1997-2010, Charles E. Owen
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -325,6 +325,8 @@ int32 dsk12(int32 io, int32 data)
|
||||||
cur_sect[cur_disk]);*/
|
cur_sect[cur_disk]);*/
|
||||||
pos = DSK_TRACSIZE * cur_track[cur_disk];
|
pos = DSK_TRACSIZE * cur_track[cur_disk];
|
||||||
pos += DSK_SECTSIZE * cur_sect[cur_disk];
|
pos += DSK_SECTSIZE * cur_sect[cur_disk];
|
||||||
|
if ((uptr == NULL) || (uptr->fileref == NULL))
|
||||||
|
return 0;
|
||||||
rtn = fseek(uptr -> fileref, pos, 0);
|
rtn = fseek(uptr -> fileref, pos, 0);
|
||||||
rtn = fread(dskbuf, 137, 1, uptr -> fileref);
|
rtn = fread(dskbuf, 137, 1, uptr -> fileref);
|
||||||
cur_byte[cur_disk] = 1;
|
cur_byte[cur_disk] = 1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80)
|
/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80)
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -144,6 +144,8 @@ extern int32 simh_dev (const int32 port, const int32 io, const int32 data);
|
||||||
extern int32 sr_dev (const int32 port, const int32 io, const int32 data);
|
extern int32 sr_dev (const int32 port, const int32 io, const int32 data);
|
||||||
extern void install_ALTAIRbootROM(void);
|
extern void install_ALTAIRbootROM(void);
|
||||||
extern void do_SIMH_sleep(void);
|
extern void do_SIMH_sleep(void);
|
||||||
|
extern void prepareMemoryAccessMessage(const t_addr loc);
|
||||||
|
extern void prepareInstructionMessage(const t_addr loc, const uint32 op);
|
||||||
|
|
||||||
extern FILE *sim_deb;
|
extern FILE *sim_deb;
|
||||||
|
|
||||||
|
@ -1279,10 +1281,9 @@ static const uint8 cpTable[256] = {
|
||||||
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
|
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* remove comments to generate table contents and define globally NEED_SIM_VM_INIT
|
/* remove comments to generate table contents and add a call to
|
||||||
static void altairz80_init(void);
|
altairz80_print_tables in the altairz80_init
|
||||||
void (*sim_vm_init) (void) = &altairz80_init;
|
static void altairz80_print_tables(void) {
|
||||||
static void altairz80_init(void) {
|
|
||||||
*/
|
*/
|
||||||
/* parityTable */
|
/* parityTable */
|
||||||
/*
|
/*
|
||||||
|
@ -1591,7 +1592,7 @@ uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
||||||
printf("%s memory 0x%05x, handler=%p\n", unmap ? "Unmapping" : " Mapping",
|
printf("%s memory 0x%05x, handler=%p\n", unmap ? "Unmapping" : " Mapping",
|
||||||
addr, routine);
|
addr, routine);
|
||||||
if (unmap) {
|
if (unmap) {
|
||||||
if (mmu_table[page].routine == routine) /* unmap only if it was mapped */
|
if (mmu_table[page].routine == routine) { /* unmap only if it was mapped */
|
||||||
if (MEMORYSIZE < MAXBANKSIZE)
|
if (MEMORYSIZE < MAXBANKSIZE)
|
||||||
if (addr < MEMORYSIZE)
|
if (addr < MEMORYSIZE)
|
||||||
mmu_table[page] = RAM_PAGE;
|
mmu_table[page] = RAM_PAGE;
|
||||||
|
@ -1600,6 +1601,7 @@ uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
||||||
else
|
else
|
||||||
mmu_table[page] = RAM_PAGE;
|
mmu_table[page] = RAM_PAGE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
mmu_table[page] = ROM_PAGE;
|
mmu_table[page] = ROM_PAGE;
|
||||||
mmu_table[page].routine = routine;
|
mmu_table[page].routine = routine;
|
||||||
|
@ -1785,44 +1787,32 @@ static int32 sim_brk_lookup (const t_addr loc, const int32 btyp) {
|
||||||
return (sim_brk_pend[0] && (loc == sim_brk_ploc[0])) ? MASK_BRK : FALSE;
|
return (sim_brk_pend[0] && (loc == sim_brk_ploc[0])) ? MASK_BRK : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepareMemoryAccessMessage(t_addr loc) {
|
|
||||||
extern char memoryAccessMessage[];
|
|
||||||
sprintf(memoryAccessMessage, "Memory access breakpoint [%05xh]", loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PUSH(x) { \
|
#define PUSH(x) { \
|
||||||
MM_PUT_BYTE(SP, (x) >> 8); \
|
MM_PUT_BYTE(SP, (x) >> 8); \
|
||||||
MM_PUT_BYTE(SP, x); \
|
MM_PUT_BYTE(SP, x); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_BREAK_BYTE(a) \
|
#define CHECK_BREAK_BYTE(a) \
|
||||||
if (sim_brk_summ && sim_brk_test((a) & 0xffff, SWMASK('M'))) { \
|
if (sim_brk_summ) { \
|
||||||
|
if (sim_brk_test((a) & 0xffff, SWMASK('M'))) { \
|
||||||
reason = STOP_MEM; \
|
reason = STOP_MEM; \
|
||||||
prepareMemoryAccessMessage((a) & 0xffff); \
|
prepareMemoryAccessMessage((a) & 0xffff); \
|
||||||
goto end_decode; \
|
goto end_decode; \
|
||||||
|
} \
|
||||||
|
sim_brk_pend[0] = FALSE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_BREAK_TWO_BYTES_EXTENDED(a1, a2, iCode) \
|
#define CHECK_BREAK_TWO_BYTES_EXTENDED(a1, a2, iCode) \
|
||||||
if (sim_brk_summ) { \
|
if (sim_brk_summ) { \
|
||||||
br1 = sim_brk_lookup((a1) & 0xffff, SWMASK('M')); \
|
int32 brl = sim_brk_lookup((a1) & 0xffff, SWMASK('M')); \
|
||||||
br2 = br1 ? FALSE : sim_brk_lookup((a2) & 0xffff, SWMASK('M'));\
|
if ((brl == TRUE) || (brl == FALSE) && (sim_brk_lookup((a2) \
|
||||||
if ((br1 == MASK_BRK) || (br2 == MASK_BRK)) { \
|
& 0xffff, SWMASK('M')) == TRUE)) { \
|
||||||
sim_brk_pend[0] = FALSE; \
|
|
||||||
} \
|
|
||||||
else if (br1 || br2) { \
|
|
||||||
reason = STOP_MEM; \
|
reason = STOP_MEM; \
|
||||||
if (br1) { \
|
prepareMemoryAccessMessage((brl ? (a1):(a2)) & 0xffff); \
|
||||||
prepareMemoryAccessMessage((a1) & 0xffff); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
prepareMemoryAccessMessage((a2) & 0xffff); \
|
|
||||||
} \
|
|
||||||
iCode; \
|
iCode; \
|
||||||
goto end_decode; \
|
goto end_decode; \
|
||||||
} \
|
} \
|
||||||
else { \
|
|
||||||
sim_brk_pend[0] = FALSE; \
|
sim_brk_pend[0] = FALSE; \
|
||||||
} \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_BREAK_TWO_BYTES(a1, a2) CHECK_BREAK_TWO_BYTES_EXTENDED(a1, a2,;)
|
#define CHECK_BREAK_TWO_BYTES(a1, a2) CHECK_BREAK_TWO_BYTES_EXTENDED(a1, a2,;)
|
||||||
|
@ -1908,7 +1898,7 @@ static t_stat sim_instr_mmu (void) {
|
||||||
register uint32 tStates;
|
register uint32 tStates;
|
||||||
uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */
|
uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */
|
||||||
uint32 startTime, now;
|
uint32 startTime, now;
|
||||||
int32 br1, br2, tStateModifier = FALSE;
|
int32 tStateModifier = FALSE;
|
||||||
|
|
||||||
switch_cpu_now = TRUE; /* hharte */
|
switch_cpu_now = TRUE; /* hharte */
|
||||||
|
|
||||||
|
@ -1991,12 +1981,13 @@ static t_stat sim_instr_mmu (void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sim_brk_summ) {
|
if (sim_brk_summ) {
|
||||||
if (sim_brk_lookup(PC, SWMASK('E')) == TRUE) { /* breakpoint? */
|
if (sim_brk_test(PC, (2u << SIM_BKPT_V_SPC) | SWMASK('E'))) { /* breakpoint? */
|
||||||
reason = STOP_IBKPT; /* stop simulation */
|
reason = STOP_IBKPT; /* stop simulation */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sim_brk_test(GetBYTE(PC), (1u << SIM_BKPT_V_SPC) | SWMASK('I'))) { /* instruction breakpoint? */
|
if (sim_brk_test(GetBYTE(PC), (1u << SIM_BKPT_V_SPC) | SWMASK('I'))) { /* instruction breakpoint? */
|
||||||
reason = STOP_IBKPT; /* stop simulation */
|
reason = STOP_INSTR; /* stop simulation */
|
||||||
|
prepareInstructionMessage(PC, GetBYTE(PC));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3826,7 +3817,7 @@ static t_stat sim_instr_mmu (void) {
|
||||||
|
|
||||||
case 0xdd: /* DD prefix */
|
case 0xdd: /* DD prefix */
|
||||||
CHECK_CPU_8080;
|
CHECK_CPU_8080;
|
||||||
switch (op = RAM_PP(PC)) {
|
switch (RAM_PP(PC)) {
|
||||||
|
|
||||||
case 0x09: /* ADD IX,BC */
|
case 0x09: /* ADD IX,BC */
|
||||||
tStates += 15;
|
tStates += 15;
|
||||||
|
@ -4712,7 +4703,7 @@ static t_stat sim_instr_mmu (void) {
|
||||||
|
|
||||||
case 0xed: /* ED prefix */
|
case 0xed: /* ED prefix */
|
||||||
CHECK_CPU_8080;
|
CHECK_CPU_8080;
|
||||||
switch (op = RAM_PP(PC)) {
|
switch (RAM_PP(PC)) {
|
||||||
|
|
||||||
case 0x40: /* IN B,(C) */
|
case 0x40: /* IN B,(C) */
|
||||||
tStates += 12;
|
tStates += 12;
|
||||||
|
@ -5205,7 +5196,6 @@ static t_stat sim_instr_mmu (void) {
|
||||||
|
|
||||||
case 0xb0: /* LDIR */
|
case 0xb0: /* LDIR */
|
||||||
tStates -= 5;
|
tStates -= 5;
|
||||||
acu = HIGH_REGISTER(AF);
|
|
||||||
BC &= ADDRMASK;
|
BC &= ADDRMASK;
|
||||||
if (BC == 0)
|
if (BC == 0)
|
||||||
BC = 0x10000;
|
BC = 0x10000;
|
||||||
|
@ -5456,7 +5446,7 @@ static t_stat sim_instr_mmu (void) {
|
||||||
|
|
||||||
case 0xfd: /* FD prefix */
|
case 0xfd: /* FD prefix */
|
||||||
CHECK_CPU_8080;
|
CHECK_CPU_8080;
|
||||||
switch (op = RAM_PP(PC)) {
|
switch (RAM_PP(PC)) {
|
||||||
|
|
||||||
case 0x09: /* ADD IY,BC */
|
case 0x09: /* ADD IY,BC */
|
||||||
tStates += 15;
|
tStates += 15;
|
||||||
|
@ -6388,10 +6378,10 @@ static char *ramTypeToString[] = { "AZ80", "HRAM", "VRAM", "CRAM" };
|
||||||
static t_stat chip_show(FILE *st, UNIT *uptr, int32 val, void *desc) {
|
static t_stat chip_show(FILE *st, UNIT *uptr, int32 val, void *desc) {
|
||||||
fprintf(st, cpu_unit.flags & UNIT_CPU_OPSTOP ? "ITRAP, " : "NOITRAP, ");
|
fprintf(st, cpu_unit.flags & UNIT_CPU_OPSTOP ? "ITRAP, " : "NOITRAP, ");
|
||||||
if (chiptype <= MAX_CHIP_TYPE)
|
if (chiptype <= MAX_CHIP_TYPE)
|
||||||
fprintf(st, chipTypeToString[chiptype]);
|
fprintf(st, "%s", chipTypeToString[chiptype]);
|
||||||
fprintf(st, ", ");
|
fprintf(st, ", ");
|
||||||
if (ramtype <= MAX_RAM_TYPE)
|
if (ramtype <= MAX_RAM_TYPE)
|
||||||
fprintf(st, ramTypeToString[ramtype]);
|
fprintf(st, "%s", ramTypeToString[ramtype]);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6603,8 +6593,8 @@ static void cpu_set_chiptype_short(int32 value, uint32 need_cpu_clear) {
|
||||||
extern REG *sim_PC;
|
extern REG *sim_PC;
|
||||||
if ((chiptype == value) || (chiptype > MAX_CHIP_TYPE))
|
if ((chiptype == value) || (chiptype > MAX_CHIP_TYPE))
|
||||||
return; /* nothing to do */
|
return; /* nothing to do */
|
||||||
if ((chiptype == CHIP_TYPE_8080) && (value == CHIP_TYPE_Z80) ||
|
if (((chiptype == CHIP_TYPE_8080) && (value == CHIP_TYPE_Z80)) ||
|
||||||
(chiptype == CHIP_TYPE_Z80) && (value == CHIP_TYPE_8080)) {
|
((chiptype == CHIP_TYPE_Z80) && (value == CHIP_TYPE_8080))) {
|
||||||
chiptype = value;
|
chiptype = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -6783,7 +6773,7 @@ static t_stat cpu_set_memory(UNIT *uptr, int32 value, char *cptr, void *desc) {
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
result = sscanf(cptr, "%i%n", &size, &i);
|
result = sscanf(cptr, "%i%n", &size, &i);
|
||||||
if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) ||
|
if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) ||
|
||||||
(cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))
|
((cptr[i + 1] == 'B') && (cptr[i + 2] == 0))))
|
||||||
return set_size(size);
|
return set_size(size);
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
}
|
}
|
||||||
|
@ -6791,6 +6781,7 @@ static t_stat cpu_set_memory(UNIT *uptr, int32 value, char *cptr, void *desc) {
|
||||||
/* AltairZ80 Simulator initialization */
|
/* AltairZ80 Simulator initialization */
|
||||||
void altairz80_init(void) {
|
void altairz80_init(void) {
|
||||||
cpu_clear();
|
cpu_clear();
|
||||||
|
/* altairz80_print_tables(); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*sim_vm_init) (void) = &altairz80_init;
|
void (*sim_vm_init) (void) = &altairz80_init;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_defs.h: MITS Altair simulator definitions
|
/* altairz80_defs.h: MITS Altair simulator definitions
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -57,7 +57,8 @@
|
||||||
#define STOP_HALT 0 /* HALT */
|
#define STOP_HALT 0 /* HALT */
|
||||||
#define STOP_IBKPT 1 /* breakpoint (program counter) */
|
#define STOP_IBKPT 1 /* breakpoint (program counter) */
|
||||||
#define STOP_MEM 2 /* breakpoint (memory access) */
|
#define STOP_MEM 2 /* breakpoint (memory access) */
|
||||||
#define STOP_OPCODE 3 /* invalid operation encountered (8080, Z80, 8086) */
|
#define STOP_INSTR 3 /* breakpoint (instruction access) */
|
||||||
|
#define STOP_OPCODE 4 /* invalid operation encountered (8080, Z80, 8086) */
|
||||||
|
|
||||||
#define UNIT_CPU_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid operation */
|
#define UNIT_CPU_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid operation */
|
||||||
#define UNIT_CPU_OPSTOP (1 << UNIT_CPU_V_OPSTOP)
|
#define UNIT_CPU_OPSTOP (1 << UNIT_CPU_V_OPSTOP)
|
||||||
|
@ -74,8 +75,11 @@
|
||||||
#define UNIT_CPU_V_SWITCHER (UNIT_V_UF+6) /* switcher 8086 <--> 8080/Z80 enabled */
|
#define UNIT_CPU_V_SWITCHER (UNIT_V_UF+6) /* switcher 8086 <--> 8080/Z80 enabled */
|
||||||
#define UNIT_CPU_SWITCHER (1 << UNIT_CPU_V_SWITCHER)
|
#define UNIT_CPU_SWITCHER (1 << UNIT_CPU_V_SWITCHER)
|
||||||
|
|
||||||
#define UNIX_PLATFORM (defined (__linux) || defined(__NetBSD__) \
|
#if defined (__linux) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__)
|
||||||
|| defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__))
|
#define UNIX_PLATFORM 1
|
||||||
|
#else
|
||||||
|
#define UNIX_PLATFORM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ADDRESS_FORMAT "[0x%05x]"
|
#define ADDRESS_FORMAT "[0x%05x]"
|
||||||
|
|
||||||
|
@ -86,7 +90,7 @@
|
||||||
#define NLP "\n"
|
#define NLP "\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (__MWERKS__) && defined (macintosh)
|
#if (defined (__MWERKS__) && defined (macintosh)) || defined(__DECC)
|
||||||
#define __FUNCTION__ __FILE__
|
#define __FUNCTION__ __FILE__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator
|
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -319,7 +319,7 @@ static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32 dskseek(const UNIT *xptr) {
|
static int32 dskseek(const UNIT *xptr) {
|
||||||
return fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] +
|
return sim_fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] +
|
||||||
DSK_SECTSIZE * current_sector[current_disk], SEEK_SET);
|
DSK_SECTSIZE * current_sector[current_disk], SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,9 +338,9 @@ static void writebuf(void) {
|
||||||
printf("DSK%i: " ADDRESS_FORMAT " fseek failed D%d T%d S%d" NLP, current_disk,
|
printf("DSK%i: " ADDRESS_FORMAT " fseek failed D%d T%d S%d" NLP, current_disk,
|
||||||
PCX, current_disk, current_track[current_disk], current_sector[current_disk]);
|
PCX, current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||||
}
|
}
|
||||||
rtn = fwrite(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref);
|
rtn = sim_fwrite(dskbuf, 1, DSK_SECTSIZE, uptr -> fileref);
|
||||||
if (rtn != 1) {
|
if (rtn != DSK_SECTSIZE) {
|
||||||
printf("DSK%i: " ADDRESS_FORMAT " fwrite failed T%d S%d Return=%d" NLP, current_disk,
|
printf("DSK%i: " ADDRESS_FORMAT " sim_fwrite failed T%d S%d Return=%d" NLP, current_disk,
|
||||||
PCX, current_track[current_disk], current_sector[current_disk], rtn);
|
PCX, current_track[current_disk], current_sector[current_disk], rtn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,7 +507,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
|
||||||
/* Disk Data In/Out */
|
/* Disk Data In/Out */
|
||||||
|
|
||||||
int32 dsk12(const int32 port, const int32 io, const int32 data) {
|
int32 dsk12(const int32 port, const int32 io, const int32 data) {
|
||||||
int32 i;
|
int32 i, rtn;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
if (current_disk >= NUM_OF_DSK) {
|
if (current_disk >= NUM_OF_DSK) {
|
||||||
|
@ -530,8 +530,21 @@ int32 dsk12(const int32 port, const int32 io, const int32 data) {
|
||||||
PCX, current_disk, current_track[current_disk], current_sector[current_disk]));
|
PCX, current_disk, current_track[current_disk], current_sector[current_disk]));
|
||||||
for (i = 0; i < DSK_SECTSIZE; i++)
|
for (i = 0; i < DSK_SECTSIZE; i++)
|
||||||
dskbuf[i] = 0;
|
dskbuf[i] = 0;
|
||||||
dskseek(uptr);
|
if (dskseek(uptr)) {
|
||||||
fread(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref);
|
if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) {
|
||||||
|
warnDSK12++;
|
||||||
|
printf("DSK%i: " ADDRESS_FORMAT " fseek error D%d T%d S%d" NLP, current_disk,
|
||||||
|
PCX, current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rtn = sim_fread(dskbuf, 1, DSK_SECTSIZE, uptr -> fileref);
|
||||||
|
if (rtn != DSK_SECTSIZE) {
|
||||||
|
if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) {
|
||||||
|
warnDSK12++;
|
||||||
|
printf("DSK%i: " ADDRESS_FORMAT " sim_fread error D%d T%d S%d" NLP, current_disk,
|
||||||
|
PCX, current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||||
|
}
|
||||||
|
}
|
||||||
current_byte[current_disk] = 0;
|
current_byte[current_disk] = 0;
|
||||||
}
|
}
|
||||||
return dskbuf[current_byte[current_disk]++] & 0xff;
|
return dskbuf[current_byte[current_disk]++] & 0xff;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_sio.c: MITS Altair serial I/O card
|
/* altairz80_sio.c: MITS Altair serial I/O card
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -105,8 +105,8 @@
|
||||||
|
|
||||||
#define PORT_TABLE_SIZE 256 /* size of port mapping table */
|
#define PORT_TABLE_SIZE 256 /* size of port mapping table */
|
||||||
#define SLEEP_ALLOWED_START_DEFAULT 100 /* default initial value for sleepAllowedCounter*/
|
#define SLEEP_ALLOWED_START_DEFAULT 100 /* default initial value for sleepAllowedCounter*/
|
||||||
|
#define DEFAULT_TIMER_DELTA 100 /* default value for timer delta in ms */
|
||||||
|
|
||||||
static t_stat sio_set_verbose (UNIT *uptr, int32 value, char *cptr, void *desc);
|
|
||||||
static t_stat simh_dev_set_timeron (UNIT *uptr, int32 value, char *cptr, void *desc);
|
static t_stat simh_dev_set_timeron (UNIT *uptr, int32 value, char *cptr, void *desc);
|
||||||
static t_stat simh_dev_set_timeroff (UNIT *uptr, int32 value, char *cptr, void *desc);
|
static t_stat simh_dev_set_timeroff (UNIT *uptr, int32 value, char *cptr, void *desc);
|
||||||
static t_stat sio_reset(DEVICE *dptr);
|
static t_stat sio_reset(DEVICE *dptr);
|
||||||
|
@ -154,6 +154,19 @@ extern UNIT cpu_unit;
|
||||||
extern volatile int32 stop_cpu;
|
extern volatile int32 stop_cpu;
|
||||||
extern int32 sim_interval;
|
extern int32 sim_interval;
|
||||||
|
|
||||||
|
#define TRACE_PRINT(device, level, args) if (device.dctrl & level) { \
|
||||||
|
printf args; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Debug Flags */
|
||||||
|
static DEBTAB generic_dt[] = {
|
||||||
|
{ "IN", IN_MSG },
|
||||||
|
{ "OUT", OUT_MSG },
|
||||||
|
{ "CMD", CMD_MSG },
|
||||||
|
{ "VERBOSE", VERBOSE_MSG },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
/* SIMH pseudo device status registers */
|
/* SIMH pseudo device status registers */
|
||||||
/* ZSDOS clock definitions */
|
/* ZSDOS clock definitions */
|
||||||
static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */
|
static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */
|
||||||
|
@ -168,12 +181,12 @@ static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parame
|
||||||
static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */
|
static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */
|
||||||
static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */
|
static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */
|
||||||
|
|
||||||
/* interrupt related */
|
/* timer interrupt related */
|
||||||
static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */
|
static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */
|
||||||
int32 timerInterrupt = FALSE; /* timer interrupt pending */
|
int32 timerInterrupt = FALSE; /* timer interrupt pending */
|
||||||
int32 timerInterruptHandler = 0x0fc00; /* default address of interrupt handling routine */
|
int32 timerInterruptHandler = 0x0fc00; /* default address of interrupt handling routine */
|
||||||
static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */
|
static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */
|
||||||
static int32 timerDelta = 100; /* interrupt every 100 ms */
|
static int32 timerDelta = DEFAULT_TIMER_DELTA; /* interrupt every 100 ms */
|
||||||
static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */
|
static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */
|
||||||
|
|
||||||
/* stop watch and timer related */
|
/* stop watch and timer related */
|
||||||
|
@ -270,7 +283,7 @@ static MTAB sio_mod[] = {
|
||||||
{ UNIT_SIO_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */
|
{ 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_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, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */
|
||||||
{ UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", &sio_set_verbose },
|
{ UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||||
/* verbose, display warning messages */
|
/* verbose, display warning messages */
|
||||||
{ UNIT_SIO_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */
|
{ 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_MAP, UNIT_SIO_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */
|
||||||
|
@ -291,12 +304,16 @@ DEVICE sio_dev = {
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &sio_reset,
|
NULL, NULL, &sio_reset,
|
||||||
NULL, &sio_attach, &sio_detach,
|
NULL, &sio_attach, &sio_detach,
|
||||||
NULL, 0, 0,
|
NULL, DEV_DEBUG, 0,
|
||||||
NULL, NULL, "Serial Input Output SIO"
|
generic_dt, NULL, "Serial Input Output SIO"
|
||||||
|
};
|
||||||
|
|
||||||
|
static MTAB ptpptr_mod[] = {
|
||||||
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static UNIT ptr_unit = {
|
static UNIT ptr_unit = {
|
||||||
UDATA (NULL, UNIT_SEQ | UNIT_ATTABLE | UNIT_ROABLE, 0)
|
UDATA (NULL, UNIT_ATTABLE | UNIT_ROABLE, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
static REG ptr_reg[] = {
|
static REG ptr_reg[] = {
|
||||||
|
@ -305,25 +322,25 @@ static REG ptr_reg[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE ptr_dev = {
|
DEVICE ptr_dev = {
|
||||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
"PTR", &ptr_unit, ptr_reg, ptpptr_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptr_reset,
|
NULL, NULL, &ptr_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, DEV_DISABLE, 0,
|
NULL, (DEV_DISABLE | DEV_DEBUG), 0,
|
||||||
NULL, NULL, "Paper Tape Reader PTR"
|
generic_dt, NULL, "Paper Tape Reader PTR"
|
||||||
};
|
};
|
||||||
|
|
||||||
static UNIT ptp_unit = {
|
static UNIT ptp_unit = {
|
||||||
UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0)
|
UDATA (NULL, UNIT_ATTABLE, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE ptp_dev = {
|
DEVICE ptp_dev = {
|
||||||
"PTP", &ptp_unit, NULL, NULL,
|
"PTP", &ptp_unit, NULL, ptpptr_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptp_reset,
|
NULL, NULL, &ptp_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, DEV_DISABLE, 0,
|
NULL, (DEV_DISABLE | DEV_DEBUG), 0,
|
||||||
NULL, NULL, "Paper Tape Puncher PTP"
|
generic_dt, NULL, "Paper Tape Puncher PTP"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Synthetic device SIMH for communication
|
/* Synthetic device SIMH for communication
|
||||||
|
@ -373,37 +390,19 @@ static MTAB simh_mod[] = {
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TRACE_PRINT(level, args) if (simh_device.dctrl & level) { \
|
|
||||||
printf args; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Debug Flags */
|
|
||||||
static DEBTAB simh_dt[] = {
|
|
||||||
{ "IN", IN_MSG },
|
|
||||||
{ "OUT", OUT_MSG },
|
|
||||||
{ "CMD", CMD_MSG },
|
|
||||||
{ "VERBOSE", VERBOSE_MSG },
|
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DEVICE simh_device = {
|
DEVICE simh_device = {
|
||||||
"SIMH", &simh_unit, simh_reg, simh_mod,
|
"SIMH", &simh_unit, simh_reg, simh_mod,
|
||||||
1, 10, 31, 1, 16, 4,
|
1, 10, 31, 1, 16, 4,
|
||||||
NULL, NULL, &simh_dev_reset,
|
NULL, NULL, &simh_dev_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, (DEV_DISABLE | DEV_DEBUG), 0,
|
NULL, (DEV_DISABLE | DEV_DEBUG), 0,
|
||||||
simh_dt, NULL, "Pseudo Device SIMH"
|
generic_dt, NULL, "Pseudo Device SIMH"
|
||||||
};
|
};
|
||||||
|
|
||||||
static void resetSIOWarningFlags(void) {
|
static void resetSIOWarningFlags(void) {
|
||||||
warnUnattachedPTP = warnUnattachedPTR = warnPTREOF = warnUnassignedPort = 0;
|
warnUnattachedPTP = warnUnattachedPTR = warnPTREOF = warnUnassignedPort = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) {
|
|
||||||
resetSIOWarningFlags();
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static t_stat sio_attach(UNIT *uptr, char *cptr) {
|
static t_stat sio_attach(UNIT *uptr, char *cptr) {
|
||||||
t_stat r = SCPE_IERR;
|
t_stat r = SCPE_IERR;
|
||||||
sio_unit.u3 = FALSE; /* no character in terminal input buffer */
|
sio_unit.u3 = FALSE; /* no character in terminal input buffer */
|
||||||
|
@ -439,6 +438,7 @@ static void pollConnection(void) {
|
||||||
/* reset routines */
|
/* reset routines */
|
||||||
static t_stat sio_reset(DEVICE *dptr) {
|
static t_stat sio_reset(DEVICE *dptr) {
|
||||||
int32 i;
|
int32 i;
|
||||||
|
TRACE_PRINT(sio_dev, VERBOSE_MSG, ("SIO: " ADDRESS_FORMAT " Reset" NLP, PCX));
|
||||||
sio_unit.u3 = FALSE; /* no character in terminal input buffer */
|
sio_unit.u3 = FALSE; /* no character in terminal input buffer */
|
||||||
resetSIOWarningFlags();
|
resetSIOWarningFlags();
|
||||||
if (sio_unit.u4) { /* is terminal input attached to a file? */
|
if (sio_unit.u4) { /* is terminal input attached to a file? */
|
||||||
|
@ -454,6 +454,7 @@ static t_stat sio_reset(DEVICE *dptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat ptr_reset(DEVICE *dptr) {
|
static t_stat ptr_reset(DEVICE *dptr) {
|
||||||
|
TRACE_PRINT(ptr_dev, VERBOSE_MSG, ("PTR: " ADDRESS_FORMAT " Reset" NLP, PCX));
|
||||||
resetSIOWarningFlags();
|
resetSIOWarningFlags();
|
||||||
ptr_unit.u3 = FALSE; /* End Of File not yet reached */
|
ptr_unit.u3 = FALSE; /* End Of File not yet reached */
|
||||||
if (ptr_unit.flags & UNIT_ATT) /* attached? */
|
if (ptr_unit.flags & UNIT_ATT) /* attached? */
|
||||||
|
@ -464,6 +465,7 @@ static t_stat ptr_reset(DEVICE *dptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat ptp_reset(DEVICE *dptr) {
|
static t_stat ptp_reset(DEVICE *dptr) {
|
||||||
|
TRACE_PRINT(ptp_dev, VERBOSE_MSG, ("PTP: " ADDRESS_FORMAT " Reset" NLP, PCX));
|
||||||
resetSIOWarningFlags();
|
resetSIOWarningFlags();
|
||||||
sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS);
|
sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS);
|
||||||
sim_map_resource(0x13, 1, RESOURCE_TYPE_IO, &sio1d, dptr->flags & DEV_DIS);
|
sim_map_resource(0x13, 1, RESOURCE_TYPE_IO, &sio1d, dptr->flags & DEV_DIS);
|
||||||
|
@ -625,17 +627,18 @@ static void voidSleep(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generic status port for keyboard input / terminal output */
|
/* generic status port for keyboard input / terminal output */
|
||||||
int32 sio0s(const int32 port, const int32 io, const int32 data) {
|
static int32 sio0sCore(const int32 port, const int32 io, const int32 data) {
|
||||||
int32 ch, result;
|
int32 ch, result;
|
||||||
SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
||||||
assert(spi.port == port);
|
assert(spi.port == port);
|
||||||
pollConnection();
|
pollConnection();
|
||||||
if (io == 0) { /* IN */
|
if (io == 0) { /* IN */
|
||||||
if (sio_unit.u4) /* attached to a file? */
|
if (sio_unit.u4) { /* attached to a file? */
|
||||||
if (sio_unit.u5) /* EOF reached? */
|
if (sio_unit.u5) /* EOF reached? */
|
||||||
sio_detach(&sio_unit); /* detach file and switch to keyboard input */
|
sio_detach(&sio_unit); /* detach file and switch to keyboard input */
|
||||||
else
|
else
|
||||||
return spi.sio_can_read | spi.sio_can_write;
|
return spi.sio_can_read | spi.sio_can_write;
|
||||||
|
}
|
||||||
if (sio_unit.flags & UNIT_ATT) { /* attached to a port? */
|
if (sio_unit.flags & UNIT_ATT) { /* attached to a port? */
|
||||||
if (tmxr_rqln(&TerminalLines[spi.terminalLine]))
|
if (tmxr_rqln(&TerminalLines[spi.terminalLine]))
|
||||||
result = spi.sio_can_read;
|
result = spi.sio_can_read;
|
||||||
|
@ -664,13 +667,25 @@ int32 sio0s(const int32 port, const int32 io, const int32 data) {
|
||||||
checkSleep();
|
checkSleep();
|
||||||
return spi.sio_can_write | spi.sio_cannot_read;
|
return spi.sio_can_write | spi.sio_cannot_read;
|
||||||
} /* OUT follows, no fall-through from IN */
|
} /* OUT follows, no fall-through from IN */
|
||||||
if (spi.hasReset && (data == spi.sio_reset)) /* reset command */
|
if (spi.hasReset && (data == spi.sio_reset)) { /* reset command */
|
||||||
sio_unit.u3 = FALSE; /* indicate that no character is available */
|
sio_unit.u3 = FALSE; /* indicate that no character is available */
|
||||||
|
TRACE_PRINT(sio_dev, CMD_MSG,
|
||||||
|
("SIO: " ADDRESS_FORMAT " Command OUT(0x%03x) = 0x%02x" NLP, PCX, port, data));
|
||||||
|
}
|
||||||
return 0x00; /* ignored since OUT */
|
return 0x00; /* ignored since OUT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 sio0s(const int32 port, const int32 io, const int32 data) {
|
||||||
|
const int32 result = sio0sCore(port, io, data);
|
||||||
|
if ((io == 0) && (sio_dev.dctrl & IN_MSG))
|
||||||
|
printf("SIO_S: " ADDRESS_FORMAT " IN(0x%03x) = 0x%02x" NLP, PCX, port, result);
|
||||||
|
else if ((io) && (sio_dev.dctrl & OUT_MSG))
|
||||||
|
printf("SIO_S: " ADDRESS_FORMAT " OUT(0x%03x) = 0x%02x" NLP, PCX, port, data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* generic data port for keyboard input / terminal output */
|
/* generic data port for keyboard input / terminal output */
|
||||||
int32 sio0d(const int32 port, const int32 io, const int32 data) {
|
static int32 sio0dCore(const int32 port, const int32 io, const int32 data) {
|
||||||
int32 ch;
|
int32 ch;
|
||||||
SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
||||||
assert(spi.port == port);
|
assert(spi.port == port);
|
||||||
|
@ -705,14 +720,23 @@ int32 sio0d(const int32 port, const int32 io, const int32 data) {
|
||||||
return 0x00; /* ignored since OUT */
|
return 0x00; /* ignored since OUT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 sio0d(const int32 port, const int32 io, const int32 data) {
|
||||||
|
const int32 result = sio0dCore(port, io, data);
|
||||||
|
if ((io == 0) && (sio_dev.dctrl & IN_MSG))
|
||||||
|
printf("SIO_D: " ADDRESS_FORMAT " IN(0x%03x) = 0x%02x" NLP, PCX, port, result);
|
||||||
|
else if ((io) && (sio_dev.dctrl & OUT_MSG))
|
||||||
|
printf("SIO_D: " ADDRESS_FORMAT " OUT(0x%03x) = 0x%02x" NLP, PCX, port, data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* PTR/PTP status port */
|
/* PTR/PTP status port */
|
||||||
int32 sio1s(const int32 port, const int32 io, const int32 data) {
|
static int32 sio1sCore(const int32 port, const int32 io, const int32 data) {
|
||||||
if (io == 0) { /* IN */
|
if (io == 0) { /* IN */
|
||||||
/* reset I bit iff PTR unit not attached or
|
/* reset I bit iff PTR unit not attached or
|
||||||
no more data available. O bit is always
|
no more data available. O bit is always
|
||||||
set since write always possible. */
|
set since write always possible. */
|
||||||
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* PTR is not attached */
|
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* PTR is not attached */
|
||||||
if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) {
|
if ((ptr_dev.dctrl & VERBOSE_MSG) && (warnUnattachedPTR < warnLevelSIO)) {
|
||||||
warnUnattachedPTR++;
|
warnUnattachedPTR++;
|
||||||
/*06*/ printf("PTR: " ADDRESS_FORMAT " Attempt to test status of unattached PTR[0x%02x]. 0x02 returned." NLP, PCX, port);
|
/*06*/ printf("PTR: " ADDRESS_FORMAT " Attempt to test status of unattached PTR[0x%02x]. 0x02 returned." NLP, PCX, port);
|
||||||
}
|
}
|
||||||
|
@ -722,24 +746,36 @@ int32 sio1s(const int32 port, const int32 io, const int32 data) {
|
||||||
(SIO_CAN_WRITE and SIO_CAN_READ) */
|
(SIO_CAN_WRITE and SIO_CAN_READ) */
|
||||||
return ptr_unit.u3 ? SIO_CAN_WRITE : (SIO_CAN_READ | SIO_CAN_WRITE);
|
return ptr_unit.u3 ? SIO_CAN_WRITE : (SIO_CAN_READ | SIO_CAN_WRITE);
|
||||||
} /* OUT follows */
|
} /* OUT follows */
|
||||||
if (data == SIO_RESET)
|
if (data == SIO_RESET) {
|
||||||
ptr_unit.u3 = FALSE; /* reset EOF indicator */
|
ptr_unit.u3 = FALSE; /* reset EOF indicator */
|
||||||
|
TRACE_PRINT(ptr_dev, CMD_MSG,
|
||||||
|
("PTR: " ADDRESS_FORMAT " Command OUT(0x%03x) = 0x%02x" NLP, PCX, port, data));
|
||||||
|
}
|
||||||
return 0x00; /* ignored since OUT */
|
return 0x00; /* ignored since OUT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 sio1s(const int32 port, const int32 io, const int32 data) {
|
||||||
|
const int32 result = sio1sCore(port, io, data);
|
||||||
|
if ((io == 0) && ((ptr_dev.dctrl & IN_MSG) || (ptp_dev.dctrl & IN_MSG)))
|
||||||
|
printf("PTP/PTR_S: " ADDRESS_FORMAT " IN(0x%02x) = 0x%02x" NLP, PCX, port, result);
|
||||||
|
else if ((io) && ((ptr_dev.dctrl & OUT_MSG) || (ptp_dev.dctrl & OUT_MSG)))
|
||||||
|
printf("PTP/PTR_S: " ADDRESS_FORMAT " OUT(0x%02x) = 0x%02x" NLP, PCX, port, data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* PTR/PTP data port */
|
/* PTR/PTP data port */
|
||||||
int32 sio1d(const int32 port, const int32 io, const int32 data) {
|
static int32 sio1dCore(const int32 port, const int32 io, const int32 data) {
|
||||||
int32 ch;
|
int32 ch;
|
||||||
if (io == 0) { /* IN */
|
if (io == 0) { /* IN */
|
||||||
if (ptr_unit.u3) { /* EOF reached, no more data available */
|
if (ptr_unit.u3) { /* EOF reached, no more data available */
|
||||||
if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnPTREOF < warnLevelSIO)) {
|
if ((ptr_dev.dctrl & VERBOSE_MSG) && (warnPTREOF < warnLevelSIO)) {
|
||||||
warnPTREOF++;
|
warnPTREOF++;
|
||||||
/*07*/ printf("PTR: " ADDRESS_FORMAT " PTR[0x%02x] attempted to read past EOF. 0x00 returned." NLP, PCX, port);
|
/*07*/ printf("PTR: " ADDRESS_FORMAT " PTR[0x%02x] attempted to read past EOF. 0x00 returned." NLP, PCX, port);
|
||||||
}
|
}
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* not attached */
|
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* not attached */
|
||||||
if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) {
|
if ((ptr_dev.dctrl & VERBOSE_MSG) && (warnUnattachedPTR < warnLevelSIO)) {
|
||||||
warnUnattachedPTR++;
|
warnUnattachedPTR++;
|
||||||
/*08*/ printf("PTR: " ADDRESS_FORMAT " Attempt to read from unattached PTR[0x%02x]. 0x00 returned." NLP, PCX, port);
|
/*08*/ printf("PTR: " ADDRESS_FORMAT " Attempt to read from unattached PTR[0x%02x]. 0x00 returned." NLP, PCX, port);
|
||||||
}
|
}
|
||||||
|
@ -754,13 +790,22 @@ int32 sio1d(const int32 port, const int32 io, const int32 data) {
|
||||||
if (ptp_unit.flags & UNIT_ATT) /* unit must be attached */
|
if (ptp_unit.flags & UNIT_ATT) /* unit must be attached */
|
||||||
putc(data, ptp_unit.fileref);
|
putc(data, ptp_unit.fileref);
|
||||||
/* else ignore data */
|
/* else ignore data */
|
||||||
else if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTP < warnLevelSIO)) {
|
else if ((ptp_dev.dctrl & VERBOSE_MSG) && (warnUnattachedPTP < warnLevelSIO)) {
|
||||||
warnUnattachedPTP++;
|
warnUnattachedPTP++;
|
||||||
/*09*/ printf("PTP: " ADDRESS_FORMAT " Attempt to output '0x%02x' to unattached PTP[0x%02x] - ignored." NLP, PCX, data, port);
|
/*09*/ printf("PTP: " ADDRESS_FORMAT " Attempt to output '0x%02x' to unattached PTP[0x%02x] - ignored." NLP, PCX, data, port);
|
||||||
}
|
}
|
||||||
return 0x00; /* ignored since OUT */
|
return 0x00; /* ignored since OUT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 sio1d(const int32 port, const int32 io, const int32 data) {
|
||||||
|
const int32 result = sio1dCore(port, io, data);
|
||||||
|
if ((io == 0) && ((ptr_dev.dctrl & IN_MSG) || (ptp_dev.dctrl & IN_MSG)))
|
||||||
|
printf("PTP/PTR_D: " ADDRESS_FORMAT " IN(0x%02x) = 0x%02x" NLP, PCX, port, result);
|
||||||
|
else if ((io) && ((ptr_dev.dctrl & OUT_MSG) || (ptp_dev.dctrl & OUT_MSG)))
|
||||||
|
printf("PTP/PTR_D: " ADDRESS_FORMAT " OUT(0x%02x) = 0x%02x" NLP, PCX, port, data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static t_stat toBool(char tf, int *result) {
|
static t_stat toBool(char tf, int *result) {
|
||||||
if (tf == 'T') {
|
if (tf == 'T') {
|
||||||
*result = TRUE;
|
*result = TRUE;
|
||||||
|
@ -856,8 +901,8 @@ static t_stat sio_dev_set_port(UNIT *uptr, int32 value, char *cptr, void *desc)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
port_table[position] = sip;
|
port_table[position] = sip;
|
||||||
sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, (sip.hasOUT ||
|
sim_map_resource(sip.port, 1, RESOURCE_TYPE_IO, (sip.hasOUT ||
|
||||||
(sip.sio_can_read == 0) && (sip.sio_cannot_read == 0) &&
|
((sip.sio_can_read == 0) && (sip.sio_cannot_read == 0) &&
|
||||||
(sip.sio_can_write == 0)) ? &sio0d : &sio0s, FALSE);
|
(sip.sio_can_write == 0))) ? &sio0d : &sio0s, FALSE);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,9 +933,8 @@ static t_stat sio_dev_set_interruptoff(UNIT *uptr, int32 value, char *cptr, void
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sio_svc(UNIT *uptr) {
|
static t_stat sio_svc(UNIT *uptr) {
|
||||||
if (sio0s(0, 0, 0) & KBD_HAS_CHAR) {
|
if (sio0s(0, 0, 0) & KBD_HAS_CHAR)
|
||||||
keyboardInterrupt = TRUE;
|
keyboardInterrupt = TRUE;
|
||||||
}
|
|
||||||
if (sio_unit.flags & UNIT_SIO_INTERRUPT)
|
if (sio_unit.flags & UNIT_SIO_INTERRUPT)
|
||||||
sim_activate(&sio_unit, sio_unit.wait); /* activate unit */
|
sim_activate(&sio_unit, sio_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -909,13 +953,11 @@ static void mapAltairPorts(void) {
|
||||||
int32 nulldev(const int32 port, const int32 io, const int32 data) {
|
int32 nulldev(const int32 port, const int32 io, const int32 data) {
|
||||||
if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) {
|
if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) {
|
||||||
warnUnassignedPort++;
|
warnUnassignedPort++;
|
||||||
if (io == 0) {
|
if (io == 0)
|
||||||
printf("SIO: " ADDRESS_FORMAT " Attempt to input from unassigned port 0x%04x - ignored." NLP, PCX, port);
|
printf("SIO: " ADDRESS_FORMAT " Attempt to input from unassigned port 0x%04x - ignored." NLP, PCX, port);
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
printf("SIO: " ADDRESS_FORMAT " Attempt to output 0x%02x to unassigned port 0x%04x - ignored." NLP, PCX, data, port);
|
printf("SIO: " ADDRESS_FORMAT " Attempt to output 0x%02x to unassigned port 0x%04x - ignored." NLP, PCX, data, port);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return io == 0 ? 0xff : 0;
|
return io == 0 ? 0xff : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1063,7 +1105,7 @@ static t_stat simh_dev_reset(DEVICE *dptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void warnNoRealTimeClock(void) {
|
static void warnNoRealTimeClock(void) {
|
||||||
TRACE_PRINT(VERBOSE_MSG,
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " Sorry - no real time clock available." NLP, PCX));
|
("SIMH: " ADDRESS_FORMAT " Sorry - no real time clock available." NLP, PCX));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,18 +1120,30 @@ static t_stat simh_dev_set_timeron(UNIT *uptr, int32 value, char *cptr, void *de
|
||||||
|
|
||||||
static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) {
|
static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) {
|
||||||
timerInterrupt = FALSE;
|
timerInterrupt = FALSE;
|
||||||
|
if (rtc_avail)
|
||||||
sim_cancel(&simh_unit);
|
sim_cancel(&simh_unit);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat simh_svc(UNIT *uptr) {
|
static t_stat simh_svc(UNIT *uptr) {
|
||||||
uint32 n = sim_os_msec();
|
uint32 now = sim_os_msec();
|
||||||
if (n >= timeOfNextInterrupt) {
|
if (now >= timeOfNextInterrupt) {
|
||||||
timerInterrupt = TRUE;
|
timerInterrupt = TRUE;
|
||||||
timeOfNextInterrupt += timerDelta;
|
if (timerDelta == 0)
|
||||||
if (n >= timeOfNextInterrupt) /* time of next interrupt is not in the future */
|
timeOfNextInterrupt = now + DEFAULT_TIMER_DELTA;
|
||||||
timeOfNextInterrupt = n + timerDelta; /* make sure it is in the future! */
|
else {
|
||||||
|
uint32 newTimeOfNextInterrupt = now + timerDelta - (now - timeOfNextInterrupt) % timerDelta;
|
||||||
|
if (newTimeOfNextInterrupt != timeOfNextInterrupt + timerDelta) {
|
||||||
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
|
("SIMH: " ADDRESS_FORMAT " Timer interrupts skipped %i. Delta %i. Expect %i. Got %i." NLP, PCX,
|
||||||
|
(newTimeOfNextInterrupt - timeOfNextInterrupt) / timerDelta - 1,
|
||||||
|
timerDelta,
|
||||||
|
timeOfNextInterrupt + timerDelta - now, newTimeOfNextInterrupt - now));
|
||||||
}
|
}
|
||||||
|
timeOfNextInterrupt = newTimeOfNextInterrupt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* post condition: now < timeOfNextInterrupt */
|
||||||
if (simh_unit.flags & UNIT_SIMH_TIMERON)
|
if (simh_unit.flags & UNIT_SIMH_TIMERON)
|
||||||
sim_activate(&simh_unit, simh_unit.wait); /* activate unit */
|
sim_activate(&simh_unit, simh_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -1175,7 +1229,7 @@ static int32 simh_in(const int32 port) {
|
||||||
|
|
||||||
case getHostFilenamesCmd:
|
case getHostFilenamesCmd:
|
||||||
#if UNIX_PLATFORM
|
#if UNIX_PLATFORM
|
||||||
if (globValid)
|
if (globValid) {
|
||||||
if (globPosNameList < globS.gl_pathc) {
|
if (globPosNameList < globS.gl_pathc) {
|
||||||
if (!(result = globS.gl_pathv[globPosNameList][globPosName++])) {
|
if (!(result = globS.gl_pathv[globPosNameList][globPosName++])) {
|
||||||
globPosNameList++;
|
globPosNameList++;
|
||||||
|
@ -1187,13 +1241,13 @@ static int32 simh_in(const int32 port) {
|
||||||
lastCommand = 0;
|
lastCommand = 0;
|
||||||
globfree(&globS);
|
globfree(&globS);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#elif defined (_WIN32)
|
#elif defined (_WIN32)
|
||||||
if (globValid)
|
if (globValid)
|
||||||
if (globFinished)
|
if (globFinished)
|
||||||
globValid = FALSE;
|
globValid = FALSE;
|
||||||
else if (firstPathCharacter <= lastPathSeparator) {
|
else if (firstPathCharacter <= lastPathSeparator)
|
||||||
result = cpmCommandLine[firstPathCharacter++];
|
result = cpmCommandLine[firstPathCharacter++];
|
||||||
}
|
|
||||||
else if (!(result = FindFileData.cFileName[globPosName++])) {
|
else if (!(result = FindFileData.cFileName[globPosName++])) {
|
||||||
globPosName = firstPathCharacter = 0;
|
globPosName = firstPathCharacter = 0;
|
||||||
if (!FindNextFile(hFind, &FindFileData)) {
|
if (!FindNextFile(hFind, &FindFileData)) {
|
||||||
|
@ -1296,7 +1350,7 @@ static int32 simh_in(const int32 port) {
|
||||||
result = getBankSelect();
|
result = getBankSelect();
|
||||||
else {
|
else {
|
||||||
result = 0;
|
result = 0;
|
||||||
TRACE_PRINT(VERBOSE_MSG,
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " Get selected bank ignored for non-banked memory." NLP, PCX));
|
("SIMH: " ADDRESS_FORMAT " Get selected bank ignored for non-banked memory." NLP, PCX));
|
||||||
}
|
}
|
||||||
lastCommand = 0;
|
lastCommand = 0;
|
||||||
|
@ -1340,7 +1394,7 @@ static int32 simh_in(const int32 port) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TRACE_PRINT(VERBOSE_MSG,
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " Undefined IN from SIMH pseudo device on port %03xh ignored." NLP,
|
("SIMH: " ADDRESS_FORMAT " Undefined IN from SIMH pseudo device on port %03xh ignored." NLP,
|
||||||
PCX, port));
|
PCX, port));
|
||||||
result = lastCommand = 0;
|
result = lastCommand = 0;
|
||||||
|
@ -1349,6 +1403,10 @@ static int32 simh_in(const int32 port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_SIMH_sleep(void) {
|
void do_SIMH_sleep(void) {
|
||||||
|
/* Do not sleep when timer interrupts are pending or are about to be created.
|
||||||
|
Otherwise there is the possibility that such interrupts are skipped. */
|
||||||
|
if ((simh_unit.flags & UNIT_SIMH_TIMERON) && rtc_avail && (sim_os_msec() + 1 >= timeOfNextInterrupt))
|
||||||
|
return;
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
if ((SIMHSleep / 1000) && !sio_unit.u4) /* time to sleep and SIO not attached to a file */
|
if ((SIMHSleep / 1000) && !sio_unit.u4) /* time to sleep and SIO not attached to a file */
|
||||||
Sleep(SIMHSleep / 1000);
|
Sleep(SIMHSleep / 1000);
|
||||||
|
@ -1390,7 +1448,7 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
if (cpu_unit.flags & UNIT_CPU_BANKED)
|
if (cpu_unit.flags & UNIT_CPU_BANKED)
|
||||||
setBankSelect(data & BANKMASK);
|
setBankSelect(data & BANKMASK);
|
||||||
else {
|
else {
|
||||||
TRACE_PRINT(VERBOSE_MSG,
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " Set selected bank to %i ignored for non-banked memory."
|
("SIMH: " ADDRESS_FORMAT " Set selected bank to %i ignored for non-banked memory."
|
||||||
NLP, PCX, data & 3));
|
NLP, PCX, data & 3));
|
||||||
}
|
}
|
||||||
|
@ -1405,6 +1463,12 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
else {
|
else {
|
||||||
timerDelta |= (data << 8);
|
timerDelta |= (data << 8);
|
||||||
setTimerDeltaPos = lastCommand = 0;
|
setTimerDeltaPos = lastCommand = 0;
|
||||||
|
if (timerDelta == 0) {
|
||||||
|
timerDelta = DEFAULT_TIMER_DELTA;
|
||||||
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
|
("SIMH: " ADDRESS_FORMAT " Timer delta set to 0 ms ignored. Using %i ms instead."
|
||||||
|
NLP, PCX, DEFAULT_TIMER_DELTA));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1420,7 +1484,7 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TRACE_PRINT(CMD_MSG,
|
TRACE_PRINT(simh_device, CMD_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " CMD(0x%02x) <- %i (0x%02x, '%s')" NLP, PCX, port, data, data,
|
("SIMH: " ADDRESS_FORMAT " CMD(0x%02x) <- %i (0x%02x, '%s')" NLP, PCX, port, data, data,
|
||||||
(0 <= data) && (data <= lastSIMHCommand) ? cmdNames[data] : "Unknown command"));
|
(0 <= data) && (data <= lastSIMHCommand) ? cmdNames[data] : "Unknown command"));
|
||||||
|
|
||||||
|
@ -1435,7 +1499,7 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
createCPMCommandLine();
|
createCPMCommandLine();
|
||||||
globError = glob(cpmCommandLine, GLOB_ERR, NULL, &globS);
|
globError = glob(cpmCommandLine, GLOB_ERR, NULL, &globS);
|
||||||
if (globError) {
|
if (globError) {
|
||||||
TRACE_PRINT(VERBOSE_MSG,
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " Cannot expand '%s'. Error is %i."
|
("SIMH: " ADDRESS_FORMAT " Cannot expand '%s'. Error is %i."
|
||||||
NLP, PCX, cpmCommandLine, globError));
|
NLP, PCX, cpmCommandLine, globError));
|
||||||
globfree(&globS);
|
globfree(&globS);
|
||||||
|
@ -1451,7 +1515,7 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
setLastPathSeparator();
|
setLastPathSeparator();
|
||||||
hFind = FindFirstFile(cpmCommandLine, &FindFileData);
|
hFind = FindFirstFile(cpmCommandLine, &FindFileData);
|
||||||
if (hFind == INVALID_HANDLE_VALUE) {
|
if (hFind == INVALID_HANDLE_VALUE) {
|
||||||
TRACE_PRINT(VERBOSE_MSG,
|
TRACE_PRINT(simh_device, VERBOSE_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " Cannot expand '%s'. Error is %lu."
|
("SIMH: " ADDRESS_FORMAT " Cannot expand '%s'. Error is %lu."
|
||||||
NLP, PCX, cpmCommandLine, GetLastError()));
|
NLP, PCX, cpmCommandLine, GetLastError()));
|
||||||
globValid = FALSE;
|
globValid = FALSE;
|
||||||
|
@ -1465,21 +1529,18 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case printTimeCmd: /* print time */
|
case printTimeCmd: /* print time */
|
||||||
if (rtc_avail) {
|
if (rtc_avail)
|
||||||
printf("SIMH: " ADDRESS_FORMAT " Current time in milliseconds = %d." NLP, PCX, sim_os_msec());
|
printf("SIMH: " ADDRESS_FORMAT " Current time in milliseconds = %d." NLP, PCX, sim_os_msec());
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
warnNoRealTimeClock();
|
warnNoRealTimeClock();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case startTimerCmd: /* create a new timer on top of stack */
|
case startTimerCmd: /* create a new timer on top of stack */
|
||||||
if (rtc_avail)
|
if (rtc_avail)
|
||||||
if (markTimeSP < TIMER_STACK_LIMIT)
|
if (markTimeSP < TIMER_STACK_LIMIT)
|
||||||
markTime[markTimeSP++] = sim_os_msec();
|
markTime[markTimeSP++] = sim_os_msec();
|
||||||
else {
|
else
|
||||||
printf("SIMH: " ADDRESS_FORMAT " Timer stack overflow." NLP, PCX);
|
printf("SIMH: " ADDRESS_FORMAT " Timer stack overflow." NLP, PCX);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
warnNoRealTimeClock();
|
warnNoRealTimeClock();
|
||||||
break;
|
break;
|
||||||
|
@ -1490,15 +1551,14 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
uint32 delta = sim_os_msec() - markTime[--markTimeSP];
|
uint32 delta = sim_os_msec() - markTime[--markTimeSP];
|
||||||
printf("SIMH: " ADDRESS_FORMAT " Timer stopped. Elapsed time in milliseconds = %d." NLP, PCX, delta);
|
printf("SIMH: " ADDRESS_FORMAT " Timer stopped. Elapsed time in milliseconds = %d." NLP, PCX, delta);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX);
|
printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
warnNoRealTimeClock();
|
warnNoRealTimeClock();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case resetPTRCmd: /* reset ptr device */
|
case resetPTRCmd: /* reset ptr device */
|
||||||
ptr_reset(NULL);
|
ptr_reset(&ptr_dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case attachPTRCmd: /* attach ptr to the file with name at beginning of CP/M command line */
|
case attachPTRCmd: /* attach ptr to the file with name at beginning of CP/M command line */
|
||||||
|
@ -1569,9 +1629,8 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
uint32 delta = sim_os_msec() - markTime[markTimeSP - 1];
|
uint32 delta = sim_os_msec() - markTime[markTimeSP - 1];
|
||||||
printf("SIMH: " ADDRESS_FORMAT " Timer running. Elapsed in milliseconds = %d." NLP, PCX, delta);
|
printf("SIMH: " ADDRESS_FORMAT " Timer running. Elapsed in milliseconds = %d." NLP, PCX, delta);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX);
|
printf("SIMH: " ADDRESS_FORMAT " No timer active." NLP, PCX);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
warnNoRealTimeClock();
|
warnNoRealTimeClock();
|
||||||
break;
|
break;
|
||||||
|
@ -1622,7 +1681,7 @@ static int32 simh_out(const int32 port, const int32 data) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TRACE_PRINT(CMD_MSG,
|
TRACE_PRINT(simh_device, CMD_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " Unknown command (%i) to SIMH pseudo device on port %03xh ignored."
|
("SIMH: " ADDRESS_FORMAT " Unknown command (%i) to SIMH pseudo device on port %03xh ignored."
|
||||||
NLP, PCX, data, port));
|
NLP, PCX, data, port));
|
||||||
}
|
}
|
||||||
|
@ -1635,13 +1694,13 @@ int32 simh_dev(const int32 port, const int32 io, const int32 data) {
|
||||||
int32 result = 0;
|
int32 result = 0;
|
||||||
if (io == 0) {
|
if (io == 0) {
|
||||||
result = simh_in(port);
|
result = simh_in(port);
|
||||||
TRACE_PRINT(IN_MSG,
|
TRACE_PRINT(simh_device, IN_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " IN(0x%02x) -> %i (0x%02x, '%c')" NLP, PCX, port, result, result,
|
("SIMH: " ADDRESS_FORMAT " IN(0x%02x) -> %i (0x%02x, '%c')" NLP, PCX, port, result, result,
|
||||||
(32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?'));
|
(32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?'));
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TRACE_PRINT(OUT_MSG,
|
TRACE_PRINT(simh_device, OUT_MSG,
|
||||||
("SIMH: " ADDRESS_FORMAT " OUT(0x%02x) <- %i (0x%02x, '%c')" NLP, PCX, port, data, data,
|
("SIMH: " ADDRESS_FORMAT " OUT(0x%02x) <- %i (0x%02x, '%c')" NLP, PCX, port, data, data,
|
||||||
(32 <= (data & 0xff)) && ((data & 0xff) <= 127) ? (data & 0xff) : '?'));
|
(32 <= (data & 0xff)) && ((data & 0xff) <= 127) ? (data & 0xff) : '?'));
|
||||||
simh_out(port, data);
|
simh_out(port, data);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_sys.c: MITS Altair system interface
|
/* altairz80_sys.c: MITS Altair system interface
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -76,6 +76,8 @@ extern DEVICE fpc_dev;
|
||||||
extern int32 chiptype;
|
extern int32 chiptype;
|
||||||
extern long disasm (unsigned char *data, char *output, int segsize, long offset);
|
extern long disasm (unsigned char *data, char *output, int segsize, long offset);
|
||||||
|
|
||||||
|
void prepareMemoryAccessMessage(const t_addr loc);
|
||||||
|
void prepareInstructionMessage(const t_addr loc, const uint32 op);
|
||||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
|
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
|
||||||
t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw);
|
t_stat parse_sym(char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw);
|
||||||
|
|
||||||
|
@ -123,11 +125,13 @@ DEVICE *sim_devices[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
char memoryAccessMessage[80];
|
static char memoryAccessMessage[256];
|
||||||
|
static char instructionMessage[256];
|
||||||
const char *sim_stop_messages[] = {
|
const char *sim_stop_messages[] = {
|
||||||
"HALT instruction",
|
"HALT instruction",
|
||||||
"Breakpoint",
|
"Breakpoint",
|
||||||
memoryAccessMessage,
|
memoryAccessMessage,
|
||||||
|
instructionMessage,
|
||||||
"Invalid Opcode"
|
"Invalid Opcode"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -347,6 +351,15 @@ static char *const MnemonicsXCB[256] = {
|
||||||
"SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */
|
"SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void prepareMemoryAccessMessage(const t_addr loc) {
|
||||||
|
sprintf(memoryAccessMessage, "Memory access breakpoint [%05xh]", loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepareInstructionMessage(const t_addr loc, const uint32 op) {
|
||||||
|
sprintf(instructionMessage, "Instruction \"%s\" breakpoint [%05xh]", chiptype == CHIP_TYPE_8080 ? Mnemonics8080[op & 0xff] :
|
||||||
|
(chiptype == CHIP_TYPE_Z80 ? MnemonicsZ80[op & 0xff] : "???"), loc);
|
||||||
|
}
|
||||||
|
|
||||||
/* Symbolic disassembler
|
/* Symbolic disassembler
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
|
@ -504,7 +517,7 @@ static int32 checkbase(char ch, const char *numString) {
|
||||||
static int32 numok(char ch, const char **numString, const int32 minvalue,
|
static int32 numok(char ch, const char **numString, const int32 minvalue,
|
||||||
const int32 maxvalue, const int32 requireSign, int32 *result) {
|
const int32 maxvalue, const int32 requireSign, int32 *result) {
|
||||||
int32 sign = 1, value = 0, base;
|
int32 sign = 1, value = 0, base;
|
||||||
if (requireSign)
|
if (requireSign) {
|
||||||
if (ch == '+')
|
if (ch == '+')
|
||||||
ch = *(*numString)++;
|
ch = *(*numString)++;
|
||||||
else if (ch == '-') {
|
else if (ch == '-') {
|
||||||
|
@ -513,6 +526,7 @@ static int32 numok(char ch, const char **numString, const int32 minvalue,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
if (!(base = checkbase(ch, *numString)))
|
if (!(base = checkbase(ch, *numString)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
while (isxdigit(ch)) {
|
while (isxdigit(ch)) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_cpu_opt.c: MITS Altair CPU (8080 and Z80)
|
/* altairz80_cpu_opt.c: MITS Altair CPU (8080 and Z80)
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -2353,7 +2353,7 @@ t_stat sim_instr_nommu(void) {
|
||||||
|
|
||||||
case 0xdd: /* DD prefix */
|
case 0xdd: /* DD prefix */
|
||||||
CHECK_CPU_8080;
|
CHECK_CPU_8080;
|
||||||
switch (op = RAM_PP(PC)) {
|
switch (RAM_PP(PC)) {
|
||||||
|
|
||||||
case 0x09: /* ADD IX,BC */
|
case 0x09: /* ADD IX,BC */
|
||||||
IX &= ADDRMASK;
|
IX &= ADDRMASK;
|
||||||
|
@ -3019,7 +3019,7 @@ t_stat sim_instr_nommu(void) {
|
||||||
|
|
||||||
case 0xed: /* ED prefix */
|
case 0xed: /* ED prefix */
|
||||||
CHECK_CPU_8080;
|
CHECK_CPU_8080;
|
||||||
switch (op = RAM_PP(PC)) {
|
switch (RAM_PP(PC)) {
|
||||||
|
|
||||||
case 0x40: /* IN B,(C) */
|
case 0x40: /* IN B,(C) */
|
||||||
temp = in(LOW_REGISTER(BC));
|
temp = in(LOW_REGISTER(BC));
|
||||||
|
@ -3405,7 +3405,6 @@ t_stat sim_instr_nommu(void) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xb0: /* LDIR */
|
case 0xb0: /* LDIR */
|
||||||
acu = HIGH_REGISTER(AF);
|
|
||||||
BC &= ADDRMASK;
|
BC &= ADDRMASK;
|
||||||
if (BC == 0)
|
if (BC == 0)
|
||||||
BC = 0x10000;
|
BC = 0x10000;
|
||||||
|
@ -3594,7 +3593,7 @@ t_stat sim_instr_nommu(void) {
|
||||||
|
|
||||||
case 0xfd: /* FD prefix */
|
case 0xfd: /* FD prefix */
|
||||||
CHECK_CPU_8080;
|
CHECK_CPU_8080;
|
||||||
switch (op = RAM_PP(PC)) {
|
switch (RAM_PP(PC)) {
|
||||||
|
|
||||||
case 0x09: /* ADD IY,BC */
|
case 0x09: /* ADD IY,BC */
|
||||||
IY &= ADDRMASK;
|
IY &= ADDRMASK;
|
||||||
|
|
BIN
AltairZ80/altairz80_doc.pdf
Normal file
BIN
AltairZ80/altairz80_doc.pdf
Normal file
Binary file not shown.
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_hdsk.c: simulated hard disk device to increase capacity
|
/* altairz80_hdsk.c: simulated hard disk device to increase capacity
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -42,6 +42,7 @@ static t_stat show_format(FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
static t_stat hdsk_reset(DEVICE *dptr);
|
static t_stat hdsk_reset(DEVICE *dptr);
|
||||||
static t_stat hdsk_attach(UNIT *uptr, char *cptr);
|
static t_stat hdsk_attach(UNIT *uptr, char *cptr);
|
||||||
|
static t_stat hdsk_detach(UNIT *uptr);
|
||||||
|
|
||||||
#define UNIT_V_HDSK_WLK (UNIT_V_UF + 0) /* write locked */
|
#define UNIT_V_HDSK_WLK (UNIT_V_UF + 0) /* write locked */
|
||||||
#define UNIT_HDSK_WLK (1 << UNIT_V_HDSK_WLK)
|
#define UNIT_HDSK_WLK (1 << UNIT_V_HDSK_WLK)
|
||||||
|
@ -77,13 +78,14 @@ extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
|
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
||||||
int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
|
int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
|
||||||
|
extern int32 find_unit_index(UNIT *uptr);
|
||||||
|
|
||||||
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr);
|
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr);
|
||||||
int32 hdsk_io(const int32 port, const int32 io, const int32 data);
|
int32 hdsk_io(const int32 port, const int32 io, const int32 data);
|
||||||
|
|
||||||
static int32 hdskLastCommand = HDSK_NONE;
|
static int32 hdskLastCommand = HDSK_NONE;
|
||||||
static int32 hdskCommandPosition = 0;
|
static int32 hdskCommandPosition = 0;
|
||||||
static int32 paramcount = 0;
|
static int32 parameterCount = 0;
|
||||||
static int32 selectedDisk;
|
static int32 selectedDisk;
|
||||||
static int32 selectedSector;
|
static int32 selectedSector;
|
||||||
static int32 selectedTrack;
|
static int32 selectedTrack;
|
||||||
|
@ -104,33 +106,115 @@ typedef struct {
|
||||||
uint16 off; /* number of reserved tracks */
|
uint16 off; /* number of reserved tracks */
|
||||||
uint8 psh; /* physical record shift factor, CP/M 3 */
|
uint8 psh; /* physical record shift factor, CP/M 3 */
|
||||||
uint8 phm; /* physical record mask, CP/M 3 */
|
uint8 phm; /* physical record mask, CP/M 3 */
|
||||||
|
int32 physicalSectorSize; /* 0 for 128 << psh, > 0 for special */
|
||||||
|
int32 offset; /* offset in physical sector where logical sector starts */
|
||||||
|
int32 *skew; /* pointer to skew table or NULL */
|
||||||
} DPB;
|
} DPB;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PNP_INFO pnp; /* Plug and Play */
|
PNP_INFO pnp; /* Plug and Play */
|
||||||
} HDSK_INFO;
|
} HDSK_INFO;
|
||||||
|
|
||||||
static HDSK_INFO hdsk_info_data = { { 0x0000, 0, 0xFD, 1 } };
|
#define SPT16 16
|
||||||
/* static HDSK_INFO *hdsk_info = &hdsk_info_data; */
|
#define SPT32 32
|
||||||
|
#define SPT26 26
|
||||||
|
|
||||||
/* Note in the following CKS = 0 for fixed media which are not supposed to be changed while CP/M is executing */
|
static HDSK_INFO hdsk_info_data = { { 0x0000, 0, 0xFD, 1 } };
|
||||||
|
|
||||||
|
static int32 standard8[SPT26] = { 0, 6, 12, 18, 24, 4, 10, 16,
|
||||||
|
22, 2, 8, 14, 20, 1, 7, 13,
|
||||||
|
19, 25, 5, 11, 17, 23, 3, 9,
|
||||||
|
15, 21 };
|
||||||
|
|
||||||
|
static int32 appple_ii_DOS[SPT16] = { 0, 6, 12, 3, 9, 15, 14, 5,
|
||||||
|
11, 2, 8, 7, 13, 4, 10, 1 };
|
||||||
|
|
||||||
|
static int32 appple_ii_DOS2[SPT32] = { 0, 1, 12, 13, 24, 25, 6, 7,
|
||||||
|
18, 19, 30, 31, 28, 29, 10, 11,
|
||||||
|
22, 23, 4, 5, 16, 17, 14, 15,
|
||||||
|
26, 27, 8, 9, 20, 21, 2, 3 };
|
||||||
|
|
||||||
|
static int32 appple_ii_PRODOS[SPT16] = { 0, 9, 3, 12, 6, 15, 1, 10,
|
||||||
|
4, 13, 7, 8, 2, 11, 5, 14 };
|
||||||
|
|
||||||
|
static int32 appple_ii_PRODOS2[SPT32] = { 0, 1, 18, 19, 6, 7, 24, 25,
|
||||||
|
12, 13, 30, 31, 2, 3, 20, 21,
|
||||||
|
8, 9, 26, 27, 14, 15, 16, 17,
|
||||||
|
4, 5, 22, 23, 10, 11, 28, 29 };
|
||||||
|
|
||||||
|
static int32 mits[SPT32] = { 0, 17, 2, 19, 4, 21, 6, 23,
|
||||||
|
8, 25, 10, 27, 12, 29, 14, 31,
|
||||||
|
16, 1, 18, 3, 20, 5, 22, 7,
|
||||||
|
24, 9, 26, 11, 28, 13, 30, 15 };
|
||||||
|
|
||||||
|
/* Note in the following CKS = 0 for fixed media which are not supposed to be
|
||||||
|
changed while CP/M is executing. Also note that spt (sectors per track) is
|
||||||
|
measured in CP/M sectors of size 128 bytes. Standard format "HDSK" must be
|
||||||
|
first as index 0 is used as default in some cases.
|
||||||
|
*/
|
||||||
static DPB dpb[] = {
|
static DPB dpb[] = {
|
||||||
/* name capac spt bsh blm exm dsm drm al0 al1 cks off psh phm */
|
/* name capac spt bsh blm exm dsm drm
|
||||||
{ "HDSK", HDSK_CAPACITY, 32, 0x05, 0x1F, 0x01, 0x07f9, 0x03FF, 0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00 }, /* AZ80 HDSK */
|
al0 al1 cks off psh phm ss off skew */
|
||||||
{ "EZ80FL", 131072, 32, 0x03, 0x07, 0x00, 127, 0x003E, 0xC0, 0x00, 0x0000, 0x0000, 0x02, 0x03 }, /* 128K FLASH */
|
{ "HDSK", HDSK_CAPACITY, 32, 0x05, 0x1F, 0x01, 0x07f9, 0x03FF,
|
||||||
{ "P112", 1474560, 72, 0x04, 0x0F, 0x00, 710, 0x00FE, 0xF0, 0x00, 0x0000, 0x0002, 0x02, 0x03 }, /* 1.44M P112 */
|
0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00, 0, 0, NULL }, /* AZ80 HDSK */
|
||||||
{ "SU720", 737280, 36, 0x04, 0x0F, 0x00, 354, 0x007E, 0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03 }, /* 720K Super I/O */
|
|
||||||
{ "OSB1", 102400, 20, 0x04, 0x0F, 0x01, 45, 0x003F, 0x80, 0x00, 0x0000, 0x0003, 0x02, 0x03 }, /* Osborne1 5.25" SS SD */
|
{ "EZ80FL", 131072, 32, 0x03, 0x07, 0x00, 127, 0x003E,
|
||||||
{ "OSB2", 204800, 40, 0x03, 0x07, 0x00, 184, 0x003F, 0xC0, 0x00, 0x0000, 0x0003, 0x02, 0x03 }, /* Osborne1 5.25" SS DD */
|
0xC0, 0x00, 0x0000, 0x0000, 0x02, 0x03, 0, 0, NULL }, /* 128K FLASH */
|
||||||
{ "NSSS1", 179200, 40, 0x03, 0x07, 0x00, 0xA4, 0x003F, 0xC0, 0x00, 0x0010, 0x0002, 0x02, 0x03 }, /* Northstar SSDD Format 1 */
|
|
||||||
{ "NSSS2", 179200, 40, 0x04, 0x0F, 0x01, 0x51, 0x003F, 0x80, 0x00, 0x0010, 0x0002, 0x02, 0x03 }, /* Northstar SSDD Format 2 */
|
{ "P112", 1474560, 72, 0x04, 0x0F, 0x00, 710, 0x00FE,
|
||||||
{ "NSDS2", 358400, 40, 0x04, 0x0F, 0x01, 0xA9, 0x003F, 0x80, 0x00, 0x0010, 0x0002, 0x02, 0x03 }, /* Northstar DSDD Format 2 */
|
0xF0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* 1.44M P112 */
|
||||||
{ "VGSS", 315392, 32, 0x04, 0x0F, 0x00, 149, 0x007F, 0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03 }, /* Vector SS SD */
|
|
||||||
{ "VGDS", 632784, 32, 0x04, 0x0F, 0x00, 299, 0x007F, 0xC0, 0x00, 0x0020, 0x0004, 0x02, 0x03 }, /* Vector DS SD */
|
{ "SU720", 737280, 36, 0x04, 0x0F, 0x00, 354, 0x007E,
|
||||||
/* Note on DISK1A Images: this is a bit of a mess. The first track on the disk is 128x26 bytes (SD) and to make this work
|
0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* 720K Super I/O */
|
||||||
I had to "move" the data from 0x2d00 in the DSK image file down to 0x4000 (2-tracks in). I used WinHex to do it. */
|
|
||||||
{ "DISK1A", 630784, 64, 0x04, 0x0F, 0x00, 299, 0x007F, 0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03 }, /* CompuPro Disk1A 8" SS SD */
|
{ "OSB1", 102400, 20, 0x04, 0x0F, 0x01, 45, 0x003F,
|
||||||
{ "SSSD8", 256256, 26, 0x03, 0x07, 0x00, 242, 0x003F, 0xC0, 0x00, 0x0000, 0x0002, 0x00, 0x00 }, /* Standard 8" SS SD */
|
0x80, 0x00, 0x0000, 0x0003, 0x02, 0x03, 0, 0, NULL }, /* Osborne1 5.25" SS SD */
|
||||||
|
|
||||||
|
{ "OSB2", 204800, 40, 0x03, 0x07, 0x00, 184, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0000, 0x0003, 0x02, 0x03, 0, 0, NULL }, /* Osborne1 5.25" SS DD */
|
||||||
|
|
||||||
|
{ "NSSS1", 179200, 40, 0x03, 0x07, 0x00, 0xA4, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0010, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Northstar SSDD Format 1 */
|
||||||
|
|
||||||
|
{ "NSSS2", 179200, 40, 0x04, 0x0F, 0x01, 0x51, 0x003F,
|
||||||
|
0x80, 0x00, 0x0010, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Northstar SSDD Format 2 */
|
||||||
|
|
||||||
|
{ "NSDS2", 358400, 40, 0x04, 0x0F, 0x01, 0xA9, 0x003F,
|
||||||
|
0x80, 0x00, 0x0010, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Northstar DSDD Format 2 */
|
||||||
|
|
||||||
|
{ "VGSS", 315392, 32, 0x04, 0x0F, 0x00, 149, 0x007F,
|
||||||
|
0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Vector SS SD */
|
||||||
|
|
||||||
|
{ "VGDS", 630784, 32, 0x04, 0x0F, 0x00, 299, 0x007F,
|
||||||
|
0xC0, 0x00, 0x0020, 0x0004, 0x02, 0x03, 0, 0, NULL }, /* Vector DS SD */
|
||||||
|
|
||||||
|
{ "DISK1A", 630784, 64, 0x04, 0x0F, 0x00, 299, 0x007F,
|
||||||
|
0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* CompuPro Disk1A 8" SS SD */
|
||||||
|
|
||||||
|
{ "SSSD8", 256256, SPT26, 0x03, 0x07, 0x00, 242, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0000, 0x0002, 0x00, 0x00, 0, 0, NULL }, /* Standard 8" SS SD */
|
||||||
|
|
||||||
|
{ "SSSD8S", 256256, SPT26, 0x03, 0x07, 0x00, 242, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0000, 0x0002, 0x00, 0x00, 0, 0, standard8 }, /* Standard 8" SS SD with skew */
|
||||||
|
|
||||||
|
{ "APPLE-DO",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, appple_ii_DOS }, /* Apple II DOS 3.3 */
|
||||||
|
|
||||||
|
{ "APPLE-PO",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, appple_ii_PRODOS }, /* Apple II PRODOS */
|
||||||
|
|
||||||
|
{ "APPLE-D2",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, appple_ii_DOS2 }, /* Apple II DOS 3.3, deblocked */
|
||||||
|
|
||||||
|
{ "APPLE-P2",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
|
||||||
|
0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, appple_ii_PRODOS2 }, /* Apple II PRODOS, deblocked */
|
||||||
|
|
||||||
|
{ "MITS", 337568, SPT32, 0x03, 0x07, 0x00, 254, 0x00FF,
|
||||||
|
0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00, 137, 3, mits }, /* MITS Altair original */
|
||||||
|
|
||||||
|
{ "MITS2", 1113536, SPT32, 0x04, 0x0F, 0x00, 0x1EF, 0x00FF,
|
||||||
|
0xF0, 0x00, 0x0000, 0x0006, 0x00, 0x00, 137, 3, mits }, /* MITS Altair original, extra */
|
||||||
|
|
||||||
{ "", 0 }
|
{ "", 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,7 +264,7 @@ DEVICE hdsk_dev = {
|
||||||
"HDSK", hdsk_unit, hdsk_reg, hdsk_mod,
|
"HDSK", hdsk_unit, hdsk_reg, hdsk_mod,
|
||||||
8, 10, 31, 1, 8, 8,
|
8, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &hdsk_reset,
|
NULL, NULL, &hdsk_reset,
|
||||||
&hdsk_boot, &hdsk_attach, NULL,
|
&hdsk_boot, &hdsk_attach, &hdsk_detach,
|
||||||
&hdsk_info_data, (DEV_DISABLE | DEV_DEBUG), 0,
|
&hdsk_info_data, (DEV_DISABLE | DEV_DEBUG), 0,
|
||||||
hdsk_dt, NULL, "Hard Disk HDSK"
|
hdsk_dt, NULL, "Hard Disk HDSK"
|
||||||
};
|
};
|
||||||
|
@ -212,7 +296,7 @@ static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Step 1: Determine capacity of this disk */
|
/* Step 1: Determine capacity of this disk */
|
||||||
uptr -> capac = sim_fsize(uptr -> fileref); /* the file length is a good candidate */
|
uptr -> capac = sim_fsize(uptr -> fileref); /* the file length is a good indication */
|
||||||
if (uptr -> capac == 0) { /* file does not exist or has length 0 */
|
if (uptr -> capac == 0) { /* file does not exist or has length 0 */
|
||||||
uptr -> capac = uptr -> HDSK_NUMBER_OF_TRACKS *
|
uptr -> capac = uptr -> HDSK_NUMBER_OF_TRACKS *
|
||||||
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE;
|
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE;
|
||||||
|
@ -255,7 +339,7 @@ static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
|
||||||
uptr -> HDSK_SECTORS_PER_TRACK = dpb[uptr -> HDSK_FORMAT_TYPE].spt >> dpb[uptr -> HDSK_FORMAT_TYPE].psh;
|
uptr -> HDSK_SECTORS_PER_TRACK = dpb[uptr -> HDSK_FORMAT_TYPE].spt >> dpb[uptr -> HDSK_FORMAT_TYPE].psh;
|
||||||
uptr -> HDSK_SECTOR_SIZE = (128 << dpb[uptr -> HDSK_FORMAT_TYPE].psh);
|
uptr -> HDSK_SECTOR_SIZE = (128 << dpb[uptr -> HDSK_FORMAT_TYPE].psh);
|
||||||
}
|
}
|
||||||
assert(uptr -> HDSK_SECTORS_PER_TRACK && uptr -> HDSK_SECTOR_SIZE);
|
assert((uptr -> HDSK_SECTORS_PER_TRACK) && (uptr -> HDSK_SECTOR_SIZE) && (uptr -> HDSK_FORMAT_TYPE >= 0));
|
||||||
|
|
||||||
/* Step 4: Number of tracks is smallest number to accomodate capacity */
|
/* Step 4: Number of tracks is smallest number to accomodate capacity */
|
||||||
uptr -> HDSK_NUMBER_OF_TRACKS = (uptr -> capac + uptr -> HDSK_SECTORS_PER_TRACK *
|
uptr -> HDSK_NUMBER_OF_TRACKS = (uptr -> capac + uptr -> HDSK_SECTORS_PER_TRACK *
|
||||||
|
@ -264,9 +348,23 @@ static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
|
||||||
uptr -> HDSK_SECTOR_SIZE) < uptr -> capac) &&
|
uptr -> HDSK_SECTOR_SIZE) < uptr -> capac) &&
|
||||||
(uptr -> capac <= (t_addr) (uptr -> HDSK_NUMBER_OF_TRACKS *
|
(uptr -> capac <= (t_addr) (uptr -> HDSK_NUMBER_OF_TRACKS *
|
||||||
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) ) );
|
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) ) );
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static t_stat hdsk_detach(UNIT *uptr) {
|
||||||
|
t_stat result;
|
||||||
|
if (uptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
result = detach_unit(uptr);
|
||||||
|
uptr -> capac = HDSK_CAPACITY;
|
||||||
|
uptr -> HDSK_FORMAT_TYPE = 0;
|
||||||
|
uptr -> HDSK_SECTOR_SIZE = 0;
|
||||||
|
uptr -> HDSK_SECTORS_PER_TRACK = 0;
|
||||||
|
uptr -> HDSK_NUMBER_OF_TRACKS = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set disk geometry routine */
|
/* Set disk geometry routine */
|
||||||
static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||||
uint32 numberOfTracks, numberOfSectors, sectorSize;
|
uint32 numberOfTracks, numberOfSectors, sectorSize;
|
||||||
|
@ -276,6 +374,10 @@ static t_stat set_geom(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
if (uptr == NULL)
|
if (uptr == NULL)
|
||||||
return SCPE_IERR;
|
return SCPE_IERR;
|
||||||
|
if (((uptr -> flags) & UNIT_ATT) == 0) {
|
||||||
|
printf("Cannot set geometry for not attached unit %i.\n", find_unit_index(uptr));
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
result = sscanf(cptr, "%d/%d/%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n);
|
result = sscanf(cptr, "%d/%d/%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n);
|
||||||
if ((result != 3) || (result == EOF) || (cptr[n] != 0)) {
|
if ((result != 3) || (result == EOF) || (cptr[n] != 0)) {
|
||||||
result = sscanf(cptr, "T:%d/N:%d/S:%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n);
|
result = sscanf(cptr, "T:%d/N:%d/S:%d%n", &numberOfTracks, &numberOfSectors, §orSize, &n);
|
||||||
|
@ -311,6 +413,10 @@ static t_stat set_format(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||||
return SCPE_IERR;
|
return SCPE_IERR;
|
||||||
if (sscanf(cptr, "%" QUOTE2(DPB_NAME_LENGTH) "s", fmtname) == 0)
|
if (sscanf(cptr, "%" QUOTE2(DPB_NAME_LENGTH) "s", fmtname) == 0)
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
|
if (((uptr -> flags) & UNIT_ATT) == 0) {
|
||||||
|
printf("Cannot set format for not attached unit %i.\n", find_unit_index(uptr));
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
for (i = 0; dpb[i].capac != 0; i++) {
|
for (i = 0; dpb[i].capac != 0; i++) {
|
||||||
if (strncmp(fmtname, dpb[i].name, strlen(fmtname)) == 0) {
|
if (strncmp(fmtname, dpb[i].name, strlen(fmtname)) == 0) {
|
||||||
uptr -> HDSK_FORMAT_TYPE = i;
|
uptr -> HDSK_FORMAT_TYPE = i;
|
||||||
|
@ -444,12 +550,13 @@ static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
|
||||||
|
|
||||||
/* check the parameters and return TRUE iff parameters are correct or have been repaired */
|
/* check the parameters and return TRUE iff parameters are correct or have been repaired */
|
||||||
static int32 checkParameters(void) {
|
static int32 checkParameters(void) {
|
||||||
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
UNIT *uptr;
|
||||||
if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) {
|
if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) {
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Disk %i does not exist, will use HDSK0 instead." NLP,
|
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Disk %i does not exist, will use HDSK0 instead." NLP,
|
||||||
selectedDisk, PCX, selectedDisk));
|
selectedDisk, PCX, selectedDisk));
|
||||||
selectedDisk = 0;
|
selectedDisk = 0;
|
||||||
}
|
}
|
||||||
|
uptr = &hdsk_dev.units[selectedDisk];
|
||||||
if ((hdsk_dev.units[selectedDisk].flags & UNIT_ATT) == 0) {
|
if ((hdsk_dev.units[selectedDisk].flags & UNIT_ATT) == 0) {
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Disk %i is not attached." NLP,
|
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Disk %i is not attached." NLP,
|
||||||
selectedDisk, PCX, selectedDisk));
|
selectedDisk, PCX, selectedDisk));
|
||||||
|
@ -475,28 +582,33 @@ static int32 checkParameters(void) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* pre-condition: checkParameters has been executed to repair any faulty parameters */
|
||||||
static int32 doSeek(void) {
|
static int32 doSeek(void) {
|
||||||
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
||||||
if (fseek(uptr -> fileref,
|
int32 hostSector = (dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ?
|
||||||
(uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) * selectedTrack +
|
selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector];
|
||||||
(uptr -> HDSK_SECTOR_SIZE * selectedSector), SEEK_SET)) {
|
int32 sectorSize = (dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize == 0) ?
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not access Sector=%02d Track=%04d." NLP,
|
uptr -> HDSK_SECTOR_SIZE : dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize;
|
||||||
selectedDisk, PCX, selectedSector, selectedTrack));
|
if (sim_fseek(uptr -> fileref,
|
||||||
|
sectorSize * (uptr -> HDSK_SECTORS_PER_TRACK * selectedTrack + hostSector) +
|
||||||
|
dpb[uptr -> HDSK_FORMAT_TYPE].offset, SEEK_SET)) {
|
||||||
|
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not access Sector=%02d[=%02d] Track=%04d." NLP,
|
||||||
|
selectedDisk, PCX, selectedSector, hostSector, selectedTrack));
|
||||||
return CPM_ERROR;
|
return CPM_ERROR;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return CPM_OK;
|
return CPM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */
|
uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */
|
||||||
|
|
||||||
|
/* pre-condition: checkParameters has been executed to repair any faulty parameters */
|
||||||
static int32 doRead(void) {
|
static int32 doRead(void) {
|
||||||
int32 i;
|
int32 i;
|
||||||
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
||||||
if (doSeek())
|
if (doSeek())
|
||||||
return CPM_ERROR;
|
return CPM_ERROR;
|
||||||
|
|
||||||
if (fread(hdskbuf, uptr -> HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) {
|
if (sim_fread(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref) != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
|
||||||
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
|
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
|
||||||
hdskbuf[i] = CPM_EMPTY;
|
hdskbuf[i] = CPM_EMPTY;
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not read Sector=%02d Track=%04d." NLP,
|
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not read Sector=%02d Track=%04d." NLP,
|
||||||
|
@ -508,18 +620,20 @@ static int32 doRead(void) {
|
||||||
return CPM_OK;
|
return CPM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* pre-condition: checkParameters has been executed to repair any faulty parameters */
|
||||||
static int32 doWrite(void) {
|
static int32 doWrite(void) {
|
||||||
int32 i;
|
int32 i;
|
||||||
|
size_t rtn;
|
||||||
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
||||||
if (((uptr -> flags) & UNIT_HDSK_WLK) == 0) { /* write enabled */
|
if (((uptr -> flags) & UNIT_HDSK_WLK) == 0) { /* write enabled */
|
||||||
if (doSeek())
|
if (doSeek())
|
||||||
return CPM_ERROR;
|
return CPM_ERROR;
|
||||||
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
|
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
|
||||||
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
|
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
|
||||||
if (fwrite(hdskbuf, uptr -> HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) {
|
rtn = sim_fwrite(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref);
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not write Sector=%02d Track=%04d." NLP,
|
if (rtn != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
|
||||||
selectedDisk, PCX, selectedSector, selectedTrack));
|
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Could not write Sector=%02d Track=%04d Result=%zd." NLP,
|
||||||
|
selectedDisk, PCX, selectedSector, selectedTrack, rtn));
|
||||||
return CPM_ERROR;
|
return CPM_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,57 +645,59 @@ static int32 doWrite(void) {
|
||||||
return CPM_OK;
|
return CPM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32 hdsk_in(const int32 port) {
|
#define PARAMETER_BLOCK_SIZE 19
|
||||||
UNIT *uptr = &hdsk_dev.units[selectedDisk];
|
static uint8 parameterBlock[PARAMETER_BLOCK_SIZE];
|
||||||
|
|
||||||
int32 result;
|
static int32 hdsk_in(const int32 port) {
|
||||||
if ((hdskCommandPosition == 6) && ((hdskLastCommand == HDSK_READ) || (hdskLastCommand == HDSK_WRITE))) {
|
if ((hdskCommandPosition == 6) && ((hdskLastCommand == HDSK_READ) || (hdskLastCommand == HDSK_WRITE))) {
|
||||||
result = checkParameters() ? ((hdskLastCommand == HDSK_READ) ? doRead() : doWrite()) : CPM_ERROR;
|
int32 result = checkParameters() ? ((hdskLastCommand == HDSK_READ) ? doRead() : doWrite()) : CPM_ERROR;
|
||||||
hdskLastCommand = HDSK_NONE;
|
hdskLastCommand = HDSK_NONE;
|
||||||
hdskCommandPosition = 0;
|
hdskCommandPosition = 0;
|
||||||
return result;
|
return result;
|
||||||
} else if (hdskLastCommand == HDSK_PARAM) {
|
}
|
||||||
DPB current = dpb[uptr -> HDSK_FORMAT_TYPE];
|
if (hdskLastCommand == HDSK_PARAM) {
|
||||||
uint8 params[17];
|
if (++parameterCount >= PARAMETER_BLOCK_SIZE)
|
||||||
params[ 0] = current.spt & 0xff; params[ 1] = (current.spt >> 8) & 0xff;
|
|
||||||
params[ 2] = current.bsh;
|
|
||||||
params[ 3] = current.blm;
|
|
||||||
params[ 4] = current.exm;
|
|
||||||
params[ 5] = current.dsm & 0xff; params[ 6] = (current.dsm >> 8) & 0xff;
|
|
||||||
params[ 7] = current.drm & 0xff; params[ 8] = (current.drm >> 8) & 0xff;
|
|
||||||
params[ 9] = current.al0;
|
|
||||||
params[10] = current.al1;
|
|
||||||
params[11] = current.cks & 0xff; params[12] = (current.cks >> 8) & 0xff;
|
|
||||||
params[13] = current.off & 0xff; params[14] = (current.off >> 8) & 0xff;
|
|
||||||
params[15] = current.psh;
|
|
||||||
params[16] = current.phm;
|
|
||||||
if (++paramcount >= 19)
|
|
||||||
hdskLastCommand = HDSK_NONE;
|
hdskLastCommand = HDSK_NONE;
|
||||||
if (paramcount <= 17)
|
return parameterBlock[parameterCount - 1];
|
||||||
return params[paramcount - 1];
|
|
||||||
else if (paramcount == 18)
|
|
||||||
return (uptr -> HDSK_SECTOR_SIZE & 0xff);
|
|
||||||
else if (paramcount == 19)
|
|
||||||
return (uptr -> HDSK_SECTOR_SIZE >> 8);
|
|
||||||
else {
|
|
||||||
printf("HDSK%d: " ADDRESS_FORMAT " Get parameter error." NLP,
|
|
||||||
selectedDisk, PCX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Illegal IN command detected (port=%03xh, cmd=%d, pos=%d)." NLP,
|
TRACE_PRINT(VERBOSE_MSG, ("HDSK%d: " ADDRESS_FORMAT " Illegal IN command detected (port=%03xh, cmd=%d, pos=%d)." NLP,
|
||||||
selectedDisk, PCX, port, hdskLastCommand, hdskCommandPosition));
|
selectedDisk, PCX, port, hdskLastCommand, hdskCommandPosition));
|
||||||
}
|
|
||||||
return CPM_OK;
|
return CPM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32 hdsk_out(const int32 port, const int32 data) {
|
static int32 hdsk_out(const int32 port, const int32 data) {
|
||||||
|
int32 thisDisk;
|
||||||
|
UNIT *uptr;
|
||||||
|
DPB current;
|
||||||
|
|
||||||
switch(hdskLastCommand) {
|
switch(hdskLastCommand) {
|
||||||
|
|
||||||
case HDSK_PARAM:
|
case HDSK_PARAM:
|
||||||
paramcount = 0;
|
parameterCount = 0;
|
||||||
selectedDisk = data;
|
thisDisk = (0 <= data) && (data < HDSK_NUMBER) ? data : 0;
|
||||||
|
uptr = &hdsk_dev.units[thisDisk];
|
||||||
|
if ((uptr -> flags) & UNIT_ATT) {
|
||||||
|
current = dpb[uptr -> HDSK_FORMAT_TYPE];
|
||||||
|
parameterBlock[17] = uptr -> HDSK_SECTOR_SIZE & 0xff;
|
||||||
|
parameterBlock[18] = (uptr -> HDSK_SECTOR_SIZE >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
current = dpb[0];
|
||||||
|
parameterBlock[17] = 128;
|
||||||
|
parameterBlock[18] = 0;
|
||||||
|
}
|
||||||
|
parameterBlock[ 0] = current.spt & 0xff; parameterBlock[ 1] = (current.spt >> 8) & 0xff;
|
||||||
|
parameterBlock[ 2] = current.bsh;
|
||||||
|
parameterBlock[ 3] = current.blm;
|
||||||
|
parameterBlock[ 4] = current.exm;
|
||||||
|
parameterBlock[ 5] = current.dsm & 0xff; parameterBlock[ 6] = (current.dsm >> 8) & 0xff;
|
||||||
|
parameterBlock[ 7] = current.drm & 0xff; parameterBlock[ 8] = (current.drm >> 8) & 0xff;
|
||||||
|
parameterBlock[ 9] = current.al0;
|
||||||
|
parameterBlock[10] = current.al1;
|
||||||
|
parameterBlock[11] = current.cks & 0xff; parameterBlock[12] = (current.cks >> 8) & 0xff;
|
||||||
|
parameterBlock[13] = current.off & 0xff; parameterBlock[14] = (current.off >> 8) & 0xff;
|
||||||
|
parameterBlock[15] = current.psh;
|
||||||
|
parameterBlock[16] = current.phm;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HDSK_READ:
|
case HDSK_READ:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* altairz80_net.c: networking capability
|
/* altairz80_net.c: networking capability
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Peter Schorn
|
Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -67,7 +67,7 @@ static struct {
|
||||||
int32 outputPosRead; /* position of next character to write to ioSocket */
|
int32 outputPosRead; /* position of next character to write to ioSocket */
|
||||||
int32 outputPosWrite; /* position of next character to append to output buffer */
|
int32 outputPosWrite; /* position of next character to append to output buffer */
|
||||||
int32 outputSize; /* number of characters in circular output buffer */
|
int32 outputSize; /* number of characters in circular output buffer */
|
||||||
} serviceDescriptor[MAX_CONNECTIONS+1] = { /* serviceDescriptor[0] holds the information for a client */
|
} serviceDescriptor[MAX_CONNECTIONS + 1] = { /* serviceDescriptor[0] holds the information for a client */
|
||||||
/* stat dat ms ios in inPR inPW inS out outPR outPW outS */
|
/* stat dat ms ios in inPR inPW inS out outPR outPW outS */
|
||||||
{0x32, 0x33, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* client Z80 port 50 and 51 */
|
{0x32, 0x33, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* client Z80 port 50 and 51 */
|
||||||
{0x28, 0x29, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* server Z80 port 40 and 41 */
|
{0x28, 0x29, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* server Z80 port 40 and 41 */
|
||||||
|
@ -290,7 +290,7 @@ int32 netData(const int32 port, const int32 io, const int32 data) {
|
||||||
return 0;
|
return 0;
|
||||||
net_svc(&net_unit);
|
net_svc(&net_unit);
|
||||||
for (i = 0; i <= MAX_CONNECTIONS; i++)
|
for (i = 0; i <= MAX_CONNECTIONS; i++)
|
||||||
if (serviceDescriptor[i].Z80DataPort == port)
|
if (serviceDescriptor[i].Z80DataPort == port) {
|
||||||
if (io == 0) { /* IN */
|
if (io == 0) { /* IN */
|
||||||
if (serviceDescriptor[i].inputSize == 0) {
|
if (serviceDescriptor[i].inputSize == 0) {
|
||||||
printf("re-read from %i" NLP, port);
|
printf("re-read from %i" NLP, port);
|
||||||
|
@ -323,5 +323,6 @@ int32 netData(const int32 port, const int32 io, const int32 data) {
|
||||||
(32 <= data) && (data <= 127) ? data : '?'));
|
(32 <= data) && (data <= 127) ? data : '?'));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* $Id: flashwriter2.c 1941 2008-06-13 05:31:03Z hharte $ *
|
* $Id: flashwriter2.c 1941 2008-06-13 05:31:03Z hharte $ *
|
||||||
* *
|
* *
|
||||||
* Copyright (c) 2007-2008 Howard M. Harte. *
|
* Copyright (c) 2007-2008 Howard M. Harte. *
|
||||||
* http:/*www.hartetec.com *
|
* http://www.hartetec.com *
|
||||||
* *
|
* *
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining *
|
* Permission is hereby granted, free of charge, to any person obtaining *
|
||||||
* a copy of this software and associated documentation files (the *
|
* a copy of this software and associated documentation files (the *
|
||||||
|
|
|
@ -149,9 +149,6 @@ extern uint8 GetByteDMA(const uint32 Addr);
|
||||||
#define UNIT_I8272_VERBOSE (1 << UNIT_V_I8272_VERBOSE)
|
#define UNIT_I8272_VERBOSE (1 << UNIT_V_I8272_VERBOSE)
|
||||||
#define I8272_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
#define I8272_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||||
#define I8272_CAPACITY_SSSD (77*1*26*128) /* Single-sided Single Density IBM Diskette1 */
|
#define I8272_CAPACITY_SSSD (77*1*26*128) /* Single-sided Single Density IBM Diskette1 */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
/* Intel 8272 Commands */
|
/* Intel 8272 Commands */
|
||||||
#define I8272_READ_TRACK 0x02
|
#define I8272_READ_TRACK 0x02
|
||||||
|
@ -307,8 +304,8 @@ t_stat i8272_attach(UNIT *uptr, char *cptr)
|
||||||
i8272_info->drive[i].ready = 0;
|
i8272_info->drive[i].ready = 0;
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
char *rtn = fgets(header, 4, uptr->fileref);
|
||||||
if(strncmp(header, "IMD", 3)) {
|
if((rtn != NULL) && strncmp(header, "IMD", 3)) {
|
||||||
printf("I8272: Only IMD disk images are supported\n");
|
printf("I8272: Only IMD disk images are supported\n");
|
||||||
i8272_info->drive[i].uptr = NULL;
|
i8272_info->drive[i].uptr = NULL;
|
||||||
return SCPE_OPENERR;
|
return SCPE_OPENERR;
|
||||||
|
@ -414,8 +411,7 @@ uint8 I8272_Read(const uint32 Addr)
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
cData = 0x00;
|
/* the switch statement ensures that cData is set in all cases! */
|
||||||
|
|
||||||
switch(Addr & 0x3) {
|
switch(Addr & 0x3) {
|
||||||
case I8272_FDC_MSR:
|
case I8272_FDC_MSR:
|
||||||
cData = i8272_info->fdc_msr | I8272_MSR_RQM;
|
cData = i8272_info->fdc_msr | I8272_MSR_RQM;
|
||||||
|
|
|
@ -86,7 +86,6 @@ static void i86_intr_handle(PC_ENV *m)
|
||||||
if (intr & INTR_SYNCH) /* raised by something */
|
if (intr & INTR_SYNCH) /* raised by something */
|
||||||
{
|
{
|
||||||
intno = m->intno;
|
intno = m->intno;
|
||||||
tmp = (uint16) mem_access_word(m, intno * 4);
|
|
||||||
{
|
{
|
||||||
tmp = m->R_FLG;
|
tmp = m->R_FLG;
|
||||||
push_word(m, tmp);
|
push_word(m, tmp);
|
||||||
|
|
|
@ -108,7 +108,7 @@ extern uint32 in(const uint32 Port);
|
||||||
So, without further ado, ...
|
So, without further ado, ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern char parity_tab[];
|
extern uint8 parity_tab[];
|
||||||
|
|
||||||
static void i86op_illegal_op(PC_ENV *m)
|
static void i86op_illegal_op(PC_ENV *m)
|
||||||
{
|
{
|
||||||
|
@ -3823,7 +3823,6 @@ static void i86op_ret_far(PC_ENV *m)
|
||||||
static void i86op_int3(PC_ENV *m)
|
static void i86op_int3(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 tmp;
|
uint16 tmp;
|
||||||
tmp = (uint16) mem_access_word(m, 3 * 4);
|
|
||||||
/* access the segment register */
|
/* access the segment register */
|
||||||
{
|
{
|
||||||
tmp = m->R_FLG;
|
tmp = m->R_FLG;
|
||||||
|
@ -3855,7 +3854,6 @@ static void i86op_int_IMM(PC_ENV *m)
|
||||||
uint16 tmp;
|
uint16 tmp;
|
||||||
uint8 intnum;
|
uint8 intnum;
|
||||||
intnum = fetch_byte_imm(m);
|
intnum = fetch_byte_imm(m);
|
||||||
tmp = mem_access_word(m, intnum * 4);
|
|
||||||
{
|
{
|
||||||
tmp = m->R_FLG;
|
tmp = m->R_FLG;
|
||||||
push_word(m, tmp);
|
push_word(m, tmp);
|
||||||
|
@ -3886,7 +3884,6 @@ static void i86op_into(PC_ENV *m)
|
||||||
uint16 tmp;
|
uint16 tmp;
|
||||||
if (ACCESS_FLAG(m,F_OF))
|
if (ACCESS_FLAG(m,F_OF))
|
||||||
{
|
{
|
||||||
tmp = mem_access_word(m, 4 * 4);
|
|
||||||
{
|
{
|
||||||
tmp = m->R_FLG;
|
tmp = m->R_FLG;
|
||||||
push_word(m, tmp);
|
push_word(m, tmp);
|
||||||
|
@ -4150,8 +4147,7 @@ static void i86op_aam(PC_ENV *m)
|
||||||
|
|
||||||
/* opcode=0xd5*/
|
/* opcode=0xd5*/
|
||||||
static void i86op_aad(PC_ENV *m)
|
static void i86op_aad(PC_ENV *m)
|
||||||
{ uint8 a;
|
{
|
||||||
a = fetch_byte_imm(m);
|
|
||||||
m->R_AX = aad_word(m,m->R_AX);
|
m->R_AX = aad_word(m,m->R_AX);
|
||||||
DECODE_CLEAR_SEGOVR(m);
|
DECODE_CLEAR_SEGOVR(m);
|
||||||
}
|
}
|
||||||
|
@ -5050,22 +5046,19 @@ static void i86op_esc_coprocess_d8(PC_ENV *m)
|
||||||
static void i86op_esc_coprocess_d9(PC_ENV *m)
|
static void i86op_esc_coprocess_d9(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 mod,rl,rh;
|
uint16 mod,rl,rh;
|
||||||
uint16 destoffset;
|
|
||||||
uint8 stkelem;
|
|
||||||
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
||||||
switch (mod)
|
switch (mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
destoffset=decode_rm00_address(m,rl);
|
decode_rm00_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
destoffset=decode_rm01_address(m,rl);
|
decode_rm01_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
destoffset=decode_rm10_address(m,rl);
|
decode_rm10_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 3: /* register to register */
|
case 3: /* register to register */
|
||||||
stkelem = (uint8) rl;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DECODE_CLEAR_SEGOVR(m);
|
DECODE_CLEAR_SEGOVR(m);
|
||||||
|
@ -5075,22 +5068,19 @@ static void i86op_esc_coprocess_d9(PC_ENV *m)
|
||||||
static void i86op_esc_coprocess_da(PC_ENV *m)
|
static void i86op_esc_coprocess_da(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 mod,rl,rh;
|
uint16 mod,rl,rh;
|
||||||
uint16 destoffset;
|
|
||||||
uint8 stkelem;
|
|
||||||
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
||||||
switch (mod)
|
switch (mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
destoffset=decode_rm00_address(m,rl);
|
decode_rm00_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
destoffset=decode_rm01_address(m,rl);
|
decode_rm01_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
destoffset=decode_rm10_address(m,rl);
|
decode_rm10_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 3: /* register to register */
|
case 3: /* register to register */
|
||||||
stkelem = (uint8) rl;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DECODE_CLEAR_SEGOVR(m);
|
DECODE_CLEAR_SEGOVR(m);
|
||||||
|
@ -5100,19 +5090,17 @@ static void i86op_esc_coprocess_da(PC_ENV *m)
|
||||||
static void i86op_esc_coprocess_db(PC_ENV *m)
|
static void i86op_esc_coprocess_db(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 mod,rl,rh;
|
uint16 mod,rl,rh;
|
||||||
uint16 destoffset;
|
|
||||||
/* uint8 stkelem;*/
|
|
||||||
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
||||||
switch (mod)
|
switch (mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
destoffset=decode_rm00_address(m,rl);
|
decode_rm00_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
destoffset=decode_rm01_address(m,rl);
|
decode_rm01_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
destoffset=decode_rm10_address(m,rl);
|
decode_rm10_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 3: /* register to register */
|
case 3: /* register to register */
|
||||||
break;
|
break;
|
||||||
|
@ -5124,22 +5112,19 @@ static void i86op_esc_coprocess_db(PC_ENV *m)
|
||||||
static void i86op_esc_coprocess_dc(PC_ENV *m)
|
static void i86op_esc_coprocess_dc(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 mod,rl,rh;
|
uint16 mod,rl,rh;
|
||||||
uint16 destoffset;
|
|
||||||
uint8 stkelem;
|
|
||||||
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
||||||
switch (mod)
|
switch (mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
destoffset=decode_rm00_address(m,rl);
|
decode_rm00_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
destoffset=decode_rm01_address(m,rl);
|
decode_rm01_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
destoffset=decode_rm10_address(m,rl);
|
decode_rm10_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 3: /* register to register */
|
case 3: /* register to register */
|
||||||
stkelem = (uint8) rl;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DECODE_CLEAR_SEGOVR(m);
|
DECODE_CLEAR_SEGOVR(m);
|
||||||
|
@ -5149,22 +5134,19 @@ static void i86op_esc_coprocess_dc(PC_ENV *m)
|
||||||
static void i86op_esc_coprocess_dd(PC_ENV *m)
|
static void i86op_esc_coprocess_dd(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 mod,rl,rh;
|
uint16 mod,rl,rh;
|
||||||
uint16 destoffset;
|
|
||||||
uint8 stkelem;
|
|
||||||
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
||||||
switch (mod)
|
switch (mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
destoffset=decode_rm00_address(m,rl);
|
decode_rm00_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
destoffset=decode_rm01_address(m,rl);
|
decode_rm01_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
destoffset=decode_rm10_address(m,rl);
|
decode_rm10_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 3: /* register to register */
|
case 3: /* register to register */
|
||||||
stkelem = (uint8) rl;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DECODE_CLEAR_SEGOVR(m);
|
DECODE_CLEAR_SEGOVR(m);
|
||||||
|
@ -5174,22 +5156,19 @@ static void i86op_esc_coprocess_dd(PC_ENV *m)
|
||||||
static void i86op_esc_coprocess_de(PC_ENV *m)
|
static void i86op_esc_coprocess_de(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 mod,rl,rh;
|
uint16 mod,rl,rh;
|
||||||
uint16 destoffset;
|
|
||||||
uint8 stkelem;
|
|
||||||
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
||||||
switch (mod)
|
switch (mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
destoffset=decode_rm00_address(m,rl);
|
decode_rm00_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
destoffset=decode_rm01_address(m,rl);
|
decode_rm01_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
destoffset=decode_rm10_address(m,rl);
|
decode_rm10_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 3: /* register to register */
|
case 3: /* register to register */
|
||||||
stkelem = (uint8) rl;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DECODE_CLEAR_SEGOVR(m);
|
DECODE_CLEAR_SEGOVR(m);
|
||||||
|
@ -5199,22 +5178,19 @@ static void i86op_esc_coprocess_de(PC_ENV *m)
|
||||||
static void i86op_esc_coprocess_df(PC_ENV *m)
|
static void i86op_esc_coprocess_df(PC_ENV *m)
|
||||||
{
|
{
|
||||||
uint16 mod,rl,rh;
|
uint16 mod,rl,rh;
|
||||||
uint16 destoffset;
|
|
||||||
uint8 stkelem;
|
|
||||||
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
FETCH_DECODE_MODRM(m,mod,rh,rl);
|
||||||
switch (mod)
|
switch (mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
destoffset=decode_rm00_address(m,rl);
|
decode_rm00_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
destoffset=decode_rm01_address(m,rl);
|
decode_rm01_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
destoffset=decode_rm10_address(m,rl);
|
decode_rm10_address(m,rl);
|
||||||
break;
|
break;
|
||||||
case 3: /* register to register */
|
case 3: /* register to register */
|
||||||
stkelem = (uint8) rl;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DECODE_CLEAR_SEGOVR(m);
|
DECODE_CLEAR_SEGOVR(m);
|
||||||
|
|
|
@ -1106,7 +1106,6 @@ uint8 shr_byte(PC_ENV *m, uint8 d, uint8 s)
|
||||||
uint16 shr_word(PC_ENV *m, uint16 d, uint16 s)
|
uint16 shr_word(PC_ENV *m, uint16 d, uint16 s)
|
||||||
{
|
{
|
||||||
uint32 cnt,res,cf,mask;
|
uint32 cnt,res,cf,mask;
|
||||||
res = d;
|
|
||||||
if (s < 16)
|
if (s < 16)
|
||||||
{
|
{
|
||||||
cnt = s % 16;
|
cnt = s % 16;
|
||||||
|
|
|
@ -130,9 +130,6 @@ static SECTOR_FORMAT sdata;
|
||||||
#define UNIT_V_MFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
#define UNIT_V_MFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
||||||
#define UNIT_MFDC_VERBOSE (1 << UNIT_V_MFDC_VERBOSE)
|
#define UNIT_MFDC_VERBOSE (1 << UNIT_V_MFDC_VERBOSE)
|
||||||
#define MFDC_CAPACITY (77*16*MFDC_SECTOR_LEN) /* Default Micropolis Disk Capacity */
|
#define MFDC_CAPACITY (77*16*MFDC_SECTOR_LEN) /* Default Micropolis Disk Capacity */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
static t_stat mfdc_reset(DEVICE *mfdc_dev);
|
static t_stat mfdc_reset(DEVICE *mfdc_dev);
|
||||||
static t_stat mfdc_attach(UNIT *uptr, char *cptr);
|
static t_stat mfdc_attach(UNIT *uptr, char *cptr);
|
||||||
|
@ -237,7 +234,6 @@ t_stat mfdc_reset(DEVICE *dptr)
|
||||||
/* Attach routine */
|
/* Attach routine */
|
||||||
t_stat mfdc_attach(UNIT *uptr, char *cptr)
|
t_stat mfdc_attach(UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
char header[4];
|
|
||||||
t_stat r;
|
t_stat r;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
@ -258,16 +254,10 @@ t_stat mfdc_attach(UNIT *uptr, char *cptr)
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
uptr->u3 = IMAGE_TYPE_DSK;
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
r = assignDiskType(uptr);
|
||||||
if(!strcmp(header, "IMD")) {
|
if (r != SCPE_OK) {
|
||||||
uptr->u3 = IMAGE_TYPE_IMD;
|
|
||||||
} else if(!strcmp(header, "CPT")) {
|
|
||||||
printf("CPT images not yet supported\n");
|
|
||||||
uptr->u3 = IMAGE_TYPE_CPT;
|
|
||||||
mfdc_detach(uptr);
|
mfdc_detach(uptr);
|
||||||
return SCPE_OPENERR;
|
return r;
|
||||||
} else {
|
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +376,7 @@ static uint8 MFDC_Read(const uint32 Addr)
|
||||||
{
|
{
|
||||||
uint8 cData;
|
uint8 cData;
|
||||||
MFDC_DRIVE_INFO *pDrive;
|
MFDC_DRIVE_INFO *pDrive;
|
||||||
|
int32 rtn;
|
||||||
|
|
||||||
cData = 0x00;
|
cData = 0x00;
|
||||||
|
|
||||||
|
@ -482,10 +473,13 @@ static uint8 MFDC_Read(const uint32 Addr)
|
||||||
} else {
|
} else {
|
||||||
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
||||||
#ifdef USE_VGI
|
#ifdef USE_VGI
|
||||||
fread(sdata.raw, MFDC_SECTOR_LEN, 1, (pDrive->uptr)->fileref);
|
rtn = sim_fread(sdata.raw, 1, MFDC_SECTOR_LEN, (pDrive->uptr)->fileref);
|
||||||
|
if (rtn != MFDC_SECTOR_LEN)
|
||||||
#else
|
#else
|
||||||
fread(sdata.u.data, 256, 1, (pDrive->uptr)->fileref);
|
rtn = sim_fread(sdata.u.data, 1, 256, (pDrive->uptr)->fileref);
|
||||||
|
if (rtn != 256)
|
||||||
#endif /* USE_VGI */
|
#endif /* USE_VGI */
|
||||||
|
printf("%s: sim_fread error. Result = %d." NLP, __FUNCTION__, rtn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IMAGE_TYPE_CPT:
|
case IMAGE_TYPE_CPT:
|
||||||
|
@ -603,9 +597,9 @@ static uint8 MFDC_Write(const uint32 Addr, uint8 cData)
|
||||||
} else {
|
} else {
|
||||||
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
||||||
#ifdef USE_VGI
|
#ifdef USE_VGI
|
||||||
fwrite(sdata.raw, MFDC_SECTOR_LEN, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(sdata.raw, 1, MFDC_SECTOR_LEN, (pDrive->uptr)->fileref);
|
||||||
#else
|
#else
|
||||||
fwrite(sdata.u.data, 256, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(sdata.u.data, 1, 256, (pDrive->uptr)->fileref);
|
||||||
#endif /* USE_VGI */
|
#endif /* USE_VGI */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -165,7 +165,7 @@ static t_stat n8vem_reset(DEVICE *dptr)
|
||||||
{
|
{
|
||||||
PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt;
|
PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt;
|
||||||
|
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reset." NLP));
|
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reset.\n"));
|
||||||
|
|
||||||
if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */
|
if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */
|
||||||
sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &n8vemdev, TRUE);
|
sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &n8vemdev, TRUE);
|
||||||
|
@ -196,7 +196,7 @@ static t_stat n8vem_reset(DEVICE *dptr)
|
||||||
|
|
||||||
static t_stat n8vem_boot(int32 unitno, DEVICE *dptr)
|
static t_stat n8vem_boot(int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Boot." NLP));
|
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Boot.\n"));
|
||||||
|
|
||||||
/* Clear the RAM and ROM mapping registers */
|
/* Clear the RAM and ROM mapping registers */
|
||||||
n8vem_info->mpcl_ram = 0;
|
n8vem_info->mpcl_ram = 0;
|
||||||
|
@ -211,7 +211,7 @@ static t_stat n8vem_boot(int32 unitno, DEVICE *dptr)
|
||||||
static t_stat n8vem_attach(UNIT *uptr, char *cptr)
|
static t_stat n8vem_attach(UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
int32 i = 0;
|
int32 i = 0, rtn;
|
||||||
|
|
||||||
i = find_unit_index(uptr);
|
i = find_unit_index(uptr);
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ static t_stat n8vem_attach(UNIT *uptr, char *cptr)
|
||||||
/* Determine length of this disk */
|
/* Determine length of this disk */
|
||||||
uptr->capac = sim_fsize(uptr->fileref);
|
uptr->capac = sim_fsize(uptr->fileref);
|
||||||
|
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Attach %s." NLP, i == 0 ? "ROM" : "RAM"));
|
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Attach %s.\n", i == 0 ? "ROM" : "RAM"));
|
||||||
|
|
||||||
if(i == 0) { /* Attaching ROM */
|
if(i == 0) { /* Attaching ROM */
|
||||||
n8vem_info->rom_attached = TRUE;
|
n8vem_info->rom_attached = TRUE;
|
||||||
|
@ -239,8 +239,10 @@ static t_stat n8vem_attach(UNIT *uptr, char *cptr)
|
||||||
if (uptr->capac > N8VEM_ROM_SIZE)
|
if (uptr->capac > N8VEM_ROM_SIZE)
|
||||||
uptr->capac = N8VEM_ROM_SIZE;
|
uptr->capac = N8VEM_ROM_SIZE;
|
||||||
|
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reading %d bytes into ROM.\n", uptr->capac));
|
rtn = fread((void *)(n8vem_info->rom), uptr->capac, 1, uptr->fileref);
|
||||||
fread((void *)(n8vem_info->rom), uptr->capac, 1, uptr->fileref);
|
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reading %d bytes into ROM."
|
||||||
|
" Result = %ssuccessful.\n",
|
||||||
|
uptr->capac, rtn == 1 ? "" : "not "));
|
||||||
}
|
}
|
||||||
} else { /* attaching RAM */
|
} else { /* attaching RAM */
|
||||||
/* Erase RAM */
|
/* Erase RAM */
|
||||||
|
@ -251,8 +253,10 @@ static t_stat n8vem_attach(UNIT *uptr, char *cptr)
|
||||||
if(uptr->capac > N8VEM_RAM_SIZE)
|
if(uptr->capac > N8VEM_RAM_SIZE)
|
||||||
uptr->capac = N8VEM_RAM_SIZE;
|
uptr->capac = N8VEM_RAM_SIZE;
|
||||||
|
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reading %d bytes into RAM.\n", uptr->capac));
|
rtn = fread((void *)(n8vem_info->ram), uptr->capac, 1, uptr->fileref);
|
||||||
fread((void *)(n8vem_info->ram), uptr->capac, 1, uptr->fileref);
|
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Reading %d bytes into RAM."
|
||||||
|
" Result = %ssuccessful.\n",
|
||||||
|
uptr->capac, rtn == 1 ? "" : "not "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -270,7 +274,7 @@ static t_stat n8vem_detach(UNIT *uptr)
|
||||||
return (SCPE_IERR);
|
return (SCPE_IERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Detach %s." NLP, i == 0 ? "ROM" : "RAM"));
|
TRACE_PRINT(VERBOSE_MSG, ("N8VEM: Detach %s.\n", i == 0 ? "ROM" : "RAM"));
|
||||||
|
|
||||||
/* rewind to the beginning of the file. */
|
/* rewind to the beginning of the file. */
|
||||||
sim_fseek(uptr->fileref, 0, SEEK_SET);
|
sim_fseek(uptr->fileref, 0, SEEK_SET);
|
||||||
|
|
|
@ -132,9 +132,6 @@ extern void raise_ss1_interrupt(uint8 intnum);
|
||||||
#define UNIT_V_DISK2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
#define UNIT_V_DISK2_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
||||||
#define UNIT_DISK2_VERBOSE (1 << UNIT_V_DISK2_VERBOSE)
|
#define UNIT_DISK2_VERBOSE (1 << UNIT_V_DISK2_VERBOSE)
|
||||||
#define DISK2_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */
|
#define DISK2_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
static t_stat disk2_reset(DEVICE *disk2_dev);
|
static t_stat disk2_reset(DEVICE *disk2_dev);
|
||||||
static t_stat disk2_attach(UNIT *uptr, char *cptr);
|
static t_stat disk2_attach(UNIT *uptr, char *cptr);
|
||||||
|
@ -226,7 +223,6 @@ static t_stat disk2_attach(UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r = SCPE_OK;
|
t_stat r = SCPE_OK;
|
||||||
DISK2_DRIVE_INFO *pDrive;
|
DISK2_DRIVE_INFO *pDrive;
|
||||||
char header[4];
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
i = find_unit_index(uptr);
|
i = find_unit_index(uptr);
|
||||||
|
@ -260,16 +256,10 @@ static t_stat disk2_attach(UNIT *uptr, char *cptr)
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
uptr->u3 = IMAGE_TYPE_DSK;
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
r = assignDiskType(uptr);
|
||||||
if(!strcmp(header, "IMD")) {
|
if (r != SCPE_OK) {
|
||||||
uptr->u3 = IMAGE_TYPE_IMD;
|
|
||||||
} else if(!strcmp(header, "CPT")) {
|
|
||||||
printf("CPT images not yet supported\n");
|
|
||||||
uptr->u3 = IMAGE_TYPE_CPT;
|
|
||||||
disk2_detach(uptr);
|
disk2_detach(uptr);
|
||||||
return SCPE_OPENERR;
|
return r;
|
||||||
} else {
|
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,6 +385,7 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData)
|
||||||
uint8 i;
|
uint8 i;
|
||||||
long file_offset;
|
long file_offset;
|
||||||
DISK2_DRIVE_INFO *pDrive;
|
DISK2_DRIVE_INFO *pDrive;
|
||||||
|
size_t rtn;
|
||||||
|
|
||||||
pDrive = &disk2_info->drive[disk2_info->sel_drive];
|
pDrive = &disk2_info->drive[disk2_info->sel_drive];
|
||||||
|
|
||||||
|
@ -457,7 +448,10 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData)
|
||||||
sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET);
|
||||||
for(i=0;i<pDrive->nsectors;i++) {
|
for(i=0;i<pDrive->nsectors;i++) {
|
||||||
/* Read sector */
|
/* Read sector */
|
||||||
fread(sdata.raw, (pDrive->sectsize + 3), 1, (pDrive->uptr)->fileref);
|
rtn = sim_fread(sdata.raw, 1, (pDrive->sectsize + 3), (pDrive->uptr)->fileref);
|
||||||
|
if (rtn != (size_t)(pDrive->sectsize + 3)) {
|
||||||
|
TRACE_PRINT(ERROR_MSG, ("DISK2: " ADDRESS_FORMAT " READ_DATA: sim_fread error." NLP, PCX));
|
||||||
|
}
|
||||||
if(sdata.u.header[2] == disk2_info->sector) {
|
if(sdata.u.header[2] == disk2_info->sector) {
|
||||||
if(sdata.u.header[0] != disk2_info->cyl) { /*pDrive->track) { */
|
if(sdata.u.header[0] != disk2_info->cyl) { /*pDrive->track) { */
|
||||||
printf("DISK2: " ADDRESS_FORMAT " READ_DATA Incorrect header: track" NLP, PCX);
|
printf("DISK2: " ADDRESS_FORMAT " READ_DATA Incorrect header: track" NLP, PCX);
|
||||||
|
@ -497,7 +491,10 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData)
|
||||||
for(i=0;i<pDrive->nsectors;i++) {
|
for(i=0;i<pDrive->nsectors;i++) {
|
||||||
/* Read sector */
|
/* Read sector */
|
||||||
file_offset = ftell((pDrive->uptr)->fileref);
|
file_offset = ftell((pDrive->uptr)->fileref);
|
||||||
fread(sdata.raw, 3, 1, (pDrive->uptr)->fileref);
|
rtn = sim_fread(sdata.raw, 1, 3, (pDrive->uptr)->fileref);
|
||||||
|
if (rtn != 3) {
|
||||||
|
TRACE_PRINT(ERROR_MSG, ("DISK2: " ADDRESS_FORMAT " WRITE_DATA: sim_fread error." NLP, PCX));
|
||||||
|
}
|
||||||
if(sdata.u.header[2] == disk2_info->sector) {
|
if(sdata.u.header[2] == disk2_info->sector) {
|
||||||
if(sdata.u.header[0] != disk2_info->cyl) {
|
if(sdata.u.header[0] != disk2_info->cyl) {
|
||||||
printf("DISK2: " ADDRESS_FORMAT " WRITE_DATA Incorrect header: track" NLP, PCX);
|
printf("DISK2: " ADDRESS_FORMAT " WRITE_DATA Incorrect header: track" NLP, PCX);
|
||||||
|
@ -510,10 +507,13 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData)
|
||||||
|
|
||||||
selchan_dma(sdata.u.data, pDrive->sectsize);
|
selchan_dma(sdata.u.data, pDrive->sectsize);
|
||||||
sim_fseek((pDrive->uptr)->fileref, file_offset+3, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, file_offset+3, SEEK_SET);
|
||||||
fwrite(sdata.u.data, (pDrive->sectsize), 1, (pDrive->uptr)->fileref);
|
sim_fwrite(sdata.u.data, 1, (pDrive->sectsize), (pDrive->uptr)->fileref);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fread(sdata.raw, pDrive->sectsize, 1, (pDrive->uptr)->fileref);
|
rtn = sim_fread(sdata.raw, 1, pDrive->sectsize, (pDrive->uptr)->fileref);
|
||||||
|
if (rtn != (size_t)(pDrive->sectsize)) {
|
||||||
|
TRACE_PRINT(ERROR_MSG, ("DISK2: " ADDRESS_FORMAT " WRITE_DATA: sim_fread error." NLP, PCX));
|
||||||
|
}
|
||||||
if(i == pDrive->nsectors) {
|
if(i == pDrive->nsectors) {
|
||||||
printf("DISK2: " ADDRESS_FORMAT " Sector not found" NLP, PCX);
|
printf("DISK2: " ADDRESS_FORMAT " Sector not found" NLP, PCX);
|
||||||
disk2_info->timeout = 1;
|
disk2_info->timeout = 1;
|
||||||
|
@ -532,7 +532,7 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData)
|
||||||
i = disk2_info->hdr_sector;
|
i = disk2_info->hdr_sector;
|
||||||
selchan_dma(sdata.raw, 3);
|
selchan_dma(sdata.raw, 3);
|
||||||
sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * (pDrive->sectsize + 3) * pDrive->nsectors) + (i * (pDrive->sectsize + 3)), SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * (pDrive->sectsize + 3) * pDrive->nsectors) + (i * (pDrive->sectsize + 3)), SEEK_SET);
|
||||||
fwrite(sdata.raw, 3, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(sdata.raw, 1, 3, (pDrive->uptr)->fileref);
|
||||||
|
|
||||||
disk2_info->hdr_sector++;
|
disk2_info->hdr_sector++;
|
||||||
if(disk2_info->hdr_sector >= pDrive->nsectors) {
|
if(disk2_info->hdr_sector >= pDrive->nsectors) {
|
||||||
|
@ -544,7 +544,10 @@ static uint8 DISK2_Write(const uint32 Addr, uint8 cData)
|
||||||
track_offset = pDrive->track * pDrive->nheads * pDrive->nsectors * (pDrive->sectsize + 3);
|
track_offset = pDrive->track * pDrive->nheads * pDrive->nsectors * (pDrive->sectsize + 3);
|
||||||
TRACE_PRINT(CMD_MSG, ("DISK2: " ADDRESS_FORMAT " READ_HEADER Command" NLP, PCX));
|
TRACE_PRINT(CMD_MSG, ("DISK2: " ADDRESS_FORMAT " READ_HEADER Command" NLP, PCX));
|
||||||
sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, track_offset + (disk2_info->head_sel * pDrive->nsectors * (pDrive->sectsize + 3)), SEEK_SET);
|
||||||
fread(sdata.raw, 3, 1, (pDrive->uptr)->fileref);
|
rtn = sim_fread(sdata.raw, 1, 3, (pDrive->uptr)->fileref);
|
||||||
|
if (rtn != 3) {
|
||||||
|
TRACE_PRINT(ERROR_MSG, ("DISK2: " ADDRESS_FORMAT " READ_HEADER: sim_fread error." NLP, PCX));
|
||||||
|
}
|
||||||
selchan_dma(sdata.raw, 3);
|
selchan_dma(sdata.raw, 3);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -193,9 +193,6 @@ extern uint8 GetByteDMA(const uint32 Addr);
|
||||||
#define UNIT_V_DISK3_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
#define UNIT_V_DISK3_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
||||||
#define UNIT_DISK3_VERBOSE (1 << UNIT_V_DISK3_VERBOSE)
|
#define UNIT_DISK3_VERBOSE (1 << UNIT_V_DISK3_VERBOSE)
|
||||||
#define DISK3_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */
|
#define DISK3_CAPACITY (C20MB_NTRACKS*C20MB_NHEADS*C20MB_NSECTORS*C20MB_SECTSIZE) /* Default Disk Capacity */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
static t_stat disk3_reset(DEVICE *disk3_dev);
|
static t_stat disk3_reset(DEVICE *disk3_dev);
|
||||||
static t_stat disk3_attach(UNIT *uptr, char *cptr);
|
static t_stat disk3_attach(UNIT *uptr, char *cptr);
|
||||||
|
@ -293,8 +290,7 @@ static t_stat disk3_attach(UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r = SCPE_OK;
|
t_stat r = SCPE_OK;
|
||||||
DISK3_DRIVE_INFO *pDrive;
|
DISK3_DRIVE_INFO *pDrive;
|
||||||
char header[4];
|
int i = 0;
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
i = find_unit_index(uptr);
|
i = find_unit_index(uptr);
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
|
@ -326,16 +322,10 @@ static t_stat disk3_attach(UNIT *uptr, char *cptr)
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
uptr->u3 = IMAGE_TYPE_DSK;
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
r = assignDiskType(uptr);
|
||||||
if(!strcmp(header, "IMD")) {
|
if (r != SCPE_OK) {
|
||||||
uptr->u3 = IMAGE_TYPE_IMD;
|
|
||||||
} else if(!strcmp(header, "CPT")) {
|
|
||||||
printf("CPT images not yet supported\n");
|
|
||||||
uptr->u3 = IMAGE_TYPE_CPT;
|
|
||||||
disk3_detach(uptr);
|
disk3_detach(uptr);
|
||||||
return SCPE_OPENERR;
|
return r;
|
||||||
} else {
|
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,6 +507,7 @@ static uint8 DISK3_Write(const uint32 Addr, uint8 cData)
|
||||||
uint32 file_offset;
|
uint32 file_offset;
|
||||||
uint32 xfr_count = 0;
|
uint32 xfr_count = 0;
|
||||||
uint8 *dataBuffer;
|
uint8 *dataBuffer;
|
||||||
|
size_t rtn;
|
||||||
|
|
||||||
if(disk3_info->mode == DISK3_MODE_ABS) {
|
if(disk3_info->mode == DISK3_MODE_ABS) {
|
||||||
TRACE_PRINT(ERROR_MSG, ("DISK3: Absolute addressing not supported." NLP));
|
TRACE_PRINT(ERROR_MSG, ("DISK3: Absolute addressing not supported." NLP));
|
||||||
|
@ -539,16 +530,19 @@ static uint8 DISK3_Write(const uint32 Addr, uint8 cData)
|
||||||
sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);
|
||||||
|
|
||||||
if(disk3_info->iopb[DISK3_IOPB_ARG1] == 1) { /* Read */
|
if(disk3_info->iopb[DISK3_IOPB_ARG1] == 1) { /* Read */
|
||||||
TRACE_PRINT(RD_DATA_MSG, ("DISK3[%d]: " ADDRESS_FORMAT " READ @0x%05x T:%04d/S:%04d/#:%d" NLP,
|
rtn = sim_fread(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref);
|
||||||
|
|
||||||
|
TRACE_PRINT(RD_DATA_MSG,
|
||||||
|
("DISK3[%d]: " ADDRESS_FORMAT " READ @0x%05x T:%04d/S:%04d/#:%d %s" NLP,
|
||||||
disk3_info->sel_drive,
|
disk3_info->sel_drive,
|
||||||
PCX,
|
PCX,
|
||||||
disk3_info->dma_addr,
|
disk3_info->dma_addr,
|
||||||
pDrive->cur_track,
|
pDrive->cur_track,
|
||||||
pDrive->cur_sect,
|
pDrive->cur_sect,
|
||||||
pDrive->xfr_nsects
|
pDrive->xfr_nsects,
|
||||||
|
rtn == (size_t)xfr_len ? "OK" : "NOK"
|
||||||
));
|
));
|
||||||
|
|
||||||
fread(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref);
|
|
||||||
|
|
||||||
/* Perform DMA Transfer */
|
/* Perform DMA Transfer */
|
||||||
for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) {
|
for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) {
|
||||||
|
@ -569,7 +563,7 @@ static uint8 DISK3_Write(const uint32 Addr, uint8 cData)
|
||||||
dataBuffer[xfr_count] = GetByteDMA(disk3_info->dma_addr + xfr_count);
|
dataBuffer[xfr_count] = GetByteDMA(disk3_info->dma_addr + xfr_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(dataBuffer);
|
free(dataBuffer);
|
||||||
|
@ -618,7 +612,7 @@ static uint8 DISK3_Write(const uint32 Addr, uint8 cData)
|
||||||
memset(fmtBuffer, disk3_info->iopb[DISK3_IOPB_ARG2], data_len);
|
memset(fmtBuffer, disk3_info->iopb[DISK3_IOPB_ARG2], data_len);
|
||||||
|
|
||||||
sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);
|
||||||
fwrite(fmtBuffer, data_len, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(fmtBuffer, 1, data_len, (pDrive->uptr)->fileref);
|
||||||
|
|
||||||
free(fmtBuffer);
|
free(fmtBuffer);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
IMSAI FIF Disk Controller by Ernie Price
|
IMSAI FIF Disk Controller by Ernie Price
|
||||||
|
|
||||||
Based on altairz80_dsk.c, Copyright (c) 2002-2008, Peter Schorn
|
Based on altairz80_dsk.c, Copyright (c) 2002-2010, Peter Schorn
|
||||||
|
|
||||||
Plug-n-Play added by Howard M. Harte
|
Plug-n-Play added by Howard M. Harte
|
||||||
|
|
||||||
|
@ -197,6 +197,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val)
|
||||||
addr;
|
addr;
|
||||||
FILE *cpx;
|
FILE *cpx;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
int32 rtn;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("%02x %02x %02x %02x %02x %02x %02x %02x \n",
|
printf("%02x %02x %02x %02x %02x %02x %02x %02x \n",
|
||||||
|
@ -242,14 +243,19 @@ static int DoDiskOperation(desc_t *dsc, uint8 val)
|
||||||
|
|
||||||
/* write a track worth of sectors */
|
/* write a track worth of sectors */
|
||||||
for (kt=0; kt < SPT; kt++) {
|
for (kt=0; kt < SPT; kt++) {
|
||||||
fwrite(blanksec, 1, sizeof(blanksec), cpx);
|
sim_fwrite(blanksec, 1, sizeof(blanksec), cpx);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case READ_SEC:
|
case READ_SEC:
|
||||||
addr = (dsc->track * SPT) + dsc->sector - 1;
|
addr = (dsc->track * SPT) + dsc->sector - 1;
|
||||||
sim_fseek(cpx, addr * SEC_SZ, SEEK_SET);
|
sim_fseek(cpx, addr * SEC_SZ, SEEK_SET);
|
||||||
fread(blanksec, 1, SEC_SZ, cpx);
|
rtn = sim_fread(blanksec, 1, SEC_SZ, cpx);
|
||||||
|
if ( (rtn != SEC_SZ) && (current_disk_flags & UNIT_DSK_VERBOSE) &&
|
||||||
|
(warnAttached[current_disk] < warnLevelDSK) ) {
|
||||||
|
warnAttached[current_disk]++;
|
||||||
|
printf("FIF%i: " ADDRESS_FORMAT " sim_fread error." NLP, current_disk, PCX);
|
||||||
|
}
|
||||||
addr = dsc->addr_l + (dsc->addr_h << 8); /* no assumption on endianness */
|
addr = dsc->addr_l + (dsc->addr_h << 8); /* no assumption on endianness */
|
||||||
for (kt = 0; kt < SEC_SZ; kt++) {
|
for (kt = 0; kt < SEC_SZ; kt++) {
|
||||||
PutBYTEWrapper(addr++, blanksec[kt]);
|
PutBYTEWrapper(addr++, blanksec[kt]);
|
||||||
|
@ -263,7 +269,7 @@ static int DoDiskOperation(desc_t *dsc, uint8 val)
|
||||||
for (kt = 0; kt < SEC_SZ; kt++) {
|
for (kt = 0; kt < SEC_SZ; kt++) {
|
||||||
blanksec[kt] = GetBYTEWrapper(addr++);
|
blanksec[kt] = GetBYTEWrapper(addr++);
|
||||||
}
|
}
|
||||||
fwrite(blanksec, 1, SEC_SZ, cpx);
|
sim_fwrite(blanksec, 1, SEC_SZ, cpx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -447,7 +453,7 @@ uint8 FTP(int32 BC, int32 DE)
|
||||||
|
|
||||||
case 20:
|
case 20:
|
||||||
memset(temp, 0x1a, SEC_SZ);
|
memset(temp, 0x1a, SEC_SZ);
|
||||||
retval = fread(temp, 1, SEC_SZ, myfile) ? 0 : 1;
|
retval = sim_fread(temp, 1, SEC_SZ, myfile) ? 0 : 1;
|
||||||
xfero( DE, temp, SEC_SZ);
|
xfero( DE, temp, SEC_SZ);
|
||||||
if (retval)
|
if (retval)
|
||||||
{
|
{
|
||||||
|
|
|
@ -112,9 +112,6 @@ extern uint8 GetBYTEWrapper(const uint32 Addr);
|
||||||
#define UNIT_V_HDC1001_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
#define UNIT_V_HDC1001_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
||||||
#define UNIT_HDC1001_VERBOSE (1 << UNIT_V_HDC1001_VERBOSE)
|
#define UNIT_HDC1001_VERBOSE (1 << UNIT_V_HDC1001_VERBOSE)
|
||||||
#define HDC1001_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
#define HDC1001_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
static t_stat hdc1001_reset(DEVICE *hdc1001_dev);
|
static t_stat hdc1001_reset(DEVICE *hdc1001_dev);
|
||||||
static t_stat hdc1001_attach(UNIT *uptr, char *cptr);
|
static t_stat hdc1001_attach(UNIT *uptr, char *cptr);
|
||||||
|
@ -198,8 +195,7 @@ static t_stat hdc1001_attach(UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r = SCPE_OK;
|
t_stat r = SCPE_OK;
|
||||||
HDC1001_DRIVE_INFO *pDrive;
|
HDC1001_DRIVE_INFO *pDrive;
|
||||||
char header[4];
|
int i = 0;
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
i = find_unit_index(uptr);
|
i = find_unit_index(uptr);
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
|
@ -231,16 +227,10 @@ static t_stat hdc1001_attach(UNIT *uptr, char *cptr)
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
uptr->u3 = IMAGE_TYPE_DSK;
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
r = assignDiskType(uptr);
|
||||||
if(!strcmp(header, "IMD")) {
|
if (r != SCPE_OK) {
|
||||||
uptr->u3 = IMAGE_TYPE_IMD;
|
|
||||||
} else if(!strcmp(header, "CPT")) {
|
|
||||||
printf("CPT images not yet supported\n");
|
|
||||||
uptr->u3 = IMAGE_TYPE_CPT;
|
|
||||||
hdc1001_detach(uptr);
|
hdc1001_detach(uptr);
|
||||||
return SCPE_OPENERR;
|
return r;
|
||||||
} else {
|
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +362,6 @@ static uint8 HDC1001_Write(const uint32 Addr, uint8 cData)
|
||||||
switch(Addr & 0x07) {
|
switch(Addr & 0x07) {
|
||||||
case TF_SDH:
|
case TF_SDH:
|
||||||
hdc1001_info->sel_drive = (cData >> 3) & 0x03;
|
hdc1001_info->sel_drive = (cData >> 3) & 0x03;
|
||||||
pDrive = &hdc1001_info->drive[hdc1001_info->sel_drive];
|
|
||||||
case TF_DATA:
|
case TF_DATA:
|
||||||
case TF_ERROR:
|
case TF_ERROR:
|
||||||
case TF_SECNT:
|
case TF_SECNT:
|
||||||
|
@ -393,14 +382,10 @@ static uint8 HDC1001_Write(const uint32 Addr, uint8 cData)
|
||||||
hdc1001_info->taskfile[TF_SDH] & 0x07,
|
hdc1001_info->taskfile[TF_SDH] & 0x07,
|
||||||
hdc1001_info->taskfile[TF_SECNO],
|
hdc1001_info->taskfile[TF_SECNO],
|
||||||
pDrive->xfr_nsects));
|
pDrive->xfr_nsects));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +526,7 @@ static uint8 HDC1001_Read(const uint32 Addr)
|
||||||
pDrive->xfr_nsects
|
pDrive->xfr_nsects
|
||||||
));
|
));
|
||||||
|
|
||||||
fread(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref);
|
sim_fread(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref);
|
||||||
|
|
||||||
/* Perform DMA Transfer */
|
/* Perform DMA Transfer */
|
||||||
for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) {
|
for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) {
|
||||||
|
@ -562,7 +547,7 @@ static uint8 HDC1001_Read(const uint32 Addr)
|
||||||
dataBuffer[xfr_count] = GetBYTEWrapper(hdc1001_info->dma_addr + xfr_count);
|
dataBuffer[xfr_count] = GetBYTEWrapper(hdc1001_info->dma_addr + xfr_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(dataBuffer, xfr_len, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(dataBuffer);
|
free(dataBuffer);
|
||||||
|
@ -593,7 +578,7 @@ static uint8 HDC1001_Read(const uint32 Addr)
|
||||||
memset(fmtBuffer, hdc1001_info->iopb[4], data_len);
|
memset(fmtBuffer, hdc1001_info->iopb[4], data_len);
|
||||||
|
|
||||||
sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);
|
||||||
fwrite(fmtBuffer, data_len, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(fmtBuffer, 1, data_len, (pDrive->uptr)->fileref);
|
||||||
|
|
||||||
free(fmtBuffer);
|
free(fmtBuffer);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
/*#define DBG_MSG*/
|
/*#define DBG_MSG*/
|
||||||
#include "altairz80_defs.h"
|
#include "altairz80_defs.h"
|
||||||
|
#include "sim_imd.h"
|
||||||
|
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -160,8 +161,6 @@ static SECTOR_FORMAT sdata;
|
||||||
#define UNIT_V_MDSAD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
#define UNIT_V_MDSAD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
||||||
#define UNIT_MDSAD_VERBOSE (1 << UNIT_V_MDSAD_VERBOSE)
|
#define UNIT_MDSAD_VERBOSE (1 << UNIT_V_MDSAD_VERBOSE)
|
||||||
#define MDSAD_CAPACITY (70*10*MDSAD_SECTOR_LEN) /* Default North Star Disk Capacity */
|
#define MDSAD_CAPACITY (70*10*MDSAD_SECTOR_LEN) /* Default North Star Disk Capacity */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
/* MDS-AD Controller Subcases */
|
/* MDS-AD Controller Subcases */
|
||||||
#define MDSAD_READ_ROM 0
|
#define MDSAD_READ_ROM 0
|
||||||
|
@ -325,8 +324,8 @@ t_stat mdsad_attach(UNIT *uptr, char *cptr)
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
uptr->u3 = IMAGE_TYPE_DSK;
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
char *rtn = fgets(header, 4, uptr->fileref);
|
||||||
if(!strcmp(header, "CPT")) {
|
if((rtn != NULL) && (strncmp(header, "CPT", 3) == 0)) {
|
||||||
printf("CPT images not yet supported\n");
|
printf("CPT images not yet supported\n");
|
||||||
uptr->u3 = IMAGE_TYPE_CPT;
|
uptr->u3 = IMAGE_TYPE_CPT;
|
||||||
mdsad_detach(uptr);
|
mdsad_detach(uptr);
|
||||||
|
@ -338,7 +337,7 @@ t_stat mdsad_attach(UNIT *uptr, char *cptr)
|
||||||
|
|
||||||
if (uptr->flags & UNIT_MDSAD_VERBOSE)
|
if (uptr->flags & UNIT_MDSAD_VERBOSE)
|
||||||
printf("MDSAD%d, attached to '%s', type=%s, len=%d\n", i, cptr,
|
printf("MDSAD%d, attached to '%s', type=%s, len=%d\n", i, cptr,
|
||||||
uptr->u3 == uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
|
uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
|
||||||
uptr->capac);
|
uptr->capac);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -450,6 +449,7 @@ static uint8 MDSAD_Read(const uint32 Addr)
|
||||||
uint8 cData;
|
uint8 cData;
|
||||||
uint8 ds;
|
uint8 ds;
|
||||||
MDSAD_DRIVE_INFO *pDrive;
|
MDSAD_DRIVE_INFO *pDrive;
|
||||||
|
int32 rtn;
|
||||||
|
|
||||||
cData = 0x00;
|
cData = 0x00;
|
||||||
|
|
||||||
|
@ -502,7 +502,7 @@ static uint8 MDSAD_Read(const uint32 Addr)
|
||||||
printf(".fileref is NULL!" NLP);
|
printf(".fileref is NULL!" NLP);
|
||||||
} else {
|
} else {
|
||||||
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
||||||
fwrite(sdata.u.data, MDSAD_SECTOR_LEN, 1,
|
sim_fwrite(sdata.u.data, 1, MDSAD_SECTOR_LEN,
|
||||||
(pDrive->uptr)->fileref);
|
(pDrive->uptr)->fileref);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -735,8 +735,11 @@ static uint8 MDSAD_Read(const uint32 Addr)
|
||||||
} else {
|
} else {
|
||||||
sim_fseek((pDrive->uptr)->fileref,
|
sim_fseek((pDrive->uptr)->fileref,
|
||||||
sec_offset, SEEK_SET);
|
sec_offset, SEEK_SET);
|
||||||
fread(&sdata.u.data[0], MDSAD_SECTOR_LEN,
|
rtn = sim_fread(&sdata.u.data[0], 1, MDSAD_SECTOR_LEN,
|
||||||
1, (pDrive->uptr)->fileref);
|
(pDrive->uptr)->fileref);
|
||||||
|
if (rtn != MDSAD_SECTOR_LEN) {
|
||||||
|
TRACE_PRINT(ERROR_MSG, ("MDSAD: " ADDRESS_FORMAT " READ: sim_fread error." NLP, PCX));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IMAGE_TYPE_CPT:
|
case IMAGE_TYPE_CPT:
|
||||||
|
|
|
@ -63,8 +63,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* use NLP for new line printing while the simulation is running */
|
/* use NLP for new line printing while the simulation is running */
|
||||||
#define UNIX_PLATFORM (defined (__linux) || defined(__NetBSD__) \
|
#if defined (__linux) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__)
|
||||||
|| defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__))
|
#define UNIX_PLATFORM 1
|
||||||
|
#else
|
||||||
|
#define UNIX_PLATFORM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#if UNIX_PLATFORM
|
#if UNIX_PLATFORM
|
||||||
#define NLP "\r\n"
|
#define NLP "\r\n"
|
||||||
|
@ -72,7 +75,7 @@
|
||||||
#define NLP "\n"
|
#define NLP "\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (__MWERKS__) && defined (macintosh)
|
#if (defined (__MWERKS__) && defined (macintosh)) || defined(__DECC)
|
||||||
#define __FUNCTION__ __FILE__
|
#define __FUNCTION__ __FILE__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -174,7 +177,7 @@ static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
|
||||||
do {
|
do {
|
||||||
DBG_PRINT(("start of track %d at file offset %ld" NLP, myDisk->ntracks, ftell(myDisk->file)));
|
DBG_PRINT(("start of track %d at file offset %ld" NLP, myDisk->ntracks, ftell(myDisk->file)));
|
||||||
|
|
||||||
fread(&imd, 1, 5, myDisk->file);
|
sim_fread(&imd, 1, 5, myDisk->file);
|
||||||
if (feof(myDisk->file))
|
if (feof(myDisk->file))
|
||||||
break;
|
break;
|
||||||
sectorSize = 128 << imd.sectsize;
|
sectorSize = 128 << imd.sectsize;
|
||||||
|
@ -197,7 +200,10 @@ static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
|
||||||
myDisk->track[imd.cyl][imd.head].nsects = imd.nsects;
|
myDisk->track[imd.cyl][imd.head].nsects = imd.nsects;
|
||||||
myDisk->track[imd.cyl][imd.head].sectsize = sectorSize;
|
myDisk->track[imd.cyl][imd.head].sectsize = sectorSize;
|
||||||
|
|
||||||
fread(sectorMap, 1, imd.nsects, myDisk->file);
|
if (sim_fread(sectorMap, 1, imd.nsects, myDisk->file) != imd.nsects) {
|
||||||
|
printf("SIM_IMD: Corrupt file [Sector Map]." NLP);
|
||||||
|
return (SCPE_OPENERR);
|
||||||
|
}
|
||||||
myDisk->track[imd.cyl][imd.head].start_sector = imd.nsects;
|
myDisk->track[imd.cyl][imd.head].start_sector = imd.nsects;
|
||||||
DBG_PRINT(("\tSector Map: "));
|
DBG_PRINT(("\tSector Map: "));
|
||||||
for(i=0;i<imd.nsects;i++) {
|
for(i=0;i<imd.nsects;i++) {
|
||||||
|
@ -209,7 +215,10 @@ static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
|
||||||
DBG_PRINT((", Start Sector=%d", myDisk->track[imd.cyl][imd.head].start_sector));
|
DBG_PRINT((", Start Sector=%d", myDisk->track[imd.cyl][imd.head].start_sector));
|
||||||
|
|
||||||
if(sectorHeadwithFlags & IMD_FLAG_SECT_HEAD_MAP) {
|
if(sectorHeadwithFlags & IMD_FLAG_SECT_HEAD_MAP) {
|
||||||
fread(sectorHeadMap, 1, imd.nsects, myDisk->file);
|
if (sim_fread(sectorHeadMap, 1, imd.nsects, myDisk->file) != imd.nsects) {
|
||||||
|
printf("SIM_IMD: Corrupt file [Sector Head Map]." NLP);
|
||||||
|
return (SCPE_OPENERR);
|
||||||
|
}
|
||||||
DBG_PRINT(("\tSector Head Map: "));
|
DBG_PRINT(("\tSector Head Map: "));
|
||||||
for(i=0;i<imd.nsects;i++) {
|
for(i=0;i<imd.nsects;i++) {
|
||||||
DBG_PRINT(("%d ", sectorHeadMap[i]));
|
DBG_PRINT(("%d ", sectorHeadMap[i]));
|
||||||
|
@ -223,7 +232,10 @@ static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sectorHeadwithFlags & IMD_FLAG_SECT_CYL_MAP) {
|
if(sectorHeadwithFlags & IMD_FLAG_SECT_CYL_MAP) {
|
||||||
fread(sectorCylMap, 1, imd.nsects, myDisk->file);
|
if (sim_fread(sectorCylMap, 1, imd.nsects, myDisk->file) != imd.nsects) {
|
||||||
|
printf("SIM_IMD: Corrupt file [Sector Cyl Map]." NLP);
|
||||||
|
return (SCPE_OPENERR);
|
||||||
|
}
|
||||||
DBG_PRINT(("\tSector Cyl Map: "));
|
DBG_PRINT(("\tSector Cyl Map: "));
|
||||||
for(i=0;i<imd.nsects;i++) {
|
for(i=0;i<imd.nsects;i++) {
|
||||||
DBG_PRINT(("%d ", sectorCylMap[i]));
|
DBG_PRINT(("%d ", sectorCylMap[i]));
|
||||||
|
@ -541,7 +553,9 @@ t_stat sectRead(DISK_INFO *myDisk,
|
||||||
case SECT_RECORD_NORM_DAM: /* Normal Data with deleted address mark */
|
case SECT_RECORD_NORM_DAM: /* Normal Data with deleted address mark */
|
||||||
|
|
||||||
/* DBG_PRINT(("Uncompressed Data" NLP)); */
|
/* DBG_PRINT(("Uncompressed Data" NLP)); */
|
||||||
fread(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file);
|
if (sim_fread(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file) != myDisk->track[Cyl][Head].sectsize) {
|
||||||
|
printf("SIM_IMD[%s]: sim_fread error for SECT_RECORD_NORM_DAM." NLP, __FUNCTION__);
|
||||||
|
}
|
||||||
*readlen = myDisk->track[Cyl][Head].sectsize;
|
*readlen = myDisk->track[Cyl][Head].sectsize;
|
||||||
break;
|
break;
|
||||||
case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */
|
case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */
|
||||||
|
@ -641,7 +655,7 @@ t_stat sectWrite(DISK_INFO *myDisk,
|
||||||
}
|
}
|
||||||
|
|
||||||
fputc(sectRecordType, myDisk->file);
|
fputc(sectRecordType, myDisk->file);
|
||||||
fwrite(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file);
|
sim_fwrite(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file);
|
||||||
*writelen = myDisk->track[Cyl][Head].sectsize;
|
*writelen = myDisk->track[Cyl][Head].sectsize;
|
||||||
|
|
||||||
return(SCPE_OK);
|
return(SCPE_OK);
|
||||||
|
@ -729,9 +743,9 @@ t_stat trackWrite(DISK_INFO *myDisk,
|
||||||
track_header.sectsize = sectorLen;
|
track_header.sectsize = sectorLen;
|
||||||
|
|
||||||
/* Forward to end of the file, write track header and sector map. */
|
/* Forward to end of the file, write track header and sector map. */
|
||||||
fseek(myDisk->file, 0, SEEK_END);
|
sim_fseek(myDisk->file, 0, SEEK_END);
|
||||||
fwrite(&track_header, sizeof(IMD_HEADER), 1, fileref);
|
sim_fwrite(&track_header, 1, sizeof(IMD_HEADER), fileref);
|
||||||
fwrite(sectorMap, 1, numSectors, fileref);
|
sim_fwrite(sectorMap, 1, numSectors, fileref);
|
||||||
|
|
||||||
/* Compute data length, and fill a sector buffer with the
|
/* Compute data length, and fill a sector buffer with the
|
||||||
* sector record type as the first byte, and fill the sector
|
* sector record type as the first byte, and fill the sector
|
||||||
|
@ -744,7 +758,7 @@ t_stat trackWrite(DISK_INFO *myDisk,
|
||||||
|
|
||||||
/* For each sector on the track, write the record type and sector data. */
|
/* For each sector on the track, write the record type and sector data. */
|
||||||
for(i=0;i<numSectors;i++) {
|
for(i=0;i<numSectors;i++) {
|
||||||
fwrite(sectorData, 1, dataLen, fileref);
|
sim_fwrite(sectorData, 1, dataLen, fileref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush the file, and free the sector buffer. */
|
/* Flush the file, and free the sector buffer. */
|
||||||
|
@ -756,3 +770,25 @@ t_stat trackWrite(DISK_INFO *myDisk,
|
||||||
|
|
||||||
return(SCPE_OK);
|
return(SCPE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Utility function to set the image type for a unit to the correct value.
|
||||||
|
* Prints an error message in case a CPT image is presented and returns
|
||||||
|
* SCPE_OPENERR in this case. Otherwise the return value is SCPE_OK
|
||||||
|
*/
|
||||||
|
t_stat assignDiskType(UNIT *uptr) {
|
||||||
|
t_stat result = SCPE_OK;
|
||||||
|
char header[4];
|
||||||
|
if (fgets(header, 4, uptr->fileref) == NULL)
|
||||||
|
uptr->u3 = IMAGE_TYPE_DSK;
|
||||||
|
else if (strncmp(header, "IMD", 3) == 0)
|
||||||
|
uptr->u3 = IMAGE_TYPE_IMD;
|
||||||
|
else if(strncmp(header, "CPT", 3) == 0) {
|
||||||
|
printf("CPT images not yet supported.\n");
|
||||||
|
uptr->u3 = IMAGE_TYPE_CPT;
|
||||||
|
result = SCPE_OPENERR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
uptr->u3 = IMAGE_TYPE_DSK;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,10 @@ typedef struct {
|
||||||
#define IMD_MODE_FM(x) (x <= IMD_MODE_250K_FM)
|
#define IMD_MODE_FM(x) (x <= IMD_MODE_250K_FM)
|
||||||
#define IMD_MODE_MFM(x) (x >= IMD_MODE_500K_MFM)
|
#define IMD_MODE_MFM(x) (x >= IMD_MODE_500K_MFM)
|
||||||
|
|
||||||
|
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
||||||
|
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
||||||
|
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8 mode;
|
uint8 mode;
|
||||||
uint8 nsects;
|
uint8 nsects;
|
||||||
|
@ -121,3 +125,4 @@ extern t_stat trackWrite(DISK_INFO *myDisk,
|
||||||
uint8 mode,
|
uint8 mode,
|
||||||
uint8 fillbyte,
|
uint8 fillbyte,
|
||||||
uint32 *flags);
|
uint32 *flags);
|
||||||
|
extern t_stat assignDiskType(UNIT *uptr);
|
||||||
|
|
|
@ -146,9 +146,6 @@ extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_typ
|
||||||
#define UNIT_V_VFDHD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
#define UNIT_V_VFDHD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
||||||
#define UNIT_VFDHD_VERBOSE (1 << UNIT_V_VFDHD_VERBOSE)
|
#define UNIT_VFDHD_VERBOSE (1 << UNIT_V_VFDHD_VERBOSE)
|
||||||
#define VFDHD_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
#define VFDHD_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
static t_stat vfdhd_reset(DEVICE *vfdhd_dev);
|
static t_stat vfdhd_reset(DEVICE *vfdhd_dev);
|
||||||
static t_stat vfdhd_attach(UNIT *uptr, char *cptr);
|
static t_stat vfdhd_attach(UNIT *uptr, char *cptr);
|
||||||
|
@ -230,7 +227,6 @@ static t_stat vfdhd_reset(DEVICE *dptr)
|
||||||
/* Attach routine */
|
/* Attach routine */
|
||||||
static t_stat vfdhd_attach(UNIT *uptr, char *cptr)
|
static t_stat vfdhd_attach(UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
char header[4];
|
|
||||||
t_stat r;
|
t_stat r;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
@ -252,16 +248,10 @@ static t_stat vfdhd_attach(UNIT *uptr, char *cptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
r = assignDiskType(uptr);
|
||||||
if(!strcmp(header, "IMD")) {
|
if (r != SCPE_OK) {
|
||||||
uptr->u3 = IMAGE_TYPE_IMD;
|
|
||||||
} else if(!strcmp(header, "CPT")) {
|
|
||||||
printf("CPT images not yet supported\n");
|
|
||||||
uptr->u3 = IMAGE_TYPE_CPT;
|
|
||||||
vfdhd_detach(uptr);
|
vfdhd_detach(uptr);
|
||||||
return SCPE_OPENERR;
|
return r;
|
||||||
} else {
|
|
||||||
uptr->u3 = IMAGE_TYPE_DSK;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* creating file, must be DSK format. */
|
/* creating file, must be DSK format. */
|
||||||
|
@ -542,6 +532,7 @@ static void VFDHD_Command(void)
|
||||||
|
|
||||||
uint32 sec_offset;
|
uint32 sec_offset;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
|
int32 rtn;
|
||||||
|
|
||||||
pDrive = &(vfdhd_info->drive[vfdhd_info->sel_drive]);
|
pDrive = &(vfdhd_info->drive[vfdhd_info->sel_drive]);
|
||||||
|
|
||||||
|
@ -604,7 +595,10 @@ static void VFDHD_Command(void)
|
||||||
printf(".fileref is NULL!" NLP);
|
printf(".fileref is NULL!" NLP);
|
||||||
} else {
|
} else {
|
||||||
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
||||||
fread(&sdata.u.sync, 274, /*VFDHD_SECTOR_LEN,*/ 1, (pDrive->uptr)->fileref);
|
rtn = sim_fread(&sdata.u.sync, 1, 274, /*VFDHD_SECTOR_LEN,*/ (pDrive->uptr)->fileref);
|
||||||
|
if (rtn != 274) {
|
||||||
|
TRACE_PRINT(ERROR_MSG, ("VFDHD: " ADDRESS_FORMAT " READ: sim_fread error." NLP, PCX));
|
||||||
|
}
|
||||||
|
|
||||||
memset(&sdata.u.preamble, 0, 40);
|
memset(&sdata.u.preamble, 0, 40);
|
||||||
memset(&sdata.u.ecc, 0, 5); /* Clear out the ECC and ECC Valid bytes */
|
memset(&sdata.u.ecc, 0, 5); /* Clear out the ECC and ECC Valid bytes */
|
||||||
|
@ -670,9 +664,9 @@ static void VFDHD_Command(void)
|
||||||
vfdhd_info->sector));
|
vfdhd_info->sector));
|
||||||
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
|
||||||
#ifdef USE_VGI
|
#ifdef USE_VGI
|
||||||
fwrite(&sdata.u.sync, VFDHD_SECTOR_LEN, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(&sdata.u.sync, 1, VFDHD_SECTOR_LEN, (pDrive->uptr)->fileref);
|
||||||
#else
|
#else
|
||||||
fwrite(sdata.u.data, 256, 1, (pDrive->uptr)->fileref);
|
sim_fwrite(sdata.u.data, 1, 256, (pDrive->uptr)->fileref);
|
||||||
#endif /* USE_VGI */
|
#endif /* USE_VGI */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -152,6 +152,7 @@ extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
|
extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,
|
||||||
int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
|
int32 (*routine)(const int32, const int32, const int32), uint8 unmap);
|
||||||
|
extern int32 find_unit_index (UNIT *uptr);
|
||||||
|
|
||||||
t_stat wd179x_svc (UNIT *uptr);
|
t_stat wd179x_svc (UNIT *uptr);
|
||||||
|
|
||||||
|
@ -165,9 +166,6 @@ extern uint8 GetBYTEWrapper(const uint32 Addr);
|
||||||
#define UNIT_WD179X_VERBOSE (1 << UNIT_V_WD179X_VERBOSE)
|
#define UNIT_WD179X_VERBOSE (1 << UNIT_V_WD179X_VERBOSE)
|
||||||
#define WD179X_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
#define WD179X_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
||||||
#define WD179X_CAPACITY_SSSD (77*1*26*128) /* Single-sided Single Density IBM Diskette1 */
|
#define WD179X_CAPACITY_SSSD (77*1*26*128) /* Single-sided Single Density IBM Diskette1 */
|
||||||
#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
|
|
||||||
#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
|
|
||||||
#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
|
|
||||||
|
|
||||||
/* Write Track (format) Statemachine states */
|
/* Write Track (format) Statemachine states */
|
||||||
#define FMT_GAP1 1
|
#define FMT_GAP1 1
|
||||||
|
@ -197,7 +195,6 @@ extern uint8 GetBYTEWrapper(const uint32 Addr);
|
||||||
|
|
||||||
static int32 wd179xdev(const int32 port, const int32 io, const int32 data);
|
static int32 wd179xdev(const int32 port, const int32 io, const int32 data);
|
||||||
static t_stat wd179x_reset(DEVICE *dptr);
|
static t_stat wd179x_reset(DEVICE *dptr);
|
||||||
int32 find_unit_index (UNIT *uptr);
|
|
||||||
uint8 floorlog2(unsigned int n);
|
uint8 floorlog2(unsigned int n);
|
||||||
|
|
||||||
WD179X_INFO wd179x_info_data = { { 0x0, 0, 0x30, 4 } };
|
WD179X_INFO wd179x_info_data = { { 0x0, 0, 0x30, 4 } };
|
||||||
|
@ -278,8 +275,6 @@ static t_stat wd179x_reset(DEVICE *dptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int32 find_unit_index (UNIT *uptr);
|
|
||||||
|
|
||||||
void wd179x_external_restore(void)
|
void wd179x_external_restore(void)
|
||||||
{
|
{
|
||||||
WD179X_DRIVE_INFO *pDrive;
|
WD179X_DRIVE_INFO *pDrive;
|
||||||
|
@ -330,8 +325,8 @@ t_stat wd179x_attach(UNIT *uptr, char *cptr)
|
||||||
wd179x_info->drive[i].ready = 0;
|
wd179x_info->drive[i].ready = 0;
|
||||||
|
|
||||||
if(uptr->capac > 0) {
|
if(uptr->capac > 0) {
|
||||||
fgets(header, 4, uptr->fileref);
|
char *rtn = fgets(header, 4, uptr->fileref);
|
||||||
if(strncmp(header, "IMD", 3)) {
|
if ((rtn != NULL) && strncmp(header, "IMD", 3)) {
|
||||||
printf("WD179X: Only IMD disk images are supported\n");
|
printf("WD179X: Only IMD disk images are supported\n");
|
||||||
wd179x_info->drive[i].uptr = NULL;
|
wd179x_info->drive[i].uptr = NULL;
|
||||||
return SCPE_OPENERR;
|
return SCPE_OPENERR;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* h316_cpu.c: Honeywell 316/516 CPU simulator
|
/* h316_cpu.c: Honeywell 316/516 CPU simulator
|
||||||
|
|
||||||
Copyright (c) 1999-2008, Robert M. Supnik
|
Copyright (c) 1999-2010, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu H316/H516 CPU
|
cpu H316/H516 CPU
|
||||||
|
|
||||||
|
10-Jan-10 RMS Fixed bugs in LDX, STX introduced in 3.8-1 (from Theo Engel)
|
||||||
28-Apr-07 RMS Removed clock initialization
|
28-Apr-07 RMS Removed clock initialization
|
||||||
03-Apr-06 RMS Fixed bugs in LLL, LRL (from Theo Engel)
|
03-Apr-06 RMS Fixed bugs in LLL, LRL (from Theo Engel)
|
||||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||||
|
@ -614,13 +615,13 @@ switch (I_GETOP (MB)) { /* case on <1:6> */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 015: case 055: /* STX */
|
case 015: case 055: /* STX */
|
||||||
if (reason = Ea (MB, &Y)) /* eff addr */
|
if (reason = Ea (MB & ~IDX, &Y)) /* eff addr */
|
||||||
break;
|
break;
|
||||||
Write (Y, XR); /* store XR */
|
Write (Y, XR); /* store XR */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 035: case 075: /* LDX */
|
case 035: case 075: /* LDX */
|
||||||
if (reason = Ea (MB, &Y)) /* eff addr */
|
if (reason = Ea (MB & ~IDX, &Y)) /* eff addr */
|
||||||
break;
|
break;
|
||||||
XR = Read (Y); /* load XR */
|
XR = Read (Y); /* load XR */
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* hp2100_cpu.h: HP 2100 CPU definitions
|
/* hp2100_cpu.h: HP 2100 CPU definitions
|
||||||
|
|
||||||
Copyright (c) 2005-2008, Robert M. Supnik
|
Copyright (c) 2005-2010, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
03-Jan-10 RMS Changed declarations of mp_control, mp_mefvv, for VMS compiler
|
||||||
15-Jul-08 JDB Rearranged declarations with hp2100_cpu.c and hp2100_defs.h
|
15-Jul-08 JDB Rearranged declarations with hp2100_cpu.c and hp2100_defs.h
|
||||||
26-Jun-08 JDB Added mp_control to CPU state externals
|
26-Jun-08 JDB Added mp_control to CPU state externals
|
||||||
24-Apr-08 JDB Added calc_defer() prototype
|
24-Apr-08 JDB Added calc_defer() prototype
|
||||||
|
@ -285,10 +286,10 @@ extern uint32 dms_enb;
|
||||||
extern uint32 dms_ump;
|
extern uint32 dms_ump;
|
||||||
extern uint32 dms_sr;
|
extern uint32 dms_sr;
|
||||||
extern uint32 dms_vr;
|
extern uint32 dms_vr;
|
||||||
extern uint32 mp_control;
|
extern FLIP_FLOP mp_control;
|
||||||
extern uint32 mp_fence;
|
extern uint32 mp_fence;
|
||||||
extern uint32 mp_viol;
|
extern uint32 mp_viol;
|
||||||
extern uint32 mp_mevff;
|
extern FLIP_FLOP mp_mevff;
|
||||||
extern uint32 iop_sp;
|
extern uint32 iop_sp;
|
||||||
extern t_bool ion_defer;
|
extern t_bool ion_defer;
|
||||||
extern uint32 intaddr;
|
extern uint32 intaddr;
|
||||||
|
|
139
I1401/i1401_cd.c
139
I1401/i1401_cd.c
|
@ -1,6 +1,6 @@
|
||||||
/* i1401_cd.c: IBM 1402 card reader/punch
|
/* i1401_cd.c: IBM 1402 card reader/punch
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M. Supnik
|
Copyright (c) 1993-2010, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -35,6 +35,8 @@
|
||||||
Cards are represented as ASCII text streams terminated by newlines.
|
Cards are represented as ASCII text streams terminated by newlines.
|
||||||
This allows cards to be created and edited as normal files.
|
This allows cards to be created and edited as normal files.
|
||||||
|
|
||||||
|
24-Mar-09 RMS Fixed read stacker operation in column binary mode
|
||||||
|
Fixed punch stacker operation (from Van Snyder)
|
||||||
28-Jun-07 RMS Added support for SS overlap modifiers
|
28-Jun-07 RMS Added support for SS overlap modifiers
|
||||||
19-Jan-07 RMS Added UNIT_TEXT flag
|
19-Jan-07 RMS Added UNIT_TEXT flag
|
||||||
20-Sep-05 RMS Revised for new code tables, compatible colbinary treatment
|
20-Sep-05 RMS Revised for new code tables, compatible colbinary treatment
|
||||||
|
@ -59,10 +61,16 @@ extern int32 ind[64], ssa, iochk;
|
||||||
extern int32 conv_old;
|
extern int32 conv_old;
|
||||||
|
|
||||||
int32 s1sel, s2sel, s4sel, s8sel;
|
int32 s1sel, s2sel, s4sel, s8sel;
|
||||||
char rbuf[2 * CBUFSIZE]; /* > CDR_WIDTH */
|
char cdr_buf[(2 * CBUFSIZE) + 1]; /* > CDR_WIDTH */
|
||||||
|
char cdp_buf[(2 * CDP_WIDTH) + 1]; /* + null */
|
||||||
|
int32 cdp_buf_full = 0; /* punch buf full? */
|
||||||
|
|
||||||
t_stat cdr_svc (UNIT *uptr);
|
t_stat cdr_svc (UNIT *uptr);
|
||||||
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
|
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat cdp_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat cdp_detach (UNIT *uptr);
|
||||||
|
t_stat cdp_npr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cd_reset (DEVICE *dptr);
|
t_stat cd_reset (DEVICE *dptr);
|
||||||
int32 bcd2asc (int32 c, UNIT *uptr);
|
int32 bcd2asc (int32 c, UNIT *uptr);
|
||||||
char colbin_to_bcd (uint32 cb);
|
char colbin_to_bcd (uint32 cb);
|
||||||
|
@ -85,7 +93,7 @@ REG cdr_reg[] = {
|
||||||
{ FLDATA (S2, s2sel, 0) },
|
{ FLDATA (S2, s2sel, 0) },
|
||||||
{ DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
{ DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT },
|
{ DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT },
|
||||||
{ BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) },
|
{ BRDATA (BUF, cdr_buf, 8, 8, CDR_WIDTH * 2) },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -112,12 +120,17 @@ REG cdp_reg[] = {
|
||||||
{ FLDATA (S4, s4sel, 0) },
|
{ FLDATA (S4, s4sel, 0) },
|
||||||
{ FLDATA (S8, s8sel, 0) },
|
{ FLDATA (S8, s8sel, 0) },
|
||||||
{ DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
|
{ BRDATA (BUF, cdp_buf, 8, 8, CDP_WIDTH * 2) },
|
||||||
|
{ FLDATA (FULL, cdp_buf_full, 0) },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
MTAB cdp_mod[] = {
|
MTAB cdp_mod[] = {
|
||||||
{ UNIT_PCH, 0, "business set", "BUSINESS" },
|
{ UNIT_PCH, 0, "business set", "BUSINESS" },
|
||||||
{ UNIT_PCH, UNIT_PCH, "Fortran set", "FORTRAN" },
|
{ UNIT_PCH, UNIT_PCH, "Fortran set", "FORTRAN" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "NPR",
|
||||||
|
&cdp_npr, NULL },
|
||||||
|
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,7 +138,7 @@ DEVICE cdp_dev = {
|
||||||
"CDP", &cdp_unit, cdp_reg, cdp_mod,
|
"CDP", &cdp_unit, cdp_reg, cdp_mod,
|
||||||
1, 10, 31, 1, 8, 7,
|
1, 10, 31, 1, 8, 7,
|
||||||
NULL, NULL, &cd_reset,
|
NULL, NULL, &cd_reset,
|
||||||
NULL, NULL, NULL
|
NULL, &cdp_attach, &cdp_detach
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stacker data structures
|
/* Stacker data structures
|
||||||
|
@ -152,7 +165,7 @@ REG stack_reg[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE stack_dev = {
|
DEVICE stack_dev = {
|
||||||
"STKR", stack_unit, stack_reg, cdp_mod,
|
"STKR", stack_unit, stack_reg, NULL,
|
||||||
5, 10, 31, 1, 8, 7,
|
5, 10, 31, 1, 8, 7,
|
||||||
NULL, NULL, &cd_reset,
|
NULL, NULL, &cd_reset,
|
||||||
NULL, NULL, NULL
|
NULL, NULL, NULL
|
||||||
|
@ -178,9 +191,9 @@ if ((cdr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||||
return SCPE_UNATT;
|
return SCPE_UNATT;
|
||||||
ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */
|
ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */
|
||||||
cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */
|
cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */
|
||||||
for (i = 0; i < 2 * CBUFSIZE; i++) /* clear extended buf */
|
for (i = 0; i < (2 * CBUFSIZE) + 1; i++) /* clear extended buf */
|
||||||
rbuf[i] = 0;
|
cdr_buf[i] = 0;
|
||||||
fgets (rbuf, (cbn)? 2 * CBUFSIZE: CBUFSIZE, /* rd bin/char card */
|
fgets (cdr_buf, (cbn)? 2 * CBUFSIZE: CBUFSIZE, /* rd bin/char card */
|
||||||
cdr_unit.fileref);
|
cdr_unit.fileref);
|
||||||
if (feof (cdr_unit.fileref)) /* eof? */
|
if (feof (cdr_unit.fileref)) /* eof? */
|
||||||
return STOP_NOCD;
|
return STOP_NOCD;
|
||||||
|
@ -202,12 +215,12 @@ if (ssa) { /* if last cd on */
|
||||||
if (cbn) { /* column binary */
|
if (cbn) { /* column binary */
|
||||||
for (i = 0; i < CDR_WIDTH; i++) {
|
for (i = 0; i < CDR_WIDTH; i++) {
|
||||||
if (conv_old) {
|
if (conv_old) {
|
||||||
c1 = ascii2bcd (rbuf[i]);
|
c1 = ascii2bcd (cdr_buf[i]);
|
||||||
c2 = ascii2bcd (rbuf[CDR_WIDTH + i]);
|
c2 = ascii2bcd (cdr_buf[CDR_WIDTH + i]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c1 = ascii2bcd (rbuf[2 * i]);
|
c1 = ascii2bcd (cdr_buf[2 * i]);
|
||||||
c2 = ascii2bcd (rbuf[(2 * i) + 1]);
|
c2 = ascii2bcd (cdr_buf[(2 * i) + 1]);
|
||||||
}
|
}
|
||||||
M[CD_CBUF1 + i] = (M[CD_CBUF1 + i] & WM) | c1;
|
M[CD_CBUF1 + i] = (M[CD_CBUF1 + i] & WM) | c1;
|
||||||
M[CD_CBUF2 + i] = (M[CD_CBUF2 + i] & WM) | c2;
|
M[CD_CBUF2 + i] = (M[CD_CBUF2 + i] & WM) | c2;
|
||||||
|
@ -216,8 +229,8 @@ if (cbn) { /* column binary */
|
||||||
} /* end if col bin */
|
} /* end if col bin */
|
||||||
else { /* normal read */
|
else { /* normal read */
|
||||||
for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */
|
for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */
|
||||||
rbuf[i] = ascii2bcd (rbuf[i]);
|
c1 = ascii2bcd (cdr_buf[i]);
|
||||||
M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | rbuf[i];
|
M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | c1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
M[CDR_BUF - 1] = 060; /* mem mark */
|
M[CDR_BUF - 1] = 060; /* mem mark */
|
||||||
|
@ -228,12 +241,15 @@ return SCPE_OK;
|
||||||
/* Card reader service. If a stacker select is active, copy to the
|
/* Card reader service. If a stacker select is active, copy to the
|
||||||
selected stacker. Otherwise, copy to the normal stacker. If the
|
selected stacker. Otherwise, copy to the normal stacker. If the
|
||||||
unit is unattached, simply exit.
|
unit is unattached, simply exit.
|
||||||
|
|
||||||
|
The original card buffer (cdr_buf) has not been changed from its input
|
||||||
|
format (ASCII text), with its newline attached. There is a guaranteed
|
||||||
|
null at the end, because the buffer was zeroed prior to the read, and
|
||||||
|
is one character longer than the maximum string length.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat cdr_svc (UNIT *uptr)
|
t_stat cdr_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
|
||||||
|
|
||||||
if (s1sel) /* stacker 1? */
|
if (s1sel) /* stacker 1? */
|
||||||
uptr = &stack_unit[1];
|
uptr = &stack_unit[1];
|
||||||
else if (s2sel) /* stacker 2? */
|
else if (s2sel) /* stacker 2? */
|
||||||
|
@ -241,13 +257,7 @@ else if (s2sel) /* stacker 2? */
|
||||||
else uptr = &stack_unit[0]; /* then default */
|
else uptr = &stack_unit[0]; /* then default */
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
for (i = 0; i < CDR_WIDTH; i++)
|
fputs (cdr_buf, uptr->fileref); /* write card */
|
||||||
rbuf[i] = bcd2ascii (rbuf[i], uptr->flags & UNIT_PCH);
|
|
||||||
for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--)
|
|
||||||
rbuf[i] = 0;
|
|
||||||
rbuf[CDR_WIDTH] = 0; /* null at end */
|
|
||||||
fputs (rbuf, uptr->fileref); /* write card */
|
|
||||||
fputc ('\n', uptr->fileref); /* plus new line */
|
|
||||||
uptr->pos = ftell (uptr->fileref); /* update position */
|
uptr->pos = ftell (uptr->fileref); /* update position */
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
perror ("Card stacker I/O error");
|
perror ("Card stacker I/O error");
|
||||||
|
@ -262,23 +272,22 @@ return SCPE_OK;
|
||||||
|
|
||||||
Modifiers have been checked by the caller
|
Modifiers have been checked by the caller
|
||||||
C modifier is recognized (column binary is implemented)
|
C modifier is recognized (column binary is implemented)
|
||||||
|
|
||||||
|
- Run out any previously buffered card
|
||||||
|
- Clear stacker select
|
||||||
|
- Copy card from memory buffer to punch buffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat punch_card (int32 ilnt, int32 mod)
|
t_stat punch_card (int32 ilnt, int32 mod)
|
||||||
{
|
{
|
||||||
int32 i, cbn, c1, c2;
|
int32 i, cbn, c1, c2;
|
||||||
static char pbuf[(2 * CDP_WIDTH) + 1]; /* + null */
|
|
||||||
t_bool use_h;
|
t_bool use_h;
|
||||||
UNIT *uptr;
|
t_stat r;
|
||||||
|
|
||||||
if (s8sel) /* stack 8? */
|
r = cdp_npr (NULL, 0, NULL, NULL); /* write card */
|
||||||
uptr = &stack_unit[2];
|
if (r != SCPE_OK)
|
||||||
else if (s4sel) /* stack 4? */
|
return r;
|
||||||
uptr = &stack_unit[4];
|
use_h = cdp_unit.flags & UNIT_PCH;
|
||||||
else uptr = &cdp_unit; /* normal output */
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
|
||||||
return SCPE_UNATT;
|
|
||||||
use_h = uptr->flags & UNIT_PCH;
|
|
||||||
ind[IN_PNCH] = s4sel = s8sel = 0; /* clear flags */
|
ind[IN_PNCH] = s4sel = s8sel = 0; /* clear flags */
|
||||||
cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */
|
cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */
|
||||||
|
|
||||||
|
@ -288,26 +297,46 @@ if (cbn) { /* column binary */
|
||||||
c1 = bcd2ascii (M[CD_CBUF1 + i] & CHAR, use_h);
|
c1 = bcd2ascii (M[CD_CBUF1 + i] & CHAR, use_h);
|
||||||
c2 = bcd2ascii (M[CD_CBUF2 + i] & CHAR, use_h);
|
c2 = bcd2ascii (M[CD_CBUF2 + i] & CHAR, use_h);
|
||||||
if (conv_old) {
|
if (conv_old) {
|
||||||
pbuf[i] = c1;
|
cdp_buf[i] = c1;
|
||||||
pbuf[i + CDP_WIDTH] = c2;
|
cdp_buf[i + CDP_WIDTH] = c2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pbuf[2 * i] = c1;
|
cdp_buf[2 * i] = c1;
|
||||||
pbuf[(2 * i) + 1] = c2;
|
cdp_buf[(2 * i) + 1] = c2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 2 * CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--)
|
for (i = (2 * CDP_WIDTH) - 1; (i >= 0) && (cdp_buf[i] == ' '); i--)
|
||||||
pbuf[i] = 0;
|
cdp_buf[i] = 0;
|
||||||
pbuf[2 * CDP_WIDTH] = 0; /* trailing null */
|
cdp_buf[2 * CDP_WIDTH] = 0; /* trailing null */
|
||||||
}
|
}
|
||||||
else { /* normal */
|
else { /* normal */
|
||||||
for (i = 0; i < CDP_WIDTH; i++)
|
for (i = 0; i < CDP_WIDTH; i++)
|
||||||
pbuf[i] = bcd2ascii (M[CDP_BUF + i] & CHAR, use_h);
|
cdp_buf[i] = bcd2ascii (M[CDP_BUF + i] & CHAR, use_h);
|
||||||
for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--)
|
for (i = CDP_WIDTH - 1; (i >= 0) && (cdp_buf[i] == ' '); i--)
|
||||||
pbuf[i] = 0;
|
cdp_buf[i] = 0;
|
||||||
pbuf[CDP_WIDTH] = 0; /* trailing null */
|
cdp_buf[CDP_WIDTH] = 0; /* trailing null */
|
||||||
}
|
}
|
||||||
fputs (pbuf, uptr->fileref); /* output card */
|
cdp_buf_full = 1; /* card buffer full */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Punch buffered card (also handles non-process runout button) */
|
||||||
|
|
||||||
|
t_stat cdp_npr (UNIT *notused, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
|
if (cdp_buf_full == 0) /* any card? */
|
||||||
|
return SCPE_OK; /* no, done */
|
||||||
|
cdp_buf_full = 0; /* buf empty */
|
||||||
|
if (s8sel) /* stack 8? */
|
||||||
|
uptr = &stack_unit[2];
|
||||||
|
else if (s4sel) /* stack 4? */
|
||||||
|
uptr = &stack_unit[4];
|
||||||
|
else uptr = &cdp_unit; /* normal output */
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
fputs (cdp_buf, uptr->fileref); /* output card */
|
||||||
fputc ('\n', uptr->fileref); /* plus new line */
|
fputc ('\n', uptr->fileref); /* plus new line */
|
||||||
uptr->pos = ftell (uptr->fileref); /* update position */
|
uptr->pos = ftell (uptr->fileref); /* update position */
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
@ -380,6 +409,26 @@ saved_IS = BOOT_START;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Card punch attach */
|
||||||
|
|
||||||
|
t_stat cdp_attach (UNIT *uptr, char *cptr)
|
||||||
|
{
|
||||||
|
cdp_buf_full = 0;
|
||||||
|
return attach_unit (uptr, cptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card punch detach */
|
||||||
|
|
||||||
|
t_stat cdp_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
r = cdp_npr (NULL, 0, NULL, NULL);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return r;
|
||||||
|
return detach_unit (uptr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Column binary to BCD
|
/* Column binary to BCD
|
||||||
|
|
||||||
This is based on documentation in the IBM 1620 manual and may not be
|
This is based on documentation in the IBM 1620 manual and may not be
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* i1401_cpu.c: IBM 1401 CPU simulator
|
/* i1401_cpu.c: IBM 1401 CPU simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M. Supnik
|
Copyright (c) 1993-2010, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
24-Apr-10 RMS Revised divide algorithm (from Van Snyder)
|
||||||
11-Jul-08 RMS Added missing A magtape modifier (from Van Snyder)
|
11-Jul-08 RMS Added missing A magtape modifier (from Van Snyder)
|
||||||
Fixed tape indicator implementation (from Bob Abeles)
|
Fixed tape indicator implementation (from Bob Abeles)
|
||||||
Fixed bug in ZA and ZS (from Bob Abeles)
|
Fixed bug in ZA and ZS (from Bob Abeles)
|
||||||
|
@ -210,8 +211,8 @@ t_stat cpu_show_conv (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
int32 store_addr_h (int32 addr);
|
int32 store_addr_h (int32 addr);
|
||||||
int32 store_addr_t (int32 addr);
|
int32 store_addr_t (int32 addr);
|
||||||
int32 store_addr_u (int32 addr);
|
int32 store_addr_u (int32 addr);
|
||||||
int32 div_add (int32 ap, int32 bp, int32 aend);
|
int32 div_add (int32 ap, int32 bp);
|
||||||
int32 div_sub (int32 ap, int32 bp, int32 aend);
|
int32 div_sub (int32 ap, int32 bp);
|
||||||
void div_sign (int32 dvrc, int32 dvdc, int32 qp, int32 rp);
|
void div_sign (int32 dvrc, int32 dvdc, int32 qp, int32 rp);
|
||||||
t_stat iomod (int32 ilnt, int32 mod, const int32 *tptr);
|
t_stat iomod (int32 ilnt, int32 mod, const int32 *tptr);
|
||||||
t_stat iodisp (int32 dev, int32 unit, int32 flag, int32 mod);
|
t_stat iodisp (int32 dev, int32 unit, int32 flag, int32 mod);
|
||||||
|
@ -518,7 +519,7 @@ int32 IS, ilnt, flags;
|
||||||
int32 op, xa, t, wm, ioind, dev, unit;
|
int32 op, xa, t, wm, ioind, dev, unit;
|
||||||
int32 a, b, i, k, asave, bsave;
|
int32 a, b, i, k, asave, bsave;
|
||||||
int32 carry, lowprd, sign, ps;
|
int32 carry, lowprd, sign, ps;
|
||||||
int32 quo, ahigh, qs;
|
int32 quo, qs;
|
||||||
int32 qzero, qawm, qbody, qsign, qdollar, qaster, qdecimal;
|
int32 qzero, qawm, qbody, qsign, qdollar, qaster, qdecimal;
|
||||||
t_stat reason, r1, r2;
|
t_stat reason, r1, r2;
|
||||||
|
|
||||||
|
@ -1432,19 +1433,16 @@ CHECK_LENGTH:
|
||||||
- AS points to the low order divisor digit.
|
- AS points to the low order divisor digit.
|
||||||
- BS points to the high order dividend digit.
|
- BS points to the high order dividend digit.
|
||||||
- The low order dividend digit is identified by sign (zone) bits.
|
- The low order dividend digit is identified by sign (zone) bits.
|
||||||
- To the left of the dividend is a zero field of length LS + 1.
|
- To the left of the dividend is a (zero) field of length LS + 1.
|
||||||
The low quotient is at low dividend - LS - 1. As BS points to the
|
So the quotient starts as BS - LS - 1.
|
||||||
high dividend, the low dividend is at BS + LD - 1, so the low
|
The divide process starts with a subdividend that begins at BS - LS
|
||||||
quotient is at BS + LD - LS - 2. The longest possible quotient is
|
and ends at BS. (Note that the subdividend is one digit wider than
|
||||||
LD - LS + 1, so the first possible non-zero quotient bit will be
|
the divisor, to allow for borrows during the divide process.) This
|
||||||
found as BS - 2.
|
means that non-zero digits in the "zero" field to the left of the
|
||||||
|
dividend CAN affect the divide.
|
||||||
|
|
||||||
This pointer calculation assumes that the divisor has no leading zeroes.
|
Start by computing the length of the divisor and testing for divide
|
||||||
For each leading zero, the start of the quotient will be one position
|
by zero.
|
||||||
further left.
|
|
||||||
|
|
||||||
Start by locating the high order non-zero digit of the divisor. This
|
|
||||||
also tests for a divide by zero.
|
|
||||||
|
|
||||||
Instruction lengths:
|
Instruction lengths:
|
||||||
|
|
||||||
|
@ -1458,17 +1456,17 @@ CHECK_LENGTH:
|
||||||
|
|
||||||
case OP_DIV:
|
case OP_DIV:
|
||||||
asave = AS;
|
asave = AS;
|
||||||
ahigh = -1;
|
t = 0; /* assume all 0's */
|
||||||
do {
|
do { /* scan divisor */
|
||||||
a = M[AS]; /* get dvr char */
|
a = M[AS]; /* get dvr char */
|
||||||
if ((a & CHAR) != BCD_ZERO) /* mark non-zero */
|
if ((bcd_to_bin[a & DIGIT]) != 0) /* mark non-zero */
|
||||||
ahigh = AS;
|
t = 1;
|
||||||
MM (AS);
|
MM (AS);
|
||||||
}
|
}
|
||||||
while ((a & WM) == 0);
|
while ((a & WM) == 0);
|
||||||
if (reason) /* address err? */
|
if (reason) /* address err? */
|
||||||
break;
|
break;
|
||||||
if (ahigh < 0) { /* div by zero? */
|
if (t == 0) { /* div by zero? */
|
||||||
ind[IN_OVF] = 1; /* set ovf indic */
|
ind[IN_OVF] = 1; /* set ovf indic */
|
||||||
qs = bsave = BS; /* quo, dividend */
|
qs = bsave = BS; /* quo, dividend */
|
||||||
do {
|
do {
|
||||||
|
@ -1485,15 +1483,15 @@ CHECK_LENGTH:
|
||||||
BS = (BS - 2) - (asave - (AS + 1)); /* final bs */
|
BS = (BS - 2) - (asave - (AS + 1)); /* final bs */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bsave = BS + (asave - ahigh); /* end subdivd */
|
bsave = BS; /* end subdivd */
|
||||||
qs = (BS - 2) - (ahigh - (AS + 1)); /* quo start */
|
qs = BS - (asave - AS) - 1; /* quo start */
|
||||||
|
|
||||||
/* Divide loop - done with subroutines to keep the code clean.
|
/* Divide loop - done with subroutines to keep the code clean.
|
||||||
In the loop,
|
In the loop,
|
||||||
|
|
||||||
asave = low order divisor
|
asave = low order divisor (constant)
|
||||||
bsave = low order subdividend
|
bsave = low order subdividend (increments)
|
||||||
qs = current quotient digit
|
qs = current quotient digit (increments)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -1504,11 +1502,13 @@ CHECK_LENGTH:
|
||||||
}
|
}
|
||||||
b = M[bsave]; /* save low divd */
|
b = M[bsave]; /* save low divd */
|
||||||
do {
|
do {
|
||||||
t = div_sub (asave, bsave, ahigh); /* subtract */
|
t = div_sub (asave, bsave); /* subtract */
|
||||||
quo++; /* incr quo digit */
|
quo++; /* incr quo digit */
|
||||||
} while (t == 0); /* until borrow */
|
} while (t == 0); /* until borrow */
|
||||||
div_add (asave, bsave, ahigh); /* restore */
|
div_add (asave, bsave); /* restore */
|
||||||
quo--;
|
quo--;
|
||||||
|
if (quo > 9) /* overflow? */
|
||||||
|
ind[IN_OVF] = 1; /* set ovf indic */
|
||||||
M[qs] = (M[qs] & WM) | sum_table[quo]; /* store quo digit */
|
M[qs] = (M[qs] & WM) | sum_table[quo]; /* store quo digit */
|
||||||
bsave++; /* adv divd, quo */
|
bsave++; /* adv divd, quo */
|
||||||
qs++;
|
qs++;
|
||||||
|
@ -1695,7 +1695,7 @@ return bin_to_bcd[addr % 10] | (thous << (V_ZONE - 2));
|
||||||
|
|
||||||
/* div_add - add string for divide */
|
/* div_add - add string for divide */
|
||||||
|
|
||||||
int32 div_add (int32 ap, int32 bp, int32 aend)
|
int32 div_add (int32 ap, int32 bp)
|
||||||
{
|
{
|
||||||
int32 a, b, c, r;
|
int32 a, b, c, r;
|
||||||
|
|
||||||
|
@ -1709,13 +1709,13 @@ do {
|
||||||
M[bp] = sum_table[r]; /* store result */
|
M[bp] = sum_table[r]; /* store result */
|
||||||
ap--;
|
ap--;
|
||||||
bp--;
|
bp--;
|
||||||
} while (ap >= aend);
|
} while ((a & WM) == 0);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* div_sub - substract string for divide */
|
/* div_sub - substract string for divide */
|
||||||
|
|
||||||
int32 div_sub (int32 ap, int32 bp, int32 aend)
|
int32 div_sub (int32 ap, int32 bp)
|
||||||
{
|
{
|
||||||
int32 a, b, c, r;
|
int32 a, b, c, r;
|
||||||
|
|
||||||
|
@ -1729,9 +1729,9 @@ do {
|
||||||
M[bp] = sum_table[r + 10]; /* store result */
|
M[bp] = sum_table[r + 10]; /* store result */
|
||||||
ap--;
|
ap--;
|
||||||
bp--;
|
bp--;
|
||||||
} while (ap >= aend);
|
} while ((a & WM) == 0);
|
||||||
b = M[bp] & CHAR; /* borrow position */
|
b = M[bp]; /* borrow position */
|
||||||
if (b && (b != BCD_ZERO)) { /* non-zero? */
|
if (bcd_to_bin[b & DIGIT] != 0) { /* non-zero? */
|
||||||
r = bcd_to_bin[b & DIGIT] - c; /* subtract borrow */
|
r = bcd_to_bin[b & DIGIT] - c; /* subtract borrow */
|
||||||
M[bp] = sum_table[r]; /* store result */
|
M[bp] = sum_table[r]; /* store result */
|
||||||
return 0; /* subtract worked */
|
return 0; /* subtract worked */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* i1401_mt.c: IBM 1401 magnetic tape simulator
|
/* i1401_mt.c: IBM 1401 magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M. Supnik
|
Copyright (c) 1993-2010, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
2005.03.08 - Started
|
2005.03.08 - Started
|
||||||
|
|
||||||
* (C) Copyright 2005, Brian Knittel.
|
* (C) Copyright 2005-2010, Brian Knittel.
|
||||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||||
|
@ -343,7 +343,7 @@ static void sca_flush (void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sca_sock != INVALID_SOCKET) {
|
if (sca_sock != INVALID_SOCKET) {
|
||||||
nbytes = sim_write_sock(sca_sock, sca_sendbuf, sca_n2send);
|
nbytes = sim_write_sock(sca_sock, (char *) sca_sendbuf, sca_n2send);
|
||||||
|
|
||||||
if (nbytes == SOCKET_ERROR)
|
if (nbytes == SOCKET_ERROR)
|
||||||
sca_socket_error();
|
sca_socket_error();
|
||||||
|
@ -655,7 +655,7 @@ static void sca_check_indata (void)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* read socket; 0 is returned if no data is available */
|
/* read socket; 0 is returned if no data is available */
|
||||||
nbytes = sim_read_sock(sca_sock, sca_rcvbuf, SCA_RCVBUF_SIZE);
|
nbytes = sim_read_sock(sca_sock, (char *) sca_rcvbuf, SCA_RCVBUF_SIZE);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_cr.c: CR/CM/CD-11 card reader simulator
|
/* pdp11_cr.c: CR/CM/CD-11 card reader simulator
|
||||||
|
|
||||||
Copyright (c) 2005-2007, John A. Dundas III
|
Copyright (c) 2005-2010, John A. Dundas III
|
||||||
Portions derived from work by Douglas W. Jones, jones@cs.uiowa.edu
|
Portions derived from work by Douglas W. Jones, jones@cs.uiowa.edu
|
||||||
Portions derived from work by Robert M Supnik
|
Portions derived from work by Robert M Supnik
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
|
03-Jan-10 JAD Eliminate gcc warnings
|
||||||
01-Feb-07 RMS Added PDP-10 support
|
01-Feb-07 RMS Added PDP-10 support
|
||||||
12-May-06 JAD Modify the DEBUG code to use the SIMH DEBUG_x
|
12-May-06 JAD Modify the DEBUG code to use the SIMH DEBUG_x
|
||||||
macros. Modify the UNIT structure to include
|
macros. Modify the UNIT structure to include
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_kg.c - Communications Arithmetic Option KG11-A
|
/* pdp11_kg.c - Communications Arithmetic Option KG11-A
|
||||||
|
|
||||||
Copyright (c) 2007-2008, John A. Dundas III
|
Copyright (c) 2007-2010, John A. Dundas III
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
kg KG11-A Communications Arithmetic Option (M7251)
|
kg KG11-A Communications Arithmetic Option (M7251)
|
||||||
|
|
||||||
|
03-Jan-10 JAD Eliminate gcc warnings
|
||||||
08-Jan-08 JAD First public release integrated with SIMH V3.7-3.
|
08-Jan-08 JAD First public release integrated with SIMH V3.7-3.
|
||||||
09-Dec-07 JAD SIMH-style debugging.
|
09-Dec-07 JAD SIMH-style debugging.
|
||||||
Finished validating against real hardware.
|
Finished validating against real hardware.
|
||||||
|
@ -178,7 +179,7 @@ static t_stat set_units (UNIT *, int32, char *, void *);
|
||||||
|
|
||||||
/* 16-bit rotate right */
|
/* 16-bit rotate right */
|
||||||
|
|
||||||
#define ROR(n,v) (((v >> n) & DMASK) | (v << (16 - n)) & DMASK)
|
#define ROR(n,v) (((v >> n) & DMASK) | ((v << (16 - n)) & DMASK))
|
||||||
|
|
||||||
/* 8-bit rotate right */
|
/* 8-bit rotate right */
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_rk.c: RK11/RKV11 cartridge disk simulator
|
/* pdp11_rk.c: RK11/RKV11 cartridge disk simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M Supnik
|
Copyright (c) 1993-2009, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
rk RK11/RKV11/RK05 cartridge disk
|
rk RK11/RKV11/RK05 cartridge disk
|
||||||
|
|
||||||
|
20-Mar-09 RMS Fixed bug in read header (from Walter F Mueller)
|
||||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||||
07-Jul-05 RMS Removed extraneous externs
|
07-Jul-05 RMS Removed extraneous externs
|
||||||
30-Sep-04 RMS Revised Unibus interface
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
|
@ -533,7 +534,7 @@ if (wc && (err == 0)) { /* seek ok? */
|
||||||
wc = i; /* trim transfer */
|
wc = i; /* trim transfer */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rkxb[i] = (cda / RK_NUMWD) / (RK_NUMSF * RK_NUMSC);
|
rkxb[i] = ((cda / RK_NUMWD) / (RK_NUMSF * RK_NUMSC)) << RKDA_V_CYL;
|
||||||
cda = cda + RK_NUMWD; /* next sector */
|
cda = cda + RK_NUMWD; /* next sector */
|
||||||
} /* end for wc */
|
} /* end for wc */
|
||||||
} /* end if format */
|
} /* end if format */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_rl.c: RL11 (RLV12) cartridge disk simulator
|
/* pdp11_rl.c: RL11 (RLV12) cartridge disk simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M Supnik
|
Copyright (c) 1993-2009, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
rl RL11(RLV12)/RL01/RL02 cartridge disk
|
rl RL11(RLV12)/RL01/RL02 cartridge disk
|
||||||
|
|
||||||
|
10-Oct-09 RMS Added debug support
|
||||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||||
07-Jul-05 RMS Removed extraneous externs
|
07-Jul-05 RMS Removed extraneous externs
|
||||||
|
@ -192,6 +193,7 @@ extern uint32 cpu_opt;
|
||||||
#define RLBAE_IMP 0000077 /* implemented */
|
#define RLBAE_IMP 0000077 /* implemented */
|
||||||
|
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
|
extern FILE *sim_deb;
|
||||||
|
|
||||||
uint16 *rlxb = NULL; /* xfer buffer */
|
uint16 *rlxb = NULL; /* xfer buffer */
|
||||||
int32 rlcs = 0; /* control/status */
|
int32 rlcs = 0; /* control/status */
|
||||||
|
@ -283,7 +285,7 @@ DEVICE rl_dev = {
|
||||||
RL_NUMDR, DEV_RDX, 24, 1, DEV_RDX, 16,
|
RL_NUMDR, DEV_RDX, 24, 1, DEV_RDX, 16,
|
||||||
NULL, NULL, &rl_reset,
|
NULL, NULL, &rl_reset,
|
||||||
&rl_boot, &rl_attach, NULL,
|
&rl_boot, &rl_attach, NULL,
|
||||||
&rl_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS
|
&rl_dib, DEV_DEBUG | DEV_DISABLE | DEV_UBUS | DEV_QBUS
|
||||||
};
|
};
|
||||||
|
|
||||||
/* I/O dispatch routines, I/O addresses 17774400 - 17774407
|
/* I/O dispatch routines, I/O addresses 17774400 - 17774407
|
||||||
|
@ -333,6 +335,9 @@ switch ((PA >> 1) & 07) { /* decode PA<2:1> */
|
||||||
break;
|
break;
|
||||||
} /* end switch */
|
} /* end switch */
|
||||||
|
|
||||||
|
if (DEBUG_PRS (rl_dev))
|
||||||
|
fprintf (sim_deb, ">>RL read: reg%d=%o\n", (PA >> 1) & 07, *data);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +346,9 @@ t_stat rl_wr (int32 data, int32 PA, int32 access)
|
||||||
int32 curr, offs, newc, maxc;
|
int32 curr, offs, newc, maxc;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
|
if (DEBUG_PRS (rl_dev))
|
||||||
|
fprintf (sim_deb, ">>RL write: reg%d=%o\n", (PA >> 1) & 07, data);
|
||||||
|
|
||||||
switch ((PA >> 1) & 07) { /* decode PA<2:1> */
|
switch ((PA >> 1) & 07) { /* decode PA<2:1> */
|
||||||
|
|
||||||
case 0: /* RLCS */
|
case 0: /* RLCS */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_rq.c: MSCP disk controller simulator
|
/* pdp11_rq.c: MSCP disk controller simulator
|
||||||
|
|
||||||
Copyright (c) 2002-2008, Robert M Supnik
|
Copyright (c) 2002-2010, Robert M Supnik
|
||||||
Derived from work by Stephen F. Shirron
|
Derived from work by Stephen F. Shirron
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
rq RQDX3 disk controller
|
rq RQDX3 disk controller
|
||||||
|
|
||||||
|
14-Jan-09 JH Added support for RD32 disc drive
|
||||||
18-Jun-07 RMS Added UNIT_IDLE flag to timer thread
|
18-Jun-07 RMS Added UNIT_IDLE flag to timer thread
|
||||||
31-Oct-05 RMS Fixed address width for large files
|
31-Oct-05 RMS Fixed address width for large files
|
||||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||||
|
@ -127,7 +128,7 @@ extern int32 cpu_opt;
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 1) /* hwre write lock */
|
#define UNIT_V_WLK (UNIT_V_UF + 1) /* hwre write lock */
|
||||||
#define UNIT_V_ATP (UNIT_V_UF + 2) /* attn pending */
|
#define UNIT_V_ATP (UNIT_V_UF + 2) /* attn pending */
|
||||||
#define UNIT_V_DTYPE (UNIT_V_UF + 3) /* drive type */
|
#define UNIT_V_DTYPE (UNIT_V_UF + 3) /* drive type */
|
||||||
#define UNIT_M_DTYPE 0xF
|
#define UNIT_M_DTYPE 0x1F
|
||||||
#define UNIT_ONL (1 << UNIT_V_ONL)
|
#define UNIT_ONL (1 << UNIT_V_ONL)
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||||
#define UNIT_ATP (1 << UNIT_V_ATP)
|
#define UNIT_ATP (1 << UNIT_V_ATP)
|
||||||
|
@ -219,7 +220,7 @@ struct rqpkt {
|
||||||
RD51 18 4 306 4 1 36*4 21600
|
RD51 18 4 306 4 1 36*4 21600
|
||||||
RD31 17 4 615 4 1 3*8 41560
|
RD31 17 4 615 4 1 3*8 41560
|
||||||
RD52 17 8 512 8 1 4*8 60480
|
RD52 17 8 512 8 1 4*8 60480
|
||||||
x RD32 17 6 820 ? ? ? 83236
|
RD32 17 6 820 6 1 4*8 83204
|
||||||
x RD33 17 7 1170 ? ? ? 138565
|
x RD33 17 7 1170 ? ? ? 138565
|
||||||
RD53 17 7 1024 7 1 5*8 138672
|
RD53 17 7 1024 7 1 5*8 138672
|
||||||
RD54 17 15 1225 15 1 7*8 311200
|
RD54 17 15 1225 15 1 7*8 311200
|
||||||
|
@ -505,6 +506,22 @@ x RA73 70(+1) 21 2667+ 21 1 ? 3920490
|
||||||
#define RA71_MED 0x25641047
|
#define RA71_MED 0x25641047
|
||||||
#define RA71_FLGS RQDF_SDI
|
#define RA71_FLGS RQDF_SDI
|
||||||
|
|
||||||
|
#define RD32_DTYPE 16
|
||||||
|
#define RD32_SECT 17
|
||||||
|
#define RD32_SURF 6
|
||||||
|
#define RD32_CYL 820
|
||||||
|
#define RD32_TPG RD32_SURF
|
||||||
|
#define RD32_GPC 1
|
||||||
|
#define RD32_XBN 54
|
||||||
|
#define RD32_DBN 48
|
||||||
|
#define RD32_LBN 83204
|
||||||
|
#define RD32_RCTS 4
|
||||||
|
#define RD32_RCTC 8
|
||||||
|
#define RD32_RBN 200
|
||||||
|
#define RD32_MOD 15
|
||||||
|
#define RD32_MED 0x25644020
|
||||||
|
#define RD32_FLGS 0
|
||||||
|
|
||||||
struct drvtyp {
|
struct drvtyp {
|
||||||
int32 sect; /* sectors */
|
int32 sect; /* sectors */
|
||||||
int32 surf; /* surfaces */
|
int32 surf; /* surfaces */
|
||||||
|
@ -539,6 +556,7 @@ static struct drvtyp drv_tab[] = {
|
||||||
{ RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" },
|
{ RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" },
|
||||||
{ RQ_DRV (RA8U), "RAUSER" }, { RQ_DRV (RA60), "RA60" },
|
{ RQ_DRV (RA8U), "RAUSER" }, { RQ_DRV (RA60), "RA60" },
|
||||||
{ RQ_DRV (RA81), "RA81" }, { RQ_DRV (RA71), "RA71" },
|
{ RQ_DRV (RA81), "RA81" }, { RQ_DRV (RA71), "RA71" },
|
||||||
|
{ RQ_DRV (RD32), "RD32" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -724,6 +742,8 @@ MTAB rq_mod[] = {
|
||||||
&rq_set_type, NULL, NULL },
|
&rq_set_type, NULL, NULL },
|
||||||
{ MTAB_XTD | MTAB_VUN, RD31_DTYPE, NULL, "RD31",
|
{ MTAB_XTD | MTAB_VUN, RD31_DTYPE, NULL, "RD31",
|
||||||
&rq_set_type, NULL, NULL },
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RD32_DTYPE, NULL, "RD32",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
{ MTAB_XTD | MTAB_VUN, RD51_DTYPE, NULL, "RD51",
|
{ MTAB_XTD | MTAB_VUN, RD51_DTYPE, NULL, "RD51",
|
||||||
&rq_set_type, NULL, NULL },
|
&rq_set_type, NULL, NULL },
|
||||||
{ MTAB_XTD | MTAB_VUN, RD52_DTYPE, NULL, "RD52",
|
{ MTAB_XTD | MTAB_VUN, RD52_DTYPE, NULL, "RD52",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_vh.c: DHQ11 asynchronous terminal multiplexor simulator
|
/* pdp11_vh.c: DHQ11 asynchronous terminal multiplexor simulator
|
||||||
|
|
||||||
Copyright (c) 2004-2008, John A. Dundas III
|
Copyright (c) 2004-2010, John A. Dundas III
|
||||||
Portions derived from work by Robert M Supnik
|
Portions derived from work by Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
vh DHQ11 asynch multiplexor for SIMH
|
vh DHQ11 asynch multiplexor for SIMH
|
||||||
|
|
||||||
|
03-Jan-10 JAD Eliminate gcc warnings
|
||||||
19-Nov-08 RMS Revised for common TMXR show routines
|
19-Nov-08 RMS Revised for common TMXR show routines
|
||||||
18-Jun-07 RMS Added UNIT_IDLE flag
|
18-Jun-07 RMS Added UNIT_IDLE flag
|
||||||
29-Oct-06 RMS Synced poll and clock
|
29-Oct-06 RMS Synced poll and clock
|
||||||
|
@ -258,13 +259,13 @@ static const int32 bitmask[4] = { 037, 077, 0177, 0377 };
|
||||||
/* RX FIFO state */
|
/* RX FIFO state */
|
||||||
|
|
||||||
static int32 rbuf_idx[VH_MUXES] = { 0 };/* index into vh_rbuf */
|
static int32 rbuf_idx[VH_MUXES] = { 0 };/* index into vh_rbuf */
|
||||||
static uint32 vh_rbuf[VH_MUXES][FIFO_SIZE] = { 0 };
|
static uint32 vh_rbuf[VH_MUXES][FIFO_SIZE] = { { 0 } };
|
||||||
|
|
||||||
/* TXQ state */
|
/* TXQ state */
|
||||||
|
|
||||||
#define TXQ_SIZE (16)
|
#define TXQ_SIZE (16)
|
||||||
static int32 txq_idx[VH_MUXES] = { 0 };
|
static int32 txq_idx[VH_MUXES] = { 0 };
|
||||||
static uint32 vh_txq[VH_MUXES][TXQ_SIZE] = { 0 };
|
static uint32 vh_txq[VH_MUXES][TXQ_SIZE] = { { 0 } };
|
||||||
|
|
||||||
/* Need to extend the TMLN structure */
|
/* Need to extend the TMLN structure */
|
||||||
|
|
||||||
|
@ -279,9 +280,9 @@ typedef struct {
|
||||||
uint16 txchar; /* single character I/O */
|
uint16 txchar; /* single character I/O */
|
||||||
} TMLX;
|
} TMLX;
|
||||||
|
|
||||||
static TMLN vh_ldsc[VH_MUXES * VH_LINES] = { 0 };
|
static TMLN vh_ldsc[VH_MUXES * VH_LINES] = { { 0 } };
|
||||||
static TMXR vh_desc = { VH_MUXES * VH_LINES, 0, 0, vh_ldsc };
|
static TMXR vh_desc = { VH_MUXES * VH_LINES, 0, 0, vh_ldsc };
|
||||||
static TMLX vh_parm[VH_MUXES * VH_LINES] = { 0 };
|
static TMLX vh_parm[VH_MUXES * VH_LINES] = { { 0 } };
|
||||||
|
|
||||||
/* Forward references */
|
/* Forward references */
|
||||||
static t_stat vh_rd (int32 *data, int32 PA, int32 access);
|
static t_stat vh_rd (int32 *data, int32 PA, int32 access);
|
||||||
|
@ -675,7 +676,7 @@ static void vh_getc ( int32 vh )
|
||||||
|
|
||||||
for (i = 0; i < VH_LINES; i++) {
|
for (i = 0; i < VH_LINES; i++) {
|
||||||
lp = &vh_parm[(vh * VH_LINES) + i];
|
lp = &vh_parm[(vh * VH_LINES) + i];
|
||||||
while (c = tmxr_getc_ln (lp->tmln)) {
|
while ((c = tmxr_getc_ln (lp->tmln)) != 0) {
|
||||||
if (c & SCPE_BREAK) {
|
if (c & SCPE_BREAK) {
|
||||||
fifo_put (vh, lp,
|
fifo_put (vh, lp,
|
||||||
RBUF_FRAME_ERR | RBUF_PUTLINE (i));
|
RBUF_FRAME_ERR | RBUF_PUTLINE (i));
|
||||||
|
@ -786,7 +787,7 @@ static t_stat vh_wr ( int32 data,
|
||||||
if (access == WRITEB)
|
if (access == WRITEB)
|
||||||
data = (PA & 1) ?
|
data = (PA & 1) ?
|
||||||
(vh_csr[vh] & 0377) | (data << 8) :
|
(vh_csr[vh] & 0377) | (data << 8) :
|
||||||
(vh_csr[vh] & ~0377) | data & 0377;
|
(vh_csr[vh] & ~0377) | (data & 0377);
|
||||||
if (data & CSR_MASTER_RESET) {
|
if (data & CSR_MASTER_RESET) {
|
||||||
if ((vh_unit[vh].flags & UNIT_MODEDHU) && (data & CSR_SKIP))
|
if ((vh_unit[vh].flags & UNIT_MODEDHU) && (data & CSR_SKIP))
|
||||||
data &= ~CSR_MASTER_RESET;
|
data &= ~CSR_MASTER_RESET;
|
||||||
|
@ -877,7 +878,7 @@ static t_stat vh_wr ( int32 data,
|
||||||
if (access == WRITEB)
|
if (access == WRITEB)
|
||||||
data = (PA & 1) ?
|
data = (PA & 1) ?
|
||||||
(lp->lpr & 0377) | (data << 8) :
|
(lp->lpr & 0377) | (data << 8) :
|
||||||
(lp->lpr & ~0377) | data & 0377;
|
(lp->lpr & ~0377) | (data & 0377);
|
||||||
/* Modify only if CSR<3:0> == 0 */
|
/* Modify only if CSR<3:0> == 0 */
|
||||||
if (CSR_GETCHAN (vh_csr[vh]) != 0)
|
if (CSR_GETCHAN (vh_csr[vh]) != 0)
|
||||||
data &= ~LPR_DISAB_XRPT;
|
data &= ~LPR_DISAB_XRPT;
|
||||||
|
@ -926,7 +927,7 @@ static t_stat vh_wr ( int32 data,
|
||||||
if (access == WRITEB)
|
if (access == WRITEB)
|
||||||
data = (PA & 1) ?
|
data = (PA & 1) ?
|
||||||
(lp->lnctrl & 0377) | (data << 8) :
|
(lp->lnctrl & 0377) | (data << 8) :
|
||||||
(lp->lnctrl & ~0377) | data & 0377;
|
(lp->lnctrl & ~0377) | (data & 0377);
|
||||||
/* catch the abort TX transition */
|
/* catch the abort TX transition */
|
||||||
if (!(lp->lnctrl & LNCTRL_TX_ABORT) &&
|
if (!(lp->lnctrl & LNCTRL_TX_ABORT) &&
|
||||||
(data & LNCTRL_TX_ABORT)) {
|
(data & LNCTRL_TX_ABORT)) {
|
||||||
|
@ -993,7 +994,7 @@ static t_stat vh_wr ( int32 data,
|
||||||
if (access == WRITEB)
|
if (access == WRITEB)
|
||||||
data = (PA & 1) ?
|
data = (PA & 1) ?
|
||||||
(lp->tbuf1 & 0377) | (data << 8) :
|
(lp->tbuf1 & 0377) | (data << 8) :
|
||||||
(lp->tbuf1 & ~0377) | data & 0377;
|
(lp->tbuf1 & ~0377) | (data & 0377);
|
||||||
lp->tbuf1 = data;
|
lp->tbuf1 = data;
|
||||||
break;
|
break;
|
||||||
case 6: /* TBUFFAD2 */
|
case 6: /* TBUFFAD2 */
|
||||||
|
@ -1008,7 +1009,7 @@ static t_stat vh_wr ( int32 data,
|
||||||
if (access == WRITEB)
|
if (access == WRITEB)
|
||||||
data = (PA & 1) ?
|
data = (PA & 1) ?
|
||||||
(lp->tbuf2 & 0377) | (data << 8) :
|
(lp->tbuf2 & 0377) | (data << 8) :
|
||||||
(lp->tbuf2 & ~0377) | data & 0377;
|
(lp->tbuf2 & ~0377) | (data & 0377);
|
||||||
lp->tbuf2 = data;
|
lp->tbuf2 = data;
|
||||||
/* if starting a DMA, clear DMA_ERR */
|
/* if starting a DMA, clear DMA_ERR */
|
||||||
if (vh_unit[vh].flags & UNIT_FASTDMA) {
|
if (vh_unit[vh].flags & UNIT_FASTDMA) {
|
||||||
|
@ -1028,7 +1029,7 @@ static t_stat vh_wr ( int32 data,
|
||||||
if (access == WRITEB)
|
if (access == WRITEB)
|
||||||
data = (PA & 1) ?
|
data = (PA & 1) ?
|
||||||
(lp->tbuffct & 0377) | (data << 8) :
|
(lp->tbuffct & 0377) | (data << 8) :
|
||||||
(lp->tbuffct & ~0377) | data & 0377;
|
(lp->tbuffct & ~0377) | (data & 0377);
|
||||||
lp->tbuffct = data;
|
lp->tbuffct = data;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
399
PDP8/pdp8_fpp.c
399
PDP8/pdp8_fpp.c
|
@ -1,6 +1,6 @@
|
||||||
/* pdp8_fpp.c: PDP-8 floating point processor (FPP8A)
|
/* pdp8_fpp.c: PDP-8 floating point processor (FPP8A)
|
||||||
|
|
||||||
Copyright (c) 2007-2008, Robert M Supnik
|
Copyright (c) 2007-2010, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,27 @@
|
||||||
|
|
||||||
fpp FPP8A floating point processor
|
fpp FPP8A floating point processor
|
||||||
|
|
||||||
|
03-Jan-10 RMS Initialized variables statically, for VMS compiler
|
||||||
|
19-Apr-09 RHM FPICL does not clear all command and status reg bits
|
||||||
|
modify fpp_reset to conform with FPP
|
||||||
|
27-Mar-09 RHM Fixed handling of Underflow fix (zero FAC on underflow)
|
||||||
|
Implemented FPP division and multiplication algorithms
|
||||||
|
FPP behavior on traps - FEXIT does not update APT
|
||||||
|
Follow FPP settings for OPADD
|
||||||
|
Correct detection of DP add/sub overflow
|
||||||
|
Detect and handle add/sub overshift
|
||||||
|
Single-step mode made consistent with FPP
|
||||||
|
Write calculation results prior to traps
|
||||||
|
24-Mar-09 RMS Many fixes from Rick Murphy:
|
||||||
|
Fix calculation of ATX shift amount
|
||||||
|
Added missing () to read, write XR macros
|
||||||
|
Fixed indirect address calculation
|
||||||
|
Fixed == written as = in normalization
|
||||||
|
Fixed off-by-one count bug in multiplication
|
||||||
|
Removed extraneous ; in divide
|
||||||
|
Fixed direction of compare in divide
|
||||||
|
Fixed count direction bug in alignment
|
||||||
|
|
||||||
Floating point formats:
|
Floating point formats:
|
||||||
|
|
||||||
00 01 02 03 04 05 06 07 08 09 10 11
|
00 01 02 03 04 05 06 07 08 09 10 11
|
||||||
|
@ -85,8 +106,8 @@ extern UNIT cpu_unit;
|
||||||
|
|
||||||
/* Index registers are in memory */
|
/* Index registers are in memory */
|
||||||
|
|
||||||
#define fpp_read_xr(xr) fpp_read (fpp_xra + xr)
|
#define fpp_read_xr(xr) fpp_read (fpp_xra + (xr))
|
||||||
#define fpp_write_xr(xr,d) fpp_write (fpp_xra +xr, d)
|
#define fpp_write_xr(xr,d) fpp_write (fpp_xra + (xr), d)
|
||||||
|
|
||||||
/* Command register */
|
/* Command register */
|
||||||
|
|
||||||
|
@ -112,8 +133,7 @@ extern UNIT cpu_unit;
|
||||||
#define FPS_IOVX 00200 /* int ovf exit */
|
#define FPS_IOVX 00200 /* int ovf exit */
|
||||||
#define FPS_FOVX 00100 /* flt ovf exit */
|
#define FPS_FOVX 00100 /* flt ovf exit */
|
||||||
#define FPS_UNF 00040 /* underflow */
|
#define FPS_UNF 00040 /* underflow */
|
||||||
#define FPS_UNFX 00020 /* undf exit */
|
#define FPS_XXXM 00020 /* FADDM/FMULM */
|
||||||
#define FPS_XXXM 00010 /* FADDM/FMULM */
|
|
||||||
#define FPS_LOCK (FPC_LOCK) /* lockout */
|
#define FPS_LOCK (FPC_LOCK) /* lockout */
|
||||||
#define FPS_EP 00004 /* ext prec */
|
#define FPS_EP 00004 /* ext prec */
|
||||||
#define FPS_PAUSE 00002 /* paused */
|
#define FPS_PAUSE 00002 /* paused */
|
||||||
|
@ -124,24 +144,28 @@ extern UNIT cpu_unit;
|
||||||
#define FPN_FRSIGN 04000
|
#define FPN_FRSIGN 04000
|
||||||
#define FPN_NFR_FP 2 /* std precision */
|
#define FPN_NFR_FP 2 /* std precision */
|
||||||
#define FPN_NFR_EP 5 /* ext precision */
|
#define FPN_NFR_EP 5 /* ext precision */
|
||||||
|
#define FPN_NFR_MDS 6 /* mul/div precision */
|
||||||
#define EXACT (uint32)((fpp_sta & FPS_EP)? FPN_NFR_EP: FPN_NFR_FP)
|
#define EXACT (uint32)((fpp_sta & FPS_EP)? FPN_NFR_EP: FPN_NFR_FP)
|
||||||
#define EXTEND ((uint32) FPN_NFR_EP)
|
#define EXTEND ((uint32) FPN_NFR_EP)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32 exp;
|
int32 exp;
|
||||||
uint32 fr[FPN_NFR_EP];
|
uint32 fr[FPN_NFR_MDS+1];
|
||||||
} FPN;
|
} FPN;
|
||||||
|
|
||||||
uint32 fpp_apta; /* APT pointer */
|
uint32 fpp_apta = 0; /* APT pointer */
|
||||||
uint32 fpp_aptsvf; /* APT saved field */
|
uint32 fpp_aptsvf = 0; /* APT saved field */
|
||||||
uint32 fpp_opa; /* operand pointer */
|
uint32 fpp_opa = 0; /* operand pointer */
|
||||||
uint32 fpp_fpc; /* FP PC */
|
uint32 fpp_fpc = 0; /* FP PC */
|
||||||
uint32 fpp_bra; /* base reg pointer */
|
uint32 fpp_bra = 0; /* base reg pointer */
|
||||||
uint32 fpp_xra; /* indx reg pointer */
|
uint32 fpp_xra = 0; /* indx reg pointer */
|
||||||
uint32 fpp_cmd; /* command */
|
uint32 fpp_cmd = 0; /* command */
|
||||||
uint32 fpp_sta; /* status */
|
uint32 fpp_sta = 0; /* status */
|
||||||
uint32 fpp_flag; /* flag */
|
uint32 fpp_flag = 0; /* flag */
|
||||||
FPN fpp_ac; /* FAC */
|
FPN fpp_ac; /* FAC */
|
||||||
|
uint32 fpp_ssf = 0; /* single-step flag */
|
||||||
|
uint32 fpp_last_lockbit = 0; /* last lockbit */
|
||||||
|
|
||||||
static FPN fpp_zero = { 0, { 0, 0, 0, 0, 0 } };
|
static FPN fpp_zero = { 0, { 0, 0, 0, 0, 0 } };
|
||||||
static FPN fpp_one = { 1, { 02000, 0, 0, 0, 0 } };
|
static FPN fpp_one = { 1, { 02000, 0, 0, 0, 0 } };
|
||||||
|
|
||||||
|
@ -155,13 +179,13 @@ uint32 fpp_2wd_dir (uint32 ir);
|
||||||
uint32 fpp_indir (uint32 ir);
|
uint32 fpp_indir (uint32 ir);
|
||||||
uint32 fpp_ad15 (uint32 hi);
|
uint32 fpp_ad15 (uint32 hi);
|
||||||
uint32 fpp_adxr (uint32 ir, uint32 base_ad);
|
uint32 fpp_adxr (uint32 ir, uint32 base_ad);
|
||||||
t_bool fpp_add (FPN *a, FPN *b, uint32 sub);
|
void fpp_add (FPN *a, FPN *b, uint32 sub);
|
||||||
t_bool fpp_mul (FPN *a, FPN *b);
|
void fpp_mul (FPN *a, FPN *b);
|
||||||
t_bool fpp_div (FPN *a, FPN *b);
|
void fpp_div (FPN *a, FPN *b);
|
||||||
t_bool fpp_imul (FPN *a, FPN *b);
|
t_bool fpp_imul (FPN *a, FPN *b);
|
||||||
uint32 fpp_fr_add (uint32 *c, uint32 *a, uint32 *b);
|
uint32 fpp_fr_add (uint32 *c, uint32 *a, uint32 *b, uint32 cnt);
|
||||||
void fpp_fr_sub (uint32 *c, uint32 *a, uint32 *b);
|
void fpp_fr_sub (uint32 *c, uint32 *a, uint32 *b, uint32 cnt);
|
||||||
void fpp_fr_mul (uint32 *c, uint32 *a, uint32 *b);
|
void fpp_fr_mul (uint32 *c, uint32 *a, uint32 *b, t_bool fix);
|
||||||
t_bool fpp_fr_div (uint32 *c, uint32 *a, uint32 *b);
|
t_bool fpp_fr_div (uint32 *c, uint32 *a, uint32 *b);
|
||||||
uint32 fpp_fr_neg (uint32 *a, uint32 cnt);
|
uint32 fpp_fr_neg (uint32 *a, uint32 cnt);
|
||||||
int32 fpp_fr_cmp (uint32 *a, uint32 *b, uint32 cnt);
|
int32 fpp_fr_cmp (uint32 *a, uint32 *b, uint32 cnt);
|
||||||
|
@ -214,6 +238,8 @@ REG fpp_reg[] = {
|
||||||
{ ORDATA (BRA, fpp_bra, 15) },
|
{ ORDATA (BRA, fpp_bra, 15) },
|
||||||
{ ORDATA (XRA, fpp_xra, 15) },
|
{ ORDATA (XRA, fpp_xra, 15) },
|
||||||
{ ORDATA (OPA, fpp_opa, 15) },
|
{ ORDATA (OPA, fpp_opa, 15) },
|
||||||
|
{ ORDATA (SSF, fpp_ssf, 12) },
|
||||||
|
{ ORDATA (LASTLOCK, fpp_last_lockbit, 12) },
|
||||||
{ FLDATA (FLAG, fpp_flag, 0) },
|
{ FLDATA (FLAG, fpp_flag, 0) },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
@ -242,6 +268,7 @@ switch (IR & 07) { /* decode IR<9:11> */
|
||||||
case 3: /* FPCOM */
|
case 3: /* FPCOM */
|
||||||
if (!fpp_flag && !(fpp_sta & FPS_RUN)) { /* flag clr, !run? */
|
if (!fpp_flag && !(fpp_sta & FPS_RUN)) { /* flag clr, !run? */
|
||||||
fpp_cmd = AC; /* load cmd */
|
fpp_cmd = AC; /* load cmd */
|
||||||
|
fpp_last_lockbit = fpp_cmd & FPS_LOCK; /* remember lock state */
|
||||||
fpp_sta = (fpp_sta & ~FPC_STA) | /* copy flags */
|
fpp_sta = (fpp_sta & ~FPC_STA) | /* copy flags */
|
||||||
(fpp_cmd & FPC_STA); /* to status */
|
(fpp_cmd & FPC_STA); /* to status */
|
||||||
}
|
}
|
||||||
|
@ -251,16 +278,25 @@ switch (IR & 07) { /* decode IR<9:11> */
|
||||||
if (fpp_sta & FPS_RUN) { /* running? */
|
if (fpp_sta & FPS_RUN) { /* running? */
|
||||||
if (fpp_sta & FPS_PAUSE) /* paused? */
|
if (fpp_sta & FPS_PAUSE) /* paused? */
|
||||||
fpp_fpc = (fpp_fpc - 1) & ADDRMASK; /* decr FPC */
|
fpp_fpc = (fpp_fpc - 1) & ADDRMASK; /* decr FPC */
|
||||||
|
fpp_sta &= ~FPS_PAUSE; /* no longer paused */
|
||||||
sim_cancel (&fpp_unit); /* stop execution */
|
sim_cancel (&fpp_unit); /* stop execution */
|
||||||
fpp_dump_apt (fpp_apta, FPS_HLTX); /* dump APT */
|
fpp_dump_apt (fpp_apta, FPS_HLTX); /* dump APT */
|
||||||
|
fpp_ssf = 1; /* assume sstep */
|
||||||
}
|
}
|
||||||
else sim_activate (&fpp_unit, 0); /* single step */
|
else if (!fpp_flag)
|
||||||
|
fpp_ssf = 1; /* FPST sing steps */
|
||||||
|
if (fpp_sta & FPS_DVZX) /* fix diag timing */
|
||||||
|
fpp_sta |= FPS_HLTX;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: /* FPST */
|
case 5: /* FPST */
|
||||||
if (!fpp_flag && !(fpp_sta & FPS_RUN)) { /* flag clr, !run? */
|
if (!fpp_flag && !(fpp_sta & FPS_RUN)) { /* flag clr, !run? */
|
||||||
|
if (fpp_ssf)
|
||||||
|
fpp_sta |= fpp_last_lockbit;
|
||||||
|
fpp_sta &= ~FPS_HLTX; /* Clear halted */
|
||||||
fpp_apta = (FPC_GETAPTF (fpp_cmd) << 12) | AC;
|
fpp_apta = (FPC_GETAPTF (fpp_cmd) << 12) | AC;
|
||||||
fpp_load_apt (fpp_apta); /* load APT */
|
fpp_load_apt (fpp_apta); /* load APT */
|
||||||
|
fpp_opa = fpp_fpc;
|
||||||
sim_activate (&fpp_unit, 0); /* start unit */
|
sim_activate (&fpp_unit, 0); /* start unit */
|
||||||
return IOT_SKP | AC;
|
return IOT_SKP | AC;
|
||||||
}
|
}
|
||||||
|
@ -278,7 +314,7 @@ switch (IR & 07) { /* decode IR<9:11> */
|
||||||
if (fpp_flag) { /* if flag set */
|
if (fpp_flag) { /* if flag set */
|
||||||
uint32 old_sta = fpp_sta;
|
uint32 old_sta = fpp_sta;
|
||||||
fpp_flag = 0; /* clr flag, status */
|
fpp_flag = 0; /* clr flag, status */
|
||||||
fpp_sta = 0;
|
fpp_sta &= ~(FPS_DP|FPS_EP|FPS_TRPX|FPS_DVZX|FPS_IOVX|FPS_FOVX|FPS_UNF);
|
||||||
int_req &= ~INT_FPP; /* clr int req */
|
int_req &= ~INT_FPP; /* clr int req */
|
||||||
return IOT_SKP | old_sta; /* ret old status */
|
return IOT_SKP | old_sta; /* ret old status */
|
||||||
}
|
}
|
||||||
|
@ -296,8 +332,10 @@ int32 fpp56 (int32 IR, int32 AC)
|
||||||
switch (IR & 07) { /* decode IR<9:11> */
|
switch (IR & 07) { /* decode IR<9:11> */
|
||||||
|
|
||||||
case 7: /* FPEP */
|
case 7: /* FPEP */
|
||||||
if ((AC & 04000) && !(fpp_sta & FPS_RUN)) /* if AC0, not run, */
|
if ((AC & 04000) && !(fpp_sta & FPS_RUN)) { /* if AC0, not run, */
|
||||||
fpp_sta = (fpp_sta | FPS_EP) & ~FPS_DP; /* set ep */
|
fpp_sta = (fpp_sta | FPS_EP) & ~FPS_DP; /* set ep */
|
||||||
|
AC = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -314,6 +352,7 @@ t_stat fpp_svc (UNIT *uptr)
|
||||||
FPN x;
|
FPN x;
|
||||||
uint32 ir, op, op2, op3, ad, ea, wd;
|
uint32 ir, op, op2, op3, ad, ea, wd;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
|
int32 sc;
|
||||||
|
|
||||||
fpp_ac.exp = SEXT12 (fpp_ac.exp); /* sext AC exp */
|
fpp_ac.exp = SEXT12 (fpp_ac.exp); /* sext AC exp */
|
||||||
do { /* repeat */
|
do { /* repeat */
|
||||||
|
@ -332,6 +371,10 @@ do { /* repeat */
|
||||||
switch (op3) { /* case on subsubop */
|
switch (op3) { /* case on subsubop */
|
||||||
|
|
||||||
case 0: /* FEXIT */
|
case 0: /* FEXIT */
|
||||||
|
/* if already trapped, don't update APT, just update status */
|
||||||
|
if (fpp_sta & (FPS_DVZX|FPS_IOVX|FPS_FOVX|FPS_UNF))
|
||||||
|
fpp_sta |= FPS_HLTX;
|
||||||
|
else
|
||||||
fpp_dump_apt (fpp_apta, 0);
|
fpp_dump_apt (fpp_apta, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -351,7 +394,6 @@ do { /* repeat */
|
||||||
if (!(fpp_sta & FPS_DP)) { /* fp or ep only */
|
if (!(fpp_sta & FPS_DP)) { /* fp or ep only */
|
||||||
fpp_copy (&x, &fpp_ac); /* copy AC */
|
fpp_copy (&x, &fpp_ac); /* copy AC */
|
||||||
fpp_norm (&x, EXACT); /* do exact length */
|
fpp_norm (&x, EXACT); /* do exact length */
|
||||||
if (!fpp_test_xp (&x)) /* no trap? */
|
|
||||||
fpp_copy (&fpp_ac, &x); /* copy back */
|
fpp_copy (&fpp_ac, &x); /* copy back */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -360,7 +402,6 @@ do { /* repeat */
|
||||||
if (fpp_sta & FPS_EP) { /* if ep, */
|
if (fpp_sta & FPS_EP) { /* if ep, */
|
||||||
fpp_copy (&x, &fpp_ac); /* copy AC */
|
fpp_copy (&x, &fpp_ac); /* copy AC */
|
||||||
fpp_round (&x); /* round */
|
fpp_round (&x); /* round */
|
||||||
if (!fpp_test_xp (&x)) /* no trap? */
|
|
||||||
fpp_copy (&fpp_ac, &x); /* copy back */
|
fpp_copy (&fpp_ac, &x); /* copy back */
|
||||||
}
|
}
|
||||||
fpp_sta &= ~(FPS_DP|FPS_EP);
|
fpp_sta &= ~(FPS_DP|FPS_EP);
|
||||||
|
@ -377,17 +418,22 @@ do { /* repeat */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 001: /* ALN */
|
case 001: /* ALN */
|
||||||
if (op3 != 0) /* if xr, */
|
if (op3 != 0) { /* if xr, */
|
||||||
wd = fpp_read_xr (op3); /* use val */
|
wd = fpp_read_xr (op3); /* use val */
|
||||||
|
fpp_opa = fpp_xra + op3;
|
||||||
|
}
|
||||||
else wd = 027; /* else 23 */
|
else wd = 027; /* else 23 */
|
||||||
if (!(fpp_sta & FPS_DP)) { /* fp or ep? */
|
if (!(fpp_sta & FPS_DP)) { /* fp or ep? */
|
||||||
int32 t = wd - fpp_ac.exp; /* alignment */
|
sc = (SEXT12(wd) - fpp_ac.exp) & 07777; /* alignment */
|
||||||
fpp_ac.exp = SEXT12 (wd); /* new exp */
|
sc = SEXT12 (sc);
|
||||||
wd = t & 07777;
|
fpp_ac.exp = SEXT12(wd); /* new exp */
|
||||||
}
|
}
|
||||||
if (wd & 04000) /* left? */
|
else sc = SEXT12 (wd); /* dp - simple cnt */
|
||||||
fpp_fr_lshn (fpp_ac.fr, 04000 - wd, EXACT);
|
if (sc < 0) /* left? */
|
||||||
else fpp_fr_algn (fpp_ac.fr, wd, EXACT);
|
fpp_fr_lshn (fpp_ac.fr, -sc, EXACT);
|
||||||
|
else fpp_fr_algn (fpp_ac.fr, sc, EXACT);
|
||||||
|
if (fpp_fr_test (fpp_ac.fr, 0, EXACT) == 0) /* zero? */
|
||||||
|
fpp_ac.exp = 0; /* clean exp */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 002: /* ATX */
|
case 002: /* ATX */
|
||||||
|
@ -395,10 +441,10 @@ do { /* repeat */
|
||||||
fpp_write_xr (op3, fpp_ac.fr[1]); /* xr<-FAC<12:23> */
|
fpp_write_xr (op3, fpp_ac.fr[1]); /* xr<-FAC<12:23> */
|
||||||
else {
|
else {
|
||||||
fpp_copy (&x, &fpp_ac); /* copy AC */
|
fpp_copy (&x, &fpp_ac); /* copy AC */
|
||||||
wd = (fpp_ac.exp - 027) & 07777; /* shift amt */
|
sc = 027 - x.exp; /* shift amt */
|
||||||
if (wd & 04000) /* left? */
|
if (sc < 0) /* left? */
|
||||||
fpp_fr_lshn (x.fr, 04000 - wd, EXACT);
|
fpp_fr_lshn (x.fr, -sc, EXACT);
|
||||||
else fpp_fr_algn (x.fr, wd, EXACT);
|
else fpp_fr_algn (x.fr, sc, EXACT);
|
||||||
fpp_write_xr (op3, x.fr[1]); /* xr<-val<12:23> */
|
fpp_write_xr (op3, x.fr[1]); /* xr<-val<12:23> */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -411,10 +457,11 @@ do { /* repeat */
|
||||||
x.exp = 027; /* standard exp */
|
x.exp = 027; /* standard exp */
|
||||||
if (!(fpp_sta & FPS_DP)) { /* fp or ep? */
|
if (!(fpp_sta & FPS_DP)) { /* fp or ep? */
|
||||||
fpp_norm (&x, EXACT); /* normalize */
|
fpp_norm (&x, EXACT); /* normalize */
|
||||||
if (fpp_test_xp (&x)) /* exception? */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
fpp_copy (&fpp_ac, &x); /* result to AC */
|
fpp_copy (&fpp_ac, &x); /* result to AC */
|
||||||
|
if (fpp_sta & FPS_DP) /* dp skips exp */
|
||||||
|
fpp_ac.exp = x.exp; /* so force copy */
|
||||||
|
fpp_opa = fpp_xra + op3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 004: /* NOP */
|
case 004: /* NOP */
|
||||||
|
@ -431,12 +478,14 @@ do { /* repeat */
|
||||||
case 010: /* LDX */
|
case 010: /* LDX */
|
||||||
wd = fpp_ad15 (0); /* load XR immed */
|
wd = fpp_ad15 (0); /* load XR immed */
|
||||||
fpp_write_xr (op3, wd);
|
fpp_write_xr (op3, wd);
|
||||||
|
fpp_opa = fpp_xra + op3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 011: /* ADDX */
|
case 011: /* ADDX */
|
||||||
wd = fpp_ad15 (0);
|
wd = fpp_ad15 (0);
|
||||||
wd = wd + fpp_read_xr (op3); /* add to XR immed */
|
wd = wd + fpp_read_xr (op3); /* add to XR immed */
|
||||||
fpp_write_xr (op3, wd); /* trims to 12b */
|
fpp_write_xr (op3, wd); /* trims to 12b */
|
||||||
|
fpp_opa = fpp_xra + op3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -452,6 +501,9 @@ do { /* repeat */
|
||||||
case 002:
|
case 002:
|
||||||
ea = fpp_2wd_dir (ir);
|
ea = fpp_2wd_dir (ir);
|
||||||
fpp_read_op (ea, &fpp_ac);
|
fpp_read_op (ea, &fpp_ac);
|
||||||
|
if (fpp_sta & FPS_DP)
|
||||||
|
fpp_opa = ea + 1;
|
||||||
|
else fpp_opa = ea + 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 003:
|
case 003:
|
||||||
|
@ -481,12 +533,13 @@ do { /* repeat */
|
||||||
fpp_write (ad, 01030 + (fpp_fpc >> 12)); /* save return */
|
fpp_write (ad, 01030 + (fpp_fpc >> 12)); /* save return */
|
||||||
fpp_write (ad + 1, fpp_fpc); /* trims to 12b */
|
fpp_write (ad + 1, fpp_fpc); /* trims to 12b */
|
||||||
fpp_fpc = (ad + 2) & ADDRMASK;
|
fpp_fpc = (ad + 2) & ADDRMASK;
|
||||||
|
fpp_opa = fpp_fpc - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 013: /* JSR */
|
case 013: /* JSR */
|
||||||
fpp_write (fpp_bra + 1, 01030 + (fpp_fpc >> 12));
|
fpp_write (fpp_bra + 1, 01030 + (fpp_fpc >> 12));
|
||||||
fpp_write (fpp_bra + 2, fpp_fpc); /* trims to 12b */
|
fpp_write (fpp_bra + 2, fpp_fpc); /* trims to 12b */
|
||||||
fpp_fpc = ad;
|
fpp_opa = fpp_fpc = ad;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -512,17 +565,18 @@ do { /* repeat */
|
||||||
fpp_add (&fpp_ac, &x, 0);
|
fpp_add (&fpp_ac, &x, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 010: /* JNX */
|
case 010: { /* JNX */
|
||||||
|
uint32 xrn = op2 & 07;
|
||||||
ad = fpp_ad15 (op3); /* get 15b addr */
|
ad = fpp_ad15 (op3); /* get 15b addr */
|
||||||
wd = fpp_read_xr (op2 & 07); /* read xr */
|
wd = fpp_read_xr (xrn); /* read xr */
|
||||||
if (ir & 00100) { /* inc? */
|
if (op2 & 010) { /* inc? */
|
||||||
wd = (wd + 1) & 07777;
|
wd = (wd + 1) & 07777;
|
||||||
fpp_write_xr (op2 & 07, wd); /* ++xr */
|
fpp_write_xr (xrn, wd); /* ++xr */
|
||||||
}
|
}
|
||||||
if (wd != 0) /* xr != 0? */
|
if (wd != 0) /* xr != 0? */
|
||||||
fpp_fpc = ad; /* jump */
|
fpp_fpc = ad; /* jump */
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 011: /* FSUB */
|
case 011: /* FSUB */
|
||||||
ea = fpp_1wd_dir (ir);
|
ea = fpp_1wd_dir (ir);
|
||||||
fpp_read_op (ea, &x);
|
fpp_read_op (ea, &x);
|
||||||
|
@ -591,7 +645,7 @@ do { /* repeat */
|
||||||
fpp_sta |= FPS_XXXM;
|
fpp_sta |= FPS_XXXM;
|
||||||
ea = fpp_1wd_dir (ir);
|
ea = fpp_1wd_dir (ir);
|
||||||
fpp_read_op (ea, &x);
|
fpp_read_op (ea, &x);
|
||||||
if (!fpp_add (&x, &fpp_ac, 0)) /* no trap? */
|
fpp_add (&x, &fpp_ac, 0);
|
||||||
fpp_write_op (ea, &x); /* store result */
|
fpp_write_op (ea, &x); /* store result */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -599,7 +653,7 @@ do { /* repeat */
|
||||||
fpp_sta |= FPS_XXXM;
|
fpp_sta |= FPS_XXXM;
|
||||||
ea = fpp_2wd_dir (ir);
|
ea = fpp_2wd_dir (ir);
|
||||||
fpp_read_op (ea, &x);
|
fpp_read_op (ea, &x);
|
||||||
if (!fpp_add (&x, &fpp_ac, 0)) /* no trap? */
|
fpp_add (&x, &fpp_ac, 0);
|
||||||
fpp_write_op (ea, &x); /* store result */
|
fpp_write_op (ea, &x); /* store result */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -607,7 +661,7 @@ do { /* repeat */
|
||||||
fpp_sta |= FPS_XXXM;
|
fpp_sta |= FPS_XXXM;
|
||||||
ea = fpp_indir (ir);
|
ea = fpp_indir (ir);
|
||||||
fpp_read_op (ea, &x);
|
fpp_read_op (ea, &x);
|
||||||
if (!fpp_add (&x, &fpp_ac, 0)) /* no trap? */
|
fpp_add (&x, &fpp_ac, 0);
|
||||||
fpp_write_op (ea, &x); /* store result */
|
fpp_write_op (ea, &x); /* store result */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -649,6 +703,7 @@ do { /* repeat */
|
||||||
fpp_sta = (fpp_sta | FPS_DP) & ~FPS_EP; /* set dp */
|
fpp_sta = (fpp_sta | FPS_DP) & ~FPS_EP; /* set dp */
|
||||||
fpp_ac.fr[0] = (ea >> 12) & 07;
|
fpp_ac.fr[0] = (ea >> 12) & 07;
|
||||||
fpp_ac.fr[1] = ea & 07777;
|
fpp_ac.fr[1] = ea & 07777;
|
||||||
|
fpp_opa = ea;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -656,7 +711,7 @@ do { /* repeat */
|
||||||
fpp_sta |= FPS_XXXM;
|
fpp_sta |= FPS_XXXM;
|
||||||
ea = fpp_1wd_dir (ir);
|
ea = fpp_1wd_dir (ir);
|
||||||
fpp_read_op (ea, &x);
|
fpp_read_op (ea, &x);
|
||||||
if (!fpp_mul (&x, &fpp_ac)) /* no trap? */
|
fpp_mul (&x, &fpp_ac);
|
||||||
fpp_write_op (ea, &x); /* store result */
|
fpp_write_op (ea, &x); /* store result */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -664,7 +719,7 @@ do { /* repeat */
|
||||||
fpp_sta |= FPS_XXXM;
|
fpp_sta |= FPS_XXXM;
|
||||||
ea = fpp_2wd_dir (ir);
|
ea = fpp_2wd_dir (ir);
|
||||||
fpp_read_op (ea, &x);
|
fpp_read_op (ea, &x);
|
||||||
if (!fpp_mul (&x, &fpp_ac)) /* no trap? */
|
fpp_mul (&x, &fpp_ac);
|
||||||
fpp_write_op (ea, &x); /* store result */
|
fpp_write_op (ea, &x); /* store result */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -672,11 +727,16 @@ do { /* repeat */
|
||||||
fpp_sta |= FPS_XXXM;
|
fpp_sta |= FPS_XXXM;
|
||||||
ea = fpp_indir (ir);
|
ea = fpp_indir (ir);
|
||||||
fpp_read_op (ea, &x);
|
fpp_read_op (ea, &x);
|
||||||
if (!fpp_mul (&x, &fpp_ac)) /* no trap? */
|
fpp_mul (&x, &fpp_ac);
|
||||||
fpp_write_op (ea, &x); /* store result */
|
fpp_write_op (ea, &x); /* store result */
|
||||||
break;
|
break;
|
||||||
} /* end sw op+mode */
|
} /* end sw op+mode */
|
||||||
|
|
||||||
|
if (fpp_ssf) {
|
||||||
|
fpp_dump_apt (fpp_apta, FPS_HLTX); /* dump APT */
|
||||||
|
fpp_ssf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (sim_interval)
|
if (sim_interval)
|
||||||
sim_interval = sim_interval - 1;
|
sim_interval = sim_interval - 1;
|
||||||
} while ((sim_interval > 0) &&
|
} while ((sim_interval > 0) &&
|
||||||
|
@ -696,7 +756,11 @@ uint32 ad;
|
||||||
ad = fpp_bra + ((ir & 0177) * 3); /* base + 3*7b off */
|
ad = fpp_bra + ((ir & 0177) * 3); /* base + 3*7b off */
|
||||||
if (fpp_sta & FPS_DP) /* dp? skip exp */
|
if (fpp_sta & FPS_DP) /* dp? skip exp */
|
||||||
ad = ad + 1;
|
ad = ad + 1;
|
||||||
return ad & ADDRMASK;
|
ad = ad & ADDRMASK;
|
||||||
|
if (fpp_sta & FPS_DP)
|
||||||
|
fpp_opa = ad + 1;
|
||||||
|
else fpp_opa = ad + 2;
|
||||||
|
return ad;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 fpp_2wd_dir (uint32 ir)
|
uint32 fpp_2wd_dir (uint32 ir)
|
||||||
|
@ -709,13 +773,18 @@ return fpp_adxr (ir, ad); /* do indexing */
|
||||||
|
|
||||||
uint32 fpp_indir (uint32 ir)
|
uint32 fpp_indir (uint32 ir)
|
||||||
{
|
{
|
||||||
uint32 ad, iad, wd1, wd2;
|
uint32 ad, wd1, wd2;
|
||||||
|
|
||||||
ad = fpp_bra + ((ir & 07) * 3); /* base + 3*3b off */
|
ad = fpp_bra + ((ir & 07) * 3); /* base + 3*3b off */
|
||||||
iad = fpp_adxr (ir, ad); /* do indexing */
|
wd1 = fpp_read (ad + 1); /* bp+off points to */
|
||||||
wd1 = fpp_read (iad + 1); /* read wds 2,3 */
|
wd2 = fpp_read (ad + 2);
|
||||||
wd2 = fpp_read (iad + 2);
|
ad = ((wd1 & 07) << 12) | wd2; /* indirect ptr */
|
||||||
return ((wd1 & 07) << 12) | wd2; /* return addr */
|
|
||||||
|
ad = fpp_adxr (ir, ad); /* do indexing */
|
||||||
|
if (fpp_sta & FPS_DP)
|
||||||
|
fpp_opa = ad + 1;
|
||||||
|
else fpp_opa = ad + 2;
|
||||||
|
return ad;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 fpp_ad15 (uint32 hi)
|
uint32 fpp_ad15 (uint32 hi)
|
||||||
|
@ -738,8 +807,10 @@ if (ir & 0100) { /* increment? */
|
||||||
fpp_write_xr (xr, wd);
|
fpp_write_xr (xr, wd);
|
||||||
}
|
}
|
||||||
if (xr != 0) { /* indexed? */
|
if (xr != 0) { /* indexed? */
|
||||||
if (fpp_sta & FPS_EP) wd = wd * 6; /* scale by len */
|
if (fpp_sta & FPS_EP)
|
||||||
else if (fpp_sta & FPS_DP) wd = wd * 2;
|
wd = wd * 6; /* scale by len */
|
||||||
|
else if (fpp_sta & FPS_DP)
|
||||||
|
wd = wd * 2;
|
||||||
else wd = wd * 3;
|
else wd = wd * 3;
|
||||||
return (base_ad + wd) & ADDRMASK; /* return index */
|
return (base_ad + wd) & ADDRMASK; /* return index */
|
||||||
}
|
}
|
||||||
|
@ -748,22 +819,28 @@ else return base_ad & ADDRMASK; /* return addr */
|
||||||
|
|
||||||
/* Computation routines */
|
/* Computation routines */
|
||||||
|
|
||||||
/* Fraction/floating add - return true if overflow */
|
/* Fraction/floating add */
|
||||||
|
|
||||||
t_bool fpp_add (FPN *a, FPN *b, uint32 sub)
|
void fpp_add (FPN *a, FPN *b, uint32 sub)
|
||||||
{
|
{
|
||||||
FPN x, y, z;
|
FPN x, y, z;
|
||||||
uint32 ediff, c;
|
uint32 c, ediff;
|
||||||
|
|
||||||
fpp_zcopy (&x, a); /* copy opnds */
|
fpp_zcopy (&x, a); /* copy opnds */
|
||||||
fpp_zcopy (&y, b);
|
fpp_zcopy (&y, b);
|
||||||
if (sub) /* subtract? */
|
if (sub) /* subtract? */
|
||||||
fpp_fr_neg (y.fr, EXACT); /* neg B, exact */
|
fpp_fr_neg (y.fr, EXACT); /* neg B, exact */
|
||||||
if (fpp_sta & FPS_DP) { /* dp? */
|
if (fpp_sta & FPS_DP) { /* dp? */
|
||||||
fpp_fr_add (z.fr, x.fr, y.fr); /* z = a + b */
|
uint32 cout = fpp_fr_add (z.fr, x.fr, y.fr, EXTEND);/* z = a + b */
|
||||||
if ((~x.fr[0] ^ y.fr[0]) & (x.fr[0] ^ z.fr[0]) & FPN_FRSIGN) {
|
uint32 zsign = z.fr[0] & FPN_FRSIGN;
|
||||||
|
cout = (cout? 04000: 0); /* make sign bit */
|
||||||
|
/* overflow is indicated when signs are equal and overflow does not
|
||||||
|
match the result sign bit */
|
||||||
|
fpp_copy (a, &z); /* result is z */
|
||||||
|
if (!((x.fr[0] ^ y.fr[0]) & FPN_FRSIGN) && (cout != zsign)) {
|
||||||
|
fpp_copy (a, &z); /* copy out result */
|
||||||
fpp_dump_apt (fpp_apta, FPS_IOVX); /* int ovf? */
|
fpp_dump_apt (fpp_apta, FPS_IOVX); /* int ovf? */
|
||||||
return TRUE;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { /* fp or ep */
|
else { /* fp or ep */
|
||||||
|
@ -778,11 +855,11 @@ else { /* fp or ep */
|
||||||
y = z;
|
y = z;
|
||||||
}
|
}
|
||||||
ediff = x.exp - y.exp; /* exp diff */
|
ediff = x.exp - y.exp; /* exp diff */
|
||||||
|
if (ediff <= (uint32) ((fpp_sta & FPS_EP)? 59: 24)) { /* any add? */
|
||||||
z.exp = x.exp; /* result exp */
|
z.exp = x.exp; /* result exp */
|
||||||
if (ediff <= (fpp_sta & FPS_EP)? 59: 24) { /* any add? */
|
|
||||||
if (ediff != 0) /* any align? */
|
if (ediff != 0) /* any align? */
|
||||||
fpp_fr_algn (y.fr, ediff, EXTEND); /* align, 60b */
|
fpp_fr_algn (y.fr, ediff, EXTEND); /* align, 60b */
|
||||||
c = fpp_fr_add (z.fr, x.fr, y.fr); /* add fractions */
|
c = fpp_fr_add (z.fr, x.fr, y.fr, EXTEND); /* add fractions */
|
||||||
if ((((x.fr[0] ^ y.fr[0]) & FPN_FRSIGN) == 0) && /* same signs? */
|
if ((((x.fr[0] ^ y.fr[0]) & FPN_FRSIGN) == 0) && /* same signs? */
|
||||||
(c || /* carry out? */
|
(c || /* carry out? */
|
||||||
((~x.fr[0] & z.fr[0] & FPN_FRSIGN)))) { /* + to - change? */
|
((~x.fr[0] & z.fr[0] & FPN_FRSIGN)))) { /* + to - change? */
|
||||||
|
@ -790,57 +867,66 @@ else { /* fp or ep */
|
||||||
z.exp = z.exp + 1; /* incr exp */
|
z.exp = z.exp + 1; /* incr exp */
|
||||||
} /* end same signs */
|
} /* end same signs */
|
||||||
} /* end in range */
|
} /* end in range */
|
||||||
|
else z = x; /* ovrshift */
|
||||||
} /* end ops != 0 */
|
} /* end ops != 0 */
|
||||||
if (fpp_norm (&z, EXTEND)) /* norm, !exact? */
|
if (fpp_norm (&z, EXTEND)) /* norm, !exact? */
|
||||||
fpp_round (&z); /* round */
|
fpp_round (&z); /* round */
|
||||||
if (fpp_test_xp (&z)) /* ovf, unf? */
|
fpp_copy (a, &z); /* copy out */
|
||||||
return TRUE;
|
fpp_test_xp (&z); /* ovf, unf? */
|
||||||
} /* end else */
|
} /* end else */
|
||||||
fpp_copy (a, &z); /* result is z */
|
return;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fraction/floating multiply - return true if overflow */
|
/* Fraction/floating multiply */
|
||||||
|
|
||||||
t_bool fpp_mul (FPN *a, FPN *b)
|
void fpp_mul (FPN *a, FPN *b)
|
||||||
{
|
{
|
||||||
FPN x, y, z;
|
FPN x, y, z;
|
||||||
|
|
||||||
fpp_zcopy (&x, a); /* copy opnds */
|
fpp_zcopy (&x, a); /* copy opnds */
|
||||||
fpp_zcopy (&y, b);
|
fpp_zcopy (&y, b);
|
||||||
|
if ((fpp_fr_test(y.fr, 0, EXACT-1) == 0) && (y.fr[EXACT-1] < 2)) {
|
||||||
|
y.exp = 0;
|
||||||
|
y.fr[EXACT-1] = 0;
|
||||||
|
}
|
||||||
if (fpp_sta & FPS_DP) /* dp? */
|
if (fpp_sta & FPS_DP) /* dp? */
|
||||||
fpp_fr_mul (z.fr, x.fr, y.fr); /* mult frac */
|
fpp_fr_mul (z.fr, x.fr, y.fr, TRUE); /* mult frac */
|
||||||
else { /* fp or ep */
|
else { /* fp or ep */
|
||||||
|
fpp_norm (&x, EXACT);
|
||||||
|
fpp_norm (&y, EXACT);
|
||||||
z.exp = x.exp + y.exp; /* add exp */
|
z.exp = x.exp + y.exp; /* add exp */
|
||||||
fpp_fr_mul (z.fr, x.fr, y.fr); /* mult frac */
|
fpp_fr_mul (z.fr, x.fr, y.fr, TRUE); /* mult frac */
|
||||||
if (fpp_norm (&z, EXTEND)) /* norm, !exact? */
|
if (fpp_norm (&z, EXTEND)) /* norm, !exact? */
|
||||||
fpp_round (&z); /* round */
|
fpp_round (&z); /* round */
|
||||||
if (fpp_test_xp (&z)) /* ovf, unf? */
|
fpp_copy (a, &z);
|
||||||
return TRUE;
|
if (z.exp > 2047)
|
||||||
|
fpp_dump_apt (fpp_apta, FPS_FOVX); /* trap */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
fpp_copy (a, &z); /* result is z */
|
fpp_copy (a, &z); /* result is z */
|
||||||
return FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fraction/floating divide - return true if div by zero or overflow */
|
/* Fraction/floating divide */
|
||||||
|
|
||||||
t_bool fpp_div (FPN *a, FPN *b)
|
void fpp_div (FPN *a, FPN *b)
|
||||||
{
|
{
|
||||||
FPN x, y, z;
|
FPN x, y, z;
|
||||||
|
|
||||||
if (fpp_fr_test (b->fr, 0, EXACT) == 0) { /* divisor 0? */
|
if (fpp_fr_test (b->fr, 0, EXACT) == 0) { /* divisor 0? */
|
||||||
fpp_dump_apt (fpp_apta, FPS_DVZX); /* error */
|
fpp_dump_apt (fpp_apta, FPS_DVZX); /* error */
|
||||||
return TRUE;
|
return;
|
||||||
}
|
}
|
||||||
if (fpp_fr_test (a->fr, 0, EXACT) == 0) /* dividend 0? */
|
if (fpp_fr_test (a->fr, 0, EXACT) == 0) /* dividend 0? */
|
||||||
return FALSE; /* quotient is 0 */
|
return; /* quotient is 0 */
|
||||||
fpp_zcopy (&x, a); /* copy opnds */
|
fpp_zcopy (&x, a); /* copy opnds */
|
||||||
fpp_zcopy (&y, b);
|
fpp_zcopy (&y, b);
|
||||||
if (fpp_sta & FPS_DP) { /* dp? */
|
if (fpp_sta & FPS_DP) { /* dp? */
|
||||||
if (fpp_fr_div (z.fr, x.fr, y.fr)) { /* fr div, ovflo? */
|
if (fpp_fr_div (z.fr, x.fr, y.fr)) { /* fr div, ovflo? */
|
||||||
fpp_dump_apt (fpp_apta, FPS_IOVX); /* error */
|
fpp_dump_apt (fpp_apta, FPS_IOVX); /* error */
|
||||||
return TRUE;
|
return;
|
||||||
}
|
}
|
||||||
|
fpp_copy (a, &z); /* result is z */
|
||||||
}
|
}
|
||||||
else { /* fp or ep */
|
else { /* fp or ep */
|
||||||
fpp_norm (&y, EXACT); /* norm divisor */
|
fpp_norm (&y, EXACT); /* norm divisor */
|
||||||
|
@ -856,11 +942,15 @@ else { /* fp or ep */
|
||||||
}
|
}
|
||||||
if (fpp_norm (&z, EXTEND)) /* norm, !exact? */
|
if (fpp_norm (&z, EXTEND)) /* norm, !exact? */
|
||||||
fpp_round (&z); /* round */
|
fpp_round (&z); /* round */
|
||||||
if (fpp_test_xp (&z)) /* ovf, unf? */
|
fpp_copy (a, &z);
|
||||||
return TRUE;
|
if (z.exp > 2048) { /* underflow? */
|
||||||
|
if (fpp_cmd & FPC_UNFX) { /* trap? */
|
||||||
|
fpp_dump_apt (fpp_apta, FPS_UNF);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
fpp_copy (a, &z); /* result is z */
|
}
|
||||||
return FALSE;
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Integer multiply - returns true if overflow */
|
/* Integer multiply - returns true if overflow */
|
||||||
|
@ -872,15 +962,17 @@ FPN x, y, z;
|
||||||
|
|
||||||
fpp_zcopy (&x, a); /* copy args */
|
fpp_zcopy (&x, a); /* copy args */
|
||||||
fpp_zcopy (&y, b);
|
fpp_zcopy (&y, b);
|
||||||
fpp_fr_mul (z.fr, x.fr, y.fr); /* mult fracs */
|
fpp_fr_mul (z.fr, x.fr, y.fr, FALSE); /* mult fracs */
|
||||||
|
a->fr[0] = z.fr[1]; /* low 24b */
|
||||||
|
a->fr[1] = z.fr[2];
|
||||||
|
if ((a->fr[0] == 0) && (a->fr[1] == 0)) /* fpp zeroes exp */
|
||||||
|
a->exp = 0; /* even in dp mode */
|
||||||
sext = (z.fr[2] & FPN_FRSIGN)? 07777: 0;
|
sext = (z.fr[2] & FPN_FRSIGN)? 07777: 0;
|
||||||
if (((z.fr[0] | z.fr[1] | sext) != 0) && /* hi 25b == 0 */
|
if (((z.fr[0] | z.fr[1] | sext) != 0) && /* hi 25b == 0 */
|
||||||
((z.fr[0] & z.fr[1] & sext) != 07777)) { /* or 777777774? */
|
((z.fr[0] & z.fr[1] & sext) != 07777)) { /* or 777777774? */
|
||||||
fpp_dump_apt (fpp_apta, FPS_IOVX);
|
fpp_dump_apt (fpp_apta, FPS_IOVX);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
a->fr[0] = z.fr[2]; /* low 24b */
|
|
||||||
a->fr[1] = z.fr[3];
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,7 +1018,7 @@ if (fpp_fr_test (a->fr, 0, cnt) == 0) { /* zero? */
|
||||||
return FALSE; /* don't round */
|
return FALSE; /* don't round */
|
||||||
}
|
}
|
||||||
while (((a->fr[0] == 0) && !(a->fr[1] & 04000)) || /* lead 13b same? */
|
while (((a->fr[0] == 0) && !(a->fr[1] & 04000)) || /* lead 13b same? */
|
||||||
((a->fr[0] = 07777) && (a->fr[1] & 04000))) {
|
((a->fr[0] == 07777) && (a->fr[1] & 04000))) {
|
||||||
fpp_fr_lsh12 (a->fr, cnt); /* move word */
|
fpp_fr_lsh12 (a->fr, cnt); /* move word */
|
||||||
a->exp = a->exp - 12;
|
a->exp = a->exp - 12;
|
||||||
}
|
}
|
||||||
|
@ -967,6 +1059,8 @@ for (i = 0; i < FPN_NFR_EP; i++) {
|
||||||
a->fr[i] = b->fr[i];
|
a->fr[i] = b->fr[i];
|
||||||
else a->fr[i] = 0;
|
else a->fr[i] = 0;
|
||||||
}
|
}
|
||||||
|
a->fr[i++] = 0;
|
||||||
|
a->fr[i] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,9 +1073,8 @@ if (a->exp > 2047) { /* overflow? */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (a->exp < -2048) { /* underflow? */
|
if (a->exp < -2048) { /* underflow? */
|
||||||
fpp_sta |= FPS_UNF; /* set flag */
|
if (fpp_cmd & FPC_UNFX) { /* trap? */
|
||||||
if (fpp_sta & FPS_UNFX) { /* trap? */
|
fpp_dump_apt (fpp_apta, FPS_UNF);
|
||||||
fpp_dump_apt (fpp_apta, FPS_UNFX);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
fpp_copy (a, &fpp_zero); /* flush to 0 */
|
fpp_copy (a, &fpp_zero); /* flush to 0 */
|
||||||
|
@ -1015,13 +1108,14 @@ return;
|
||||||
|
|
||||||
/* N-precision integer routines */
|
/* N-precision integer routines */
|
||||||
|
|
||||||
/* Fraction add/sub - always carried out to 60b */
|
/* Fraction add/sub */
|
||||||
|
|
||||||
|
uint32 fpp_fr_add (uint32 *c, uint32 *a, uint32 *b, uint32 cnt)
|
||||||
|
|
||||||
uint32 fpp_fr_add (uint32 *c, uint32 *a, uint32 *b)
|
|
||||||
{
|
{
|
||||||
uint32 i, cin;
|
uint32 i, cin;
|
||||||
|
|
||||||
for (i = FPN_NFR_EP, cin = 0; i > 0; i--) {
|
for (i = cnt, cin = 0; i > 0; i--) {
|
||||||
c[i - 1] = a[i - 1] + b[i - 1] + cin;
|
c[i - 1] = a[i - 1] + b[i - 1] + cin;
|
||||||
cin = (c[i - 1] >> 12) & 1;
|
cin = (c[i - 1] >> 12) & 1;
|
||||||
c[i - 1] = c[i - 1] & 07777;
|
c[i - 1] = c[i - 1] & 07777;
|
||||||
|
@ -1029,11 +1123,11 @@ for (i = FPN_NFR_EP, cin = 0; i > 0; i--) {
|
||||||
return cin;
|
return cin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpp_fr_sub (uint32 *c, uint32 *a, uint32 *b)
|
void fpp_fr_sub (uint32 *c, uint32 *a, uint32 *b, uint32 cnt)
|
||||||
{
|
{
|
||||||
uint32 i, cin;
|
uint32 i, cin;
|
||||||
|
|
||||||
for (i = FPN_NFR_EP, cin = 0; i > 0; i--) {
|
for (i = cnt, cin = 0; i > 0; i--) {
|
||||||
c[i - 1] = a[i - 1] - b[i - 1] - cin;
|
c[i - 1] = a[i - 1] - b[i - 1] - cin;
|
||||||
cin = (c[i - 1] >> 12) & 1;
|
cin = (c[i - 1] >> 12) & 1;
|
||||||
c[i - 1] = c[i - 1] & 07777;
|
c[i - 1] = c[i - 1] & 07777;
|
||||||
|
@ -1062,25 +1156,48 @@ return;
|
||||||
If a-sign != c-sign, shift-in = result-sign
|
If a-sign != c-sign, shift-in = result-sign
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void fpp_fr_mul (uint32 *c, uint32 *a, uint32 *b)
|
void fpp_fr_mul (uint32 *c, uint32 *a, uint32 *b, t_bool fix)
|
||||||
{
|
{
|
||||||
uint32 i, cnt, lo, c_old, cin;
|
uint32 i, cnt, lo, wc, fill, b_sign;
|
||||||
|
|
||||||
fpp_fr_fill (c, 0, EXTEND); /* clr answer */
|
b_sign = b[0] & FPN_FRSIGN; /* remember b's sign */
|
||||||
|
|
||||||
|
fpp_fr_fill (c, 0, FPN_NFR_MDS); /* clr answer */
|
||||||
if (fpp_sta & FPS_EP) /* ep? */
|
if (fpp_sta & FPS_EP) /* ep? */
|
||||||
lo = FPN_NFR_EP - 1; /* test <59> */
|
lo = FPN_NFR_EP; /* low order mpyr word */
|
||||||
else lo = FPN_NFR_FP - 1; /* sp, test <23> */
|
else
|
||||||
cnt = (lo + 1) * 12; /* # iterations */
|
lo = FPN_NFR_FP; /* low order mpyr word */
|
||||||
for (i = 0; i < cnt; i++) { /* loop thru mpcd */
|
|
||||||
c_old = c[0];
|
if (fix)
|
||||||
if (b[lo] & 1) /* mpcd bit set? */
|
fpp_fr_algn (a, 12, FPN_NFR_MDS + 1); /* fill left with sign */
|
||||||
fpp_fr_add (c, a, c); /* add mpyr */
|
wc = 2; /* 3 words at start */
|
||||||
cin = (((a[0] ^ c_old) & FPN_FRSIGN)? c[0]: a[0]) & FPN_FRSIGN;
|
fill = 0;
|
||||||
fpp_fr_rsh1 (c, cin, EXTEND); /* shift answer */
|
cnt = lo * 12; /* total steps */
|
||||||
fpp_fr_rsh1 (b, 0, EXACT); /* shift mpcd */
|
for (i = 0; i < cnt; i++) {
|
||||||
|
if ((i % 12) == 0) {
|
||||||
|
wc++; /* do another word */
|
||||||
|
lo--; /* and next mpyr word */
|
||||||
|
fpp_fr_algn (c, 24, wc + 1);
|
||||||
|
c[wc] = 0;
|
||||||
|
c[0] = c[1] = fill; /* propagate sign */
|
||||||
}
|
}
|
||||||
if (a[0] & FPN_FRSIGN) /* mpyr negative? */
|
if (b[lo] & FPN_FRSIGN) /* mpyr bit set? */
|
||||||
fpp_fr_sub (c, c, a); /* adjust result */
|
fpp_fr_add(c, a, c, wc);
|
||||||
|
fill = ((c[0] & FPN_FRSIGN) ? 07777 : 0); /* remember sign */
|
||||||
|
fpp_fr_lsh1 (c, wc); /* shift the result */
|
||||||
|
fpp_fr_lsh1 (b + lo, 1); /* shift mpcd */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fix) /* imul shifts result */
|
||||||
|
fpp_fr_rsh1 (c, c[0] & FPN_FRSIGN, EXACT + 1); /* result is 1 wd right */
|
||||||
|
if (b_sign) { /* if mpyr was negative */
|
||||||
|
if (fix)
|
||||||
|
fpp_fr_lsh12 (a, FPN_NFR_MDS+1); /* restore a */
|
||||||
|
fpp_fr_sub (c, c, a, EXACT); /* adjust result */
|
||||||
|
fpp_fr_sub (c, c, a, EXACT);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,29 +1205,35 @@ return;
|
||||||
|
|
||||||
t_bool fpp_fr_div (uint32 *c, uint32 *a, uint32 *b)
|
t_bool fpp_fr_div (uint32 *c, uint32 *a, uint32 *b)
|
||||||
{
|
{
|
||||||
uint32 i, old_c, lo, cnt, sign;
|
uint32 i, old_c, lo, cnt, sign, b_sign, addsub, limit;
|
||||||
|
/* Number of words processed by each divide step */
|
||||||
|
static uint32 limits[7] = {6, 6, 5, 4, 3, 3, 2};
|
||||||
|
|
||||||
fpp_fr_fill (c, 0, EXTEND); /* clr answer */
|
fpp_fr_fill (c, 0, FPN_NFR_MDS); /* clr answer */
|
||||||
sign = (a[0] ^ b[0]) & FPN_FRSIGN; /* sign of result */
|
sign = (a[0] ^ b[0]) & FPN_FRSIGN; /* sign of result */
|
||||||
|
b_sign = (b[0] & FPN_FRSIGN);
|
||||||
if (a[0] & FPN_FRSIGN) /* |a| */
|
if (a[0] & FPN_FRSIGN) /* |a| */
|
||||||
fpp_fr_neg (a, EXACT);
|
fpp_fr_neg (a, EXACT);
|
||||||
if (b[0] & FPN_FRSIGN); /* |b| */
|
if (fpp_sta & FPS_EP) /* ep? 6 words */
|
||||||
fpp_fr_neg (b, EXACT);
|
lo = FPN_NFR_EP-1;
|
||||||
if (fpp_sta & FPS_EP) /* ep? 5 words */
|
else lo = FPN_NFR_FP-1; /* fp, dp? 3 words */
|
||||||
lo = FPN_NFR_EP - 1;
|
|
||||||
else lo = FPN_NFR_FP; /* fp, dp? 3 words */
|
|
||||||
cnt = (lo + 1) * 12;
|
cnt = (lo + 1) * 12;
|
||||||
|
addsub = 04000; /* setup first op */
|
||||||
for (i = 0; i < cnt; i++) { /* loop */
|
for (i = 0; i < cnt; i++) { /* loop */
|
||||||
fpp_fr_lsh1 (c, EXTEND); /* shift quotient */
|
limit = limits[i / 12]; /* how many wds this time */
|
||||||
if (fpp_fr_cmp (a, b, EXTEND) >= 0) { /* sub work? */
|
fpp_fr_lsh1 (c, FPN_NFR_MDS); /* shift quotient */
|
||||||
fpp_fr_sub (a, a, b); /* divd - divr */
|
if (addsub ^ b_sign) /* diff signs, subtr */
|
||||||
if (a[0] & FPN_FRSIGN) /* sign flip? */
|
fpp_fr_sub (a, a, b, limit); /* divd - divr */
|
||||||
return TRUE; /* no, overflow */
|
else
|
||||||
|
fpp_fr_add (a, a, b, limit); /* restore */
|
||||||
|
if (!(a[0] & FPN_FRSIGN)) {
|
||||||
c[lo] |= 1; /* set quo bit */
|
c[lo] |= 1; /* set quo bit */
|
||||||
|
addsub = 04000; /* sign for nxt loop */
|
||||||
}
|
}
|
||||||
fpp_fr_lsh1 (a, EXTEND); /* shift dividend */
|
else addsub = 0;
|
||||||
|
fpp_fr_lsh1 (a, limit); /* shift dividend */
|
||||||
}
|
}
|
||||||
old_c = c[0]; /* save hi quo */
|
old_c = c[0]; /* save ho quo */
|
||||||
if (sign) /* expect neg ans? */
|
if (sign) /* expect neg ans? */
|
||||||
fpp_fr_neg (c, EXTEND); /* -quo */
|
fpp_fr_neg (c, EXTEND); /* -quo */
|
||||||
if (old_c & FPN_FRSIGN) /* sign set before */
|
if (old_c & FPN_FRSIGN) /* sign set before */
|
||||||
|
@ -1126,7 +1249,7 @@ uint32 i, cin;
|
||||||
|
|
||||||
for (i = cnt, cin = 1; i > 0; i--) {
|
for (i = cnt, cin = 1; i > 0; i--) {
|
||||||
a[i - 1] = (~a[i - 1] + cin) & 07777;
|
a[i - 1] = (~a[i - 1] + cin) & 07777;
|
||||||
cin = (a[i - 1] == 0);
|
cin = (cin != 0 && a[i - 1] == 0);
|
||||||
}
|
}
|
||||||
return cin;
|
return cin;
|
||||||
}
|
}
|
||||||
|
@ -1244,7 +1367,7 @@ if (sc >= (cnt * 12)) { /* out of range? */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (sc >= 12) {
|
while (sc >= 12) {
|
||||||
for (i = cnt - 1; i > 0; i++)
|
for (i = cnt - 1; i > 0; i--)
|
||||||
a[i] = a[i - 1];
|
a[i] = a[i - 1];
|
||||||
a[0] = sign;
|
a[0] = sign;
|
||||||
sc = sc - 12;
|
sc = sc - 12;
|
||||||
|
@ -1263,7 +1386,6 @@ void fpp_read_op (uint32 ea, FPN *a)
|
||||||
{
|
{
|
||||||
uint32 i;
|
uint32 i;
|
||||||
|
|
||||||
fpp_opa = ea;
|
|
||||||
if (!(fpp_sta & FPS_DP)) {
|
if (!(fpp_sta & FPS_DP)) {
|
||||||
a->exp = fpp_read (ea++);
|
a->exp = fpp_read (ea++);
|
||||||
a->exp = SEXT12 (a->exp);
|
a->exp = SEXT12 (a->exp);
|
||||||
|
@ -1277,7 +1399,7 @@ void fpp_write_op (uint32 ea, FPN *a)
|
||||||
{
|
{
|
||||||
uint32 i;
|
uint32 i;
|
||||||
|
|
||||||
fpp_opa = ea;
|
fpp_opa = ea + 2;
|
||||||
if (!(fpp_sta & FPS_DP))
|
if (!(fpp_sta & FPS_DP))
|
||||||
fpp_write (ea++, a->exp);
|
fpp_write (ea++, a->exp);
|
||||||
for (i = 0; i < EXACT; i++)
|
for (i = 0; i < EXACT; i++)
|
||||||
|
@ -1328,7 +1450,7 @@ fpp_fpc = ((wd0 & 07) << 12) | apt_read (ad++);
|
||||||
if (FPC_GETFAST (fpp_cmd) != 017) {
|
if (FPC_GETFAST (fpp_cmd) != 017) {
|
||||||
fpp_xra = ((wd0 & 00070) << 9) | apt_read (ad++);
|
fpp_xra = ((wd0 & 00070) << 9) | apt_read (ad++);
|
||||||
fpp_bra = ((wd0 & 00700) << 6) | apt_read (ad++);
|
fpp_bra = ((wd0 & 00700) << 6) | apt_read (ad++);
|
||||||
ad++;
|
fpp_opa = ((wd0 & 07000) << 3) | apt_read (ad++);
|
||||||
fpp_ac.exp = apt_read (ad++);
|
fpp_ac.exp = apt_read (ad++);
|
||||||
for (i = 0; i < EXACT; i++)
|
for (i = 0; i < EXACT; i++)
|
||||||
fpp_ac.fr[i] = apt_read (ad++);
|
fpp_ac.fr[i] = apt_read (ad++);
|
||||||
|
@ -1370,9 +1492,8 @@ return;
|
||||||
t_stat fpp_reset (DEVICE *dptr)
|
t_stat fpp_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
sim_cancel (&fpp_unit);
|
sim_cancel (&fpp_unit);
|
||||||
fpp_sta = 0;
|
|
||||||
fpp_cmd = 0;
|
|
||||||
fpp_flag = 0;
|
fpp_flag = 0;
|
||||||
|
fpp_last_lockbit = 0;
|
||||||
int_req &= ~INT_FPP;
|
int_req &= ~INT_FPP;
|
||||||
if (sim_switches & SWMASK ('P')) {
|
if (sim_switches & SWMASK ('P')) {
|
||||||
fpp_apta = 0;
|
fpp_apta = 0;
|
||||||
|
@ -1382,6 +1503,14 @@ if (sim_switches & SWMASK ('P')) {
|
||||||
fpp_xra = 0;
|
fpp_xra = 0;
|
||||||
fpp_opa = 0;
|
fpp_opa = 0;
|
||||||
fpp_ac = fpp_zero;
|
fpp_ac = fpp_zero;
|
||||||
|
fpp_ssf = 0;
|
||||||
|
fpp_sta = 0;
|
||||||
|
fpp_cmd = 0;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
fpp_sta &= ~(FPS_DP|FPS_EP|FPS_TRPX|FPS_DVZX|FPS_IOVX|FPS_FOVX|FPS_UNF);
|
||||||
|
fpp_cmd &= (FPC_DP|FPC_UNFX|FPC_IE);
|
||||||
|
}
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp8_sys.c: PDP-8 simulator interface
|
/* pdp8_sys.c: PDP-8 simulator interface
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M Supnik
|
Copyright (c) 1993-2009, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
24-Mar-09 RMS Added link to FPP
|
||||||
24-Jun-08 RMS Fixed bug in new rim loader (found by Don North)
|
24-Jun-08 RMS Fixed bug in new rim loader (found by Don North)
|
||||||
24-May-08 RMS Fixed signed/unsigned declaration inconsistency
|
24-May-08 RMS Fixed signed/unsigned declaration inconsistency
|
||||||
03-Sep-07 RMS Added FPP8 support
|
03-Sep-07 RMS Added FPP8 support
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
extern DEVICE cpu_dev;
|
extern DEVICE cpu_dev;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern DEVICE tsc_dev;
|
extern DEVICE tsc_dev;
|
||||||
|
extern DEVICE fpp_dev;
|
||||||
extern DEVICE ptr_dev, ptp_dev;
|
extern DEVICE ptr_dev, ptp_dev;
|
||||||
extern DEVICE tti_dev, tto_dev;
|
extern DEVICE tti_dev, tto_dev;
|
||||||
extern DEVICE clk_dev, lpt_dev;
|
extern DEVICE clk_dev, lpt_dev;
|
||||||
|
@ -91,6 +93,7 @@ int32 sim_emax = 4;
|
||||||
DEVICE *sim_devices[] = {
|
DEVICE *sim_devices[] = {
|
||||||
&cpu_dev,
|
&cpu_dev,
|
||||||
&tsc_dev,
|
&tsc_dev,
|
||||||
|
&fpp_dev,
|
||||||
&clk_dev,
|
&clk_dev,
|
||||||
&ptr_dev,
|
&ptr_dev,
|
||||||
&ptp_dev,
|
&ptp_dev,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* vax_cpu.c: VAX CPU
|
/* vax_cpu.c: VAX CPU
|
||||||
|
|
||||||
Copyright (c) 1998-2008, Robert M Supnik
|
Copyright (c) 1998-2010, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
cpu VAX central processor
|
cpu VAX central processor
|
||||||
|
|
||||||
|
24-Apr-10 RMS Added OLDVMS idle timer option
|
||||||
|
Fixed bug in SET CPU IDLE
|
||||||
21-May-08 RMS Removed inline support
|
21-May-08 RMS Removed inline support
|
||||||
28-May-08 RMS Inlined instruction prefetch, physical memory routines
|
28-May-08 RMS Inlined instruction prefetch, physical memory routines
|
||||||
13-Aug-07 RMS Fixed bug in read access g-format indexed specifiers
|
13-Aug-07 RMS Fixed bug in read access g-format indexed specifiers
|
||||||
|
@ -173,6 +175,8 @@
|
||||||
#define UNIT_CONH (1u << UNIT_V_CONH)
|
#define UNIT_CONH (1u << UNIT_V_CONH)
|
||||||
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
|
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
|
||||||
#define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL))
|
#define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL))
|
||||||
|
#define VAX_IDLE_DFLT 1000
|
||||||
|
#define OLD_IDLE_DFLT 200
|
||||||
|
|
||||||
#define OPND_SIZE 16
|
#define OPND_SIZE 16
|
||||||
#define INST_SIZE 52
|
#define INST_SIZE 52
|
||||||
|
@ -259,7 +263,7 @@ int32 ibufl, ibufh; /* prefetch buf */
|
||||||
int32 ibcnt, ppc; /* prefetch ctl */
|
int32 ibcnt, ppc; /* prefetch ctl */
|
||||||
uint32 cpu_idle_ipl_mask = 0x8; /* idle if on IPL 3 */
|
uint32 cpu_idle_ipl_mask = 0x8; /* idle if on IPL 3 */
|
||||||
uint32 cpu_idle_type = 1; /* default to VMS */
|
uint32 cpu_idle_type = 1; /* default to VMS */
|
||||||
int32 cpu_idle_wait = 1000; /* for these cycles */
|
int32 cpu_idle_wait = VAX_IDLE_DFLT; /* for these cycles */
|
||||||
jmp_buf save_env;
|
jmp_buf save_env;
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||||
|
@ -3377,15 +3381,17 @@ return more;
|
||||||
struct os_idle {
|
struct os_idle {
|
||||||
char *name;
|
char *name;
|
||||||
uint32 mask;
|
uint32 mask;
|
||||||
|
int32 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct os_idle os_tab[] = {
|
static struct os_idle os_tab[] = {
|
||||||
{ "VMS", 0x8 },
|
{ "VMS", 0x8, VAX_IDLE_DFLT },
|
||||||
{ "NETBSD", 0x2 },
|
{ "NETBSD", 0x2, VAX_IDLE_DFLT },
|
||||||
{ "ULTRIX", 0x2 },
|
{ "ULTRIX", 0x2, VAX_IDLE_DFLT },
|
||||||
{ "OPENBSD", 0x1 },
|
{ "OPENBSD", 0x1, VAX_IDLE_DFLT },
|
||||||
{ "32V", 0x1 },
|
{ "32V", 0x1, VAX_IDLE_DFLT },
|
||||||
{ NULL, 0 }
|
{ "OLDVMS", 0xB, OLD_IDLE_DFLT },
|
||||||
|
{ NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Set and show idle */
|
/* Set and show idle */
|
||||||
|
@ -3399,7 +3405,8 @@ if (cptr != NULL) {
|
||||||
if (strcmp (os_tab[i].name, cptr) == 0) {
|
if (strcmp (os_tab[i].name, cptr) == 0) {
|
||||||
cpu_idle_type = i + 1;
|
cpu_idle_type = i + 1;
|
||||||
cpu_idle_ipl_mask = os_tab[i].mask;
|
cpu_idle_ipl_mask = os_tab[i].mask;
|
||||||
return sim_set_idle (uptr, val, cptr, desc);
|
cpu_idle_wait = os_tab[i].value;
|
||||||
|
return sim_set_idle (uptr, val, NULL, desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
|
|
89
descrip.mms
89
descrip.mms
|
@ -2,6 +2,7 @@
|
||||||
# Written By: Robert Alan Byer / byer@mail.ourservers.net
|
# Written By: Robert Alan Byer / byer@mail.ourservers.net
|
||||||
# Modified By: Mark Pizzolato / mark@infocomm.com
|
# Modified By: Mark Pizzolato / mark@infocomm.com
|
||||||
# Norman Lastovica / norman.lastovica@oracle.com
|
# Norman Lastovica / norman.lastovica@oracle.com
|
||||||
|
# Camiel Vanderhoeven / camiel@camicom.com
|
||||||
#
|
#
|
||||||
# This MMS/MMK build script is used to compile the various simulators in
|
# This MMS/MMK build script is used to compile the various simulators in
|
||||||
# the SIMH package for OpenVMS using DEC C v6.0-001(AXP), v6.5-001(AXP),
|
# the SIMH package for OpenVMS using DEC C v6.0-001(AXP), v6.5-001(AXP),
|
||||||
|
@ -182,21 +183,24 @@ ALTAIR_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIR_DIR))/DEF=($(CC_DEFS))
|
||||||
# MITS Altair Z80 Simulator Definitions.
|
# MITS Altair Z80 Simulator Definitions.
|
||||||
#
|
#
|
||||||
ALTAIRZ80_DIR = SYS$DISK:[.ALTAIRZ80]
|
ALTAIRZ80_DIR = SYS$DISK:[.ALTAIRZ80]
|
||||||
ALTAIRZ80_LIB = $(LIB_DIR)ALTAIRZ80-$(ARCH).OLB
|
ALTAIRZ80_LIB1 = $(LIB_DIR)ALTAIRZ80L1-$(ARCH).OLB
|
||||||
ALTAIRZ80_SOURCE = $(ALTAIRZ80_DIR)/ALTAIRZ80_CPU.C,$(ALTAIRZ80_DIR)/ALTAIRZ80_CPU_NOMMU.C,\
|
ALTAIRZ80_SOURCE1 = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.C,$(ALTAIRZ80_DIR)ALTAIRZ80_CPU_NOMMU.C,\
|
||||||
$(ALTAIRZ80_DIR)/ALTAIRZ80_DSK.C,$(ALTAIRZ80_DIR)/DISASM.C,\
|
$(ALTAIRZ80_DIR)ALTAIRZ80_DSK.C,$(ALTAIRZ80_DIR)DISASM.C,\
|
||||||
$(ALTAIRZ80_DIR)/ALTAIRZ80_SIO.C,$(ALTAIRZ80_DIR)/ALTAIRZ80_SYS.C,\
|
$(ALTAIRZ80_DIR)ALTAIRZ80_SIO.C,$(ALTAIRZ80_DIR)ALTAIRZ80_SYS.C,\
|
||||||
$(ALTAIRZ80_DIR)/ALTAIRZ80_HDSK.C,$(ALTAIRZ80_DIR)/ALTAIRZ80_NET.C,\
|
$(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.C,$(ALTAIRZ80_DIR)ALTAIRZ80_NET.C,\
|
||||||
$(ALTAIRZ80_DIR)/FLASHWRITER2.C,$(ALTAIRZ80_DIR)/I86_DECODE.C,\
|
$(ALTAIRZ80_DIR)FLASHWRITER2.C,$(ALTAIRZ80_DIR)I86_DECODE.C,\
|
||||||
$(ALTAIRZ80_DIR)/I86_OPS.C,$(ALTAIRZ80_DIR)/I86_PRIM_OPS.C,\
|
$(ALTAIRZ80_DIR)I86_OPS.C,$(ALTAIRZ80_DIR)I86_PRIM_OPS.C,\
|
||||||
$(ALTAIRZ80_DIR)/I8272.C,$(ALTAIRZ80_DIR)/INSNSA.C,$(ALTAIRZ80_DIR)/INSNSD.C,\
|
$(ALTAIRZ80_DIR)I8272.C,$(ALTAIRZ80_DIR)INSNSA.C,$(ALTAIRZ80_DIR)INSNSD.C,\
|
||||||
$(ALTAIRZ80_DIR)/MFDC.C,$(ALTAIRZ80_DIR)/N8VEM.C,$(ALTAIRZ80_DIR)/VFDHD.C,\
|
$(ALTAIRZ80_DIR)MFDC.C,$(ALTAIRZ80_DIR)N8VEM.C,$(ALTAIRZ80_DIR)VFDHD.C
|
||||||
$(ALTAIRZ80_DIR)/S100_DISK1A.C,$(ALTAIRZ80_DIR)/S100_DISK2.C,\
|
ALTAIRZ80_LIB2 = $(LIB_DIR)ALTAIRZ80L2-$(ARCH).OLB
|
||||||
$(ALTAIRZ80_DIR)/S100_FIF.C,$(ALTAIRZ80_DIR)/S100_MDRIVEH.C,\
|
ALTAIRZ80_SOURCE2 = $(ALTAIRZ80_DIR)S100_DISK1A.C,$(ALTAIRZ80_DIR)S100_DISK2.C,\
|
||||||
$(ALTAIRZ80_DIR)/S100_MDSAD.C,$(ALTAIRZ80_DIR)/S100_SELCHAN.C,\
|
$(ALTAIRZ80_DIR)S100_FIF.C,$(ALTAIRZ80_DIR)S100_MDRIVEH.C,\
|
||||||
$(ALTAIRZ80_DIR)/S100_SS1.C,$(ALTAIRZ80_DIR)/S100_64FDC.C,\
|
$(ALTAIRZ80_DIR)S100_MDSAD.C,$(ALTAIRZ80_DIR)S100_SELCHAN.C,\
|
||||||
$(ALTAIRZ80_DIR)/S100_SCP300F.C,$(ALTAIRZ80_DIR)/SIM_IMD.C,\
|
$(ALTAIRZ80_DIR)S100_SS1.C,$(ALTAIRZ80_DIR)S100_64FDC.C,\
|
||||||
$(ALTAIRZ80_DIR)/WD179X.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_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEF=($(CC_DEFS))
|
ALTAIRZ80_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEF=($(CC_DEFS))
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -256,8 +260,8 @@ H316_OPTIONS = /INCL=($(SIMH_DIR),$(H316_DIR))/DEF=($(CC_DEFS))
|
||||||
# Hewlett-Packard HP-2100 Simulator Definitions.
|
# Hewlett-Packard HP-2100 Simulator Definitions.
|
||||||
#
|
#
|
||||||
HP2100_DIR = SYS$DISK:[.HP2100]
|
HP2100_DIR = SYS$DISK:[.HP2100]
|
||||||
HP2100_LIB = $(LIB_DIR)HP2100-$(ARCH).OLB
|
HP2100_LIB1 = $(LIB_DIR)HP2100L1-$(ARCH).OLB
|
||||||
HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\
|
HP2100_SOURCE1 = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\
|
||||||
$(HP2100_DIR)HP2100_DQ.C,$(HP2100_DIR)HP2100_DR.C,\
|
$(HP2100_DIR)HP2100_DQ.C,$(HP2100_DIR)HP2100_DR.C,\
|
||||||
$(HP2100_DIR)HP2100_LPS.C,$(HP2100_DIR)HP2100_MS.C,\
|
$(HP2100_DIR)HP2100_LPS.C,$(HP2100_DIR)HP2100_MS.C,\
|
||||||
$(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\
|
$(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\
|
||||||
|
@ -267,8 +271,9 @@ HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\
|
||||||
$(HP2100_DIR)HP2100_CPU0.C,$(HP2100_DIR)HP2100_CPU1.C,\
|
$(HP2100_DIR)HP2100_CPU0.C,$(HP2100_DIR)HP2100_CPU1.C,\
|
||||||
$(HP2100_DIR)HP2100_CPU2.C,$(HP2100_DIR)HP2100_CPU3.C,\
|
$(HP2100_DIR)HP2100_CPU2.C,$(HP2100_DIR)HP2100_CPU3.C,\
|
||||||
$(HP2100_DIR)HP2100_CPU4.C,$(HP2100_DIR)HP2100_CPU5.C,\
|
$(HP2100_DIR)HP2100_CPU4.C,$(HP2100_DIR)HP2100_CPU5.C,\
|
||||||
$(HP2100_DIR)HP2100_CPU6.C,$(HP2100_DIR)HP2100_CPU7.C,\
|
$(HP2100_DIR)HP2100_CPU6.C,$(HP2100_DIR)HP2100_CPU7.C
|
||||||
$(HP2100_DIR)HP2100_FP1.C,$(HP2100_DIR)HP2100_BACI.C,\
|
HP2100_LIB2 = $(LIB_DIR)HP2100L2-$(ARCH).OLB
|
||||||
|
HP2100_SOURCE2 = $(HP2100_DIR)HP2100_FP1.C,$(HP2100_DIR)HP2100_BACI.C,\
|
||||||
$(HP2100_DIR)HP2100_MPX.C,$(HP2100_DIR)HP2100_PIF.C
|
$(HP2100_DIR)HP2100_MPX.C,$(HP2100_DIR)HP2100_PIF.C
|
||||||
.IF ALPHA_OR_IA64
|
.IF ALPHA_OR_IA64
|
||||||
HP2100_OPTIONS = /INCL=($(SIMH_DIR),$(HP2100_DIR))\
|
HP2100_OPTIONS = /INCL=($(SIMH_DIR),$(HP2100_DIR))\
|
||||||
|
@ -362,7 +367,7 @@ PDP8_SOURCE = $(PDP8_DIR)PDP8_CPU.C,$(PDP8_DIR)PDP8_CLK.C,\
|
||||||
$(PDP8_DIR)PDP8_SYS.C,$(PDP8_DIR)PDP8_TT.C,\
|
$(PDP8_DIR)PDP8_SYS.C,$(PDP8_DIR)PDP8_TT.C,\
|
||||||
$(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C,\
|
$(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C,\
|
||||||
$(PDP8_DIR)PDP8_TSC.C,$(PDP8_DIR)PDP8_TD.C,\
|
$(PDP8_DIR)PDP8_TSC.C,$(PDP8_DIR)PDP8_TD.C,\
|
||||||
$(PDP8_DIR)PDP8_CT.C
|
$(PDP8_DIR)PDP8_CT.C,$(PDP8_DIR)PDP8_FPP.C
|
||||||
PDP8_OPTIONS = /INCL=($(SIMH_DIR),$(PDP8_DIR))/DEF=($(CC_DEFS))
|
PDP8_OPTIONS = /INCL=($(SIMH_DIR),$(PDP8_DIR))/DEF=($(CC_DEFS))
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -509,14 +514,14 @@ I7094_OPTIONS = /INCL=($(SIMH_DIR),$(I7094_DIR))/DEF=($(CC_DEFS))
|
||||||
ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI LGP H316 HP2100 I1401 I1620 IBM1130 ID16 \
|
ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI LGP H316 HP2100 I1401 I1620 IBM1130 ID16 \
|
||||||
ID32 NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 VAX VAX780 SDS \
|
ID32 NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 VAX VAX780 SDS \
|
||||||
I7094
|
I7094
|
||||||
@CONTINUE
|
$! No further actions necessary
|
||||||
.ELSE
|
.ELSE
|
||||||
#
|
#
|
||||||
# Else We Are On VAX And Build Everything EXCEPT the 64b simulators
|
# Else We Are On VAX And Build Everything EXCEPT the 64b simulators
|
||||||
#
|
#
|
||||||
ALL : ALTAIR ALTAIRZ80 GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \
|
ALL : ALTAIR ALTAIRZ80 GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \
|
||||||
NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX VAX780 SDS
|
NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX VAX780 SDS
|
||||||
@CONTINUE
|
$! No further actions necessary
|
||||||
.ENDIF
|
.ENDIF
|
||||||
|
|
||||||
CLEAN :
|
CLEAN :
|
||||||
|
@ -559,9 +564,20 @@ $(ALTAIR_LIB) : $(ALTAIR_SOURCE)
|
||||||
$ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ
|
$ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ
|
||||||
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
$(ALTAIRZ80_LIB) : $(ALTAIRZ80_SOURCE)
|
$(ALTAIRZ80_LIB1) : $(ALTAIRZ80_SOURCE1)
|
||||||
$!
|
$!
|
||||||
$! Building The $(ALTAIRZ80_LIB) Library.
|
$! Building The $(ALTAIRZ80_LIB1) Library.
|
||||||
|
$!
|
||||||
|
$ $(CC)$(ALTAIRZ80_OPTIONS) -
|
||||||
|
/OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST)
|
||||||
|
$ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN -
|
||||||
|
LIBRARY/CREATE $(MMS$TARGET)
|
||||||
|
$ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ
|
||||||
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
|
$(ALTAIRZ80_LIB2) : $(ALTAIRZ80_SOURCE2)
|
||||||
|
$!
|
||||||
|
$! Building The $(ALTAIRZ80_LIB2) Library.
|
||||||
$!
|
$!
|
||||||
$ $(CC)$(ALTAIRZ80_OPTIONS) -
|
$ $(CC)$(ALTAIRZ80_OPTIONS) -
|
||||||
/OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST)
|
/OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST)
|
||||||
|
@ -628,9 +644,20 @@ $(H316_LIB) : $(H316_SOURCE)
|
||||||
$ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ
|
$ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ
|
||||||
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
$(HP2100_LIB) : $(HP2100_SOURCE)
|
$(HP2100_LIB1) : $(HP2100_SOURCE1)
|
||||||
$!
|
$!
|
||||||
$! Building The $(HP2100_LIB) Library.
|
$! Building The $(HP2100_LIB1) Library.
|
||||||
|
$!
|
||||||
|
$ $(CC)$(HP2100_OPTIONS) -
|
||||||
|
/OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST)
|
||||||
|
$ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN -
|
||||||
|
LIBRARY/CREATE $(MMS$TARGET)
|
||||||
|
$ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ
|
||||||
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
|
$(HP2100_LIB2) : $(HP2100_SOURCE2)
|
||||||
|
$!
|
||||||
|
$! Building The $(HP2100_LIB2) Library.
|
||||||
$!
|
$!
|
||||||
$ $(CC)$(HP2100_OPTIONS) -
|
$ $(CC)$(HP2100_OPTIONS) -
|
||||||
/OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST)
|
/OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST)
|
||||||
|
@ -918,13 +945,14 @@ ALTAIR : $(SIMH_LIB) $(ALTAIR_LIB)
|
||||||
$(BLD_DIR)SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
$(BLD_DIR)SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
||||||
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB)
|
ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB1) $(ALTAIRZ80_LIB2)
|
||||||
$!
|
$!
|
||||||
$! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator.
|
$! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator.
|
||||||
$!
|
$!
|
||||||
$ $(CC)$(ALTAIRZ80_OPTIONS)/OBJ=$(BLD_DIR) SCP.C
|
$ $(CC)$(ALTAIRZ80_OPTIONS)/OBJ=$(BLD_DIR) SCP.C
|
||||||
$ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIRZ80-$(ARCH).EXE -
|
$ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIRZ80-$(ARCH).EXE -
|
||||||
$(BLD_DIR)SCP.OBJ,$(ALTAIRZ80_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
$(BLD_DIR)SCP.OBJ,$(ALTAIRZ80_LIB1)/LIBRARY, -
|
||||||
|
$(ALTAIRZ80_LIB2)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
||||||
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -976,13 +1004,14 @@ H316 : $(SIMH_LIB) $(H316_LIB)
|
||||||
$(BLD_DIR)SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
$(BLD_DIR)SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
||||||
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
HP2100 : $(SIMH_LIB) $(HP2100_LIB)
|
HP2100 : $(SIMH_LIB) $(HP2100_LIB1) $(HP2100_LIB2)
|
||||||
$!
|
$!
|
||||||
$! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator.
|
$! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator.
|
||||||
$!
|
$!
|
||||||
$ $(CC)$(HP2100_OPTIONS)/OBJ=$(BLD_DIR) SCP.C
|
$ $(CC)$(HP2100_OPTIONS)/OBJ=$(BLD_DIR) SCP.C
|
||||||
$ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)HP2100-$(ARCH).EXE -
|
$ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)HP2100-$(ARCH).EXE -
|
||||||
$(BLD_DIR)SCP.OBJ,$(HP2100_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
$(BLD_DIR)SCP.OBJ,$(HP2100_LIB1)/LIBRARY, -
|
||||||
|
$(HP2100_LIB2)/LIBRARY,$(SIMH_LIB)/LIBRARY
|
||||||
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
$ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;*
|
||||||
|
|
||||||
I1401 : $(SIMH_LIB) $(I1401_LIB)
|
I1401 : $(SIMH_LIB) $(I1401_LIB)
|
||||||
|
|
13
makefile
13
makefile
|
@ -251,13 +251,19 @@ SDS = ${SDSD}/sds_cpu.c ${SDSD}/sds_drm.c ${SDSD}/sds_dsk.c ${SDSD}/sds_io.c \
|
||||||
${SDSD}/sds_stddev.c ${SDSD}/sds_sys.c
|
${SDSD}/sds_stddev.c ${SDSD}/sds_sys.c
|
||||||
SDS_OPT = -I ${SDSD}
|
SDS_OPT = -I ${SDSD}
|
||||||
|
|
||||||
|
SWTPD = SWTP
|
||||||
|
SWTP = ${SWTPD}/swtp_cpu.c ${SWTPD}/swtp_dsk.c ${SWTPD}/swtp_sio.c \
|
||||||
|
${SWTPD}/swtp_sys.c
|
||||||
|
SWTP_OPT = -I ${SWTPD}
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build everything
|
# Build everything
|
||||||
#
|
#
|
||||||
ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
|
ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
|
||||||
vax vax780 nova eclipse hp2100 i1401 i1620 s3 \
|
vax vax780 nova eclipse hp2100 i1401 i1620 s3 \
|
||||||
altair altairz80 gri i1620 i7094 ibm1130 id16 \
|
altair altairz80 gri i1620 i7094 ibm1130 id16 \
|
||||||
id32 sds lgp h316
|
id32 sds lgp h316 swtp
|
||||||
|
|
||||||
all : ${ALL}
|
all : ${ALL}
|
||||||
|
|
||||||
|
@ -400,3 +406,8 @@ sds : ${BIN}sds${EXE}
|
||||||
|
|
||||||
${BIN}sds${EXE} : ${SDS} ${SIM}
|
${BIN}sds${EXE} : ${SDS} ${SIM}
|
||||||
${CC} ${SDS} ${SIM} ${SDS_OPT} -o $@ ${LDFLAGS}
|
${CC} ${SDS} ${SIM} ${SDS_OPT} -o $@ ${LDFLAGS}
|
||||||
|
|
||||||
|
swtp : ${BIN}swtp${EXE}
|
||||||
|
|
||||||
|
${BIN}swtp${EXE} : ${SWTP} ${SIM}
|
||||||
|
${CC} ${SWTP} ${SIM} ${SWTP_OPT} -o $@ ${LDFLAGS}
|
36
sim_rev.h
36
sim_rev.h
|
@ -1,6 +1,6 @@
|
||||||
/* sim_rev.h: simulator revisions and current rev level
|
/* sim_rev.h: simulator revisions and current rev level
|
||||||
|
|
||||||
Copyright (c) 1993-2008, Robert M Supnik
|
Copyright (c) 1993-2010, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -29,13 +29,45 @@
|
||||||
|
|
||||||
#define SIM_MAJOR 3
|
#define SIM_MAJOR 3
|
||||||
#define SIM_MINOR 8
|
#define SIM_MINOR 8
|
||||||
#define SIM_PATCH 1
|
#define SIM_PATCH 2
|
||||||
#define SIM_DELTA 0
|
#define SIM_DELTA 0
|
||||||
|
|
||||||
/* V3.8 revision history
|
/* V3.8 revision history
|
||||||
|
|
||||||
patch date module(s) and fix(es)
|
patch date module(s) and fix(es)
|
||||||
|
|
||||||
|
2 tbd h316_cpu.c:
|
||||||
|
- fixed bugs in MPY, DIV introduced in 3.8-1
|
||||||
|
|
||||||
|
i1401_cd.c:
|
||||||
|
- fixed read stacker operation in column binary mode
|
||||||
|
- fixed punch stacker operation (from Van Snyder)
|
||||||
|
|
||||||
|
1401_cpu.c:
|
||||||
|
- revised divide algorithm (from Van Snyder)
|
||||||
|
|
||||||
|
i1401_mt.c:
|
||||||
|
- added no rewind option (from Van Snyder)
|
||||||
|
|
||||||
|
pdp11_rk.c:
|
||||||
|
- fixed bug in read header (from Walter F Mueller)
|
||||||
|
|
||||||
|
pdp11_rl.c:
|
||||||
|
- added debug support
|
||||||
|
|
||||||
|
pdp11_rq.c:
|
||||||
|
- added RD32 support
|
||||||
|
|
||||||
|
pdp8_fpp.c:
|
||||||
|
- many bug fixes (all from Rick Murphy); now functional
|
||||||
|
|
||||||
|
pdp8_sys.c:
|
||||||
|
- added link to FPP
|
||||||
|
|
||||||
|
vax_cpu.c:
|
||||||
|
- added OLDVMS idle timer option
|
||||||
|
- fixed bug in SET CPU IDLE
|
||||||
|
|
||||||
1 08-Feb-09 scp.c:
|
1 08-Feb-09 scp.c:
|
||||||
- revised RESTORE unit logic for consistency
|
- revised RESTORE unit logic for consistency
|
||||||
- "detach_all" ignores error status returns if shutting down (from Dave Bryan)
|
- "detach_all" ignores error status returns if shutting down (from Dave Bryan)
|
||||||
|
|
BIN
swtp/6800boot.dsk
Normal file
BIN
swtp/6800boot.dsk
Normal file
Binary file not shown.
BIN
swtp/6800work.dsk
Normal file
BIN
swtp/6800work.dsk
Normal file
Binary file not shown.
BIN
swtp/swtp
Normal file
BIN
swtp/swtp
Normal file
Binary file not shown.
100
swtp/swtp.txt
Normal file
100
swtp/swtp.txt
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
SWTP 6800 Emulator
|
||||||
|
=====================
|
||||||
|
|
||||||
|
1. Background.
|
||||||
|
|
||||||
|
The Southwest Technical Products (SWTP) SWTP 6800 was announced 1n the 1976 SWTP Catalog, which boasted you could buy and build this powerful computer kit for only $395. The kit consisted at that time of only the parts to build a case, power supply, mother board, CPU card, serial card with RS-232 or 20 ma loop interface, and memory card with 2048 *bytes* of static memory.
|
||||||
|
|
||||||
|
2. Hardware
|
||||||
|
|
||||||
|
We are simulating a fairly "loaded" SWTP 6800 from about 1978, with the following configuration:
|
||||||
|
|
||||||
|
device simulates
|
||||||
|
name(s)
|
||||||
|
|
||||||
|
CPU SWTP MP-A with Motorola 6080 CPU board, 62KB of RAM, 2K of EPROM with start boot ROM.
|
||||||
|
SIO SWTP MP-S Dual Serial Interface Board. Port 1 is assumed to be connected to a serial "glass TTY" that is your terminal running the Simulator.
|
||||||
|
PTR Second serial port of SIO is assumed to be connected to the paper tap reader/punch.
|
||||||
|
PTP Second serial port of SIO is assumed to be connected to the paper tap reader/punch.
|
||||||
|
DSK SWTP DC-4 Floppy Disk controller with up to four drives.
|
||||||
|
|
||||||
|
2.1 The CPU Card (MP-A)
|
||||||
|
|
||||||
|
We allow you to select memory sizes, but be aware that some sample software requires the full 32K (i.e. FLEX). We emulate the SWTP SWTBUG boot rom.
|
||||||
|
|
||||||
|
SET CPU ITRAP Causes the simulator to halt if an invalid 8080 Opcode is detected.
|
||||||
|
SET CPU NOITRAP Does not stop on an invalid Opcode. This is how the real 6800 operates.
|
||||||
|
SET CPU MTRAP Causes the simulator to halt if an invalid address is accessed.
|
||||||
|
SET CPU NOMTRAP Does not stop on invalid address access. This is how a real 6800 operates.
|
||||||
|
SET CPU 4K
|
||||||
|
SET CPU 8K
|
||||||
|
SET CPU 12K
|
||||||
|
SET CPU 16K
|
||||||
|
......
|
||||||
|
SET CPU 32K All these set various CPU memory configurations.
|
||||||
|
The 2K EPROM at the high end of memory is always present and will always boot.
|
||||||
|
SET CPU MA000 Enable 8 K bytes of memory at $A000-$BFFF. Otherwise, only 128 bytes re available at $A000.
|
||||||
|
SET CPU NOMA000 Enable only 128 bytes of memory at $A000.
|
||||||
|
|
||||||
|
The SWTBUG EPROM maps to both addresses $E000-E3FF and $FC00-FFFF.
|
||||||
|
|
||||||
|
The real 6800, on receiving a HLT (Halt) instruction, freezes the processor and only an interrupt or CPU hardware reset will restore it. The simulator is a lot nicer, it will halt but send you back to the simulator command line.
|
||||||
|
|
||||||
|
CPU Registers include the following:
|
||||||
|
|
||||||
|
name size comments
|
||||||
|
|
||||||
|
PC 16 Program Counter
|
||||||
|
A 8 Accumulator A
|
||||||
|
B 8 Accumulator B
|
||||||
|
IX 16 Index Register
|
||||||
|
C 1 Carry flag
|
||||||
|
Z 1 Zero Flag
|
||||||
|
H 1 Half-Carry flag
|
||||||
|
I 1 Interrupt flag
|
||||||
|
N 1 Negative flag
|
||||||
|
V 1 Overflao Flag
|
||||||
|
|
||||||
|
|
||||||
|
2.2 The Serial I/O Card (MP-S)
|
||||||
|
|
||||||
|
This simple programmed I/O device provides 2 serial ports to the outside world, which could be hardware jumpered to support RS-232 plugs or a TTY current loop interface. The standard I/O addresses assigned by SWTP was $8004-8005 for the first port, and $8006-8007 for the second. We follow this standard in the Simulator.
|
||||||
|
|
||||||
|
The simulator directs I/O to/from the first port to the screen. The second port reads from an attachable "tape reader" file on input, and writes to an attachable "punch file" on output. These files are considered a simple stream of 8-bit bytes.
|
||||||
|
|
||||||
|
2.3 The Floppy Disk controller (DC4)
|
||||||
|
|
||||||
|
The SWTP DC4 is a simple programmed I/O interface to the SWTP MF-68 5-inch dual floppy drive, which was basically a pair of Shugart SA-400s with a power supply and buffer board builtin. The controller supports neither interrupts nor DMA, so floppy access required the sustained attention of the CPU. The standard I/O addresses were $8018-801B, and we follow the standard. Details on controlling this hardware are in the swtp_dsk.c source file.
|
||||||
|
|
||||||
|
|
||||||
|
3. Sample Software
|
||||||
|
|
||||||
|
Running an SWTP 6800 in 1978 you would be running the FLEX Version 2.0 Operating System from Technical Systems Consultants, Inc.
|
||||||
|
|
||||||
|
3.1 CP/M Version 2.2
|
||||||
|
|
||||||
|
This version is a port of the standard FLEX Version 2.0 to the SWTP 6800.
|
||||||
|
|
||||||
|
To boot FLEX:
|
||||||
|
|
||||||
|
sim> set cpu hex
|
||||||
|
sim> set cpu itrap
|
||||||
|
sim> set cpu mtrap
|
||||||
|
sim> att dsk 6800boot.dsk
|
||||||
|
sim> att dsk1 6800work.dsk
|
||||||
|
sim> set cpu MA000
|
||||||
|
sim> set dsk1 rw
|
||||||
|
sim> go
|
||||||
|
|
||||||
|
$D ; Capital D causes SWTBUG to boot Flex
|
||||||
|
FLEX 2.0
|
||||||
|
|
||||||
|
DATE (MM,DD,YY)? 03,09,99 ; Must enter a date from last century!
|
||||||
|
|
||||||
|
+++ ;Flex prompt!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
9
swtp/swtp6800
Normal file
9
swtp/swtp6800
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
reset
|
||||||
|
set cpu hex
|
||||||
|
set cpu itrap
|
||||||
|
set cpu mtrap
|
||||||
|
att dsk 6800boot.dsk
|
||||||
|
att dsk1 6800work.dsk
|
||||||
|
set cpu MA000
|
||||||
|
set dsk1 rw
|
||||||
|
g
|
2293
swtp/swtp_cpu.c
Normal file
2293
swtp/swtp_cpu.c
Normal file
File diff suppressed because it is too large
Load diff
46
swtp/swtp_defs.h
Normal file
46
swtp/swtp_defs.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/* swtp_defs.h: SWTP 6800 simulator definitions
|
||||||
|
|
||||||
|
Copyright (c) 2005, 2007, William Beech
|
||||||
|
|
||||||
|
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
|
||||||
|
WILLIAM A BEECH 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 William A Beech shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from William A Beech.
|
||||||
|
|
||||||
|
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../sim_defs.h" // simulator defs
|
||||||
|
|
||||||
|
/* Memory */
|
||||||
|
|
||||||
|
#define MAXMEMSIZE 65536 // max memory size
|
||||||
|
#define MEMSIZE (cpu_unit.capac)// actual memory size
|
||||||
|
#define ADDRMASK (MAXMEMSIZE - 1)// address mask
|
||||||
|
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||||
|
|
||||||
|
/* Simulator stop codes */
|
||||||
|
|
||||||
|
#define STOP_RSRV 1 // must be 1
|
||||||
|
#define STOP_HALT 2 // HALT-really WAI
|
||||||
|
#define STOP_IBKPT 3 // breakpoint
|
||||||
|
#define STOP_OPCODE 4 // invalid opcode
|
||||||
|
#define STOP_MEMORY 5 // invalid memory address
|
||||||
|
|
506
swtp/swtp_dsk.c
Normal file
506
swtp/swtp_dsk.c
Normal file
|
@ -0,0 +1,506 @@
|
||||||
|
/* swtp_dc4_dsk.c: SWTP DC-4 DISK Simulator
|
||||||
|
|
||||||
|
Copyright (c) 2005, William A. Beech
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of William A. Beech shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from William A. Beech.
|
||||||
|
|
||||||
|
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
|
||||||
|
|
||||||
|
|
||||||
|
The DC-4 is a 5-inch floppy controller which can control up
|
||||||
|
to 4 daisy-chained 5-inch floppy drives. The controller is based on
|
||||||
|
the Western Digital 1797 Floppy Disk Controller (FDC) chip. This
|
||||||
|
file only emulates the minimum DC-4 functionality to interface with
|
||||||
|
the virtual disk file.
|
||||||
|
|
||||||
|
The floppy controller is interfaced to the CPU by use of 5 memory
|
||||||
|
addreses. These are device numbers 5 and 6 (0x8014-0x801B).
|
||||||
|
|
||||||
|
Address Mode Function
|
||||||
|
------- ---- --------
|
||||||
|
|
||||||
|
0x8014 Read Returns FDC interrupt status
|
||||||
|
0x8014 Write Selects the drive/head/motor control
|
||||||
|
0x8018 Read Returns status of FDC
|
||||||
|
0x8018 Write FDC command register
|
||||||
|
0x8019 Read Returns FDC track register
|
||||||
|
0x8019 Write Set FDC track register
|
||||||
|
0x801A Read Returns FDC sector register
|
||||||
|
0x801A Write Set FDC sector register
|
||||||
|
0x801B Read Read data
|
||||||
|
0x801B Write Write data
|
||||||
|
|
||||||
|
Drive Select Read (0x8014):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| I | D | X | X | X | X | X | X |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
I = Set indicates an interrupt request from the FDC pending.
|
||||||
|
D = DRQ pending - same as bit 1 of FDC status register.
|
||||||
|
|
||||||
|
Drive Select Write (0x8014):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| M | S | X | X | X | X | Device|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
M = If this bit is 1, the one-shot is triggered/retriggered to
|
||||||
|
start/keep the motors on.
|
||||||
|
S = Side select. If set, side one is selected otherwise side zero
|
||||||
|
is selected.
|
||||||
|
X = not used
|
||||||
|
Device = value 0 thru 3, selects drive 0-3 to be controlled.
|
||||||
|
|
||||||
|
Drive Status Read (0x8018):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| R | P | H | S | C | L | D | B |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
B - When 1, the controller is busy.
|
||||||
|
D - When 1, index mark detected (type I) or data request - read data
|
||||||
|
ready/write data empty (type II or III).
|
||||||
|
H - When 1, track 0 (type I) or lost data (type II or III).
|
||||||
|
C - When 1, crc error detected.
|
||||||
|
S - When 1, seek (type I) or RNF (type II or III) error.
|
||||||
|
H - When 1, head is currently loaded (type I) or record type/
|
||||||
|
write fault (type II or III).
|
||||||
|
P - When 1, indicates that diskette is write-protected.
|
||||||
|
R - When 1, drive is not ready.
|
||||||
|
|
||||||
|
Drive Control Write (0x8018) for type I commands:
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| 0 | S2| S1| S0| H | V | R1| R0|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
R0/R1 - Selects the step rate.
|
||||||
|
V - When 1, verify on destination track.
|
||||||
|
H - When 1, loads head to drive surface.
|
||||||
|
S0/S1/S2 = 000 - home.
|
||||||
|
001 - seek track in data register.
|
||||||
|
010 - step without updating track register.
|
||||||
|
011 - step and update track register.
|
||||||
|
100 - step in without updating track register.
|
||||||
|
101 - step in and update track register.
|
||||||
|
110 - step out without updating track register.
|
||||||
|
111 - step out and update track register.
|
||||||
|
|
||||||
|
Drive Control Write (0x8018) for type II commands:
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| 1 | 0 | T | M | S | E | B | A |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
A - Zero for read, 1 on write deleted data mark else data mark.
|
||||||
|
B - When 1, shifts sector length field definitions one place.
|
||||||
|
E - When, delay operation 15 ms, 0 no delay.
|
||||||
|
S - When 1, select side 1, 0 select side 0.
|
||||||
|
M - When 1, multiple records, 0 for single record.
|
||||||
|
T - When 1, write command, 0 for read.
|
||||||
|
|
||||||
|
Drive Control Write (0x8018) for type III commands:
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| 1 | 1 | T0| T1| 0 | E | 0 | 0 |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
E - When, delay operation 15 ms, 0 no delay.
|
||||||
|
T0/T1 - 00 - read address command.
|
||||||
|
10 - read track command.
|
||||||
|
11 - write track command.
|
||||||
|
|
||||||
|
Tracks are numbered from 0 up to one minus the last track in the 1797!
|
||||||
|
|
||||||
|
Track Register Read (0x8019):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| Track Number |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
Reads the current 8-bit value from the track position.
|
||||||
|
|
||||||
|
Track Register Write (0x8019):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| Track Number |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
Writes the 8-bit value to the track register.
|
||||||
|
|
||||||
|
Sectors are numbers from 1 up to the last sector in the 1797!
|
||||||
|
|
||||||
|
Sector Register Read (0x801A):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| Sector Number |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
Reads the current 8-bit value from the sector position.
|
||||||
|
|
||||||
|
Sector Register Write (0x801A):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| Sector Number |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
Writes the 8-bit value to the sector register.
|
||||||
|
|
||||||
|
Data Register Read (0x801B):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| Data |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
Reads the current 8-bit value from the data register.
|
||||||
|
|
||||||
|
Data Register Write (0x801B):
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| Data |
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
Writes the 8-bit value to the data register.
|
||||||
|
|
||||||
|
A FLEX disk is defined as follows:
|
||||||
|
|
||||||
|
Track Sector Use
|
||||||
|
0 1 Boot sector
|
||||||
|
0 2 Boot sector (cont)
|
||||||
|
0 3 Unused
|
||||||
|
0 4 System Identity Record (explained below)
|
||||||
|
0 5 Unused
|
||||||
|
0 6-last Directory - 10 entries/sector (explained below)
|
||||||
|
1 1 First available data sector
|
||||||
|
last-1 last Last available data sector
|
||||||
|
|
||||||
|
System Identity Record
|
||||||
|
|
||||||
|
Byte Use
|
||||||
|
0x10 Volume ID (8 bytes)
|
||||||
|
0x18 ???
|
||||||
|
0x19 ???
|
||||||
|
0x1A ???
|
||||||
|
0x1B Volume number (2 bytes)
|
||||||
|
0x1D First free sector (2 bytes)
|
||||||
|
0x1F Last track minus one (byte)
|
||||||
|
0x20 Last sector (byte)
|
||||||
|
0x21 Total sectors on disk (2 bytes)
|
||||||
|
0x23 Month (byte
|
||||||
|
0x24 Day (byte)
|
||||||
|
0x25 Year (byte)
|
||||||
|
0x26 Last track minus one (byte)
|
||||||
|
0x27 Last sector (byte)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "swtp_defs.h"
|
||||||
|
|
||||||
|
#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */
|
||||||
|
#define UNIT_ENABLE (1 << UNIT_V_ENABLE)
|
||||||
|
|
||||||
|
/* emulate a SS FLEX disk with 72 sectors and 80 tracks */
|
||||||
|
|
||||||
|
#define NUM_DISK 4 /* standard 1797 maximum */
|
||||||
|
#define SECT_SIZE 256 /* standard FLEX sector */
|
||||||
|
#define NUM_SECT 72 /* sectors/track */
|
||||||
|
#define TRAK_SIZE (SECT_SIZE * NUM_SECT)
|
||||||
|
#define HEADS 1 /* handle as SS with twice the sectors */
|
||||||
|
#define NUM_CYL 80 /* maximum tracks */
|
||||||
|
#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE)
|
||||||
|
|
||||||
|
/* 1797 status bits */
|
||||||
|
|
||||||
|
#define BUSY 0x01
|
||||||
|
#define DRQ 0x02
|
||||||
|
#define WRPROT 0x40
|
||||||
|
#define NOTRDY 0x80
|
||||||
|
|
||||||
|
/* debug prints */
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
|
||||||
|
t_stat dsk_svc (UNIT *uptr);
|
||||||
|
t_stat dsk_reset (DEVICE *dptr);
|
||||||
|
int32 fdcdrv(int32 io, int32 data);
|
||||||
|
int32 fdccmd(int32 io, int32 data);
|
||||||
|
int32 fdctrk(int32 io, int32 data);
|
||||||
|
int32 fdcsec(int32 io, int32 data);
|
||||||
|
int32 fdcdata(int32 io, int32 data);
|
||||||
|
|
||||||
|
/* Global data on status */
|
||||||
|
|
||||||
|
int32 cur_dsk = NUM_DISK; /* Currently selected drive */
|
||||||
|
int32 cur_trk[NUM_DISK] = {0, 0, 0, 0};
|
||||||
|
int32 cur_sec[NUM_DISK] = {0, 0, 0, 0};
|
||||||
|
int32 cur_byt[NUM_DISK] = {0, 0, 0, 0};
|
||||||
|
int32 cur_flg[NUM_DISK] = {NOTRDY, NOTRDY, NOTRDY, NOTRDY};
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
|
||||||
|
uint8 dskbuf[SECT_SIZE]; /* Data Buffer */
|
||||||
|
UNIT *dptr = NULL; /* fileref to write dirty buffer to */
|
||||||
|
int32 fdcbyte;
|
||||||
|
int32 intrq = 0; /* interrupt request flag */
|
||||||
|
|
||||||
|
/* DC-4 Simh Device Data Structures */
|
||||||
|
|
||||||
|
UNIT dsk_unit[] = {
|
||||||
|
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||||
|
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||||
|
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||||
|
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) } };
|
||||||
|
|
||||||
|
REG dsk_reg[] = {
|
||||||
|
{ HRDATA (DISK, cur_dsk, 4) },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB dsk_mod[] = {
|
||||||
|
{ UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL },
|
||||||
|
{ UNIT_ENABLE, 0, "RO", "RO", NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
DEVICE dsk_dev = {
|
||||||
|
"DSK", dsk_unit, dsk_reg, dsk_mod,
|
||||||
|
NUM_DISK, 16, 16, 1, 16, 8,
|
||||||
|
NULL, NULL, &dsk_reset,
|
||||||
|
NULL, NULL, NULL };
|
||||||
|
|
||||||
|
/* service routines to handle simlulator functions */
|
||||||
|
|
||||||
|
/* service routine - actually gets char & places in buffer */
|
||||||
|
|
||||||
|
t_stat dsk_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset routine */
|
||||||
|
|
||||||
|
t_stat dsk_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
cur_dsk = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* I/O instruction handlers, called from the CPU module when an
|
||||||
|
memory read or write to the proper addresses is issued.
|
||||||
|
|
||||||
|
Each function is passed an 'io' flag, where 0 means a read from
|
||||||
|
the port, and 1 means a write to the port. On input, the actual
|
||||||
|
input is passed as the return value, on output, 'data' is written
|
||||||
|
to the device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* DC-4 drive select register routine - this register is not part of the 1797
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 fdcdrv(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
/* **** probably need to grab the parameters from the SIR and set the limits */
|
||||||
|
if (io) { /* write to DC-4 drive register */
|
||||||
|
cur_dsk = data & 0x03; /* only 2 drive select bits */
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Drive set to %d\n\r", cur_dsk);
|
||||||
|
#endif
|
||||||
|
if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0)
|
||||||
|
cur_flg[cur_dsk] |= WRPROT; /* set WPROT */
|
||||||
|
return 0;
|
||||||
|
} else { /* read from DC-4 drive register */
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Drive read as %02X\n\r", intrq);
|
||||||
|
#endif
|
||||||
|
return intrq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WD 1797 FDC command register routine */
|
||||||
|
|
||||||
|
int32 fdccmd(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
static int32 val = 0, val1 = NOTRDY, i;
|
||||||
|
static long pos;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
|
if ((dsk_unit[cur_dsk].flags & UNIT_ATT) == 0) { /* not attached */
|
||||||
|
cur_flg[cur_dsk] |= NOTRDY; /* set not ready flag */
|
||||||
|
printf("Drive %d is not attached\n\r", cur_dsk);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
cur_flg[cur_dsk] &= ~NOTRDY; /* clear not ready flag */
|
||||||
|
}
|
||||||
|
uptr = dsk_dev.units + cur_dsk; /* get virtual drive address */
|
||||||
|
if (io) { /* write command to fdc */
|
||||||
|
switch(data) {
|
||||||
|
case 0x8C: /* read command */
|
||||||
|
case 0x9C:
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Read of disk %d, track %d, sector %d\n\r",
|
||||||
|
cur_dsk, cur_trk[cur_dsk], cur_sec[cur_dsk]);
|
||||||
|
#endif
|
||||||
|
pos = TRAK_SIZE * cur_trk[cur_dsk]; /* calculate file offset */
|
||||||
|
pos += SECT_SIZE * (cur_sec[cur_dsk] - 1);
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Read pos = %ld ($%04X)\n\r", pos, pos);
|
||||||
|
#endif
|
||||||
|
sim_fseek(uptr -> fileref, pos, 0); /* seek to offset */
|
||||||
|
sim_fread(dskbuf, 256, 1, uptr -> fileref); /* read in buffer */
|
||||||
|
cur_flg[cur_dsk] |= BUSY | DRQ; /* set DRQ & BUSY */
|
||||||
|
i = cur_byt[cur_dsk] = 0; /* clear counter */
|
||||||
|
break;
|
||||||
|
case 0xAC: /* write command */
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Write of disk %d, track %d, sector %d\n\r",
|
||||||
|
cur_dsk, cur_trk[cur_dsk], cur_sec[cur_dsk]);
|
||||||
|
#endif
|
||||||
|
if (cur_flg[cur_dsk] & WRPROT) {
|
||||||
|
printf("Drive %d is write-protected\n\r", cur_dsk);
|
||||||
|
} else {
|
||||||
|
pos = TRAK_SIZE * cur_trk[cur_dsk]; /* calculate file offset */
|
||||||
|
pos += SECT_SIZE * (cur_sec[cur_dsk] - 1);
|
||||||
|
#if DEBUG > 1
|
||||||
|
printf("Write pos = %ld ($%04X)\n\r", pos, pos);
|
||||||
|
#endif
|
||||||
|
sim_fseek(uptr -> fileref, pos, 0); /* seek to offset */
|
||||||
|
dptr = uptr; /* save pointer for actual write */
|
||||||
|
cur_flg[cur_dsk] |= BUSY | DRQ;/* set DRQ & BUSY */
|
||||||
|
i = cur_byt[cur_dsk] = 0; /* clear counter */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x18: /* seek command */
|
||||||
|
case 0x1B:
|
||||||
|
cur_trk[cur_dsk] = fdcbyte; /* set track */
|
||||||
|
cur_flg[cur_dsk] &= ~(BUSY | DRQ); /* clear flags */
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Seek of disk %d, track %d\n\r", cur_dsk, fdcbyte);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 0x0B: /* restore command */
|
||||||
|
cur_trk[cur_dsk] = 0; /* home the drive */
|
||||||
|
cur_flg[cur_dsk] &= ~(BUSY | DRQ); /* clear flags */
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Drive %d homed\n\r", cur_dsk);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown FDC command %02H\n\r", data);
|
||||||
|
}
|
||||||
|
} else { /* read status from fdc */
|
||||||
|
val = cur_flg[cur_dsk]; /* set return value */
|
||||||
|
if (val1 == 0 && val == 0x03) /* delay BUSY going high */
|
||||||
|
val = 0x02; /* set DRQ first */
|
||||||
|
if (val != val1) { /* now allow BUSY after on read */
|
||||||
|
val1 = val;
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Drive %d status=%02X\n\r", cur_dsk, cur_flg[cur_dsk]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WD 1797 FDC track register routine */
|
||||||
|
|
||||||
|
int32 fdctrk(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
if (io) {
|
||||||
|
cur_trk[cur_dsk] = data & 0xFF;
|
||||||
|
#if DEBUG > 1
|
||||||
|
printf("Drive %d track set to %d\n\r", cur_dsk, data);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
;
|
||||||
|
#if DEBUG > 1
|
||||||
|
printf("Drive %d track read as %d\n\r", cur_dsk, cur_trk[cur_dsk]);
|
||||||
|
#endif
|
||||||
|
return cur_trk[cur_dsk];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WD 1797 FDC sector register routine */
|
||||||
|
|
||||||
|
int32 fdcsec(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
if (io) {
|
||||||
|
cur_sec[cur_dsk] = data & 0xFF;
|
||||||
|
if (cur_sec[cur_dsk] == 0) /* fix for swtp boot! */
|
||||||
|
cur_sec[cur_dsk] = 1;
|
||||||
|
#if DEBUG > 1
|
||||||
|
printf("Drive %d sector set to %d\n\r", cur_dsk, data);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
;
|
||||||
|
#if DEBUG > 1
|
||||||
|
printf("Drive %d sector read as %d\n\r", cur_dsk, cur_sec[cur_dsk]);
|
||||||
|
#endif
|
||||||
|
return cur_sec[cur_dsk];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WD 1797 FDC data register routine */
|
||||||
|
|
||||||
|
int32 fdcdata(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
if (io) { /* write byte to fdc */
|
||||||
|
fdcbyte = data; /* save for seek */
|
||||||
|
if ((i = cur_byt[cur_dsk]) < SECT_SIZE) { /* copy bytes to buffer */
|
||||||
|
#if DEBUG > 3
|
||||||
|
printf("Writing byte %d of %02X\n\r", cur_byt[cur_dsk], data);
|
||||||
|
#endif
|
||||||
|
cur_byt[cur_dsk]++; /* step counter */
|
||||||
|
dskbuf[i] = data; /* byte into buffer */
|
||||||
|
if (cur_byt[cur_dsk] == SECT_SIZE) {
|
||||||
|
cur_flg[cur_dsk] &= ~(BUSY | DRQ);
|
||||||
|
if (dptr) { /* if initiated by FDC write command */
|
||||||
|
sim_fwrite(dskbuf, 256, 1, dptr -> fileref); /* write it */
|
||||||
|
dptr = NULL;
|
||||||
|
}
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Sector write complete\n\r");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else { /* read byte from fdc */
|
||||||
|
if ((i = cur_byt[cur_dsk]) < SECT_SIZE) { /* copy bytes from buffer */
|
||||||
|
#if DEBUG > 1
|
||||||
|
printf("Reading byte %d\n\r", cur_byt[cur_dsk]);
|
||||||
|
#endif
|
||||||
|
cur_byt[cur_dsk]++; /* step counter */
|
||||||
|
if (cur_byt[cur_dsk] == SECT_SIZE) { /* done? */
|
||||||
|
cur_flg[cur_dsk] &= ~(BUSY | DRQ); /* clear flags */
|
||||||
|
#if DEBUG > 0
|
||||||
|
printf("Sector read complete\n\r");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return (dskbuf[i] & 0xFF);
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
312
swtp/swtp_sio.c
Normal file
312
swtp/swtp_sio.c
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
/* swtp_sio: SWTP serial I/O card
|
||||||
|
|
||||||
|
Copyright (c) 2005, William Beech
|
||||||
|
|
||||||
|
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
|
||||||
|
Willaim Beech 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 William A. Beech shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from William A. Beech.
|
||||||
|
|
||||||
|
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
|
||||||
|
|
||||||
|
These functions support a simulated SWTP MP-S interface card.
|
||||||
|
The card had two physical I/O ports which could be connected
|
||||||
|
to any serial I/O device that would connect to a current loop
|
||||||
|
or RS232 interface. Available baud rates were jumper selectable
|
||||||
|
for each port from 110 to 9600. The ports appear at all 4 addresses.
|
||||||
|
This fact is used by SWTBUG to determine the presence of the MP-S vice
|
||||||
|
MP-C serial card.
|
||||||
|
|
||||||
|
All I/O is via either programmed I/O or interrupt controlled I/O.
|
||||||
|
It has a status port and a data port. A write to the status port
|
||||||
|
can select some options for the device (0x03 will reset the port).
|
||||||
|
A read of the status port gets the port status:
|
||||||
|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
| I | P | O | F |CTS|DCD|TXE|RXF|
|
||||||
|
+---+---+---+---+---+---+---+---+
|
||||||
|
|
||||||
|
RXF - A 1 in this bit position means a character has been received
|
||||||
|
on the data port and is ready to be read.
|
||||||
|
TXE - A 1 in this bit means the port is ready to receive a character
|
||||||
|
on the data port and transmit it out over the serial line.
|
||||||
|
|
||||||
|
A read to the data port gets the buffered character, a write
|
||||||
|
to the data port writes the character to the device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "swtp_defs.h"
|
||||||
|
|
||||||
|
#define UNIT_V_ANSI (UNIT_V_UF + 0) // ANSI mode
|
||||||
|
#define UNIT_ANSI (1 << UNIT_V_ANSI)
|
||||||
|
|
||||||
|
t_stat sio_svc (UNIT *uptr);
|
||||||
|
t_stat sio_reset (DEVICE *dptr);
|
||||||
|
t_stat ptr_svc (UNIT *uptr);
|
||||||
|
t_stat ptr_reset (DEVICE *dptr);
|
||||||
|
t_stat ptp_svc (UNIT *uptr);
|
||||||
|
t_stat ptp_reset (DEVICE *dptr);
|
||||||
|
|
||||||
|
int32 ptr_stopioe = 0, ptp_stopioe = 0; // stop on error
|
||||||
|
|
||||||
|
// MP-S Standard I/O Data Structures
|
||||||
|
|
||||||
|
UNIT sio_unit = { UDATA (&sio_svc, 0, 0),
|
||||||
|
KBD_POLL_WAIT };
|
||||||
|
|
||||||
|
REG sio_reg[] = {
|
||||||
|
{ ORDATA (DATA, sio_unit.buf, 8) },
|
||||||
|
{ ORDATA (STAT, sio_unit.u3, 8) },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB sio_mod[] = {
|
||||||
|
{ UNIT_ANSI, 0, "TTY", "TTY", NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
DEVICE sio_dev = {
|
||||||
|
"MP-S", &sio_unit, sio_reg, sio_mod,
|
||||||
|
1, 10, 31, 1, 8, 8,
|
||||||
|
NULL, NULL, &sio_reset,
|
||||||
|
NULL, NULL, NULL };
|
||||||
|
|
||||||
|
UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
|
||||||
|
KBD_POLL_WAIT };
|
||||||
|
DEVICE ptr_dev = {
|
||||||
|
"PTR", &ptr_unit, NULL, NULL,
|
||||||
|
1, 10, 31, 1, 8, 8,
|
||||||
|
NULL, NULL, &ptr_reset,
|
||||||
|
NULL, NULL, NULL };
|
||||||
|
|
||||||
|
UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
|
||||||
|
KBD_POLL_WAIT };
|
||||||
|
DEVICE ptp_dev = {
|
||||||
|
"PTP", &ptp_unit, NULL, NULL,
|
||||||
|
1, 10, 31, 1, 8, 8,
|
||||||
|
NULL, NULL, &ptp_reset,
|
||||||
|
NULL, NULL, NULL };
|
||||||
|
|
||||||
|
/* Service routines to handle simulator functions */
|
||||||
|
|
||||||
|
/* service routine - actually gets char & places in buffer */
|
||||||
|
|
||||||
|
int32 ptp_rdr(int32 io, int32 data);
|
||||||
|
|
||||||
|
int32 ptp_flag = 0, ptr_flag = 0;
|
||||||
|
|
||||||
|
/* console input service routine */
|
||||||
|
|
||||||
|
int32 sio_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
int32 temp;
|
||||||
|
|
||||||
|
sim_activate (&sio_unit, sio_unit.wait); // continue poll
|
||||||
|
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
|
||||||
|
return temp; // no char or error?
|
||||||
|
sio_unit.buf = temp & 0xFF; // Save char
|
||||||
|
sio_unit.u3 |= 0x01; // Set RXF flag
|
||||||
|
|
||||||
|
/* Do any special character handling here */
|
||||||
|
|
||||||
|
sio_unit.pos++; // step character count
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* paper tape reader input service routine */
|
||||||
|
|
||||||
|
int32 ptr_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* paper tape punch output service routine */
|
||||||
|
|
||||||
|
int32 ptp_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset console */
|
||||||
|
|
||||||
|
int32 sio_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
sio_unit.buf = 0; // Data buffer
|
||||||
|
sio_unit.u3 = 0x02; // Status buffer
|
||||||
|
sim_activate (&sio_unit, sio_unit.wait); // activate unit
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset paper tape reader */
|
||||||
|
|
||||||
|
int32 ptr_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
ptr_unit.buf = 0;
|
||||||
|
ptr_unit.u3 = 0x02;
|
||||||
|
sim_cancel (&ptr_unit); // deactivate unit
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset paper tape punch */
|
||||||
|
|
||||||
|
int32 ptp_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
ptp_unit.buf = 0;
|
||||||
|
ptp_unit.u3 = 0x02;
|
||||||
|
sim_cancel (&ptp_unit); // deactivate unit
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* I/O instruction handlers, called from the CPU module when a
|
||||||
|
read or write occur to addresses 0x8000-0x801F.
|
||||||
|
|
||||||
|
Each function is passed an 'io' flag, where 0 means a read from
|
||||||
|
the port, and 1 means a write to the port. On input, the actual
|
||||||
|
input is passed as the return value, on output, 'data' is written
|
||||||
|
to the device.
|
||||||
|
|
||||||
|
This code emulates a SWTP MP-S Serial Card with a Model 33 Teletype
|
||||||
|
attached. The Model 33 uses DC1-DC4 codes to enable or disable the
|
||||||
|
paper tape reader and punch. Those devices are defined in this module,
|
||||||
|
and the code built to emulate those functions if the PTP and/or PTR
|
||||||
|
are attached in the simulator.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Port 1 (0x8004-0x8007) controls the Model 33 Teletype */
|
||||||
|
|
||||||
|
int32 ptr_flg1 = 0;
|
||||||
|
int32 odata, status;
|
||||||
|
|
||||||
|
|
||||||
|
int32 sio0s(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
|
if (io == 0) { // control register read
|
||||||
|
if (ptr_flag) { // reader enabled?
|
||||||
|
if ((ptr_unit.flags & UNIT_ATT) == 0) // attached?
|
||||||
|
ptr_unit.u3 &= 0xFE; // no, clear RXF flag
|
||||||
|
else {
|
||||||
|
uptr = ptr_dev.units;// not EOF?
|
||||||
|
if (feof(uptr -> fileref))
|
||||||
|
ptr_unit.u3 &= 0xFE;
|
||||||
|
else
|
||||||
|
ptr_unit.u3 |= 0x01;
|
||||||
|
}
|
||||||
|
return (status = ptr_unit.u3); // no - done
|
||||||
|
} else {
|
||||||
|
return (status = sio_unit.u3); // return console status
|
||||||
|
}
|
||||||
|
} else { // control register write
|
||||||
|
if (data == 0x03) { // reset port!
|
||||||
|
sio_unit.u3 = 0x02; // reset console
|
||||||
|
sio_unit.buf = 0;
|
||||||
|
sio_unit.pos = 0;
|
||||||
|
ptr_unit.u3 = 0x02; // reset reader
|
||||||
|
ptr_unit.buf = 0;
|
||||||
|
ptr_unit.pos = 0;
|
||||||
|
ptp_unit.u3 = 0x02; // reset punch
|
||||||
|
ptp_unit.buf = 0;
|
||||||
|
ptp_unit.pos = 0;
|
||||||
|
}
|
||||||
|
return (status = 0); // invalid io
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 sio0d(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
|
if (io == 0) { // data register read
|
||||||
|
if (ptr_flag) { // RDR enabled?
|
||||||
|
if ((ptr_unit.flags & UNIT_ATT) == 0) // attached?
|
||||||
|
return 0; // no, done
|
||||||
|
// printf("ptr_unit.u3=%02X\n", ptr_unit.u3);
|
||||||
|
if ((ptr_unit.u3 & 0x01) == 0) { // yes, more data?
|
||||||
|
// printf("Returning old %02X\n", odata); // no, return previous byte
|
||||||
|
return (odata & 0xFF);
|
||||||
|
}
|
||||||
|
uptr = ptr_dev.units; // get data byte
|
||||||
|
if ((odata = getc(uptr -> fileref)) == EOF) { // end of file?
|
||||||
|
// printf("Got EOF\n");
|
||||||
|
ptr_unit.u3 &= 0xFE; // clear RXF flag
|
||||||
|
return (odata = 0); // no data
|
||||||
|
}
|
||||||
|
// printf("Returning new %02X\n", odata);
|
||||||
|
ptr_unit.pos++; // step character count
|
||||||
|
ptr_unit.u3 &= 0xFE; // clear RXF flag
|
||||||
|
return (odata & 0xFF); // return character
|
||||||
|
} else {
|
||||||
|
sio_unit.u3 &= 0xFE; // clear RXF flag
|
||||||
|
return (odata = sio_unit.buf); // return next char
|
||||||
|
}
|
||||||
|
} else { // data register write
|
||||||
|
if (isprint(data) || data == '\r' || data == '\n') { // printable?
|
||||||
|
sim_putchar(data); // print character on console
|
||||||
|
if (ptp_flag && ptp_unit.flags & UNIT_ATT) { // PTP enabled & attached?
|
||||||
|
uptr = ptp_dev.units; // punch character to file
|
||||||
|
putc(data, uptr -> fileref);
|
||||||
|
ptp_unit.pos++; // step character counter
|
||||||
|
}
|
||||||
|
} else { // DC1-DC4 control Reader/Punch
|
||||||
|
switch (data) {
|
||||||
|
case 0x11: // RDR on
|
||||||
|
ptr_flag = 1;
|
||||||
|
ptr_flg1 = 0;
|
||||||
|
ptr_unit.u3 |= 0x01;
|
||||||
|
// printf("Reader on\r\n");
|
||||||
|
break;
|
||||||
|
case 0x12: // PTP on
|
||||||
|
ptp_flag = 1;
|
||||||
|
ptp_unit.u3 |= 0x02;
|
||||||
|
// printf("Punch on\r\n");
|
||||||
|
break;
|
||||||
|
case 0x13: // RDR off
|
||||||
|
ptr_flag = 0;
|
||||||
|
// printf("Reader off-%d bytes read\r\n", ptr_unit.pos);
|
||||||
|
break;
|
||||||
|
case 0x14: // PTP off
|
||||||
|
ptp_flag = 0;
|
||||||
|
// printf("Punch off-%d bytes written\r\n", ptp_unit.pos);
|
||||||
|
break;
|
||||||
|
default: // ignore all other characters
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (odata = 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* because each port appears at 2 addresses and this fact is used
|
||||||
|
to determine if it is a MP-C or MP-S repeatedly in the SWTBUG
|
||||||
|
monitor, this code assures that reads of the high ports return
|
||||||
|
the same data as was read the last time on the low ports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 sio1s(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 sio1d(int32 io, int32 data)
|
||||||
|
{
|
||||||
|
return odata;
|
||||||
|
}
|
||||||
|
|
425
swtp/swtp_sys.c
Normal file
425
swtp/swtp_sys.c
Normal file
|
@ -0,0 +1,425 @@
|
||||||
|
/* swtp_sys.c: SWTP 6800 system interface
|
||||||
|
|
||||||
|
Copyright (c) 2005, William Beech
|
||||||
|
|
||||||
|
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
|
||||||
|
WILLIAM A BEECH 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 William A. Beech shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from William A. Beech.
|
||||||
|
|
||||||
|
Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "swtp_defs.h"
|
||||||
|
|
||||||
|
/* externals */
|
||||||
|
|
||||||
|
extern DEVICE cpu_dev;
|
||||||
|
extern DEVICE dsk_dev;
|
||||||
|
extern UNIT cpu_unit;
|
||||||
|
extern REG cpu_reg[];
|
||||||
|
extern DEVICE sio_dev;
|
||||||
|
extern DEVICE ptr_dev;
|
||||||
|
extern DEVICE ptp_dev;
|
||||||
|
extern DEVICE lpt_dev;
|
||||||
|
extern unsigned char M[];
|
||||||
|
extern int32 saved_PC;
|
||||||
|
extern int32 sim_switches;
|
||||||
|
//extern int32 (*sim_vm_fprint_addr)(FILE*, DEVICE*,t_addr);
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
|
||||||
|
int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag);
|
||||||
|
int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
t_addr fprint_addr(FILE *stream, DEVICE *dptr, t_addr addr);
|
||||||
|
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw);
|
||||||
|
void sim_special_init (void);
|
||||||
|
|
||||||
|
/* links into scp */
|
||||||
|
|
||||||
|
void (*sim_vm_init)(void) = &sim_special_init;
|
||||||
|
|
||||||
|
/* SCP data structures
|
||||||
|
|
||||||
|
sim_name simulator name string
|
||||||
|
sim_PC pointer to saved PC register descriptor
|
||||||
|
sim_emax number of words needed for examine
|
||||||
|
sim_devices array of pointers to simulated devices
|
||||||
|
sim_stop_messages array of pointers to stop messages
|
||||||
|
sim_load binary loader
|
||||||
|
*/
|
||||||
|
|
||||||
|
char sim_name[] = "SWTP 6800";
|
||||||
|
|
||||||
|
REG *sim_PC = &cpu_reg[0];
|
||||||
|
|
||||||
|
int32 sim_emax = 16;
|
||||||
|
|
||||||
|
DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptp_dev, &ptr_dev, &dsk_dev, NULL };
|
||||||
|
|
||||||
|
const char *sim_stop_messages[] = {
|
||||||
|
"Unknown error",
|
||||||
|
"Unknown I/O Instruction",
|
||||||
|
"HALT instruction",
|
||||||
|
"Breakpoint",
|
||||||
|
"Invalid Opcode",
|
||||||
|
"Invalid Memory" };
|
||||||
|
|
||||||
|
static const char *opcode[] = {
|
||||||
|
"???", "NOP", "???", "???", //0x00
|
||||||
|
"???", "???", "TAP", "TPA",
|
||||||
|
"INX", "DEX", "CLV", "SEV",
|
||||||
|
"CLC", "SEC", "CLI", "SEI",
|
||||||
|
"SBA", "CBA", "???", "???", //0x10
|
||||||
|
"???", "???", "TAB", "TBA",
|
||||||
|
"???", "DAA", "???", "ABA",
|
||||||
|
"???", "???", "???", "???",
|
||||||
|
"BRA", "???", "BHI", "BLS", //0x20
|
||||||
|
"BCC", "BCS", "BNE", "BEQ",
|
||||||
|
"BVC", "BVS", "BPL", "BMI",
|
||||||
|
"BGE", "BLT", "BGT", "BLE",
|
||||||
|
"TSX", "INS", "PULA", "PULB", //0x30
|
||||||
|
"DES", "TXS", "PSHA", "PSHB",
|
||||||
|
"???", "RTS", "???", "RTI",
|
||||||
|
"???", "???", "WAI", "SWI",
|
||||||
|
"NEGA", "???", "???", "COMA", //0x40
|
||||||
|
"LSRA", "???", "RORA", "ASRA",
|
||||||
|
"ASLA", "ROLA", "DECA", "???",
|
||||||
|
"INCA", "TSTA", "???", "CLRA",
|
||||||
|
"NEGB", "???", "???", "COMB", //0x50
|
||||||
|
"LSRB", "???", "RORB", "ASRB",
|
||||||
|
"ASLB", "ROLB", "DECB", "???",
|
||||||
|
"INCB", "TSTB", "???", "CLRB",
|
||||||
|
"NEG", "???", "???", "COM", //0x60
|
||||||
|
"LSR", "???", "ROR", "ASR",
|
||||||
|
"ASL", "ROL", "DEC", "???",
|
||||||
|
"INC", "TST", "JMP", "CLR",
|
||||||
|
"NEG", "???", "???", "COM", //0x70
|
||||||
|
"LSR", "???", "ROR", "ASR",
|
||||||
|
"ASL", "ROL", "DEC", "???",
|
||||||
|
"INC", "TST", "JMP", "CLR",
|
||||||
|
"SUBA", "CMPA", "SBCA", "???", //0x80
|
||||||
|
"ANDA", "BITA", "LDAA", "???",
|
||||||
|
"EORA", "ADCA", "ORAA", "ADDA",
|
||||||
|
"CPX", "BSR", "LDS", "???",
|
||||||
|
"SUBA", "CMPA", "SBCA", "???", //0x90
|
||||||
|
"ANDA", "BITA", "LDAA", "STAA",
|
||||||
|
"EORA", "ADCA", "ORAA", "ADDA",
|
||||||
|
"CPX", "???", "LDS", "STS",
|
||||||
|
"SUBA", "CMPA", "SBCA", "???", //0xA0
|
||||||
|
"ANDA", "BITA", "LDAA", "STAA",
|
||||||
|
"EORA", "ADCA", "ORAA", "ADDA",
|
||||||
|
"CPX X", "JSR X", "LDS X", "STS X",
|
||||||
|
"SUBA", "CMPA", "SBCA", "???", //0xB0
|
||||||
|
"ANDA", "BITA", "LDAA", "STAA",
|
||||||
|
"EORA", "ADCA", "ORAA", "ADDA",
|
||||||
|
"CPX", "JSR", "LDS", "STS",
|
||||||
|
"SUBB", "CMPB", "SBCB", "???", //0xC0
|
||||||
|
"ANDB", "BITB", "LDAB", "???",
|
||||||
|
"EORB", "ADCB", "ORAB", "ADDB",
|
||||||
|
"???", "???", "LDX", "???",
|
||||||
|
"SUBB", "CMPB", "SBCB", "???", //0xD0
|
||||||
|
"ANDB", "BITB", "LDAB", "STAB",
|
||||||
|
"EORB", "ADCB", "ORAB", "ADDB",
|
||||||
|
"???", "???", "LDX", "STX",
|
||||||
|
"SUBB", "CMPB", "SBCB", "???", //0xE0
|
||||||
|
"ANDB", "BITB", "LDAB", "STAB",
|
||||||
|
"EORB", "ADCB", "ORAB", "ADDB",
|
||||||
|
"???", "???", "LDX", "STX",
|
||||||
|
"SUBB", "CMPB", "SBCB", "???", //0xF0
|
||||||
|
"ANDB", "BITB", "LDAB", "STAB",
|
||||||
|
"EORB", "ADCB", "ORAB", "ADDB",
|
||||||
|
"???", "???", "LDX", "STX",
|
||||||
|
};
|
||||||
|
|
||||||
|
int32 oplen[256] = {
|
||||||
|
0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1, //0x00
|
||||||
|
1,1,0,0,0,0,1,1,0,1,0,1,0,0,0,0,
|
||||||
|
2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||||
|
1,1,1,1,1,1,1,1,0,1,0,1,0,0,1,1,
|
||||||
|
1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1, //0x40
|
||||||
|
1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1,
|
||||||
|
2,0,0,2,2,0,2,2,2,2,2,0,2,2,2,2,
|
||||||
|
3,0,0,3,3,0,3,3,3,3,3,0,3,3,3,3,
|
||||||
|
2,2,2,0,2,2,2,0,2,2,2,2,3,2,3,0, //0x80
|
||||||
|
2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,2,
|
||||||
|
2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||||
|
3,3,3,0,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||||
|
2,2,2,0,2,2,2,0,2,2,2,2,0,0,3,0, //0xC0
|
||||||
|
2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,
|
||||||
|
2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,
|
||||||
|
3,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3 };
|
||||||
|
|
||||||
|
/* This is the dumper/loader. This command uses the -h to signify a
|
||||||
|
hex dump/load vice a binary one. If no address is given to load, it
|
||||||
|
takes the address from the hex record or the current PC for binary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||||
|
{
|
||||||
|
int32 i, cnt = 0, addr = 0, start = 0x10000, end = 0, bytecnt,
|
||||||
|
cksum1, cksum, bytes[250];
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
sscanf(cptr," %x-%x", &start, &end);
|
||||||
|
if (flag) { // dump
|
||||||
|
if (start == 0x10000) // no address parameter
|
||||||
|
return SCPE_2FARG;
|
||||||
|
if (sim_switches & 0x80) { // hex dump
|
||||||
|
addr = start;
|
||||||
|
while (addr <= end) { // more records to write
|
||||||
|
if ((addr + 16) <= end) // how many bytes this record
|
||||||
|
bytecnt = 16 + 3;
|
||||||
|
else
|
||||||
|
bytecnt = end - addr + 4;
|
||||||
|
cksum = -1 - (bytecnt) - (addr >> 8) - (addr & 0xFF); //init cksum
|
||||||
|
fprintf(fileref, "S1%02X%02X%02X", bytecnt, addr>>8, addr&0xFF); //header
|
||||||
|
for (i=0; i<bytecnt-3; i++, addr++, cnt++) { // data
|
||||||
|
fprintf(fileref, "%02X", M[addr]);
|
||||||
|
cksum -= M[addr];
|
||||||
|
}
|
||||||
|
fprintf(fileref, "%02X\r\n", cksum & 0xff); // eor
|
||||||
|
}
|
||||||
|
fprintf(fileref, "S9\r\n"); // eof
|
||||||
|
} else { // binary dump
|
||||||
|
for (addr = start; addr <= end; addr++, cnt++) {
|
||||||
|
putc(M[addr], fileref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf ("%d Bytes dumped starting at %04X\n", cnt, start);
|
||||||
|
} else { // load
|
||||||
|
if (sim_switches & 0x80) { // hex load
|
||||||
|
while ((fgets(buffer, 255, fileref)) != NULL) {
|
||||||
|
if (buffer[0] != 'S')
|
||||||
|
printf("Not a Motorola hex format file\n");
|
||||||
|
else {
|
||||||
|
if (buffer[0] == '0') // name record
|
||||||
|
printf("Name record found and ignored\n");
|
||||||
|
else if (buffer[1] == '1') { // another record
|
||||||
|
sscanf(buffer+2,"%2x%4x", &bytecnt, &addr);
|
||||||
|
if (start == 0x10000)
|
||||||
|
start = addr;
|
||||||
|
for (i=0; i < bytecnt-3; i++)
|
||||||
|
sscanf(buffer+8+(2*i), "%2x", &bytes[i]);
|
||||||
|
sscanf(buffer+8+(2*i), "%2x", &cksum1);
|
||||||
|
cksum = -1 - (bytecnt) - (addr >> 8) - (addr & 0xFF); //init cksum
|
||||||
|
for (i=0; i < bytecnt-3; i++)
|
||||||
|
cksum -= bytes[i];
|
||||||
|
cksum &= 0xFF;
|
||||||
|
if (cksum != cksum1)
|
||||||
|
printf("Checksum error\n");
|
||||||
|
else {
|
||||||
|
for (i=0; i < bytecnt-3; i++) {
|
||||||
|
M[addr++] = bytes[i];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (buffer[1] == '9') // end of file
|
||||||
|
printf("End of file\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // binary load
|
||||||
|
if (start == 0x10000) // no starting address
|
||||||
|
addr = saved_PC;
|
||||||
|
else
|
||||||
|
addr = start;
|
||||||
|
start = addr;
|
||||||
|
while ((i = getc (fileref)) != EOF) {
|
||||||
|
M[addr] = i;
|
||||||
|
addr++;
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf ("%d Bytes loaded starting at %04X\n", cnt, start);
|
||||||
|
}
|
||||||
|
return (SCPE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Symbolic output
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
*of = output stream
|
||||||
|
addr = current PC
|
||||||
|
*val = pointer to values
|
||||||
|
*uptr = pointer to unit
|
||||||
|
sw = switches
|
||||||
|
Outputs:
|
||||||
|
status = error code
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
|
||||||
|
UNIT *uptr, int32 sw)
|
||||||
|
{
|
||||||
|
int32 i, inst, inst1;
|
||||||
|
|
||||||
|
if (sw & SWMASK ('D')) { // dump memory
|
||||||
|
for (i=0; i<16; i++)
|
||||||
|
fprintf(of, "%02X ", val[i]);
|
||||||
|
fprintf(of, " ");
|
||||||
|
for (i=0; i<16; i++)
|
||||||
|
if (isprint(val[i]))
|
||||||
|
fprintf(of, "%c", val[i]);
|
||||||
|
else
|
||||||
|
fprintf(of, ".");
|
||||||
|
return -15;
|
||||||
|
} else if (sw & SWMASK ('M')) { // dump instruction mnemonic
|
||||||
|
inst = val[0];
|
||||||
|
if (!oplen[inst]) { // invalid opcode
|
||||||
|
fprintf(of, "%02X", inst);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
inst1 = inst & 0xF0;
|
||||||
|
fprintf (of, "%s", opcode[inst]); // mnemonic
|
||||||
|
if (strlen(opcode[inst]) == 3)
|
||||||
|
fprintf(of, " ");
|
||||||
|
if (inst1 == 0x20 || inst == 0x8D) { // rel operand
|
||||||
|
inst1 = val[1];
|
||||||
|
if (val[1] & 0x80)
|
||||||
|
inst1 |= 0xFF00;
|
||||||
|
fprintf(of, " $%04X", (addr + inst1 + 2) & ADDRMASK);
|
||||||
|
} else if (inst1 == 0x80 || inst1 == 0xC0) { // imm operand
|
||||||
|
if ((inst & 0x0F) < 0x0C)
|
||||||
|
fprintf(of, " #$%02X", val[1]);
|
||||||
|
else
|
||||||
|
fprintf(of, " #$%02X%02X", val[1], val[2]);
|
||||||
|
} else if (inst1 == 0x60 || inst1 == 0xA0 || inst1 == 0xE0) // ind operand
|
||||||
|
fprintf(of, " %d,X", val[1]);
|
||||||
|
else if (inst1 == 0x70 || inst1 == 0xb0 || inst1 == 0xF0) // ext operand
|
||||||
|
fprintf(of, " $%02X%02X", val[1], val[2]);
|
||||||
|
return (-(oplen[inst] - 1));
|
||||||
|
} else
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* address output routine */
|
||||||
|
|
||||||
|
t_addr fprint_addr(FILE *of, DEVICE *dptr, t_addr addr)
|
||||||
|
{
|
||||||
|
fprintf(of, "%04X", addr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Symbolic input
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
*cptr = pointer to input string
|
||||||
|
addr = current PC
|
||||||
|
*uptr = pointer to unit
|
||||||
|
*val = pointer to output values
|
||||||
|
sw = switches
|
||||||
|
Outputs:
|
||||||
|
status = error status
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw)
|
||||||
|
{
|
||||||
|
int32 cflag, i = 0, j, r;
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||||
|
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||||
|
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||||
|
if (cptr[0] == 0)
|
||||||
|
return SCPE_ARG; /* must have 1 char */
|
||||||
|
val[0] = (uint32) cptr[0];
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
|
||||||
|
if (cptr[0] == 0)
|
||||||
|
return SCPE_ARG; /* must have 1 char */
|
||||||
|
val[0] = ((uint32) cptr[0] << 8) + (uint32) cptr[1];
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* An instruction: get opcode (all characters until null, comma,
|
||||||
|
or numeric (including spaces).
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (*cptr == ',' || *cptr == '\0' ||
|
||||||
|
isdigit(*cptr))
|
||||||
|
break;
|
||||||
|
gbuf[i] = toupper(*cptr);
|
||||||
|
cptr++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow for RST which has numeric as part of opcode */
|
||||||
|
|
||||||
|
if (toupper(gbuf[0]) == 'R' &&
|
||||||
|
toupper(gbuf[1]) == 'S' &&
|
||||||
|
toupper(gbuf[2]) == 'T') {
|
||||||
|
gbuf[i] = toupper(*cptr);
|
||||||
|
cptr++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow for 'MOV' which is only opcode that has comma in it. */
|
||||||
|
|
||||||
|
if (toupper(gbuf[0]) == 'M' &&
|
||||||
|
toupper(gbuf[1]) == 'O' &&
|
||||||
|
toupper(gbuf[2]) == 'V') {
|
||||||
|
gbuf[i] = toupper(*cptr);
|
||||||
|
cptr++;
|
||||||
|
i++;
|
||||||
|
gbuf[i] = toupper(*cptr);
|
||||||
|
cptr++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* kill trailing spaces if any */
|
||||||
|
gbuf[i] = '\0';
|
||||||
|
for (j = i - 1; gbuf[j] == ' '; j--) {
|
||||||
|
gbuf[j] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find opcode in table */
|
||||||
|
for (j = 0; j < 256; j++) {
|
||||||
|
if (strcmp(gbuf, opcode[j]) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j > 255) /* not found */
|
||||||
|
return SCPE_ARG;
|
||||||
|
|
||||||
|
val[0] = j; /* store opcode */
|
||||||
|
if (oplen[j] < 2) /* if 1-byter we are done */
|
||||||
|
return SCPE_OK;
|
||||||
|
if (*cptr == ',') cptr++;
|
||||||
|
cptr = get_glyph(cptr, gbuf, 0); /* get address */
|
||||||
|
sscanf(gbuf, "%o", &r);
|
||||||
|
if (oplen[j] == 2) {
|
||||||
|
val[1] = r & 0xFF;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
val[1] = r & 0xFF;
|
||||||
|
val[2] = (r >> 8) & 0xFF;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize optional interfaces */
|
||||||
|
|
||||||
|
void sim_special_init (void)
|
||||||
|
{
|
||||||
|
// *sim_vm_fprint_addr = &fprint_addr;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue