mirror of
https://github.com/simh/simh.git
synced 2026-04-15 16:11:13 +00:00
Beta Simulators (PDQ-3 and SAGE) from Holger Veit
This commit is contained in:
BIN
PDQ-3/hdt/CPU_C5.bin
Normal file
BIN
PDQ-3/hdt/CPU_C5.bin
Normal file
Binary file not shown.
BIN
PDQ-3/master.imd
Normal file
BIN
PDQ-3/master.imd
Normal file
Binary file not shown.
174
PDQ-3/names.sim
Normal file
174
PDQ-3/names.sim
Normal file
@@ -0,0 +1,174 @@
|
||||
name CSP:proc53 initdriver
|
||||
name CSP:proc52 ExtractSegno
|
||||
name CSP:proc51 getsib
|
||||
name CSP:proc50 myselfer
|
||||
name CSP:proc49 S_IOR_Set
|
||||
name CSP:proc48 S_Read_Seg
|
||||
name CSP:proc47 S_Chuck_G_Dir
|
||||
name CSP:proc46 S_Finish_CU
|
||||
name CSP:proc45 S_Execute_CU
|
||||
name CSP:proc44 S_Geq_U
|
||||
name CSP:proc43 S_Blow_Up
|
||||
name CSP:proc42 S_Bump_Heap
|
||||
name CSP:proc41 S_R_Mem_Avail
|
||||
name CSP:proc40 S_Mem_Avail
|
||||
name CSP:proc39 S_Halt
|
||||
name CSP:proc38 S_Unit_Clear
|
||||
name CSP:proc37 S_Unit_Wait
|
||||
name CSP:proc36 S_Pwr_of_Ten
|
||||
name CSP:proc35 S_Unit_Busy
|
||||
name CSP:proc34 S_Io_Result
|
||||
name CSP:proc33 S_Release
|
||||
name CSP:proc32 S_Mark
|
||||
name CSP:proc31 X_Sqrt
|
||||
name CSP:proc30 X_Exp
|
||||
name CSP:proc29 X_Ln
|
||||
name CSP:proc28 S_Unload_Seg
|
||||
name CSP:proc27 S_Load_Seg
|
||||
name CSP:proc26 S_Unit_Status
|
||||
name CSP:proc25 X_Sin
|
||||
name CSP:proc24 S_Blk_Exit
|
||||
name CSP:proc23 S_Attach
|
||||
name CSP:proc22 S_Rel_Seg
|
||||
name CSP:proc21 S_Get_Seg
|
||||
name CSP:proc20 S_Stop_P
|
||||
name CSP:proc19 S_Start_P
|
||||
name CSP:proc18 S_Check
|
||||
name CSP:proc17 S_Assign
|
||||
name CSP:proc16 S_Geq_S
|
||||
name CSP:proc15 S_Leq_S
|
||||
name CSP:proc14 S_Equ_S
|
||||
name CSP:proc13 S_New
|
||||
name CSP:proc12 S_IO_Check
|
||||
name CSP:proc11 S_Scan
|
||||
name CSP:proc10 S_Fill_Char
|
||||
name CSP:proc9 S_Time
|
||||
name CSP:proc8 S_Tree_Search
|
||||
name CSP:proc17 S_Id_Search
|
||||
name CSP:proc6 S_Unit_Write
|
||||
name CSP:proc5 S_Unit_Read
|
||||
name CSP:proc4 S_Exit
|
||||
name CSP:proc3 S_Move_Right
|
||||
name CSP:proc2 S_Move_Left
|
||||
name CSP:proc1 csp_initunit
|
||||
name GOTOXYU:proc1 gotoxyu_initunit
|
||||
name GOTOXYU:proc2 Z19_XY
|
||||
name PASCALIO:proc1 pascalio_initunit
|
||||
name PASCALIO:proc2 F_Read_Real
|
||||
name PASCALIO:proc3 F_Write_Real
|
||||
name PASCALIO:proc4 F_Seek
|
||||
name LONGINT:proc1 longint_initunit
|
||||
name LONGINT:proc2 F_Read_Dec
|
||||
name LONGINT:proc3 F_Write_Dec
|
||||
name LONGINT:proc4 Decops
|
||||
name TRANSCEN:proc1 transcen_initunit
|
||||
name TRANSCEN:proc2 S_Sin
|
||||
name TRANSCEN:proc3 S_Cos
|
||||
name TRANSCEN:proc4 S_Log10
|
||||
name TRANSCEN:proc5 S_Arctan
|
||||
name TRANSCEN:proc6 S_Ln
|
||||
name TRANSCEN:proc7 S_Exp
|
||||
name TRANSCEN:proc8 S_Sqrt
|
||||
name HEAPOPS:proc1 heapops_initunit
|
||||
name HEAPOPS:proc2 H_Mark
|
||||
name HEAPOPS:proc3 H_Release
|
||||
name HEAPOPS:proc4 H_New
|
||||
name HEAPOPS:proc5 H_Dispose
|
||||
name HEAPOPS:proc6 H_Mem_Lock
|
||||
name HEAPOPS:proc7 H_Mem_Swap
|
||||
name HEAPOPS:proc8 H_Var_New
|
||||
name HEAPOPS:proc9 H_Var_Dispose
|
||||
name HEAPOPS:proc10 H_Var_Avail
|
||||
name HEAPOPS:proc11 H_Unlock_Seg
|
||||
name HEAPOPS:proc12 H_Clean_Up
|
||||
name EXCEPTIO:proc1 exceptio_initunit
|
||||
name EXCEPTIO:proc2 Handle_Exception
|
||||
name EXCEPTIN:proc1 exceptin_initunit
|
||||
name EXCEPTIN:proc2 Ex_Stats
|
||||
name HALTUNIT:proc1 haltunit_initunit
|
||||
name HALTUNIT:proc2 Do_Halt
|
||||
name CLOCKDRI:proc1 clockdri_initunit
|
||||
name CLOCKDRI:proc2 Clk_Init
|
||||
name CLOCKDRI:proc3 Clk_Read
|
||||
name CLOCKDRI:proc4 Clk_Write
|
||||
name CLOCKDRI:proc5 Clk_Clear
|
||||
name CLOCKDRI:proc6 Clk_Power
|
||||
name CLOCKDRI:proc7 Clk_Status
|
||||
name CLOCKDRI:proc8 Clk_Term
|
||||
name DTCDRIVE:proc1 dtcdrive_initunit
|
||||
name DTCDRIVE:proc2 Dtc_Init
|
||||
name DTCDRIVE:proc3 Dtc_Read
|
||||
name DTCDRIVE:proc4 Dtc_Write
|
||||
name DTCDRIVE:proc5 Dtc_Clear
|
||||
name DTCDRIVE:proc6 Dtc_Power
|
||||
name DTCDRIVE:proc7 Dtc_Status
|
||||
name DTCDRIVE:proc8 Dtc_Term
|
||||
name DZ11DRIV:proc1 dz11driv_initunit
|
||||
name DZ11DRIV:proc2 DZ_Init
|
||||
name DZ11DRIV:proc3 DZ_Read
|
||||
name DZ11DRIV:proc4 DZ_Write
|
||||
name DZ11DRIV:proc5 DZ_Clear
|
||||
name DZ11DRIV:proc6 DZ_Power
|
||||
name DZ11DRIV:proc7 DZ_Status
|
||||
name DZ11DRIV:proc8 DZ_Term
|
||||
name FLOPPYDR:proc1 floppydr_initunit
|
||||
name FLOPPYDR:proc2 Fl_Init
|
||||
name FLOPPYDR:proc3 Fl_Read
|
||||
name FLOPPYDR:proc4 Fl_Write
|
||||
name FLOPPYDR:proc5 Fl_Clear
|
||||
name FLOPPYDR:proc6 Fl_Power
|
||||
name FLOPPYDR:proc7 Fl_Status
|
||||
name FLOPPYDR:proc8 Fl_Term
|
||||
name PRIAMDRI:proc1 priamdri_initunit
|
||||
name PRIAMDRI:proc2 Prm_Init
|
||||
name PRIAMDRI:proc3 Prm_Read
|
||||
name PRIAMDRI:proc4 Prm_Write
|
||||
name PRIAMDRI:proc5 Prm_Clear
|
||||
name PRIAMDRI:proc6 Prm_Power
|
||||
name PRIAMDRI:proc7 Prm_Status
|
||||
name PRIAMDRI:proc8 Prm_Term
|
||||
name RL02DRIV:proc1 rl02driv_initunit
|
||||
name RL02DRIV:proc2 RL_Init
|
||||
name RL02DRIV:proc3 RL_Read
|
||||
name RL02DRIV:proc4 RL_Write
|
||||
name RL02DRIV:proc5 RL_Clear
|
||||
name RL02DRIV:proc6 RL_Power
|
||||
name RL02DRIV:proc7 RL_Status
|
||||
name RL02DRIV:proc8 RL_Term
|
||||
name SERDRIVE:proc1 serdrive_initunit
|
||||
name SERDRIVE:proc2 Ser_Init
|
||||
name SERDRIVE:proc3 Ser_Read
|
||||
name SERDRIVE:proc4 Ser_Write
|
||||
name SERDRIVE:proc5 Ser_Clear
|
||||
name SERDRIVE:proc6 Ser_Power
|
||||
name SERDRIVE:proc7 Ser_Status
|
||||
name SERDRIVE:proc8 Ser_Term
|
||||
name STANDRIV:proc1 standriv_initunit
|
||||
name STANDRIV:proc2 Stan_Init
|
||||
name STANDRIV:proc3 Stan_Read
|
||||
name STANDRIV:proc4 Stan_Write
|
||||
name STANDRIV:proc5 Stan_Clear
|
||||
name STANDRIV:proc6 Stan_Power
|
||||
name STANDRIV:proc7 Stan_Status
|
||||
name STANDRIV:proc8 Stan_Term
|
||||
name SYSDRIVE:proc1 sysdrive_initunit
|
||||
name SYSDRIVE:proc2 Intr_Init
|
||||
name SYSDRIVE:proc3 Intr_Enable
|
||||
name SYSDRIVE:proc4 Enter_HDT
|
||||
name TM11DRIV:proc1 standriv_initunit
|
||||
name TM11DRIV:proc2 TM_Init
|
||||
name TM11DRIV:proc3 TM_Read
|
||||
name TM11DRIV:proc4 TM_Write
|
||||
name TM11DRIV:proc5 TM_Clear
|
||||
name TM11DRIV:proc6 TM_Power
|
||||
name TM11DRIV:proc7 TM_Status
|
||||
name TM11DRIV:proc8 TM_Term
|
||||
name SPOOLUNI:proc1 spooluni_initunit
|
||||
name SPOOLUNI:proc2 Spool_Status
|
||||
name SPOOLUNI:proc3 Spool_Restart
|
||||
name SPOOLUNI:proc4 Spool_Stop
|
||||
name SPOOLUNI:proc5 Spool_File
|
||||
name SHELL:proc1 SHELL_initunit
|
||||
name GETCMD:proc1 GETCMD_initunit
|
||||
name SERDRIVE:proc9 SER_EnDis_RCVXMIT
|
||||
name SERDRIVE:proc16 SER_RawEmit
|
||||
232
PDQ-3/opcode.dbg
Normal file
232
PDQ-3/opcode.dbg
Normal file
@@ -0,0 +1,232 @@
|
||||
0 0 ;SLDC0
|
||||
1 0 ;SLDC1
|
||||
2 0 ;SLDC2
|
||||
3 0 ;SLDC3
|
||||
4 0 ;SLDC4
|
||||
5 0 ;SLDC5
|
||||
6 0 ;SLDC6
|
||||
7 0 ;SLDC7
|
||||
8 0 ;SLDC8
|
||||
9 0 ;SLDC9
|
||||
a 0 ;SLDC10
|
||||
b 0 ;SLDC11
|
||||
c 0 ;SLDC12
|
||||
d 0 ;SLDC13
|
||||
e 0 ;SLDC14
|
||||
f 0 ;SLDC15
|
||||
10 0 ;SLDC16
|
||||
11 0 ;SLDC17
|
||||
12 0 ;SLDC18
|
||||
13 0 ;SLDC19
|
||||
14 0 ;SLDC20
|
||||
15 0 ;SLDC21
|
||||
16 0 ;SLDC22
|
||||
17 0 ;SLDC23
|
||||
18 0 ;SLDC24
|
||||
19 0 ;SLDC25
|
||||
1a 0 ;SLDC26
|
||||
1b 0 ;SLDC27
|
||||
1c 0 ;SLDC28
|
||||
1d 0 ;SLDC29
|
||||
1e 0 ;SLDC30
|
||||
1f 0 ;SLDC31
|
||||
20 0 ;SLDL1
|
||||
21 0 ;SLDL2
|
||||
22 0 ;SLDL3
|
||||
23 0 ;SLDL4
|
||||
24 0 ;SLDL5
|
||||
25 0 ;SLDL6
|
||||
26 0 ;SLDL7
|
||||
27 0 ;SLDL8
|
||||
28 0 ;SLDL9
|
||||
29 0 ;SLDL10
|
||||
2a 0 ;SLDL11
|
||||
2b 0 ;SLDL12
|
||||
2c 0 ;SLDL13
|
||||
2d 0 ;SLDL14
|
||||
2e 0 ;SLDL15
|
||||
2f 0 ;SLDL16
|
||||
30 0 ;SLDO1
|
||||
31 0 ;SLDO2
|
||||
32 0 ;SLDO3
|
||||
33 0 ;SLDO4
|
||||
34 0 ;SLDO5
|
||||
35 0 ;SLDO6
|
||||
36 0 ;SLDO7
|
||||
37 0 ;SLDO8
|
||||
38 0 ;SLDO9
|
||||
39 0 ;SLDO10
|
||||
3a 0 ;SLDO11
|
||||
3b 0 ;SLDO12
|
||||
3c 0 ;SLDO13
|
||||
3d 0 ;SLDO14
|
||||
3e 0 ;SLDO15
|
||||
3f 0 ;SLDO16
|
||||
40 3 ;
|
||||
41 3 ;
|
||||
42 3 ;
|
||||
43 3 ;
|
||||
44 3 ;
|
||||
45 3 ;
|
||||
46 3 ;
|
||||
47 3 ;
|
||||
48 3 ;
|
||||
49 3 ;
|
||||
4a 3 ;
|
||||
4b 3 ;
|
||||
4c 3 ;
|
||||
4d 3 ;
|
||||
4e 3 ;
|
||||
4f 3 ;
|
||||
50 3 ;
|
||||
51 3 ;
|
||||
52 3 ;
|
||||
53 3 ;
|
||||
54 3 ;
|
||||
55 3 ;
|
||||
56 3 ;
|
||||
57 3 ;
|
||||
58 3 ;
|
||||
59 3 ;
|
||||
5a 3 ;
|
||||
5b 3 ;
|
||||
5c 3 ;
|
||||
5d 3 ;
|
||||
5e 3 ;
|
||||
5f 3 ;
|
||||
60 3 ;
|
||||
61 3 ;
|
||||
62 3 ;
|
||||
63 3 ;
|
||||
64 3 ;
|
||||
65 3 ;
|
||||
66 3 ;
|
||||
67 3 ;
|
||||
68 3 ;
|
||||
69 3 ;
|
||||
6a 3 ;
|
||||
6b 3 ;
|
||||
6c 3 ;
|
||||
6d 3 ;
|
||||
6e 3 ;
|
||||
6f 3 ;
|
||||
70 3 ;
|
||||
71 3 ;
|
||||
72 3 ;
|
||||
73 3 ;
|
||||
74 3 ;
|
||||
75 3 ;
|
||||
76 3 ;
|
||||
77 3 ;
|
||||
78 0 ;SIND0
|
||||
79 0 ;SIND1
|
||||
7a 0 ;SIND2
|
||||
7b 0 ;SIND3
|
||||
7c 0 ;SIND4
|
||||
7d 0 ;SIND5
|
||||
7e 0 ;SIND6
|
||||
7f 0 ;SIND7
|
||||
80 0 ;LDCB
|
||||
81 0 ;LDCI
|
||||
82 0 ;LCA
|
||||
83 0 ;LDC
|
||||
84 0 ;LLA
|
||||
85 3 ;LDO
|
||||
86 0 ;LAO
|
||||
87 0 ;LDL
|
||||
88 0 ;LDA
|
||||
89 0 ;LOD
|
||||
8a 0 ;UJP
|
||||
8b 0 ;UJPL
|
||||
8c 0 ;MPI
|
||||
8d 0 ;DVI
|
||||
8e 0 ;STM
|
||||
8f 0 ;MODI
|
||||
90 0 ;CPL
|
||||
91 0 ;CPG
|
||||
92 0 ;CPI
|
||||
93 0 ;CXL
|
||||
94 0 ;CXG
|
||||
95 0 ;CXI
|
||||
96 0 ;RPU
|
||||
97 0 ;CPF
|
||||
98 0 ;LDCN
|
||||
99 0 ;LSL
|
||||
9a 3 ;LDE
|
||||
9b 3 ;LAE
|
||||
9c 0 ;NOP
|
||||
9d 0 ;LPR
|
||||
9e 3 ;BPT
|
||||
9f 0 ;BNOT
|
||||
a0 0 ;LOR
|
||||
a1 0 ;LAND
|
||||
a2 0 ;ADI
|
||||
a3 0 ;SBI
|
||||
a4 0 ;STL
|
||||
a5 0 ;SRO
|
||||
a6 0 ;STR
|
||||
a7 0 ;LDB
|
||||
a8 3 ;
|
||||
a9 3 ;
|
||||
aa 3 ;
|
||||
ab 3 ;
|
||||
ac 3 ;
|
||||
ad 3 ;
|
||||
ae 3 ;
|
||||
af 3 ;
|
||||
b0 0 ;EQUI
|
||||
b1 0 ;NEQI
|
||||
b2 0 ;LEQI
|
||||
b3 0 ;GEQI
|
||||
b4 0 ;LEUSW
|
||||
b5 0 ;GEUSW
|
||||
b6 0 ;EQUPWR
|
||||
b7 0 ;LEQPWR
|
||||
b8 0 ;GEQPWR
|
||||
b9 0 ;EQUBYT
|
||||
ba 3 ;LEQBYT
|
||||
bb 3 ;GEQBYT
|
||||
bc 0 ;SRS
|
||||
bd 3 ;SWAP
|
||||
be 3 ;TNC
|
||||
bf 3 ;RND
|
||||
c0 3 ;ADR
|
||||
c1 3 ;SBR
|
||||
c2 3 ;MPR
|
||||
c3 0 ;DVR
|
||||
c4 0 ;STO
|
||||
c5 0 ;MOV
|
||||
c6 3 ;DUP2
|
||||
c7 0 ;ADJ
|
||||
c8 0 ;STB
|
||||
c9 0 ;LDP
|
||||
ca 0 ;STP
|
||||
cb 0 ;CHK
|
||||
cc 0 ;FLT
|
||||
cd 0 ;EQUREAL
|
||||
ce 0 ;LEQREAL
|
||||
cf 3 ;GEQREAL
|
||||
d0 0 ;LDM
|
||||
d1 0 ;SPR
|
||||
d2 3 ;EFJ
|
||||
d3 3 ;NFJ
|
||||
d4 0 ;FJP
|
||||
d5 0 ;FJPL
|
||||
d6 0 ;XJP
|
||||
d7 0 ;IXA
|
||||
d8 0 ;IXP
|
||||
d9 3 ;STE
|
||||
da 0 ;INN
|
||||
db 0 ;UNI
|
||||
dc 0 ;INT
|
||||
dd 0 ;DIF
|
||||
de 0 ;SIGNAL
|
||||
df 0 ;WAIT
|
||||
e0 3 ;ABI
|
||||
e1 0 ;NGI
|
||||
e2 0 ;DUP1
|
||||
e3 3 ;ABR
|
||||
e4 3 ;NGR
|
||||
e5 0 ;LNOT
|
||||
e6 0 ;IND
|
||||
e7 0 ;INC
|
||||
1733
PDQ-3/pdq3_cpu.c
Normal file
1733
PDQ-3/pdq3_cpu.c
Normal file
File diff suppressed because it is too large
Load Diff
441
PDQ-3/pdq3_debug.c
Normal file
441
PDQ-3/pdq3_debug.c
Normal file
@@ -0,0 +1,441 @@
|
||||
/* pdq3_debug.c: PDQ3 debug helper
|
||||
|
||||
Work derived from Copyright (c) 2004-2012, Robert M. Supnik
|
||||
Copyright (c) 2013 Holger Veit
|
||||
|
||||
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 names of Robert M Supnik and Holger Veit
|
||||
shall not 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 and Holger Veit.
|
||||
|
||||
20130421 hv initial version
|
||||
20130928 hv fix problem with callstack when S_Start_P patches MSCW
|
||||
20131012 hv view calltree returned incorrect segment of caller
|
||||
*/
|
||||
#include "pdq3_defs.h"
|
||||
|
||||
static uint8 *opdebug = NULL;
|
||||
|
||||
static void dbg_opdbgcreate() {
|
||||
int i;
|
||||
FILE *fd = fopen(DEBUG_OPDBGFILE, "w");
|
||||
if (fd==NULL) {
|
||||
fprintf(stderr,"Cannot create %s\n", DEBUG_OPDBGFILE);
|
||||
exit(1);
|
||||
}
|
||||
for (i=DEBUG_MINOPCODE; i<DEBUG_MAXOPCODE; i++) {
|
||||
if (DEBUG_VALIDOP(i)) {
|
||||
fprintf(fd,"%x %d ;%s\n",
|
||||
i, DEBUG_PRE|DEBUG_POST, optable[i].name);
|
||||
} else {
|
||||
fprintf(fd,"%x %d ;invalid\n",
|
||||
i, DEBUG_PRE|DEBUG_POST);
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
fprintf(stderr,"%s created. Adapt file manually and restart simh\n", DEBUG_OPDBGFILE);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static void dbg_opdbginit() {
|
||||
char line[100];
|
||||
int i, f;
|
||||
FILE* fd = fopen(DEBUG_OPDBGFILE,"r");
|
||||
if (fd == NULL)
|
||||
dbg_opdbgcreate(); /* will not return */
|
||||
|
||||
if (opdebug == NULL)
|
||||
opdebug = (uint8*)calloc(DEBUG_MAXOPCODE-DEBUG_MINOPCODE,sizeof(uint8));
|
||||
|
||||
for (i=DEBUG_MINOPCODE; i<DEBUG_MAXOPCODE; i++)
|
||||
opdebug[i-DEBUG_MINOPCODE] = DEBUG_PRE|DEBUG_POST;
|
||||
while (!feof(fd)) {
|
||||
fgets(line,100,fd);
|
||||
sscanf(line,"%x %d", &i, &f);
|
||||
opdebug[i-DEBUG_MINOPCODE] = f;
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
t_stat dbg_check(t_value op, uint8 flag) {
|
||||
if (opdebug[op-DEBUG_MINOPCODE] & flag) {
|
||||
if (flag & DEBUG_PRE) {
|
||||
opdebug[op-DEBUG_MINOPCODE] &= ~DEBUG_PRE;
|
||||
return STOP_DBGPRE;
|
||||
} else
|
||||
return STOP_DBGPOST;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dbg_dump_tib(FILE *fd, uint16 base) {
|
||||
t_stat rc;
|
||||
uint16 data;
|
||||
fprintf(fd, "TIB at $%04x (CTP=$%04x, RQ=$%04x)\n",base, reg_ctp, reg_rq);
|
||||
if ((rc=ReadEx(base, OFF_WAITQ, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " WAITQ: $%04x\n",data);
|
||||
if ((rc=ReadBEx(base+OFFB_PRIOR, 0, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " PRIOR: %02x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_SPLOW, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " SPLOW: $%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_SPUPR, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " SPUPR: $%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_SP, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " SP: $%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_MP, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " MP: $%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_BP, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " BP: $%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_IPC, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " IPC: #%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_SEGB, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " SEGB: $%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_HANGP, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " HANGP: $%04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_IORSLT, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " IORSLT: %04x\n",data);
|
||||
if ((rc=ReadEx(base, OFF_SIBS, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " SIBS: $%04x\n",data);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dbg_dump_queue(FILE* fd, const char* qname, uint16 q) {
|
||||
t_stat rc;
|
||||
fprintf(fd, "dump queue %s: address=$%04x\n ",qname, q);
|
||||
while (q != NIL) {
|
||||
fprintf(fd, "$%04x->",q);
|
||||
if ((rc=ReadEx(q, OFF_WAITQ, &q)) != SCPE_OK) return rc;
|
||||
}
|
||||
fprintf(fd, "NIL\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dbg_dump_mscw(FILE* fd, uint16 base) {
|
||||
t_stat rc;
|
||||
uint16 data;
|
||||
fprintf(fd, "MSCW at $%04x\n",base);
|
||||
if ((rc=ReadEx(base, OFF_MSSTAT, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " MSSTAT: $%04x\n", data);
|
||||
if ((rc=ReadEx(base, OFF_MSDYNL, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " MSDYNL: $%04x\n", data);
|
||||
if ((rc=ReadEx(base, OFF_MSIPC, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " MSIPC: $%04x\n", data);
|
||||
if ((rc=ReadBEx(base+OFFB_MSSEG, 0, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " MSSEG: %02x\n", data);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
void dbg_enable() {
|
||||
cpu_dev.dctrl |= (DBG_CPU_READ|DBG_CPU_WRITE|DBG_CPU_STACK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Segment Tracking support
|
||||
*****************************************************************************/
|
||||
|
||||
static char* pdq3_segname(uint16 nameptr) {
|
||||
static char name[10];
|
||||
uint16 data;
|
||||
int i;
|
||||
for (i=0; i<8; i++) {
|
||||
ReadBEx(nameptr,i,&data);
|
||||
name[i] = data != ' ' ? data : 0;
|
||||
}
|
||||
name[8] = 0;
|
||||
return name;
|
||||
}
|
||||
|
||||
t_stat dbg_dump_seg(FILE* fd, uint16 segptr) {
|
||||
t_stat rc;
|
||||
uint16 data;
|
||||
if ((rc=ReadEx(segptr, OFF_SEGBASE, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " BASE: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEGLENG, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " LENGTH: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEGREFS, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " REFS: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEGADDR, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " ADDR: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEGUNIT, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " UNIT: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_PREVSP, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " PREVSP: $%04x\n",data);
|
||||
fprintf(fd, " NAME: %s\n", pdq3_segname(segptr+OFF_SEGNAME));
|
||||
if ((rc=ReadEx(segptr, OFF_SEGLINK, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " LINK: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEGGLOBAL, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " GLOBAL: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEGINIT, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " INIT: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEG13, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " entry13: $%04x\n",data);
|
||||
if ((rc=ReadEx(segptr, OFF_SEGBACK, &data)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " SELF: $%04x\n",data);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dbg_dump_segtbl(FILE* fd) {
|
||||
int i;
|
||||
uint16 segptr, nsegs;
|
||||
t_stat rc;
|
||||
|
||||
if (reg_ssv < 0x2030 || reg_ssv > 0xf000) {
|
||||
printf("Cannot list segments in bootloader: incomplete tables\n");
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
if ((rc=Read(reg_ssv, -1, &nsegs, 0)) != SCPE_OK) return rc;
|
||||
|
||||
fprintf(fd, "Segment table: ssv=$%04x size=%d\n",reg_ssv, nsegs);
|
||||
for (i=0; i<=nsegs; i++) {
|
||||
if ((rc=ReadEx(reg_ssv, i, &segptr)) != SCPE_OK) return rc;
|
||||
fprintf(fd, " %02x %04x %s\n",i,segptr, pdq3_segname(segptr + OFF_SEGNAME));
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* segment tracking */
|
||||
typedef struct _seginfo {
|
||||
uint16 base; /* base load address */
|
||||
struct _seginfo* next;
|
||||
uint16 idx; /* index into SSV table */
|
||||
char name[10]; /* segment name */
|
||||
uint16 size;
|
||||
uint16 nproc;
|
||||
uint16 segno;
|
||||
} SEGINFO;
|
||||
|
||||
#define SEGHASHSIZE 97
|
||||
SEGINFO* seghash[SEGHASHSIZE];
|
||||
#define SEGHASHFUNC(i) (i % SEGHASHSIZE)
|
||||
|
||||
void dbg_segtrackinit() {
|
||||
int i;
|
||||
for (i=0; i<SEGHASHSIZE; i++)
|
||||
seghash[i] = NULL;
|
||||
}
|
||||
|
||||
static SEGINFO* new_seginfo(SEGINFO* next, uint16 base) {
|
||||
SEGINFO* s = (SEGINFO*)malloc(sizeof(SEGINFO));
|
||||
s->next = next;
|
||||
s->base = base;
|
||||
return s;
|
||||
}
|
||||
|
||||
static SEGINFO* find_seginfo(uint16 base, int* idx) {
|
||||
SEGINFO* s;
|
||||
*idx = SEGHASHFUNC(base);
|
||||
s = seghash[*idx];
|
||||
while (s && s->base != base) s = s->next;
|
||||
return s;
|
||||
}
|
||||
|
||||
t_stat dbg_segtrack(uint16 segbase) {
|
||||
t_stat rc;
|
||||
int idx;
|
||||
SEGINFO* s = find_seginfo(segbase, &idx);
|
||||
if (!s) {
|
||||
s = seghash[idx] = new_seginfo(seghash[idx], segbase);
|
||||
if ((rc=ReadEx(segbase, 0, &s->size)) != SCPE_OK) return rc;
|
||||
strcpy(s->name, segbase==0xf418 ? "HDT" : pdq3_segname(segbase+2));
|
||||
if ((rc=ReadBEx(segbase+s->size, 0, &s->segno)) != SCPE_OK) return rc;
|
||||
if ((rc=ReadBEx(segbase+s->size, 1, &s->nproc)) != SCPE_OK) return rc;
|
||||
// printf("Entered at %04x: %s sz=%x seg=%x np=%x\n",segbase, s->name, s->size, s->segno, s->nproc);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Name Alias Handling
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct _aliases {
|
||||
char* key;
|
||||
char* alias;
|
||||
struct _aliases* next;
|
||||
} ALIASES;
|
||||
|
||||
#define ALIASHASHSIZE 97
|
||||
static ALIASES* aliases[ALIASHASHSIZE];
|
||||
|
||||
static void dbg_initaliases() {
|
||||
int i;
|
||||
for (i=0; i<ALIASHASHSIZE; i++)
|
||||
aliases[i] = NULL;
|
||||
}
|
||||
|
||||
static int aliashash(const char* key) {
|
||||
int i, h=0;
|
||||
int len = strlen(key);
|
||||
for (i=0; i<len; i++)
|
||||
h += key[i];
|
||||
return h % ALIASHASHSIZE;
|
||||
}
|
||||
|
||||
static ALIASES* find_alias(const char* key, int* idx) {
|
||||
ALIASES* a;
|
||||
char gbuf[CBUFSIZE], gbuf2[CBUFSIZE];
|
||||
|
||||
get_glyph(key, gbuf, 0);
|
||||
*idx = aliashash(key);
|
||||
a = aliases[*idx];
|
||||
if (a) get_glyph(a->key, gbuf2, 0);
|
||||
while (a && strcmp(gbuf2,gbuf)) {
|
||||
a = a->next;
|
||||
if (a) get_glyph(a->key, gbuf2, 0);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
t_stat dbg_enteralias(const char* key, const char* value) {
|
||||
int idx;
|
||||
ALIASES* a = find_alias(key, &idx);
|
||||
if (!a) {
|
||||
a = (ALIASES*)malloc(sizeof(ALIASES));
|
||||
a->key = strdup(key);
|
||||
a->alias = strdup(value);
|
||||
a->next = aliases[idx];
|
||||
aliases[idx] = a;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dbg_listalias(FILE* fd) {
|
||||
int i;
|
||||
ALIASES* a;
|
||||
fprintf(fd, "Name table:\n");
|
||||
for (i=0; i<ALIASHASHSIZE; i++) {
|
||||
a = aliases[i];
|
||||
while (a) {
|
||||
fprintf(fd, " Name %s = %s\n", a->key, a->alias);
|
||||
a = a->next;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Procedure tracking support
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct _procinfo {
|
||||
struct _procinfo *next;
|
||||
uint16 procno;
|
||||
SEGINFO* seg;
|
||||
uint16 localsz;
|
||||
uint16 freesz;
|
||||
uint16 mscw;
|
||||
uint16 segb;
|
||||
uint16 instipc;
|
||||
uint16 ipc;
|
||||
} PROCINFO;
|
||||
|
||||
const char* find_procname(PROCINFO* p) {
|
||||
ALIASES* a;
|
||||
int dummy;
|
||||
static char buf[100];
|
||||
sprintf(buf,"%s:proc%d", p->seg->name, p->procno);
|
||||
a = find_alias(buf, &dummy);
|
||||
if (a) return a->alias;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static PROCINFO* procroot = NULL;
|
||||
|
||||
static PROCINFO* new_procinfo(uint16 segbase, uint16 procno, uint16 mscw, uint16 osegb) {
|
||||
int dummy;
|
||||
uint16 procbase, procaddr;
|
||||
uint16 exitic, sz1, sz2;
|
||||
PROCINFO* p = (PROCINFO*)malloc(sizeof(PROCINFO));
|
||||
p->procno = procno;
|
||||
p->mscw = mscw;
|
||||
p->seg = find_seginfo(segbase, &dummy);
|
||||
p->segb = osegb;
|
||||
p->instipc = ADDR_OFF(PCX);
|
||||
ReadEx(mscw,OFF_MSIPC, &p->ipc);
|
||||
ReadEx(segbase, 0, &procbase);
|
||||
ReadEx(segbase+procbase-procno, 0, &procaddr);
|
||||
ReadEx(segbase+procaddr, 0, &p->localsz);
|
||||
ReadEx(segbase+procaddr-1, 0, &exitic);
|
||||
ReadBEx(segbase, exitic, &sz1);
|
||||
if (sz1==0x96) {
|
||||
ReadBEx(segbase, exitic+1, &sz1);
|
||||
if (sz1 & 0x80) {
|
||||
ReadBEx(segbase, exitic+2, &sz2);
|
||||
sz1 = ((sz1 & 0x7f)<<8) | sz2;
|
||||
}
|
||||
p->freesz = sz1;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
t_stat dbg_procenter(uint16 segbase, uint16 procno, uint16 mscw, uint16 osegb) {
|
||||
PROCINFO* p = new_procinfo(segbase, procno, mscw, osegb);
|
||||
p->next = procroot;
|
||||
procroot = p;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dbg_procleave() {
|
||||
t_stat rc;
|
||||
PROCINFO* p = procroot;
|
||||
uint16 ipc,pipc;
|
||||
while (p) {
|
||||
pipc = p->ipc;
|
||||
if ((rc=ReadEx(p->mscw,OFF_MSIPC, &ipc)) != SCPE_OK) return rc;
|
||||
procroot = p->next;
|
||||
free(p);
|
||||
if (pipc == ipc) break;
|
||||
p = procroot;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dbg_calltree(FILE* fd) {
|
||||
PROCINFO* p = procroot, *lastp;
|
||||
|
||||
if (!p) {
|
||||
fprintf(fd,"Callstack is empty\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
fprintf(fd,"Calltree:\nCurrently in %s at %04x:%04x\n",
|
||||
find_procname(p), reg_segb, reg_ipc);
|
||||
lastp = p;
|
||||
p = p->next;
|
||||
while (p) {
|
||||
fprintf(fd," at %04x:%04x called by %s (%04x:%04x)\n",
|
||||
lastp->segb, lastp->instipc, find_procname(p), p->segb, p->instipc);
|
||||
lastp = p;
|
||||
p = p->next;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Initialization
|
||||
*****************************************************************************/
|
||||
|
||||
t_stat dbg_init() {
|
||||
dbg_opdbginit();
|
||||
dbg_segtrackinit();
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
415
PDQ-3/pdq3_defs.h
Normal file
415
PDQ-3/pdq3_defs.h
Normal file
@@ -0,0 +1,415 @@
|
||||
/* pdq3_defs.h: PDQ3 simulator definitions
|
||||
|
||||
Work derived from Copyright (c) 2004-2012, Robert M. Supnik
|
||||
Copyright (c) 2013 Holger Veit
|
||||
|
||||
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 names of Robert M Supnik and Holger Veit
|
||||
shall not 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 and Holger Veit.
|
||||
|
||||
20131103 hv INT_CONR/CONT assignments incorrect in docs, must be swapped
|
||||
*/
|
||||
#ifndef _PDQ3_DEFS_H_
|
||||
#define _PDQ3_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
/* constants */
|
||||
#define NIL 0xfc00 /* Pascal Microengine NIL value */
|
||||
#define MSCW_SZ 4 /* size of MSCW */
|
||||
#define REAL_SZ 2 /* size of real number (REAL*4) */
|
||||
#define BSET_SZ 4080 /* usable size of set in bits */
|
||||
#define ISET_SZ 255 /* size of set in words */
|
||||
#define WORD_SZ 16 /* size of machine word in bits */
|
||||
|
||||
#define OFF_SEGBASE 0 /* offsets into SIB entry */
|
||||
#define OFF_SEGLENG 1
|
||||
#define OFF_SEGREFS 2
|
||||
#define OFF_SEGADDR 3
|
||||
#define OFF_SEGUNIT 4
|
||||
#define OFF_PREVSP 5
|
||||
#define OFF_SEGNAME 6
|
||||
#define OFF_SEGLINK 10
|
||||
#define OFF_SEGGLOBAL 11
|
||||
#define OFF_SEGINIT 12
|
||||
#define OFF_SEG13 13
|
||||
#define OFF_SEGBACK 14
|
||||
|
||||
#define OFF_MSSTAT 0 /* offsets into MSCW */
|
||||
#define OFF_MSDYNL 1
|
||||
#define OFF_MSIPC 2
|
||||
#define OFFB_MSSEG 3
|
||||
#define OFFB_MSFLAG 3
|
||||
|
||||
#define OFF_WAITQ 0 /* offset into TIB */
|
||||
#define OFF_QLINK 0
|
||||
#define OFFB_PRIOR 1
|
||||
#define OFFB_FLAGS 1
|
||||
#define OFF_SPLOW 2
|
||||
#define OFF_SPUPR 3
|
||||
#define OFF_SP 4
|
||||
#define OFF_MP 5
|
||||
#define OFF_BP 6
|
||||
#define OFF_IPC 7
|
||||
#define OFF_SEGB 8
|
||||
#define OFF_HANGP 9
|
||||
#define OFF_IORSLT 10
|
||||
#define OFF_SIBS 11
|
||||
|
||||
#define OFF_SEMCOUNT 0 /* offset into SEMA variable */
|
||||
#define OFF_SEMWAITQ 1
|
||||
|
||||
#define SSR_BERR 0x01 /* bits of system status register */
|
||||
#define SSR_TICK 0x02
|
||||
#define SSR_INTVL 0x04
|
||||
#define SSR_BIT3 0x08
|
||||
#define SSR_PWRF 0x10
|
||||
#define SSR_PRNT 0x20
|
||||
#define SSR_INTEN 0x40
|
||||
#define SSR_INIT 0x80
|
||||
|
||||
/* fixed interrupts */
|
||||
#define INT_BERR 0 /* interrupt levels */
|
||||
#define INT_PWRF 1
|
||||
#define INT_DMAFD 2
|
||||
#define INT_CONR 3 /* Appendix B.0.1 has CONT and CONR swapped, see Errata */
|
||||
#define INT_CONT 4
|
||||
#define INT_PRNT 5
|
||||
#define INT_TICK 6
|
||||
#define INT_INTVL 7
|
||||
|
||||
/* assignable QBUS interrupts, daisy-chained - highest prio = 8, lowest = 31 */
|
||||
#define INT_QBUS8 8
|
||||
#define INT_QBUS9 9
|
||||
#define INT_QBUS10 10
|
||||
#define INT_QBUS11 11
|
||||
#define INT_QBUS12 12
|
||||
#define INT_QBUS13 13
|
||||
#define INT_QBUS14 14
|
||||
#define INT_QBUS15 15
|
||||
#define INT_QBUS16 16
|
||||
#define INT_QBUS17 17
|
||||
#define INT_QBUS18 18
|
||||
#define INT_QBUS19 19
|
||||
#define INT_QBUS20 20
|
||||
#define INT_QBUS21 21
|
||||
#define INT_QBUS22 22
|
||||
#define INT_QBUS23 23
|
||||
#define INT_QBUS24 24
|
||||
#define INT_QBUS25 25
|
||||
#define INT_QBUS26 26
|
||||
#define INT_QBUS27 27
|
||||
#define INT_QBUS28 28
|
||||
#define INT_QBUS29 29
|
||||
#define INT_QBUS30 30
|
||||
#define INT_QBUS31 31
|
||||
|
||||
/* common unit user-defined attributes */
|
||||
#define u_unitno u3
|
||||
|
||||
/* Memory */
|
||||
#define MEMSIZE 65536 /* memory size in bytes */
|
||||
#define MAXMEMSIZE (65535 * 2) /* maximum memory size in bytes */
|
||||
#define memorysize uptr->capac
|
||||
|
||||
/* CPU Unit flags */
|
||||
#define UNIT_V_PDQ3 (UNIT_V_UF + 0)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1)
|
||||
#define UNIT_V_PASEXC (UNIT_V_UF + 2)
|
||||
|
||||
|
||||
#define UNIT_PDQ3 (1u << UNIT_V_PDQ3)
|
||||
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
|
||||
#define UNIT_PASEXC (1u << UNIT_V_PASEXC)
|
||||
|
||||
#define Q_PDQ3 (cpu_unit.flags & UNIT_PDQ3)
|
||||
#define Q_MSIZE (cpu_unit.flags & UNIT_MSIZE)
|
||||
#define Q_PASEXC (cpu_unit.flags & UNIT_PASEXC)
|
||||
|
||||
#define setbit(reg,val) reg |= (val)
|
||||
#define clrbit(reg,val) reg &= ~(val)
|
||||
#define isbitset(reg, val) (reg & (val))
|
||||
#define isbitclr(reg, val) ((reg & (val)) == 0)
|
||||
|
||||
/* debug flags */
|
||||
#define DBG_NONE 0x0000
|
||||
|
||||
#define DBG_FD_CMD 0x0001
|
||||
#define DBG_FD_READ 0x0002
|
||||
#define DBG_FD_WRITE 0x0004
|
||||
#define DBG_FD_SVC 0x0008
|
||||
#define DBG_FD_IMD 0x0010
|
||||
#define DBG_FD_IMD2 0x0020 /* deep inspection */
|
||||
#define DBG_FD_DMA 0x0040
|
||||
#define DBG_FD_DMA2 0x0080 /* deep inspection */
|
||||
|
||||
//define DBG_CPU_TRACE 0x0001 unused
|
||||
#define DBG_CPU_INT 0x0001
|
||||
#define DBG_CPU_INT2 0x0002 /* deep inspection */
|
||||
#define DBG_CPU_READ 0x0004
|
||||
#define DBG_CPU_WRITE 0x0008
|
||||
#define DBG_CPU_FETCH 0x0010
|
||||
#define DBG_CPU_PUSH 0x0020
|
||||
#define DBG_CPU_POP 0x0040
|
||||
#define DBG_CPU_PICK 0x0080
|
||||
#define DBG_CPU_STACK (DBG_CPU_PUSH|DBG_CPU_POP|DBG_CPU_PICK)
|
||||
#define DBG_CPU_CONC 0x0100
|
||||
#define DBG_CPU_CONC2 0x0200 /* deep inspection */
|
||||
#define DBG_CPU_CONC3 0x0400 /* even deeper inspection */
|
||||
|
||||
#define DBG_CON_READ 0x0001
|
||||
#define DBG_CON_WRITE 0x0002
|
||||
#define DBG_CON_SVC 0x0004
|
||||
|
||||
#define DBG_TIM_READ 0x0001
|
||||
#define DBG_TIM_WRITE 0x0002
|
||||
#define DBG_TIM_SVC 0x0004
|
||||
|
||||
#define DBG_PCFORMAT0 "[%04x:%04x] "
|
||||
#define DBG_PCFORMAT1 " [%04x:%04x] "
|
||||
#define DBG_PCFORMAT2 " [%04x:%04x] "
|
||||
#define DBG_PC reg_segb,ADDR_OFF(PCX)
|
||||
#define DBG_PC2 reg_segb,reg_ipc
|
||||
|
||||
/* calibration timers */
|
||||
#define TMR_CONPOLL 0
|
||||
|
||||
/* console sio data rates */
|
||||
#define CON_POLLUNIT 0
|
||||
#define CON_TERMUNIT 1
|
||||
#define CON_POLLFIRST 1 /* immediate */
|
||||
#define CON_POLLRATE 100
|
||||
#define CON_POLLWAIT 12500
|
||||
//#define CON_TERMRATE 1300
|
||||
#define CON_TERMRATE 300
|
||||
|
||||
/* floppy size */
|
||||
#define FDC_MAX_TRACKS 77
|
||||
|
||||
/* IMD anachronism */
|
||||
#ifndef MAX_COMMENT_LEN
|
||||
#define MAX_COMMENT_LEN 256
|
||||
#endif
|
||||
|
||||
/* XXX @TODO Pascal error codes (Raise()) */
|
||||
#define PASERROR_SYSTEM 0
|
||||
#define PASERROR_VALRANGE 1
|
||||
#define PASERROR_NOSEG 2
|
||||
#define PASERROR_PROCERR 3
|
||||
#define PASERROR_STKOVFL 4
|
||||
#define PASERROR_INTOVFL 5
|
||||
#define PASERROR_DIVZERO 6
|
||||
#define PASERROR_MEMERR 7
|
||||
#define PASERROR_USERBRK 8
|
||||
#define PASERROR_SYSIO 9
|
||||
#define PASERROR_USERIO 10
|
||||
#define PASERROR_UNIMPL 11
|
||||
#define PASERROR_FPERR 12
|
||||
#define PASERROR_STRINGOVFL 13
|
||||
#define PASERROR_HALT 14
|
||||
|
||||
/* simh error codes */
|
||||
#define STOP_IBKPT 1
|
||||
#define STOP_MEM 2
|
||||
#define STOP_ERROP 3
|
||||
#define STOP_ERRADR 4
|
||||
#define STOP_ERRIO 5
|
||||
#define STOP_IMPL 6
|
||||
#define STOP_BPT 7
|
||||
#define STOP_DBGPRE 8
|
||||
#define STOP_DBGPOST 9
|
||||
#define STOP_PASEXC 10
|
||||
|
||||
/* IO addresses and vectors */
|
||||
#define CON_IOBASE 0xfc10
|
||||
#define CON_RCV_VEC 0x0012
|
||||
#define CON_XMT_VEC 0x000e
|
||||
#define CON_PRT_VEC 0x0016
|
||||
#define SES_IOBASE 0xfc18
|
||||
#define SES_BERR_VEC 0x0002
|
||||
#define SES_PWRF_VEC 0x0006
|
||||
#define SSR_IOBASE 0xfc24
|
||||
#define TIM_IOBASE 0xfc20
|
||||
#define TIM_TICK_VEC 0x001a
|
||||
#define TIM_INTVL_VEC 0x001e
|
||||
#define FDC_IOBASE 0xfc30
|
||||
#define FDC_VEC 0x000a
|
||||
#define CPU_SERIALNO 0xf5ff /* is part of ROM */
|
||||
#define ROM_BASE 0xfc68
|
||||
#define ROM 0xf400
|
||||
#define ROM_SIZE 0x01ff /* excluding serial number */
|
||||
|
||||
/* address calculations */
|
||||
#define ADDRMASK_SEG 0xffff0000
|
||||
#define ADDRMASK_OFF 0x0000ffff
|
||||
#define ADDR_16bit(a) ((a) & 0x0000ffff)
|
||||
#define ADDR_SEG(a) (((a)>>16) & ADDRMASK_OFF)
|
||||
#define ADDR_OFF(a) ((a) & ADDRMASK_OFF)
|
||||
#define MAKE_BADDR(s,o) ((ADDR_16bit(s)<<16) | ADDR_16bit(o))
|
||||
#define MAKE_WADDR(a) MAKE_BADDR(NIL,ADDR_OFF(a))
|
||||
#define ADDR_ISWORD(a) (ADDR_SEG(a) == NIL)
|
||||
|
||||
/* opcode table */
|
||||
#define OP_ERROR -1
|
||||
#define OP_NULL 0
|
||||
#define OP_UB 1
|
||||
#define OP_W 2
|
||||
#define OP_B 3
|
||||
#define OP_DBB 4
|
||||
#define OP_UBB 5
|
||||
#define OP_BUB 6
|
||||
#define OP_SB 7
|
||||
#define OP_DBUB 8
|
||||
#define OP_UBUB 9
|
||||
#define OP_UBDBUB 10
|
||||
#define OP_DB 11
|
||||
#define OP_SW 12
|
||||
#define OP_AB 13
|
||||
|
||||
typedef struct _optable {
|
||||
char* name;
|
||||
int16 flags;
|
||||
} OPTABLE;
|
||||
extern OPTABLE optable[];
|
||||
|
||||
/* debug support */
|
||||
#define DEBUG_OPDBGFILE "opcode.dbg"
|
||||
#define DEBUG_MINOPCODE 0
|
||||
#define DEBUG_MAXOPCODE 0xe8
|
||||
#define DEBUG_VALIDOP(op) (optable[op].flags >= 0)
|
||||
#define DEBUG_PRE 0x01
|
||||
#define DEBUG_POST 0x02
|
||||
extern t_stat dbg_init();
|
||||
extern t_stat dbg_check(t_value data,uint8 prepost);
|
||||
extern t_stat dbg_dump_tib(FILE* fd, uint16 base);
|
||||
extern t_stat dbg_dump_queue(FILE* fd, const char* qname, uint16 q);
|
||||
extern t_stat dbg_dump_mscw(FILE* fd, uint16 base);
|
||||
extern t_stat dbg_dump_seg(FILE* fd, uint16 segptr);
|
||||
extern t_stat dbg_dump_segtbl(FILE* fd);
|
||||
extern t_stat dbg_segtrack(uint16 segbase);
|
||||
extern t_stat dbg_procenter(uint16 segbase, uint16 procno, uint16 mscw, uint16 osegb);
|
||||
extern t_stat dbg_procleave();
|
||||
extern void dbg_enable();
|
||||
extern t_stat dbg_calltree(FILE* fd);
|
||||
extern t_stat dbg_enteralias(const char* key, const char* value);
|
||||
extern t_stat dbg_listalias(FILE*);
|
||||
/* floating point */
|
||||
typedef union flcvt {
|
||||
float f;
|
||||
uint16 i[2];
|
||||
} T_FLCVT;
|
||||
|
||||
/* wrapper structure for terminal multiplexer,
|
||||
pointer to pointer stored in device->ctxt */
|
||||
typedef struct {
|
||||
int pfirst, prate; /* pollrate first time, later */
|
||||
TMLN ldsc;
|
||||
TMXR desc;
|
||||
UNIT* term;
|
||||
UNIT* poll;
|
||||
} SERMUX;
|
||||
extern t_stat mux_attach(UNIT*, char*, SERMUX*);
|
||||
extern t_stat mux_detach(UNIT*, SERMUX*);
|
||||
|
||||
/* externals */
|
||||
extern DEVICE cpu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern DEVICE con_dev;
|
||||
extern UNIT con_unit[];
|
||||
extern DEVICE fdc_dev;
|
||||
extern UNIT fdc_unit[];
|
||||
extern DEVICE timer_dev;
|
||||
extern UNIT timer_unit[];
|
||||
extern t_addr PCX; /* PC at the begin of execution */
|
||||
extern uint16 reg_segb;
|
||||
extern uint32 reg_dmabase;
|
||||
extern uint16 reg_mp;
|
||||
extern uint16 reg_bp;
|
||||
extern uint16 reg_sp;
|
||||
extern uint16 reg_splow;
|
||||
extern uint16 reg_spupr;
|
||||
extern uint16 reg_ctp;
|
||||
extern uint16 reg_rq;
|
||||
extern uint16 reg_ipc;
|
||||
extern uint16 reg_fc68;
|
||||
extern uint16 reg_romsize;
|
||||
extern uint16 reg_ssv;
|
||||
extern uint16 reg_ssr;
|
||||
extern uint16 reg_cpuserial;
|
||||
extern uint32 reg_intpending;
|
||||
|
||||
extern t_stat Read(t_addr base, t_addr woffset, uint16 *data, uint32 dctrl);
|
||||
extern t_stat Write(t_addr base, t_addr boffset, uint16 data, uint32 dctrl);
|
||||
extern t_stat ReadB(t_addr base, t_addr boffset, uint16 *data, uint32 dctrl);
|
||||
extern t_stat WriteB(t_addr base, t_addr boffset, uint16 data, uint32 dctrl);
|
||||
extern t_stat ReadEx(t_addr base, t_addr woffset, uint16 *data);
|
||||
extern t_stat ReadBEx(t_addr base, t_addr boffset, uint16 *data);
|
||||
|
||||
extern t_stat rom_read(t_addr base, uint16 *data);
|
||||
extern t_stat rom_write(t_addr base, uint16 data);
|
||||
extern t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
|
||||
|
||||
extern t_stat con_read(t_addr ioaddr, uint16 *data);
|
||||
extern t_stat con_write(t_addr ioaddr, uint16 data);
|
||||
extern t_stat con_binit();
|
||||
extern t_stat fdc_read(t_addr ioaddr, uint16 *data);
|
||||
extern t_stat fdc_write(t_addr ioaddr, uint16 data);
|
||||
extern t_stat fdc_autoload();
|
||||
extern t_stat fdc_binit();
|
||||
extern t_stat tim_read(t_addr ioaddr, uint16 *data);
|
||||
extern t_stat tim_write(t_addr ioaddr, uint16 data);
|
||||
|
||||
extern void cpu_assertInt(int level, t_bool tf);
|
||||
extern t_stat cpu_raiseInt(int level);
|
||||
extern t_stat cpu_setIntVec(uint16 vector,int level);
|
||||
extern void cpu_setRegs(uint16 ctp, uint16 ssv, uint16 rq);
|
||||
extern void cpu_finishAutoload();
|
||||
extern t_stat cpu_buserror();
|
||||
|
||||
typedef t_stat (*IOREAD)(t_addr ioaddr, uint16 *data);
|
||||
typedef t_stat (*IOWRITE)(t_addr ioaddr, uint16 data);
|
||||
|
||||
typedef struct _ioinfo {
|
||||
struct _ioinfo* next;
|
||||
uint16 iobase;
|
||||
uint16 iosize;
|
||||
uint16 qvector;
|
||||
uint16 qprio;
|
||||
IOREAD read;
|
||||
IOWRITE write;
|
||||
} IOINFO;
|
||||
|
||||
typedef struct _devctxt {
|
||||
IOINFO* ioi;
|
||||
} DEVCTXT;
|
||||
|
||||
extern t_stat pdq3_ioinit();
|
||||
extern t_stat add_ioh(IOINFO* ioi);
|
||||
extern t_stat del_ioh(IOINFO* ioi);
|
||||
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 set_iovec(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
extern t_stat show_iovec(FILE *st, UNIT *uptr, int value, void *desc);
|
||||
extern t_stat set_ioprio(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
extern t_stat show_ioprio(FILE *st, UNIT *uptr, int value, void *desc);
|
||||
|
||||
#endif
|
||||
1176
PDQ-3/pdq3_fdc.c
Normal file
1176
PDQ-3/pdq3_fdc.c
Normal file
File diff suppressed because it is too large
Load Diff
355
PDQ-3/pdq3_mem.c
Normal file
355
PDQ-3/pdq3_mem.c
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Work derived from Copyright (c) 2004-2012, Robert M. Supnik
|
||||
Copyright (c) 2013 Holger Veit
|
||||
|
||||
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 names of Robert M Supnik and Holger Veit
|
||||
shall not 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 and Holger Veit.
|
||||
|
||||
20130920 hv initial version, moved some code from pdq3_cpu.c
|
||||
*/
|
||||
#include "pdq3_defs.h"
|
||||
|
||||
/* the memory */
|
||||
uint16 M[MAXMEMSIZE];
|
||||
|
||||
/******************************************************************************
|
||||
* IO dispatcher
|
||||
*****************************************************************************/
|
||||
|
||||
static t_bool initio = FALSE;
|
||||
#define IOSIZE 4096
|
||||
#define IOPAGEMASK 0x0fff
|
||||
IOREAD ioreaders[IOSIZE];
|
||||
IOWRITE iowriters[IOSIZE];
|
||||
|
||||
/* I/O devices are implemented this way:
|
||||
* a unit will register its own I/O addresses together with its handler
|
||||
* in a hash which allows simple lookup of memory mapped I/O addresses
|
||||
*/
|
||||
t_stat pdq3_ioinit() {
|
||||
int i;
|
||||
if (!initio) {
|
||||
for (i=0; i < IOSIZE; i++) {
|
||||
ioreaders[i] = NULL;
|
||||
iowriters[i] = NULL;
|
||||
}
|
||||
for (i=8; i < 32; i++)
|
||||
cpu_setIntVec(NIL, i);
|
||||
initio = TRUE;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat add_ioh(IOINFO* ioi) {
|
||||
while (ioi) {
|
||||
int i;
|
||||
for (i=0; i<ioi->iosize; i++) {
|
||||
int idx = (ioi->iobase + i) & IOPAGEMASK;
|
||||
ioreaders[idx] = ioi->read;
|
||||
iowriters[idx] = ioi->write;
|
||||
}
|
||||
ioi = ioi->next;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat del_ioh(IOINFO* ioi) {
|
||||
while (ioi) {
|
||||
int i;
|
||||
for (i=0; i<ioi->iosize; i++) {
|
||||
int idx = (ioi->iobase + i) & IOPAGEMASK;
|
||||
ioreaders[idx] = NULL;
|
||||
iowriters[idx] = NULL;
|
||||
}
|
||||
ioi = ioi->next;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* configuration
|
||||
*****************************************************************************/
|
||||
t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc) {
|
||||
DEVICE* dptr;
|
||||
DEVCTXT* ctxt;
|
||||
IOINFO* ioi;
|
||||
t_bool first = TRUE;
|
||||
if (!uptr) return SCPE_IERR;
|
||||
if ((dptr = find_dev_from_unit(uptr)) == 0) return SCPE_IERR;
|
||||
ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
ioi = ctxt->ioi;
|
||||
while (ioi) {
|
||||
if (ioi->iobase) {
|
||||
if (ioi->iobase > 0xfc00) {
|
||||
fprintf(st, first ? "IOBASE=$%04x":",$%04x", ioi->iobase);
|
||||
first = FALSE;
|
||||
}
|
||||
}
|
||||
ioi = ioi->next;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||
t_stat rc;
|
||||
DEVICE* dptr;
|
||||
DEVCTXT* ctxt;
|
||||
IOINFO* ioi;
|
||||
t_bool first = TRUE;
|
||||
if (!cptr) return SCPE_ARG;
|
||||
if (!uptr) return SCPE_IERR;
|
||||
if ((dptr = find_dev_from_unit(uptr)) == 0) return SCPE_IERR;
|
||||
ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
ioi = ctxt->ioi;
|
||||
if (ioi->next)
|
||||
return SCPE_ARG; /* note: fixed devices on mainboard cannot be changed */
|
||||
ioi->iobase = get_uint(cptr, 16, 0xffff, &rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
t_stat set_iovec(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||
t_stat rc;
|
||||
DEVICE* dptr;
|
||||
DEVCTXT* ctxt;
|
||||
IOINFO* ioi;
|
||||
t_bool first = TRUE;
|
||||
if (!cptr) return SCPE_ARG;
|
||||
if (!uptr) return SCPE_IERR;
|
||||
if ((dptr = find_dev_from_unit(uptr)) == 0) return SCPE_IERR;
|
||||
ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
ioi = ctxt->ioi;
|
||||
if (ioi->next)
|
||||
return SCPE_ARG; /* note: fixed devices on mainboard cannot be changed */
|
||||
ioi->qvector = get_uint(cptr, 16, 0xff, &rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
t_stat show_iovec(FILE *st, UNIT *uptr, int value, void *desc) {
|
||||
DEVICE* dptr;
|
||||
DEVCTXT* ctxt;
|
||||
IOINFO* ioi;
|
||||
t_bool first = TRUE;
|
||||
if (!uptr) return SCPE_IERR;
|
||||
if ((dptr = find_dev_from_unit(uptr)) == 0) return SCPE_IERR;
|
||||
ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
ioi = ctxt->ioi;
|
||||
while (ioi) {
|
||||
if (ioi->qprio < 32) {
|
||||
fprintf(st, first ? "VECTOR=$%04x":",$%04x", ioi->qvector);
|
||||
first = FALSE;
|
||||
}
|
||||
ioi = ioi->next;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat set_ioprio(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||
t_stat rc;
|
||||
DEVICE* dptr;
|
||||
DEVCTXT* ctxt;
|
||||
IOINFO* ioi;
|
||||
t_bool first = TRUE;
|
||||
if (!cptr) return SCPE_ARG;
|
||||
if (!uptr) return SCPE_IERR;
|
||||
if ((dptr = find_dev_from_unit(uptr)) == 0) return SCPE_IERR;
|
||||
ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
ioi = ctxt->ioi;
|
||||
if (ioi->next)
|
||||
return SCPE_ARG; /* note: fixed devices on mainboard cannot be changed */
|
||||
ioi->qprio = get_uint(cptr, 16, 31, &rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
t_stat show_ioprio(FILE *st, UNIT *uptr, int value, void *desc) {
|
||||
DEVICE* dptr;
|
||||
DEVCTXT* ctxt;
|
||||
IOINFO* ioi;
|
||||
t_bool first = TRUE;
|
||||
if (!uptr) return SCPE_IERR;
|
||||
if ((dptr = find_dev_from_unit(uptr)) == 0) return SCPE_IERR;
|
||||
ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
ioi = ctxt->ioi;
|
||||
while (ioi) {
|
||||
if (ioi->qprio < 32) {
|
||||
fprintf(st, first ? "PRIO=%d":",%d", ioi->qprio);
|
||||
first = FALSE;
|
||||
}
|
||||
ioi = ioi->next;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* central memory handling
|
||||
*****************************************************************************/
|
||||
t_stat Read(t_addr base, t_addr woffset, uint16 *data, uint32 dctrl) {
|
||||
t_stat rc;
|
||||
uint16 ea = base + woffset;
|
||||
|
||||
/* Note: the PRIAM driver attempts to read the ready bit from FF25 (bit 9) which should be 1.
|
||||
* As long as we don't have a HDP device, the invalid value should be 0x0000 */
|
||||
*data = 0x0000; /* preload invalid data value */
|
||||
|
||||
if (ea < 0xf000 || (ea == 0xfffe && cpu_unit.capac > 65535)) {
|
||||
*data = M[ea]; /* normal memory */
|
||||
rc = SCPE_OK;
|
||||
} else {
|
||||
IOREAD reader = ioreaders[ea & IOPAGEMASK];
|
||||
rc = reader ? (*reader)(ea, data) : SCPE_NXM;
|
||||
}
|
||||
if (rc != SCPE_OK) {
|
||||
cpu_buserror();
|
||||
sim_debug(DBG_CPU_READ, &cpu_dev, DBG_PCFORMAT1 "Invalid Mem read from $%04x\n", DBG_PC, ea);
|
||||
printf("read buserror: ea=$%04x at $%x:#%x\n",ea,reg_segb,reg_ipc);
|
||||
return rc;
|
||||
}
|
||||
if (dctrl & DBG_CPU_PICK) {
|
||||
sim_debug(DBG_CPU_PICK, &cpu_dev, DBG_PCFORMAT1 "Pick %04x at SP=$%04x\n", DBG_PC, *data, ea);
|
||||
} else if (dctrl & DBG_CPU_POP) {
|
||||
sim_debug(DBG_CPU_POP, &cpu_dev, DBG_PCFORMAT2 "Pop %04x from SP=$%04x\n", DBG_PC, *data, ea);
|
||||
} else {
|
||||
sim_debug(dctrl, &cpu_dev, DBG_PCFORMAT2 "Word read %04x from $%04x\n", DBG_PC, *data, ea);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* read routine that does not generate bus errors, for SIMH Examine
|
||||
* will read 0x0000 for unknown memory */
|
||||
t_stat ReadEx(t_addr base, t_addr woffset, uint16 *data) {
|
||||
t_stat rc;
|
||||
uint16 ea = base + woffset;
|
||||
*data = 0x0000; /* preload invalid data value */
|
||||
if (ea < 0xf000) {
|
||||
*data = M[ea]; /* normal memory */
|
||||
rc = SCPE_OK;
|
||||
} else {
|
||||
IOREAD reader = ioreaders[ea & IOPAGEMASK];
|
||||
rc = reader ? (*reader)(ea, data) : SCPE_NXM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
t_stat Write(t_addr base, t_addr woffset, uint16 data, uint32 dctrl) {
|
||||
t_stat rc;
|
||||
uint16 ea = base + woffset;
|
||||
if (ea < 0xf000) {
|
||||
M[ea] = data;
|
||||
rc = SCPE_OK;
|
||||
} else {
|
||||
IOWRITE write = iowriters[ea & IOPAGEMASK];
|
||||
rc = write ? (*write)(ea, data) : SCPE_NXM;
|
||||
}
|
||||
if (rc != SCPE_OK) {
|
||||
cpu_buserror();
|
||||
sim_debug(DBG_CPU_WRITE, &cpu_dev, DBG_PCFORMAT0 "Invalid Mem write to $%04x\n", DBG_PC, ea);
|
||||
printf("write buserror %x at %x:%x\n",ea,reg_segb,reg_ipc);
|
||||
//exit(1);
|
||||
return rc;
|
||||
}
|
||||
if (dctrl & DBG_CPU_STACK)
|
||||
sim_debug(DBG_CPU_PUSH, &cpu_dev, DBG_PCFORMAT1 "Push %04x to SP=$%04x\n", DBG_PC, data, ea);
|
||||
else
|
||||
sim_debug(dctrl, &cpu_dev, DBG_PCFORMAT2 "Word write %04x to $%04x\n", DBG_PC, data, ea);
|
||||
return rc;
|
||||
}
|
||||
|
||||
t_stat ReadB(t_addr base, t_addr boffset, uint16 *data, uint32 dctrl)
|
||||
{
|
||||
t_stat rc;
|
||||
t_addr ea = base + boffset/2;
|
||||
if ((rc=Read(ea, 0, data, DBG_NONE)) != SCPE_OK) return rc;
|
||||
if (boffset & 1)
|
||||
*data >>= 8;
|
||||
*data &= 0xff;
|
||||
if (dctrl & DBG_CPU_FETCH)
|
||||
sim_debug(DBG_CPU_FETCH, &cpu_dev, DBG_PCFORMAT0 "Fetch %02x from SEGB:%04x\n",
|
||||
DBG_PC, *data, reg_ipc);
|
||||
else
|
||||
sim_debug(dctrl, &cpu_dev, DBG_PCFORMAT2 "Byte[%d] read %02x from $%04x\n",
|
||||
DBG_PC, boffset & 1, *data, ea);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ReadBEx(t_addr base, t_addr boffset, uint16 *data)
|
||||
{
|
||||
t_stat rc;
|
||||
t_addr ea = base + boffset/2;
|
||||
if ((rc=ReadEx(ea, 0, data)) != SCPE_OK) return rc;
|
||||
if (boffset & 1)
|
||||
*data >>= 8;
|
||||
*data &= 0xff;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat WriteB(t_addr base, t_addr boffset, uint16 data, uint32 dctrl)
|
||||
{
|
||||
uint16 wdata;
|
||||
t_addr ea = base + boffset/2;
|
||||
if (ea < 0xfc00) {
|
||||
sim_debug(dctrl, &cpu_dev, DBG_PCFORMAT2 "Byte[%d] write %02x to $%04x\n",
|
||||
DBG_PC, boffset & 1, data, ea);
|
||||
wdata = M[ea];
|
||||
} else {
|
||||
printf(DBG_PCFORMAT0 "Invalid byte[%d] write %02x to I/O addr $%04x\n", DBG_PC, boffset & 1, data, ea);
|
||||
return STOP_ERRIO;
|
||||
}
|
||||
if (boffset & 1) {
|
||||
wdata = (wdata & 0xff) | (data<<8);
|
||||
} else {
|
||||
wdata = (wdata & 0xff00) | (data & 0xff);
|
||||
}
|
||||
return Write(ea, 0, wdata, 0);
|
||||
}
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc;
|
||||
t_addr i;
|
||||
|
||||
if (val < 0 || val > 1)
|
||||
return SCPE_ARG;
|
||||
|
||||
val = val ? 65536 : 32768;
|
||||
|
||||
for (mc = 0, i = val; i < memorysize; i++)
|
||||
mc = mc | M[i];
|
||||
|
||||
if (mc && !get_yn ("Really truncate memory [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
|
||||
memorysize = val;
|
||||
for (i = memorysize; i < MAXMEMSIZE; i++)
|
||||
M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat rom_read(t_addr ea, uint16 *data)
|
||||
{
|
||||
*data = M[ea];
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat rom_write(t_addr ea, uint16 data) {
|
||||
M[ea] = data;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
641
PDQ-3/pdq3_stddev.c
Normal file
641
PDQ-3/pdq3_stddev.c
Normal file
@@ -0,0 +1,641 @@
|
||||
/* PDQ3_stddev.c: PDQ3 simulator standard devices
|
||||
|
||||
Work derived from Copyright (c) 2004-2012, Robert M. Supnik
|
||||
Copyright (c) 2013 Holger Veit
|
||||
|
||||
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 names of Robert M Supnik and Holger Veit
|
||||
shall not 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 and Holger Veit.
|
||||
|
||||
20130902 hv added telnet multiplexer code
|
||||
20131020 hv fixed CON interrupt handling
|
||||
20131103 hv connect CON_ATTACH logic with DSR, so that DSR is set if tcp connect
|
||||
*/
|
||||
#include "pdq3_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 sim_switches;
|
||||
extern UNIT con_unit[];
|
||||
|
||||
static t_stat con_termsvc(UNIT *uptr);
|
||||
static t_stat con_pollsvc(UNIT *uptr);
|
||||
static t_stat con_attach(UNIT*, char*);
|
||||
static t_stat con_detach(UNIT*);
|
||||
static t_stat con_reset(DEVICE* dptr);
|
||||
|
||||
static t_stat tim_reset(DEVICE *dptr);
|
||||
static t_stat tim0_svc(UNIT* uptr);
|
||||
static t_stat tim1_svc(UNIT* uptr);
|
||||
static t_stat tim2_svc(UNIT* uptr);
|
||||
|
||||
/* CON USART registers */
|
||||
/* This is described as positive logic, and represents the
|
||||
* content of the corresponding registers.
|
||||
* However, the USART is connected to inverted DAL lines
|
||||
* and needs to be written to with the inverted value
|
||||
* This is done in CPU Read/Write */
|
||||
#define CONC1_LOOP 0x80 /* 0=loopmode diagnostic, 1=normal full duplex */
|
||||
#define CONC1_BRK 0x40 /* 1=send break */
|
||||
#define CONC1_MISC 0x20 /* 1=one stop bit, 0=two */
|
||||
#define CONC1_ECHO 0x10 /* 1=echo received data */
|
||||
#define CONC1_PE 0x08 /* 1=check parity */
|
||||
#define CONC1_RE 0x04 /* 1=enable receiver */
|
||||
#define CONC1_RTS 0x02 /* 1=enable transmitter if CTS */
|
||||
#define CONC1_DTR 0x01 /* 1=enable CD, DSR,RI interrupts */
|
||||
static uint8 con_ctrl1;
|
||||
#define CONC2_CLENMASK 0xc0 /* number of bits */
|
||||
#define CONC2_CLEN8 0x00
|
||||
#define CONC2_CLEN7 0x40
|
||||
#define CONC2_CLEN6 0x80
|
||||
#define CONC2_CLEN5 0xc0
|
||||
#define CONC2_MODE 0x20 /* not used set to 0 (async mode) */
|
||||
#define CONC2_ODDEVN 0x10 /* 0=even parity */
|
||||
#define CONC2_RXCLK 0x08 /* not used, set to 1 */
|
||||
#define CONC2_CLKMASK 0x07 /* clock selector */
|
||||
#define CONC2_CLK110 0x06 /* must be set to 001 (rate 1 clock) */
|
||||
static uint8 con_ctrl2;
|
||||
#define CONS_DSC 0x80 /* set to 1 after status read, cleared by DSR/DCD/RI */
|
||||
#define CONS_DSR 0x40 /* DSR input */
|
||||
#define CONS_CD 0x20 /* DCD input */
|
||||
#define CONS_FE 0x10 /* 1=framing error */
|
||||
#define CONS_PE 0x08 /* 1=parity error */
|
||||
#define CONS_OE 0x04 /* 1= overrun error */
|
||||
#define CONS_DR 0x02 /* set to 1 if data received, 0 if data read */
|
||||
#define CONS_THRE 0x01 /* set to 1 if data xmit buffer empty */
|
||||
static uint8 con_status;
|
||||
static uint8 con_xmit;
|
||||
static uint8 con_rcv;
|
||||
|
||||
/************************************************************************************************
|
||||
* Utilities
|
||||
***********************************************************************************************/
|
||||
t_stat mux_attach(UNIT* uptr, char* cptr, SERMUX* mux) {
|
||||
t_stat rc;
|
||||
mux->desc.ldsc = &mux->ldsc;
|
||||
if ((rc = tmxr_attach(&mux->desc, uptr, cptr)) == SCPE_OK) {
|
||||
mux->poll->wait = mux->pfirst;
|
||||
sim_activate(mux->poll, mux->poll->wait);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
t_stat mux_detach(UNIT* uptr, SERMUX* mux) {
|
||||
t_stat rc = tmxr_detach(&mux->desc, uptr);
|
||||
mux->ldsc.rcve = 0;
|
||||
sim_cancel(mux->poll);
|
||||
sim_cancel(mux->term);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* Onboard Console
|
||||
***********************************************************************************************/
|
||||
|
||||
/* con data structures
|
||||
con_dev con device descriptor
|
||||
con_unit con unit descriptor
|
||||
con_mod con modifier list
|
||||
con_reg con register list
|
||||
*/
|
||||
IOINFO con_ioinfo1 = { NULL, CON_IOBASE, 4, CON_RCV_VEC, 4, con_read, con_write };
|
||||
IOINFO con_ioinfo2 = { &con_ioinfo1, 0, 0, CON_XMT_VEC, 3, con_read, con_write };
|
||||
DEVCTXT con_ctxt = { &con_ioinfo2 };
|
||||
|
||||
UNIT con_unit[] = {
|
||||
{ UDATA (&con_pollsvc, UNIT_ATTABLE, 0), CON_POLLRATE, },
|
||||
{ UDATA (&con_termsvc, UNIT_IDLE, 0), CON_TERMRATE, }
|
||||
};
|
||||
|
||||
REG con_reg[] = {
|
||||
{ HRDATA (CTRL1, con_ctrl1, 8) },
|
||||
{ HRDATA (CTRL2, con_ctrl2, 8) },
|
||||
{ HRDATA (STAT, con_status, 8) },
|
||||
{ HRDATA (XMIT, con_xmit, 8) },
|
||||
{ HRDATA (RCV, con_rcv, 8) },
|
||||
{ NULL }
|
||||
};
|
||||
MTAB con_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", NULL, &show_iobase },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", NULL, &show_iovec },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "PRIO", "PRIO", NULL, &show_ioprio },
|
||||
{ 0 }
|
||||
};
|
||||
DEBTAB con_dflags[] = {
|
||||
{ "WRITE", DBG_CON_WRITE },
|
||||
{ "READ", DBG_CON_READ },
|
||||
{ "SVC", DBG_CON_SVC },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
SERMUX con_mux[1] = {
|
||||
{ CON_POLLFIRST, /*pfirst*/
|
||||
CON_POLLRATE, /*prate*/
|
||||
{ 0 }, /*ldsc*/
|
||||
{ 1,0,0,0 }, /*desc*/
|
||||
&con_unit[1], /*term*/
|
||||
&con_unit[0] /*poll*/
|
||||
}
|
||||
};
|
||||
|
||||
DEVICE con_dev = {
|
||||
"CON", /*name*/
|
||||
con_unit, /*units*/
|
||||
con_reg, /*registers*/
|
||||
con_mod, /*modifiers*/
|
||||
2, /*numunits*/
|
||||
16, /*aradix*/
|
||||
16, /*awidth*/
|
||||
1, /*aincr*/
|
||||
8, /*dradix*/
|
||||
8, /*dwidth*/
|
||||
NULL, /*examine*/
|
||||
NULL, /*deposit*/
|
||||
&con_reset, /*reset*/
|
||||
NULL, /*boot*/
|
||||
con_attach, /*attach*/
|
||||
con_detach, /*detach*/
|
||||
&con_ctxt, /*ctxt*/
|
||||
DEV_DEBUG|DEV_DISABLE, /*flags*/
|
||||
0, /*dctrl*/
|
||||
con_dflags, /*debflags*/
|
||||
NULL, /*msize*/
|
||||
NULL /*lname*/
|
||||
};
|
||||
|
||||
/* bus reset handler */
|
||||
t_stat con_binit() {
|
||||
SERMUX *mux = &con_mux[0];
|
||||
|
||||
con_status = CONS_THRE;
|
||||
if (mux->ldsc.conn) setbit(con_status, CONS_DSR);
|
||||
|
||||
con_ctrl1 = 0; /* no echo, receiver disabled, transmitter disabled */
|
||||
con_ctrl2 = 0; /* ASYNC mode, 8bits, Clock 1X */
|
||||
con_xmit = 0;
|
||||
con_rcv = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* common handlers */
|
||||
static t_stat con_reset(DEVICE* dptr)
|
||||
{
|
||||
int32 wait;
|
||||
SERMUX * mux = &con_mux[0];
|
||||
UNIT *term = mux->term;
|
||||
UNIT *poll = mux->poll;
|
||||
DEVCTXT* ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
|
||||
wait = poll->wait = CON_POLLWAIT;
|
||||
sim_rtcn_init (wait, TMR_CONPOLL); /* init poll timer */
|
||||
|
||||
sim_cancel(term);
|
||||
|
||||
/* register/deregister I/O handlers */
|
||||
if (dptr->flags & DEV_DIS) {
|
||||
del_ioh(ctxt->ioi);
|
||||
} else {
|
||||
add_ioh(ctxt->ioi);
|
||||
poll->buf = 0;
|
||||
sim_activate (poll, wait);
|
||||
}
|
||||
return con_binit();
|
||||
}
|
||||
|
||||
t_stat con_attach(UNIT* uptr, char* cptr) {
|
||||
setbit(con_status, CONS_DSR|CONS_DSC);
|
||||
return mux_attach(uptr, cptr, &con_mux[0]);
|
||||
}
|
||||
|
||||
t_stat con_detach(UNIT* uptr) {
|
||||
clrbit(con_status, CONS_DSR);
|
||||
setbit(con_status, CONS_DSC);
|
||||
return mux_detach(uptr, &con_mux[0]);
|
||||
}
|
||||
|
||||
#define XMITENABLED() (isbitset(con_ctrl1,CONC1_RTS))
|
||||
#define XMITENABLE() setbit(con_ctrl1,CONC1_RTS)
|
||||
#define XMITDISABLE() clrbit(con_ctrl1,CONC1_RTS)
|
||||
#define XMITEMPTY() (isbitset(con_status, CONS_THRE))
|
||||
|
||||
#define RCVENABLED() (isbitset(con_ctrl1,CONC1_RE))
|
||||
#define RCVFULL() (isbitset(con_status, CONS_DR))
|
||||
#define RCVENABLE() setbit(con_ctrl1,CONC1_RE)
|
||||
#define RCVDISABLE() clrbit(con_ctrl1,CONC1_RE)
|
||||
|
||||
#define DSRACTIVE() (isbitset(con_ctrl1,CONC1_DTR) && isbitset(con_status,CONS_DSR))
|
||||
|
||||
/* The transmit interrupt is raised continuously,
|
||||
* as long as the transmit holding reg is empty and the transmitter is enabled.
|
||||
* It will be deasserted when the tranmit reg is full or tranmitter disabled.
|
||||
*/
|
||||
#define XMITINTR() cpu_assertInt(INT_CONT, XMITEMPTY())
|
||||
|
||||
/* The receive interrupt is raised continuously,
|
||||
* when the receiver holding register is full and the receiver is enabled.
|
||||
* it will be deasserted when the receiver reg is read or the receiver disabled.
|
||||
*/
|
||||
#define RCVINTR() cpu_assertInt(INT_CONR, RCVFULL())
|
||||
|
||||
/* The DSR interrupt is raised when DSC is set to 1 (pos logic)
|
||||
* and DTR is active, cleared if status is read */
|
||||
#define DSRINTR() cpu_assertInt(INT_PRNT, DSRACTIVE())
|
||||
|
||||
/* Terminal output service */
|
||||
t_stat con_termsvc (UNIT *uptr) {
|
||||
SERMUX *mux = &con_mux[0];
|
||||
t_bool isnetwork = (mux->poll->flags & UNIT_ATT);
|
||||
t_stat rc;
|
||||
int ch = uptr->buf & 0xff;
|
||||
|
||||
// sim_debug(DBG_CON_SVC, &con_dev, "termsvc: isnetwork=%d\n",isnetwork);
|
||||
/* TODO? sim_tt_outcvt */
|
||||
|
||||
if (XMITENABLED()) { /* tranmitter enabled */
|
||||
/* attached to a telnet port? */
|
||||
// printf("*** Emit: %02x ***\n",uptr->buf & 0xff);
|
||||
if (isnetwork) {
|
||||
if ((rc=tmxr_putc_ln(&mux->ldsc, ch)) != SCPE_OK) {
|
||||
sim_activate(uptr, uptr->wait);
|
||||
return SCPE_OK;
|
||||
} else
|
||||
tmxr_poll_tx(&mux->desc);
|
||||
} else {
|
||||
if ((rc=sim_putchar_s(ch)) != SCPE_OK) {
|
||||
sim_activate(uptr, uptr->wait);
|
||||
return rc==SCPE_STALL ? SCPE_OK : rc;
|
||||
}
|
||||
}
|
||||
setbit(con_status,CONS_THRE); /* set transmitter holding reg empty */
|
||||
cpu_assertInt(INT_CONT, TRUE); /* generate an interrupt because of DRQO */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Terminal input service */
|
||||
t_stat con_pollsvc(UNIT *uptr) {
|
||||
int32 c, kbdc;
|
||||
SERMUX *mux = &con_mux[0];
|
||||
t_bool isnetwork = (mux->poll->flags & UNIT_ATT);
|
||||
|
||||
uptr->wait = sim_rtcn_calb(mux->prate, TMR_CONPOLL); /* calibrate timer */
|
||||
sim_activate (uptr, uptr->wait); /* restart polling */
|
||||
|
||||
kbdc = sim_poll_kbd(); /* check keyboard */
|
||||
if (kbdc == SCPE_STOP) return kbdc; /* handle CTRL-E */
|
||||
|
||||
/* network-redirected input? */
|
||||
if (isnetwork) {
|
||||
if (tmxr_poll_conn(&mux->desc) >= 0) /* incoming connection */
|
||||
mux->ldsc.rcve = 1;
|
||||
tmxr_poll_rx(&mux->desc); /* poll for input */
|
||||
if (!tmxr_rqln(&mux->ldsc)) return SCPE_OK;
|
||||
/* input ready */
|
||||
c = tmxr_getc_ln(&mux->ldsc);
|
||||
if ((c & TMXR_VALID) == 0) return SCPE_OK;
|
||||
} else {
|
||||
c = kbdc; /* use char polled from keyboard */
|
||||
if (c < SCPE_KFLAG) return c; /* ignore data if not valid */
|
||||
}
|
||||
|
||||
c = sim_tt_inpcvt(c, TT_GET_MODE(uptr->flags));
|
||||
uptr->buf = c & 0xff;
|
||||
uptr->pos = uptr->pos + 1;
|
||||
|
||||
if (RCVENABLED()) { /* receiver enabled? */
|
||||
if (RCVFULL()) /* handle data overrun */
|
||||
setbit(con_status,CONS_OE);
|
||||
|
||||
con_rcv = c & 0xff; /* put in receiver register */
|
||||
setbit(con_status,CONS_DR); /* notify: data received */
|
||||
cpu_assertInt(INT_CONR, TRUE); /* generate interrupt because of DRQI */
|
||||
|
||||
if (isbitset(con_ctrl1, CONC1_ECHO)) { /* echo? XXX handle in telnet handler? */
|
||||
/* XXX use direct send here, not sending via con_termsvc */
|
||||
if (isnetwork)
|
||||
tmxr_putc_ln(&mux->ldsc, c);
|
||||
else
|
||||
sim_putchar_s(c);
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static int set_parity(int c, int odd)
|
||||
{
|
||||
int i, p = 0;
|
||||
for (i=0; i<8; i++)
|
||||
if (c & (1<<i)) p ^= 1;
|
||||
c |= p ? 0 : 0x80;
|
||||
if (!odd) c ^= 0x80;
|
||||
return c;
|
||||
}
|
||||
static int get_parity(int c, int even)
|
||||
{
|
||||
int i, p = 0;
|
||||
for (i=0; i<8; i++)
|
||||
if (c & (1<<i)) p ^= 1;
|
||||
if (even) p ^= 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
// functions from memory handler to read and write a char
|
||||
// note: the usart is connected to inverted data lines,
|
||||
// this is fixed by negating input and output
|
||||
//
|
||||
// The logic in here uses the positive logic conventions as
|
||||
// described in the WD1931 data sheet, not the ones in the PDQ-3_Hardware_Users_Manual
|
||||
t_stat con_write(t_addr ioaddr, uint16 data) {
|
||||
SERMUX * mux = &con_mux[0];
|
||||
UNIT *term = mux->term;
|
||||
UNIT *poll = mux->poll;
|
||||
|
||||
/* note usart has inverted bus, so all data is inverted */
|
||||
data = (~data) & 0xff;
|
||||
switch (ioaddr & 0x0003) {
|
||||
case 0: /* CTRL1 */
|
||||
con_ctrl1 = data;
|
||||
if (!RCVENABLED()) { /* disable receiver */
|
||||
clrbit(con_status,CONS_FE|CONS_PE|CONS_OE|CONS_DR);
|
||||
sim_cancel(poll);
|
||||
} else {
|
||||
sim_activate(poll, poll->wait); /* start poll service, will raise interrupt if buffer full */
|
||||
}
|
||||
if (!XMITENABLED()) { /* disable transmitter */
|
||||
/* will drain current pending xmit service. RTS output is assumed to become inactive
|
||||
* (it is not necessary to emulate it) */
|
||||
} else {
|
||||
if (XMITEMPTY()) {
|
||||
} else {
|
||||
/* some char in THR, start service to emit */
|
||||
sim_activate(term, term->wait);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
con_ctrl2 = data;
|
||||
break;
|
||||
case 2:
|
||||
// ignore this here - DLE register
|
||||
break;
|
||||
case 3:
|
||||
switch (con_ctrl2 & CONC2_CLENMASK) {
|
||||
case CONC2_CLEN5: data &= 0x1f; break;
|
||||
case CONC2_CLEN6: data &= 0x3f; break;
|
||||
case CONC2_CLEN7: data &= 0x7f;
|
||||
if (isbitset(con_ctrl1,CONC1_PE))
|
||||
data = set_parity(data, con_ctrl2 & CONC2_ODDEVN);
|
||||
break;
|
||||
case CONC2_CLEN8: data &= 0xff; break;
|
||||
}
|
||||
con_xmit = data;
|
||||
term->buf = data;
|
||||
clrbit(con_status,CONS_THRE);
|
||||
if (XMITENABLED())
|
||||
sim_activate(term,term->wait);
|
||||
}
|
||||
// RCVINTR();
|
||||
XMITINTR();
|
||||
DSRINTR();
|
||||
|
||||
sim_debug(DBG_CON_WRITE, &con_dev, DBG_PCFORMAT0 "Byte write %02x (pos logic) to $%04x\n", DBG_PC, data & 0xff, ioaddr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat con_read(t_addr ioaddr, uint16 *data) {
|
||||
SERMUX *mux = &con_mux[0];
|
||||
|
||||
switch (ioaddr & 0x0003) {
|
||||
case 0: /* CTRL1 */
|
||||
*data = con_ctrl1;
|
||||
break;
|
||||
case 1:
|
||||
*data = con_ctrl2;
|
||||
break;
|
||||
case 2:
|
||||
if (mux->ldsc.conn) setbit(con_status, CONS_DSR);
|
||||
else clrbit(con_status, CONS_DSR);
|
||||
*data = con_status;
|
||||
clrbit(con_status,CONS_DSC); /* acknowledge change in DSR/DCD */
|
||||
break;
|
||||
case 3:
|
||||
*data = con_rcv;
|
||||
clrbit(con_status,CONS_DR);
|
||||
cpu_assertInt(INT_CONR, FALSE);
|
||||
}
|
||||
sim_debug(DBG_CON_READ, &con_dev, DBG_PCFORMAT1 "Byte read %02x (pos logic) from $%04x\n", DBG_PC, *data & 0xff, ioaddr);
|
||||
|
||||
/* note usart has inverted bus, so returned data must be negated */
|
||||
*data = ~(*data);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* Onboard 8253 timer
|
||||
***********************************************************************************************/
|
||||
|
||||
struct i8253 {
|
||||
uint16 cnt;
|
||||
uint16 preset;
|
||||
uint16 mode;
|
||||
t_bool hilo; /* which half of 16 bit cnt is to be set */
|
||||
};
|
||||
struct i8253 tim[3];
|
||||
|
||||
IOINFO tim_ioinfo1 = { NULL, TIM_IOBASE, 4, TIM_TICK_VEC, 6, tim_read, tim_write };
|
||||
IOINFO tim_ioinfo2 = { &tim_ioinfo1, 0, 0, TIM_INTVL_VEC, 7, tim_read, tim_write };
|
||||
DEVCTXT tim_ctxt = { &tim_ioinfo2 };
|
||||
|
||||
UNIT tim_unit[] = {
|
||||
{ UDATA (&tim0_svc, 0, 0), CON_POLLRATE, },
|
||||
{ UDATA (&tim1_svc, 0, 0), CON_POLLRATE, },
|
||||
{ UDATA (&tim2_svc, 0, 0), CON_POLLRATE, }
|
||||
};
|
||||
|
||||
REG tim_reg[] = {
|
||||
{ HRDATA (CNT0, tim[0].cnt, 16) },
|
||||
{ HRDATA (CNT1, tim[1].cnt, 16) },
|
||||
{ HRDATA (CNT2, tim[2].cnt, 16) },
|
||||
{ HRDATA (MODE0, tim[0].mode, 8) },
|
||||
{ HRDATA (MODE1, tim[1].mode, 8) },
|
||||
{ HRDATA (MODE2, tim[2].mode, 8) },
|
||||
{ NULL }
|
||||
};
|
||||
MTAB tim_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", NULL, &show_iobase },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", NULL, &show_iovec },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "PRIO", "PRIO", NULL, &show_ioprio },
|
||||
{ 0 }
|
||||
};
|
||||
DEBTAB tim_dflags[] = {
|
||||
{ "WRITE", DBG_TIM_WRITE },
|
||||
{ "READ", DBG_TIM_READ },
|
||||
{ "SVC", DBG_TIM_SVC },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
DEVICE tim_dev = {
|
||||
"TIM", /*name*/
|
||||
tim_unit, /*units*/
|
||||
tim_reg, /*registers*/
|
||||
tim_mod, /*modifiers*/
|
||||
3, /*numunits*/
|
||||
16, /*aradix*/
|
||||
16, /*awidth*/
|
||||
1, /*aincr*/
|
||||
8, /*dradix*/
|
||||
8, /*dwidth*/
|
||||
NULL, /*examine*/
|
||||
NULL, /*deposit*/
|
||||
&tim_reset, /*reset*/
|
||||
NULL, /*boot*/
|
||||
NULL, /*attach*/
|
||||
NULL, /*detach*/
|
||||
&tim_ctxt, /*ctxt*/
|
||||
DEV_DEBUG, /*flags*/
|
||||
0, /*dctrl*/
|
||||
tim_dflags, /*debflags*/
|
||||
NULL, /*msize*/
|
||||
NULL /*lname*/
|
||||
};
|
||||
|
||||
t_stat tim_reset(DEVICE *dptr)
|
||||
{
|
||||
DEVCTXT* ctxt = (DEVCTXT*)dptr->ctxt;
|
||||
|
||||
if (dptr->flags & DEV_DIS) {
|
||||
del_ioh(ctxt->ioi);
|
||||
sim_cancel(&tim_unit[0]);
|
||||
sim_cancel(&tim_unit[1]);
|
||||
sim_cancel(&tim_unit[2]);
|
||||
} else {
|
||||
add_ioh(ctxt->ioi);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat tim_read(t_addr ioaddr, uint16 *data)
|
||||
{
|
||||
int n = ioaddr & 0x0003;
|
||||
if (n == 3)
|
||||
*data = 0xff;
|
||||
else {
|
||||
*data = (tim[n].hilo ? tim[n].cnt : (tim[n].cnt >> 8)) & 0xff;
|
||||
sim_debug(DBG_TIM_READ, &tim_dev, DBG_PCFORMAT1 "Read %s timer%d: %02x\n",
|
||||
DBG_PC, tim[n].hilo ? "high" : "low", n, *data);
|
||||
tim[n].hilo = ! tim[n].hilo;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static uint16 sethi(uint16 val, uint16 data) {
|
||||
val &= 0xff;
|
||||
val |= (data << 8);
|
||||
return val;
|
||||
}
|
||||
static uint16 setlo(uint16 val, uint16 data) {
|
||||
val &= 0xff00;
|
||||
val |= data;
|
||||
return val;
|
||||
}
|
||||
t_stat tim_write(t_addr ioaddr, uint16 data)
|
||||
{
|
||||
int n = ioaddr & 0x0003;
|
||||
data &= 0xff;
|
||||
if (n == 3) {
|
||||
n = (data & 0xc0) >> 6;
|
||||
sim_debug(DBG_TIM_WRITE, &tim_dev, DBG_PCFORMAT0 "Timer%d: mode=%d\n",
|
||||
DBG_PC, n, (data >> 1) & 7);
|
||||
if (n == 3) {
|
||||
printf("Unimplemented: Mode=0xc0\n");
|
||||
return STOP_IMPL;
|
||||
}
|
||||
if (data & 0x01) {
|
||||
printf("Unimplemented: BCD mode: timer=%d\n",n);
|
||||
return STOP_IMPL;
|
||||
}
|
||||
if (!( (data & 0x0e)==0x00 || (data & 0x0e)==0x04)) {
|
||||
printf("Unimplemented: Mode not 0 or 2: timer=%d\n",n);
|
||||
return STOP_IMPL;
|
||||
}
|
||||
if ((data & 0x30) != 0x30) {
|
||||
printf("Unimplemented: not 16 bit load: timer=%d\n",n);
|
||||
return STOP_IMPL;
|
||||
}
|
||||
tim[n].mode = data;
|
||||
} else {
|
||||
if (tim[n].hilo) {
|
||||
tim[n].preset = sethi(tim[n].preset, data);
|
||||
tim[n].cnt = sethi(tim[n].cnt, data);
|
||||
if (n < 2) { /* timer 2 is triggered by timer 1 */
|
||||
int32 time = 1250000 / tim[n].cnt;
|
||||
sim_cancel(&tim_unit[n]);
|
||||
sim_activate(&tim_unit[n], time);
|
||||
}
|
||||
} else {
|
||||
tim[n].preset = setlo(tim[n].preset, data);
|
||||
tim[n].cnt = setlo(tim[n].cnt, data);
|
||||
}
|
||||
sim_debug(DBG_TIM_WRITE, &tim_dev, DBG_PCFORMAT0 "Timer%d: %s cnt=%02x\n",
|
||||
DBG_PC, n, tim[n].hilo ? "high":"low", data);
|
||||
tim[n].hilo = !tim[n].hilo;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* baud rate timer 0 is programmed in mode 2 - actually, this is ignored */
|
||||
static t_stat tim0_svc(UNIT* uptr)
|
||||
{
|
||||
int32 time = 1250000 / tim[0].preset;
|
||||
sim_activate(uptr, time);
|
||||
sim_debug(DBG_TIM_SVC, &tim_dev, DBG_PCFORMAT2 "Timer0: SVC call\n", DBG_PC);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* system timer 1 is programmed in mode 2, causes interrupt each time it is 0 */
|
||||
static t_stat tim1_svc(UNIT* uptr)
|
||||
{
|
||||
int32 time = 1250000 / tim[0].preset;
|
||||
sim_debug(DBG_TIM_SVC, &tim_dev, DBG_PCFORMAT2 "Timer1: SVC call\n", DBG_PC);
|
||||
sim_activate(uptr, time);
|
||||
cpu_raiseInt(INT_TICK);
|
||||
reg_ssr |= SSR_TICK; /* notify TICK timer int occurred */
|
||||
|
||||
/* handle interval timer */
|
||||
if (tim[2].cnt > 0) tim[2].cnt--;
|
||||
if (tim[2].cnt == 0) {
|
||||
cpu_raiseInt(INT_INTVL);
|
||||
reg_ssr |= SSR_INTVL; /* notify INTVL timer int occurred */
|
||||
if ((tim[2].mode & 0x0e) == 0x04) {
|
||||
tim[2].cnt = tim[2].preset; /* restart timer */
|
||||
} /* otherwise single shot */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* interval timer 2 is programmed in mode 0 (single shot) or 2 (rate generator)
|
||||
* this is triggered by timer1 - svc is ignored here */
|
||||
static t_stat tim2_svc(UNIT* uptr)
|
||||
{
|
||||
sim_debug(DBG_TIM_SVC, &tim_dev, DBG_PCFORMAT2 "Timer2: SVC call - should not occur\n", DBG_PC);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
621
PDQ-3/pdq3_sys.c
Normal file
621
PDQ-3/pdq3_sys.c
Normal file
@@ -0,0 +1,621 @@
|
||||
/* pdq3_sys.c: PDQ3 simulator interface
|
||||
|
||||
Work derived from Copyright (c) 2004-2012, Robert M. Supnik
|
||||
Copyright (c) 2013 Holger Veit
|
||||
|
||||
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 names of Robert M Supnik and Holger Veit
|
||||
shall not 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 and Holger Veit.
|
||||
|
||||
2013xxxx hv initial version (written up to the leval to test against bootloader)
|
||||
20130907 hv added VIEWSEG command
|
||||
20130925 hv added CALL and NAME command
|
||||
20130927 hv wrong disassembly of LDC instr
|
||||
*/
|
||||
#include "pdq3_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
static int disass(t_addr addr);
|
||||
t_stat parse_sym_m (char *cptr, t_value *val, int32 sw);
|
||||
void pdq3_vm_init (void);
|
||||
static t_stat pdq3_cmd_exstack(int32 arg, char *buf);
|
||||
static t_stat pdq3_cmd_exmscw(int32 arg, char *buf);
|
||||
static t_stat pdq3_cmd_extib(int32 arg, char *buf);
|
||||
static t_stat pdq3_cmd_exseg(int32 arg, char *buf);
|
||||
static t_stat pdq3_cmd_calcea(int32 arg, char *buf);
|
||||
static t_stat pdq3_cmd_calltree(int32 arg, char *buf);
|
||||
static t_stat pdq3_cmd_namealias(int32 arg, char *buf);
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern DEVICE tty_dev;
|
||||
extern DEVICE fdc_dev;
|
||||
extern DEVICE tim_dev;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 M[];
|
||||
extern uint16 reg_pc;
|
||||
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax maximum number of words for examine/deposit
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "PDQ3";
|
||||
REG *sim_PC = &cpu_reg[0]; /* note this is the artifical register PCX */
|
||||
int32 sim_emax = 6;
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&con_dev,
|
||||
&fdc_dev,
|
||||
&tim_dev,
|
||||
NULL
|
||||
};
|
||||
const char *sim_stop_messages[] = {
|
||||
"---",
|
||||
"PC Breakpoint",
|
||||
"MEM Breakpoint",
|
||||
"Invalid Opcode",
|
||||
"Invalid MEM Access",
|
||||
"Invalid I/O Access",
|
||||
"Not yet implemented",
|
||||
"BPT instruction",
|
||||
"DEBUG PRE exec stop",
|
||||
"DEBUG POST exec stop",
|
||||
"HALT on Pascal Exception",
|
||||
};
|
||||
|
||||
CTAB pdq3_cmds[] = {
|
||||
{ "VSTACK", &pdq3_cmd_exstack, 0, "Display last N elements of stack. Top is where SP points to" },
|
||||
{ "VMSCW", &pdq3_cmd_exmscw, 0, "Display current MSCW" },
|
||||
{ "VTIB", &pdq3_cmd_extib, 0, "Display current TIB" },
|
||||
{ "VSEG", &pdq3_cmd_exseg, 0, "Display a segment table entry" },
|
||||
{ "VCALL", &pdq3_cmd_calltree, 0, "Display the call tree" },
|
||||
{ "NAME", &pdq3_cmd_namealias, 0, "Define a name" },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
void (*sim_vm_init)(void) = &pdq3_vm_init;
|
||||
|
||||
/* Loader proper */
|
||||
t_stat sim_load (FILE *fi, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
int rombase;
|
||||
int c1, c2, i;
|
||||
if (flag == 1) /* don't dump */
|
||||
return SCPE_ARG;
|
||||
/* this assumes a HDT style ROM, where the first 2 bytes refer to the
|
||||
* actual word start of the ROM, e.g. with PDQ-3 the HDT ROM has 0xf401
|
||||
* as the first word, so it will load at word address 0xf400, and 0xfc68
|
||||
* will be preset to 0xf401
|
||||
*/
|
||||
c1 = fgetc(fi);
|
||||
c2 = fgetc(fi);
|
||||
rombase = c1 + c2 * 256;
|
||||
rom_write(rombase & 0xfffe, rombase);
|
||||
reg_fc68 = rombase;
|
||||
i = 0;
|
||||
while (!feof(fi) && i<0x1ff) {
|
||||
c1 = fgetc(fi);
|
||||
c2 = fgetc(fi);
|
||||
rom_write(rombase+i, (uint16)(c1 + c2*256));
|
||||
i++;
|
||||
}
|
||||
reg_romsize = i;
|
||||
/* preset the cpu_serial number from ROM, may be overwritten manually for special purposes */
|
||||
rom_read(rombase+i-1, ®_cpuserial);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Note: this simh handles ABSOLUTE word addresses and segmented byte addresses.
|
||||
* A word address addresses a single cell in memory (up to 65536 cells).
|
||||
* A byte address only occurs in IPC context, it is relative to the content of
|
||||
* the reg_segb register.
|
||||
* Convention:
|
||||
* $xxxx = word address
|
||||
* xxxx:yyyy = byte address yyyy relative to segment xxxx
|
||||
* #yyyy = byte address relative to current reg_segb
|
||||
* The t_addr type must be 32 bit, the upper half contains the segment, the lower
|
||||
* half contains the offset. If the upper half is NIL, it is a word address
|
||||
*/
|
||||
void pdq3_fprint_addr (FILE *st, DEVICE *dptr, t_addr addr)
|
||||
{
|
||||
if (ADDR_ISWORD(addr))
|
||||
fprintf(st,"$");
|
||||
else if (ADDR_SEG(addr) == reg_segb)
|
||||
fprintf(st,"#");
|
||||
else {
|
||||
fprint_val (st, ADDR_SEG(addr), dptr->dradix, dptr->dwidth, PV_LEFT);
|
||||
fprintf(st,":");
|
||||
}
|
||||
fprint_val (st, ADDR_OFF(addr), dptr->dradix, dptr->dwidth, PV_LEFT);
|
||||
return;
|
||||
}
|
||||
|
||||
t_addr pdq3_parse_addr (DEVICE *dptr, char *cptr, char **tptr)
|
||||
{
|
||||
t_addr seg, off;
|
||||
if (cptr[0] == '#') {
|
||||
off = strtotv(cptr+1, tptr, dptr->aradix);
|
||||
return MAKE_BADDR(reg_segb,off);
|
||||
} else if (cptr[0] == '$') {
|
||||
off = strtotv(cptr+1, tptr, dptr->aradix);
|
||||
return MAKE_WADDR(off);
|
||||
} else {
|
||||
char gbuf[CBUFSIZE];
|
||||
get_glyph (cptr, gbuf, 0);
|
||||
if (!strncmp(gbuf,"SEGB",4)) {
|
||||
seg = reg_segb; *tptr = cptr+4;
|
||||
} else
|
||||
seg = strtotv(cptr, tptr, dptr->aradix);
|
||||
if (*tptr[0] == ':') {
|
||||
cptr = *tptr + 1;
|
||||
off = strtotv(cptr, tptr, dptr->aradix);
|
||||
return MAKE_BADDR(seg,off);
|
||||
} else
|
||||
return MAKE_WADDR(seg);
|
||||
}
|
||||
}
|
||||
|
||||
void pdq3_vm_init (void)
|
||||
{
|
||||
sim_vm_fprint_addr = &pdq3_fprint_addr;
|
||||
sim_vm_parse_addr = &pdq3_parse_addr;
|
||||
sim_vm_cmd = pdq3_cmds;
|
||||
return;
|
||||
}
|
||||
|
||||
static t_stat pdq3_cmd_exstack(int32 arg, char *buf)
|
||||
{
|
||||
t_stat rc;
|
||||
uint16 data;
|
||||
int i;
|
||||
int n = buf[0] ? atol(buf) : 0;
|
||||
if (n < 0) n = 0;
|
||||
printf("SP: $%04x LOW: $%04x UPR: $%04x\n",
|
||||
reg_sp, reg_splow, reg_spupr);
|
||||
for (i=n; i>=0; i--) {
|
||||
if ((rc=Read(reg_sp+i, 0, &data, 0)) != SCPE_OK) continue;
|
||||
if (i==0) printf(" TOS: "); else printf(" %3d: ",i);
|
||||
printf("%04x ($%04x)\n", data, reg_sp+i);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat pdq3_cmd_exmscw(int32 arg, char *buf)
|
||||
{
|
||||
char* next;
|
||||
return dbg_dump_mscw(stdout, buf[0] ? pdq3_parse_addr(&cpu_dev, buf, &next) : reg_mp);
|
||||
}
|
||||
|
||||
static t_stat pdq3_cmd_extib(int32 arg, char *buf)
|
||||
{
|
||||
char* next;
|
||||
return dbg_dump_tib(stdout, buf[0] ? pdq3_parse_addr(&cpu_dev, buf, &next) : reg_ctp);
|
||||
}
|
||||
|
||||
static t_stat pdq3_cmd_exseg(int32 arg, char *buf)
|
||||
{
|
||||
t_stat rc;
|
||||
uint16 nsegs;
|
||||
uint16 segnum, segptr;
|
||||
char* next;
|
||||
FILE* fd = stdout; /* XXX */
|
||||
|
||||
if (reg_ssv < 0x2030 || reg_ssv > 0xf000) {
|
||||
fprintf(fd, "Cannot list segments in bootloader: incomplete tables\n");
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
if ((rc=Read(reg_ssv, -1, &nsegs, 0)) != SCPE_OK) return rc;
|
||||
|
||||
if (buf[0]) {
|
||||
segnum = pdq3_parse_addr(&cpu_dev, buf, &next);
|
||||
fprintf(fd, "Segment $%02x\n", segnum);
|
||||
if (segnum > nsegs) {
|
||||
fprintf(fd, "Too high: maxsegs=$%02x\n",nsegs);
|
||||
return SCPE_ARG;
|
||||
}
|
||||
if ((rc=Read(reg_ssv, segnum, &segptr, 0)) != SCPE_OK) return rc;
|
||||
rc = dbg_dump_seg(fd, segptr);
|
||||
} else
|
||||
rc = dbg_dump_segtbl(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static t_stat pdq3_cmd_calltree(int32 arg, char *buf) {
|
||||
return dbg_calltree(stdout);
|
||||
}
|
||||
|
||||
static t_stat pdq3_cmd_namealias(int32 arg, char *buf) {
|
||||
char* name, *alias;
|
||||
|
||||
if (buf[0]==0)
|
||||
return dbg_listalias(stdout);
|
||||
|
||||
name = strtok(buf, " \t");
|
||||
alias = strtok(NULL, " \t\n");
|
||||
return dbg_enteralias(name,alias);
|
||||
}
|
||||
|
||||
/**************************************************************************************
|
||||
* PDQ utility functions
|
||||
*************************************************************************************/
|
||||
OPTABLE optable[] = {
|
||||
/*00*/ { "SLDC0", OP_NULL }, { "SLDC1", OP_NULL },
|
||||
/*02*/ { "SLDC2", OP_NULL }, { "SLDC3", OP_NULL },
|
||||
/*04*/ { "SLDC4", OP_NULL }, { "SLDC5", OP_NULL },
|
||||
/*06*/ { "SLDC6", OP_NULL }, { "SLDC7", OP_NULL },
|
||||
/*08*/ { "SLDC8", OP_NULL }, { "SLDC9", OP_NULL },
|
||||
/*0a*/ { "SLDC10", OP_NULL }, { "SLDC11", OP_NULL },
|
||||
/*0c*/ { "SLDC12", OP_NULL }, { "SLDC13", OP_NULL },
|
||||
/*0e*/ { "SLDC14", OP_NULL }, { "SLDC15", OP_NULL },
|
||||
/*10*/ { "SLDC16", OP_NULL }, { "SLDC17", OP_NULL },
|
||||
/*12*/ { "SLDC18", OP_NULL }, { "SLDC19", OP_NULL },
|
||||
/*14*/ { "SLDC20", OP_NULL }, { "SLDC21", OP_NULL },
|
||||
/*16*/ { "SLDC22", OP_NULL }, { "SLDC23", OP_NULL },
|
||||
/*18*/ { "SLDC24", OP_NULL }, { "SLDC25", OP_NULL },
|
||||
/*1a*/ { "SLDC26", OP_NULL }, { "SLDC27", OP_NULL },
|
||||
/*1c*/ { "SLDC28", OP_NULL }, { "SLDC29", OP_NULL },
|
||||
/*1e*/ { "SLDC30", OP_NULL }, { "SLDC31", OP_NULL },
|
||||
/*20*/ { "SLDL1", OP_NULL }, { "SLDL2", OP_NULL },
|
||||
/*22*/ { "SLDL3", OP_NULL }, { "SLDL4", OP_NULL },
|
||||
/*24*/ { "SLDL5", OP_NULL }, { "SLDL6", OP_NULL },
|
||||
/*26*/ { "SLDL7", OP_NULL }, { "SLDL8", OP_NULL },
|
||||
/*28*/ { "SLDL9", OP_NULL }, { "SLDL10", OP_NULL },
|
||||
/*2a*/ { "SLDL11", OP_NULL }, { "SLDL12", OP_NULL },
|
||||
/*2c*/ { "SLDL13", OP_NULL }, { "SLDL14", OP_NULL },
|
||||
/*2e*/ { "SLDL15", OP_NULL }, { "SLDL16", OP_NULL },
|
||||
/*30*/ { "SLDO1", OP_NULL }, { "SLDO2", OP_NULL },
|
||||
/*32*/ { "SLDO3", OP_NULL }, { "SLDO4", OP_NULL },
|
||||
/*34*/ { "SLDO5", OP_NULL }, { "SLDO6", OP_NULL },
|
||||
/*36*/ { "SLDO7", OP_NULL }, { "SLDO8", OP_NULL },
|
||||
/*38*/ { "SLDO9", OP_NULL }, { "SLDO10", OP_NULL },
|
||||
/*3a*/ { "SLDO11", OP_NULL }, { "SLDO12", OP_NULL },
|
||||
/*3c*/ { "SLDO13", OP_NULL }, { "SLDO14", OP_NULL },
|
||||
/*3e*/ { "SLDO15", OP_NULL }, { "SLDO16", OP_NULL },
|
||||
/*40*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*42*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*44*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*46*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*48*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*4a*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*4c*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*4e*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*50*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*52*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*54*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*56*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*58*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*5a*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*5c*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*5e*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*60*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*62*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*64*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*66*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*68*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*6a*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*6c*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*6e*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*70*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*72*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*74*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*76*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*78*/ { "SIND0", OP_NULL }, { "SIND1", OP_NULL },
|
||||
/*7a*/ { "SIND2", OP_NULL }, { "SIND3", OP_NULL },
|
||||
/*7c*/ { "SIND4", OP_NULL }, { "SIND5", OP_NULL },
|
||||
/*7e*/ { "SIND6", OP_NULL }, { "SIND7", OP_NULL },
|
||||
/*80*/ { "LDCB", OP_UB }, { "LDCI", OP_W },
|
||||
/*82*/ { "LCA", OP_AB }, { "LDC", OP_BUB },
|
||||
/*84*/ { "LLA", OP_B }, { "LDO", OP_B },
|
||||
/*86*/ { "LAO", OP_B }, { "LDL", OP_B },
|
||||
/*88*/ { "LDA", OP_DBB }, { "LOD", OP_DBB },
|
||||
/*8a*/ { "UJP", OP_SB }, { "UJPL", OP_SW },
|
||||
/*8c*/ { "MPI", OP_NULL }, { "DVI", OP_NULL },
|
||||
/*8e*/ { "STM", OP_UB }, { "MODI", OP_NULL },
|
||||
/*90*/ { "CPL", OP_UB }, { "CPG", OP_UB },
|
||||
/*92*/ { "CPI", OP_DBUB }, { "CXL", OP_UBUB },
|
||||
/*94*/ { "CXG", OP_UBUB }, { "CXI", OP_UBDBUB },
|
||||
/*96*/ { "RPU", OP_B }, { "CPF", OP_NULL },
|
||||
/*98*/ { "LDCN", OP_NULL }, { "LSL", OP_DB },
|
||||
/*9a*/ { "LDE", OP_UBB }, { "LAE", OP_UBB },
|
||||
/*9c*/ { "NOP", OP_NULL }, { "LPR", OP_NULL },
|
||||
/*9e*/ { "BPT", OP_NULL }, { "BNOT", OP_NULL },
|
||||
/*a0*/ { "LOR", OP_NULL }, { "LAND", OP_NULL },
|
||||
/*a2*/ { "ADI", OP_NULL }, { "SBI", OP_NULL },
|
||||
/*a4*/ { "STL", OP_B }, { "SRO", OP_B },
|
||||
/*a6*/ { "STR", OP_DBB }, { "LDB", OP_NULL },
|
||||
/*a8*/ { "LHO", OP_NULL }, { "LVO", OP_NULL },
|
||||
/*aa*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*ac*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*ae*/ { "", OP_ERROR }, { "", OP_ERROR },
|
||||
/*b0*/ { "EQUI", OP_NULL }, { "NEQI", OP_NULL },
|
||||
/*b2*/ { "LEQI", OP_NULL }, { "GEQI", OP_NULL },
|
||||
/*b4*/ { "LEUSW", OP_NULL }, { "GEUSW", OP_NULL },
|
||||
/*b6*/ { "EQUPWR", OP_NULL }, { "LEQPWR", OP_NULL },
|
||||
/*b8*/ { "GEQPWR", OP_NULL }, { "EQUBYT", OP_B },
|
||||
/*ba*/ { "LEQBYT", OP_B }, { "GEQBYT", OP_B },
|
||||
/*bc*/ { "SRS", OP_NULL }, { "SWAP", OP_NULL },
|
||||
/*be*/ { "TNC", OP_NULL }, { "RND", OP_NULL },
|
||||
/*c0*/ { "ADR", OP_NULL }, { "SBR", OP_NULL },
|
||||
/*c2*/ { "MPR", OP_NULL }, { "DVR", OP_NULL },
|
||||
/*c4*/ { "STO", OP_NULL }, { "MOV", OP_B },
|
||||
/*c6*/ { "DUP2", OP_NULL }, { "ADJ", OP_UB },
|
||||
/*c8*/ { "STB", OP_NULL }, { "LDP", OP_NULL },
|
||||
/*ca*/ { "STP", OP_NULL }, { "CHK", OP_NULL },
|
||||
/*cc*/ { "FLT", OP_NULL }, { "EQUREAL",OP_NULL },
|
||||
/*ce*/ { "LEQREAL",OP_NULL }, { "GEQREAL",OP_NULL },
|
||||
/*d0*/ { "LDM", OP_UB }, { "SPR", OP_NULL },
|
||||
/*d2*/ { "EFJ", OP_SB }, { "NFJ", OP_SB },
|
||||
/*d4*/ { "FJP", OP_SB }, { "FJPL", OP_SW },
|
||||
/*d6*/ { "XJP", OP_B }, { "IXA", OP_B },
|
||||
/*d8*/ { "IXP", OP_UBUB }, { "STE", OP_UBB },
|
||||
/*da*/ { "INN", OP_NULL }, { "UNI", OP_NULL },
|
||||
/*dc*/ { "INT", OP_NULL }, { "DIF", OP_NULL },
|
||||
/*de*/ { "SIGNAL", OP_NULL }, { "WAIT", OP_NULL },
|
||||
/*e0*/ { "ABI", OP_NULL }, { "NGI", OP_NULL },
|
||||
/*e2*/ { "DUP1", OP_NULL }, { "ABR", OP_NULL },
|
||||
/*e4*/ { "NGR", OP_NULL }, { "LNOT", OP_NULL },
|
||||
/*e6*/ { "IND", OP_B }, { "INC", OP_B },
|
||||
};
|
||||
|
||||
static uint16 UB(t_value arg)
|
||||
{
|
||||
return arg & 0xff;
|
||||
}
|
||||
static uint16 DB(t_value arg)
|
||||
{
|
||||
return UB(arg);
|
||||
}
|
||||
static int16 W(t_value arg1, t_value arg2)
|
||||
{
|
||||
uint16 wl = arg1 & 0xff;
|
||||
uint16 wh = arg2 & 0xff;
|
||||
return wl | ((wh << 8) & 0xff00);
|
||||
}
|
||||
|
||||
static int16 SW(t_value arg1, t_value arg2)
|
||||
{
|
||||
return W(arg1,arg2);
|
||||
}
|
||||
static int16 SB(t_value arg)
|
||||
{
|
||||
int16 w = arg & 0xff;
|
||||
if (w & 0x80) w |= 0xff00;
|
||||
return w;
|
||||
}
|
||||
static uint16 B(t_value arg1, t_value arg2, int* sz) {
|
||||
uint16 wh = arg1 & 0xff;
|
||||
uint16 wl;
|
||||
if (wh & 0x80) {
|
||||
wl = arg2 & 0xff;
|
||||
wl |= ((wh & 0x7f) << 8);
|
||||
*sz = 2;
|
||||
return wl;
|
||||
} else {
|
||||
*sz = 1;
|
||||
return wh;
|
||||
}
|
||||
}
|
||||
|
||||
t_stat print_hd(FILE *of, t_value val, t_bool hexdec, t_bool isbyte)
|
||||
{
|
||||
uint16 data = isbyte ? (val & 0xff) : (val & 0xffff);
|
||||
|
||||
if (hexdec)
|
||||
fprintf(of,"%0xh",data);
|
||||
else
|
||||
fprintf(of,"%d",data);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
uint16 op, arg1, arg2, arg3;
|
||||
int16 sarg;
|
||||
t_stat size = 0;
|
||||
int optype, sz;
|
||||
t_bool hexdec = (sw & SWMASK('H')) ? TRUE : FALSE;
|
||||
addr = ADDR_OFF(addr);
|
||||
|
||||
op = val[0];
|
||||
if (op > 0xe7) return SCPE_ARG;
|
||||
|
||||
optype = optable[op].flags;
|
||||
if (optype > OP_ERROR) {
|
||||
fprintf(of,"%-8s", optable[op].name);
|
||||
switch (optype) {
|
||||
case OP_NULL:
|
||||
break;
|
||||
case OP_UB:
|
||||
size = 1; arg1 = UB(val[1]);
|
||||
print_hd(of, arg1, hexdec, FALSE);
|
||||
break;
|
||||
case OP_W:
|
||||
size = 2; sarg = W(val[1],val[2]);
|
||||
print_hd(of, sarg, hexdec, FALSE);
|
||||
break;
|
||||
case OP_AB:
|
||||
arg1 = B(val[1],val[2], &sz); size = sz;
|
||||
fprintf(of,"#%x", arg1*2);
|
||||
break;
|
||||
case OP_B:
|
||||
arg1 = B(val[1],val[2], &sz); size = sz;
|
||||
print_hd(of, arg1, hexdec, FALSE);
|
||||
break;
|
||||
case OP_DBB:
|
||||
arg1 = DB(val[1]);
|
||||
arg2 = B(val[2],val[3], &sz); size = sz+1;
|
||||
print_hd(of, arg1, hexdec, TRUE); fputc(',',of);
|
||||
print_hd(of, arg2, hexdec, FALSE);
|
||||
break;
|
||||
case OP_UBB:
|
||||
arg1 = UB(val[1]);
|
||||
arg2 = B(val[2],val[3], &sz); size = sz+1;
|
||||
print_hd(of, arg1, hexdec, TRUE); fputc(',',of);
|
||||
print_hd(of, arg2, hexdec, FALSE);
|
||||
break;
|
||||
case OP_BUB:
|
||||
arg1 = B(val[1],val[2], &sz); size = sz+1;
|
||||
arg2 = UB(val[sz+1]);
|
||||
print_hd(of, arg1, hexdec, FALSE); fputc(',',of);
|
||||
print_hd(of, arg2, hexdec, TRUE);
|
||||
break;
|
||||
case OP_SB:
|
||||
size = 1; sarg = SB(val[1]);
|
||||
fprintf(of,"#%x", addr+sarg+2);
|
||||
break;
|
||||
case OP_SW:
|
||||
size = 2; sarg = SW(val[1],val[2]);
|
||||
fprintf(of,"#%x", addr+sarg+3);
|
||||
break;
|
||||
case OP_DBUB:
|
||||
size = 2; arg1 = DB(val[1]);
|
||||
arg2 = UB(val[2]);
|
||||
print_hd(of, arg1, hexdec, TRUE); fputc(',',of);
|
||||
print_hd(of, arg2, hexdec, TRUE);
|
||||
break;
|
||||
case OP_UBUB:
|
||||
size = 2; arg1 = UB(val[1]);
|
||||
arg2 = UB(val[2]);
|
||||
print_hd(of, arg1, hexdec, TRUE); fputc(',',of);
|
||||
print_hd(of, arg2, hexdec, TRUE);
|
||||
break;
|
||||
case OP_UBDBUB:
|
||||
size = 3; arg1 = UB(val[1]);
|
||||
arg2 = DB(val[2]);
|
||||
arg3 = UB(val[3]);
|
||||
print_hd(of, arg1, hexdec, TRUE); fputc(',',of);
|
||||
print_hd(of, arg2, hexdec, TRUE); fputc(',',of);
|
||||
print_hd(of, arg3, hexdec, TRUE);
|
||||
break;
|
||||
case OP_DB:
|
||||
size = 1; arg1 = DB(val[1]);
|
||||
print_hd(of, arg1, hexdec, TRUE);
|
||||
break;
|
||||
}
|
||||
return -size;
|
||||
} else {
|
||||
fprintf(of,"%-8s","DB"); print_hd(of, op, hexdec, TRUE);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Symbolic decode
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to data
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = status code
|
||||
*/
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
t_addr off;
|
||||
T_FLCVT t;
|
||||
int ch;
|
||||
|
||||
t_bool hexdec = (sw & SWMASK('H')) ? TRUE : FALSE;
|
||||
if (sw & SWMASK('M') && !ADDR_ISWORD(addr)) {
|
||||
return fprint_sym_m(of, addr, val, uptr, sw);
|
||||
}
|
||||
if (sw & SWMASK('B')) { /* as BYTE */
|
||||
if (ADDR_ISWORD(addr)) {
|
||||
fprint_val(of, (val[0]>>8) & 0xff, cpu_dev.dradix, 8, PV_RZRO);
|
||||
fprintf(of, ",");
|
||||
fprint_val(of, val[0] & 0xff, cpu_dev.dradix, 8, PV_RZRO);
|
||||
} else
|
||||
fprint_val(of, val[0], cpu_dev.dradix, 8, PV_RZRO);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK('C')) { /* as CHAR */
|
||||
if (ADDR_ISWORD(addr)) {
|
||||
ch = val[0] & 0xff;
|
||||
fprintf(of, isprint(ch) ? "%c," : "%02x,", ch);
|
||||
ch = val[0]>>8;
|
||||
fprintf(of, isprint(ch) ? "%c" : "%02x", ch);
|
||||
} else {
|
||||
ch = val[0] & 0xff;
|
||||
fprintf(of, isprint(ch) ? "%c" : "%02x", ch);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK('W')) { /* as WORD */
|
||||
if (ADDR_ISWORD(addr)) {
|
||||
fprint_val(of, val[0], cpu_dev.dradix, 16, PV_RZRO);
|
||||
off = ADDR_OFF(addr);
|
||||
if (off > (reg_bp+MSCW_SZ-1))
|
||||
fprintf(of," (GLOBAL+%d)", off - reg_bp - MSCW_SZ + 1);
|
||||
else if (off >= reg_mp && off <= (reg_mp+OFFB_MSSEG))
|
||||
fprintf(of," (MP+%d)", off - reg_mp);
|
||||
else if (off > (reg_mp+MSCW_SZ-1))
|
||||
fprintf(of," (LOCAL+%d)", off - reg_mp - MSCW_SZ + 1);
|
||||
else if (off >= reg_sp && off < reg_spupr)
|
||||
fprintf(of," (SP+%d)", off - reg_sp);
|
||||
} else {
|
||||
fprint_val(of, val[0], cpu_dev.dradix, 8, PV_RZRO);
|
||||
fprint_val(of, val[1], cpu_dev.dradix, 8, PV_RZRO);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK('F')) { /* as FLOAT */
|
||||
t.i[0] = val[1];
|
||||
t.i[1] = val[0];
|
||||
fprintf(of, "%12.6e", t.f);
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK('S')) { /* as semaphore */
|
||||
fprintf(of, "SEM(count=%d, waitq=$%04x)", val[0], val[1]);
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK('M')) { /* as MSCW */
|
||||
dbg_dump_mscw(of, val[0]);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK('T')) { /* as TIB */
|
||||
dbg_dump_tib(of, addr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/* 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
|
||||
*/
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
return SCPE_ARG;
|
||||
}
|
||||
2
PDQ-3/run.cmd
Normal file
2
PDQ-3/run.cmd
Normal file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
pdq3.exe testhdt.sim
|
||||
125
PDQ-3/testhdt.sim
Normal file
125
PDQ-3/testhdt.sim
Normal file
@@ -0,0 +1,125 @@
|
||||
;set debug debug.log
|
||||
set debug stdout
|
||||
;set fdc debug=read
|
||||
;set fdc debug=write
|
||||
;set fdc debug=verbose
|
||||
;set fdc debug=svc
|
||||
;set fdc debug=imd
|
||||
;set fdc debug=dma
|
||||
;set fdc debug=dmavb
|
||||
;set fdc debug=cmd
|
||||
;set cpu exc
|
||||
;set cpu debug=int
|
||||
;set cpu debug=trace
|
||||
;set cpu debug=write
|
||||
;set cpu debug=read
|
||||
;set cpu debug=fetch
|
||||
;set cpu debug=stack
|
||||
;set cpu debug=conc
|
||||
;set con debug=svc
|
||||
;set con debug=read
|
||||
;set con debug=write
|
||||
;set tim debug=read
|
||||
;set tim debug=write
|
||||
;set tim debug=svc
|
||||
|
||||
att con 8000
|
||||
|
||||
att fdc0 master.imd
|
||||
set fdc0 wrtlck
|
||||
set fdc1 disable
|
||||
|
||||
; HDT boot
|
||||
;break f418:368
|
||||
;break f418:36a
|
||||
;break f418:218
|
||||
|
||||
; HDT:bootfd
|
||||
;break f418:e0
|
||||
|
||||
; HDT CHK instruction: will fail if CPU serial is > 0x7fff
|
||||
;break 2018:067d
|
||||
;break 2018:070f
|
||||
|
||||
; entering PASCALSY
|
||||
;break eb1e:10
|
||||
|
||||
; problem main loop in syscode1
|
||||
;break dc26:1d0a
|
||||
;break d488:b1b
|
||||
;break d488:b55
|
||||
|
||||
; bug in SPR(4), does not save SP in TIB?
|
||||
;break d488:bb8
|
||||
;break d488:bc7
|
||||
|
||||
; problem with wait?
|
||||
;break d488:0917
|
||||
|
||||
; interrupt debugging
|
||||
;break d078:4f
|
||||
;break d488:919
|
||||
;break d488:ebe
|
||||
;break dc26:ec3
|
||||
;break d1bd:79
|
||||
;break b80d:715
|
||||
;break dc26:1d35
|
||||
;break d488:806
|
||||
;break d488:915
|
||||
;break dc26:1d36
|
||||
|
||||
; SHELL handling
|
||||
;break badf:98
|
||||
;break badf:51
|
||||
;break bbd2:1ba
|
||||
;break bbd2:1be
|
||||
;break bbd2:32a
|
||||
|
||||
; Ser_RawEmit
|
||||
;break c964:5f2
|
||||
;break d488:d80
|
||||
;break c964:6be
|
||||
|
||||
; ticker interrrupts
|
||||
;break d078:4f
|
||||
;break d1bd:6e
|
||||
|
||||
; Start/Stop Process
|
||||
;break d488:7f0
|
||||
;break d488:92e
|
||||
;break d488:934
|
||||
;break d488:958
|
||||
;break d488:0dd9
|
||||
;break c964:756
|
||||
;break c964:a6
|
||||
;break c964:cf4
|
||||
|
||||
; waiting for DSR sem
|
||||
;break c964:624
|
||||
|
||||
; Ser_Read
|
||||
;break c964:466
|
||||
;break c964:4f9
|
||||
;break c964:4fa
|
||||
;break c964:327
|
||||
;break c964:59e
|
||||
;break c964:323
|
||||
|
||||
;break d078:4c
|
||||
;break d078:4f
|
||||
;break d1bd:6a
|
||||
;break d1bd:6d
|
||||
|
||||
;break d488:ed0
|
||||
|
||||
|
||||
|
||||
load hdt/CPU_C5.BIN
|
||||
dep _ssr 80
|
||||
dep _ses 80
|
||||
|
||||
|
||||
do names.sim
|
||||
boot cpu
|
||||
set debug stdout
|
||||
|
||||
Reference in New Issue
Block a user