mirror of
https://github.com/PDP-10/its.git
synced 2026-02-15 12:26:27 +00:00
RUG - PDP-11 debugger.
This commit is contained in:
BIN
src/chsncp/rt11m.50
Normal file
BIN
src/chsncp/rt11m.50
Normal file
Binary file not shown.
846
src/pdp11/defs.126
Normal file
846
src/pdp11/defs.126
Normal file
@@ -0,0 +1,846 @@
|
||||
;;; DEFS - Definitions and configuration data -*-PALX-*-
|
||||
|
||||
.nlist
|
||||
.auxil
|
||||
|
||||
;;; Define YES and NO so they're acceptable SETF answers
|
||||
yes===1
|
||||
no===0
|
||||
|
||||
.macro setf q,a
|
||||
.if ndf a
|
||||
.print "q "
|
||||
.ttymac ans
|
||||
.if ndf ans
|
||||
setf ^"Bad input, try again:",a
|
||||
.mexit
|
||||
.endc
|
||||
a==ans
|
||||
.endm
|
||||
.endc
|
||||
.endm
|
||||
|
||||
|
||||
; Define system names for following question
|
||||
|
||||
mit===1 ; MIT's PDP 11/34
|
||||
sao===2 ; SAO's LSI 11/03
|
||||
lll===3
|
||||
mit44==4 ; MIT's new PDP 11/44
|
||||
|
||||
|
||||
drl===1 ; RL01 type disk drives
|
||||
drk===2 ; RK05 type disk drives
|
||||
drp===3 ; RP11 type disk drives
|
||||
|
||||
setf ^"System (MIT, MIT44, SAO, or LLL)?",sys
|
||||
|
||||
;define some appropriate macros
|
||||
|
||||
.if eq <sys-mit>*<sys-mit44>
|
||||
|
||||
.macro ifMIT code
|
||||
code
|
||||
.endm
|
||||
|
||||
.macro ifSAO code
|
||||
.endm
|
||||
|
||||
.macro ifLLL code
|
||||
.endm
|
||||
|
||||
.macro ifOTHER code
|
||||
.endm
|
||||
.endc ; eq <sys-mit>*<sys-mit44>
|
||||
|
||||
.if eq sys-sao
|
||||
|
||||
.macro ifMIT code
|
||||
.endm
|
||||
|
||||
.macro ifSAO code
|
||||
code
|
||||
.endm
|
||||
|
||||
.macro ifLLL code
|
||||
.endm
|
||||
|
||||
.macro ifOTHER code
|
||||
.endm
|
||||
.endc ; eq sys-sao
|
||||
|
||||
.if eq sys-lll
|
||||
|
||||
.macro ifMIT code
|
||||
.endm
|
||||
|
||||
.macro ifSAO code
|
||||
.endm
|
||||
|
||||
.macro ifLLL code
|
||||
code
|
||||
.endm
|
||||
|
||||
.macro ifOTHER code
|
||||
.endm
|
||||
.endc ; eq sys-lll
|
||||
|
||||
.if ne <<sys-mit>*<sys-mit44>*<sys-lll>*<sys-sao>>
|
||||
|
||||
.macro ifMIT code
|
||||
.endm
|
||||
|
||||
.macro ifSAO code
|
||||
.endm
|
||||
|
||||
.macro ifLLL code
|
||||
.endm
|
||||
|
||||
.macro ifOTHER code
|
||||
code
|
||||
.endm
|
||||
.endc ; all other systems
|
||||
|
||||
|
||||
|
||||
.sbttl Math Department's PDP 11/34 system
|
||||
|
||||
.if eq sys-mit
|
||||
ifMIT <
|
||||
|
||||
; Define CPU model
|
||||
pdp11==34 ; PDP11/34
|
||||
havswr===1 ; presume it has swr, check at runtime now
|
||||
sysdsk===drl ; presume RL01s from henceforth
|
||||
|
||||
.print "Are you sure you want to assemble for a machine you don't have??"
|
||||
|
||||
; No. of various devices
|
||||
nrk==0 ; RK11
|
||||
nrx==0 ; RX11
|
||||
nrl==2 ; RL11
|
||||
nrp==0 ; RP11
|
||||
ncr==0 ; CR11
|
||||
nlp==1 ; LPT
|
||||
ndp==0 ; DP11
|
||||
ndu==1 ; DU11
|
||||
|
||||
; No. of various terminal interfaces
|
||||
ndz==1 ; DZ11
|
||||
nkl==0 ; KL11, DL11-A,-B
|
||||
ndl==4 ; DL11-C,-D,-E
|
||||
ndc==1 ; DC11 (for simulator)
|
||||
|
||||
; Various options
|
||||
pfail===1 ; assemble power fail code
|
||||
|
||||
>
|
||||
.endc
|
||||
|
||||
.sbttl Math Department's PDP 11/44 system
|
||||
|
||||
.if eq sys-mit44
|
||||
ifMIT <
|
||||
|
||||
; Define CPU model
|
||||
pdp11==44 ; PDP11/44
|
||||
havswr===1 ; it has switch register
|
||||
|
||||
|
||||
;;; find out what disk to use
|
||||
|
||||
setf ^"System disk (drp, drl, drk)?",sysdsk
|
||||
|
||||
|
||||
; No. of various devices
|
||||
|
||||
nrk==0 ; RK11
|
||||
nrx==0 ; RX11
|
||||
nrl==2 ; RL11
|
||||
nrp==0 ; RP11
|
||||
ncr==0 ; CR11
|
||||
nlp==1 ; LPT
|
||||
ndp==0 ; DP11
|
||||
ndu==1 ; DU11
|
||||
|
||||
.if eq <sysdsk-drp>
|
||||
nrp==1 ; have an RP11
|
||||
nrl==0 ; have no RL11
|
||||
.endc
|
||||
|
||||
; No. of various terminal interfaces
|
||||
|
||||
ndz==1 ; DZ11
|
||||
nkl==0 ; KL11, DL11-A,-B
|
||||
ndl==4 ; DL11-C,-D,-E
|
||||
ndc==1 ; DC11 (for simulator)
|
||||
|
||||
; Various options
|
||||
|
||||
pfail===0 ; don't assemble power fail code
|
||||
|
||||
>
|
||||
.endc
|
||||
|
||||
.sbttl Orszag's LSI11 system
|
||||
|
||||
ifSAO <
|
||||
|
||||
; Define CPU model
|
||||
pdp11==03 ; LSI11
|
||||
|
||||
sysdsk===0
|
||||
|
||||
; No. of various devices
|
||||
nrk==0 ; RK11
|
||||
nrx==1 ; RX11
|
||||
nrl==0 ; RL11
|
||||
nrp==1 ; RP11
|
||||
ncr==0 ; CR11
|
||||
nlp==1 ; LPT (well, actually a terminet kludge..)
|
||||
ndp==0 ; DP11
|
||||
ndu==1 ; DU11
|
||||
|
||||
; Maximum no. of various terminal interfaces
|
||||
ndz==0 ; DZ11
|
||||
nkl==3 ; KL11, DL11-A,-B
|
||||
ndl==2 ; DL11-C,-D,-E
|
||||
ndc==0 ; DC11
|
||||
|
||||
; Various options
|
||||
pfail===0 ; no power fail code
|
||||
|
||||
>
|
||||
|
||||
.sbttl LLL (S1 project LSI-11)
|
||||
|
||||
ifLLL <
|
||||
|
||||
; Define CPU model
|
||||
pdp11==03 ; LSI11
|
||||
|
||||
sysdsk===0
|
||||
|
||||
; No. of various devices
|
||||
nrk==0 ; RK11
|
||||
nrx==1 ; RX11
|
||||
nrl==0 ; RL11
|
||||
nrp==0 ; RP11
|
||||
ncr==0 ; CR11
|
||||
nlp==1 ; LPT
|
||||
ndp==0 ; DP11
|
||||
ndu==0 ; DU11
|
||||
|
||||
; Maximum no. of various terminal interfaces
|
||||
ndz==0 ; DZ11
|
||||
nkl==1 ; KL11, DL11-A,-B
|
||||
ndl==0 ; DL11-C,-D,-E
|
||||
ndc==0 ; DC11
|
||||
|
||||
; Various options
|
||||
pfail===0 ; no power fail code
|
||||
|
||||
>
|
||||
|
||||
.sbttl Configuration calculations
|
||||
|
||||
; Floating vector address calculation
|
||||
|
||||
ifSAO <
|
||||
dpv==0 ; no DP11
|
||||
dzv==0 ; no DZ11
|
||||
klv==300 ; DLV11-J first vector interrupt address
|
||||
dlv==330 ; DLV11s from here on
|
||||
duv==350 ; DUV11
|
||||
>
|
||||
ifMIT <
|
||||
dpv==300 ; DP11
|
||||
klv==0 ; no KL11, DL11-A,-B
|
||||
dlv==310 ; DL11-C,-D,-E
|
||||
dzv==350 ; DZ11
|
||||
duv==360 ; DU11
|
||||
>
|
||||
|
||||
; Floating address calculation
|
||||
|
||||
ifSAO <
|
||||
duaddr==160010 ; address of 1st DU11
|
||||
dzaddr==0 ; no DZ11
|
||||
>
|
||||
ifMIT <
|
||||
duaddr==160010 ; address of 1st DU11
|
||||
dzaddr==160020 ; address of 1st DZ11
|
||||
>
|
||||
|
||||
.sbttl Register definitons
|
||||
|
||||
|
||||
r0=%0
|
||||
r1=%1
|
||||
r2=%2
|
||||
r3=%3
|
||||
r4=%4
|
||||
r5=%5
|
||||
sp=%6
|
||||
pc=%7
|
||||
|
||||
.xcref r0,r1,r2,r3,r4,r5,sp,pc
|
||||
|
||||
; Assume a switch register for most cpus, none for 11/03 and ask for 11/34.
|
||||
.if ndf havswr
|
||||
.iif eq pdp11-03, havswr===0
|
||||
.iif eq pdp11-34, setf ^"Does your 11/34 have the real programmer's console?",havswr
|
||||
.endc
|
||||
|
||||
.iif eq pdp11-44, havswr===1 ; PDP11/44 has a switch register!!!
|
||||
|
||||
.iif ndf havswr, havswr===1
|
||||
|
||||
.if ne havswr
|
||||
swr==177570 ; switch register
|
||||
.endc
|
||||
|
||||
.lif ne pdp11-03
|
||||
ps==177776 ; processor status word
|
||||
|
||||
.if ndf memman
|
||||
.iif eq <pdp11-10>*<pdp11-20>, memman===0
|
||||
.ielse memman===1
|
||||
.endc
|
||||
|
||||
.if ndf eis
|
||||
.iif eq <pdp11-10>*<pdp11-20>, eis===0
|
||||
.ielse eis===1
|
||||
.endc
|
||||
|
||||
pr0==000 ; processor priority definitions
|
||||
pr1==040
|
||||
pr2==100
|
||||
pr3==140
|
||||
pr4==200
|
||||
pr5==240
|
||||
pr6==300
|
||||
pr7==340
|
||||
|
||||
.lif ne pdp11-03
|
||||
lks==177546 ; line clock
|
||||
|
||||
tks==177560 ; console tty registers
|
||||
tkb==177562
|
||||
tps==177564
|
||||
tpb==177566
|
||||
|
||||
.if ne nrk
|
||||
rkdsr==177400 ; RK11 disk registers
|
||||
rkerr==177402
|
||||
rkcsr==177404
|
||||
rkwcr==177406
|
||||
rkbar==177410
|
||||
rkdar==177412
|
||||
.endc
|
||||
|
||||
.if ne nrl
|
||||
rlcsr==174400 ; RL11 disk registers
|
||||
rlbar==174402
|
||||
rldar==174404
|
||||
rlmpr==174406
|
||||
.endc
|
||||
|
||||
.if ne nrp
|
||||
rpcou1==176700
|
||||
rpcou2==176702
|
||||
rpcou3==176704
|
||||
rpcou4==176706
|
||||
rpdsr==176710
|
||||
rperr==176712
|
||||
rpcsr==176714
|
||||
rpwcr==176716
|
||||
rpbar==176720
|
||||
rpcar==176722
|
||||
rpdar==176724
|
||||
rpm1r==176726
|
||||
rpm2r==176730
|
||||
rpm3r==176732
|
||||
rpsucr==176734
|
||||
rpsilo==176736
|
||||
.endc
|
||||
|
||||
.if ne nrx
|
||||
rxcs==177170 ; floppy disk control/status register
|
||||
rxdb==177172 ; floppy disk data buffer register
|
||||
.endc
|
||||
|
||||
.if ne nlp
|
||||
lps==177514
|
||||
lpb==177516
|
||||
lvs==177510
|
||||
lvb==177512
|
||||
.endc
|
||||
|
||||
.sbttl Instruction macros
|
||||
|
||||
.if ne pdp11-03
|
||||
.if ne pdp11-34
|
||||
|
||||
; MTPS and MFPS macros simulate PS intructions on 11/03 (LSI)
|
||||
; and 11/34 processors.
|
||||
.macro mtps src
|
||||
movb src,@#ps
|
||||
.endm
|
||||
|
||||
.macro mfps dst
|
||||
movb @#ps,dst
|
||||
.endm
|
||||
|
||||
.endc
|
||||
.endc
|
||||
|
||||
.if ne pdp11-44
|
||||
.if ne pdp11-45
|
||||
.if ne pdp11-70
|
||||
|
||||
; SPL macro changes the the priority to its argument. It
|
||||
; (unfortunately) does this with a MOV, thus clobbering
|
||||
; the condition codes and such.
|
||||
.macro spl n
|
||||
.iif ne n, mtps #n*40
|
||||
.else
|
||||
.iif eq pdp11-03, mtps #0
|
||||
.ielse clrb @#ps
|
||||
.endc
|
||||
.endm
|
||||
|
||||
.endc
|
||||
.endc
|
||||
.endc
|
||||
|
||||
|
||||
.if eq <pdp11-10>*<pdp11-20>
|
||||
|
||||
; SOB macro expands into code which performs identically to
|
||||
; the SOB instruction found on more powerfull 11 processors
|
||||
.macro sob r,addr
|
||||
dec r
|
||||
bne addr
|
||||
.endm
|
||||
|
||||
; RTT macro expands into a RTI. This is so RTTs can be used in
|
||||
; places where they would be called for on 11/40s, 11/45s etc.
|
||||
.macro rtt
|
||||
rti
|
||||
.endm
|
||||
|
||||
|
||||
; XOR macro simulates XOR instruction on 11/45.
|
||||
; Caution: this macro is not intended to work with
|
||||
; (Rn)+, -(Rn) or (SP) destinations.
|
||||
.macro xor r,d
|
||||
mov r,-(sp)
|
||||
bic d,(sp)
|
||||
bic r,d
|
||||
bis (sp)+,d
|
||||
.endm
|
||||
|
||||
|
||||
; SXT macro performs sign extend as on PDP11/45.
|
||||
.macro sxt d
|
||||
if mi,<
|
||||
mov #-1,d
|
||||
>
|
||||
else <
|
||||
clr d
|
||||
>
|
||||
.endm
|
||||
|
||||
.endc ; eq <pdp11-10>*<pdp11-20>
|
||||
|
||||
.if eq eis
|
||||
; ASH macro generates a series of ASR or ASL instructions to
|
||||
; simulate the 11/45 ASH instruction.
|
||||
.macro ash src,r
|
||||
.ntype %.m,r
|
||||
.iif ne %.m&70, .error ASH dst must be register
|
||||
.ntype %.m,src
|
||||
.iif ne %.m-27, .error ASH macro must have constant shift
|
||||
%.m===0'src
|
||||
.if ge %.m
|
||||
.rept %.m
|
||||
asl r
|
||||
.endr
|
||||
.iff
|
||||
.rept -%.m
|
||||
asr r
|
||||
.endr
|
||||
.endc
|
||||
.endm
|
||||
|
||||
|
||||
; MUL macro generates call to either MUL1 or MUL2 depending upon
|
||||
; whether register destination is even or odd. Simulates 11/45 MUL.
|
||||
.macro mul src,r
|
||||
.ntype %.m,r
|
||||
.iif ne %.m&70, .error MUL dst must be register
|
||||
push src,r
|
||||
.iif ne %.m&1, jsr r5,mul1
|
||||
.ielse jsr r5,mul2
|
||||
pop r
|
||||
.iif eq %.m&1, pop r+1
|
||||
.endm
|
||||
|
||||
|
||||
; DIV macro generates call to DIV2 to simulate 11/45 DIV instruction.
|
||||
.macro div src,r
|
||||
.ntype %.m,r
|
||||
.iif ne %.m&70, .error DIV dst must be register
|
||||
push r,r+1,src
|
||||
jsr r5,div2
|
||||
pop r+1,r
|
||||
.endm
|
||||
|
||||
.endc ; eq eis
|
||||
|
||||
.sbttl Random macros
|
||||
|
||||
.macro push a0,a1,a2,a3,a4,a5,a6,a7
|
||||
.irp d,<a0,a1,a2,a3,a4,a5,a6,a7>
|
||||
.if idn d,#0
|
||||
clr -(sp)
|
||||
.iff
|
||||
.lif nb d
|
||||
mov d,-(sp)
|
||||
.endc
|
||||
.endm
|
||||
.endm push
|
||||
|
||||
|
||||
.macro pop a0,a1,a2,a3,a4,a5,a6,a7
|
||||
.irp d,<a0,a1,a2,a3,a4,a5,a6,a7>
|
||||
.if idn d,*
|
||||
tst (sp)+
|
||||
.iff
|
||||
.lif nb d
|
||||
mov (sp)+,d
|
||||
.endc
|
||||
.endm
|
||||
.endm pop
|
||||
|
||||
|
||||
.macro typval text
|
||||
.print ïtextŠ
|
||||
.endm
|
||||
|
||||
|
||||
; .EXIT bootloads BOOT.
|
||||
.macro .exit
|
||||
ifMIT < reset
|
||||
mov #174400,r0
|
||||
tstb (r0)
|
||||
bpl .-2
|
||||
mov #13,4(r0)
|
||||
mov #4,(r0)
|
||||
tstb (r0)
|
||||
bpl .-2
|
||||
mov #77601,4(r0)
|
||||
mov #6,(r0)
|
||||
tstb (r0)
|
||||
bpl .-2
|
||||
mov #177400,6(r0)
|
||||
mov #0,4(r0)
|
||||
mov #0,2(r0)
|
||||
mov #14,(r0)
|
||||
tstb (r0)
|
||||
bpl .-2
|
||||
clr pc
|
||||
>
|
||||
ifSAO <
|
||||
jmp @#173000
|
||||
>
|
||||
ifOTHER < ; all other systems, jump to hardware boot
|
||||
.iif ndf asmrt1, asmrt1===0 ; if we don't know what asmrt1 is default to 0
|
||||
.if eq asmrt1
|
||||
jmp @#173000
|
||||
.iff
|
||||
mov pc,r0 ; don't do an HRESET, we can be restarted
|
||||
emt 350 ; return to rt-11
|
||||
>
|
||||
.endm
|
||||
|
||||
|
||||
; DSECT defines a dummy section, used to define symbols
|
||||
; that are offsets from a register (or some other variable).
|
||||
; An optional second argument is set to length of structure.
|
||||
; Example of use:
|
||||
; DSECT < PCBNEXT: 0 ;PCBNEXT=0
|
||||
; PCBLAST: 0 ;PCBLAST=2
|
||||
; PCBFOOO: 0
|
||||
; >
|
||||
.macro dsect sect,len
|
||||
.if p1 ; define symbols only on pass 1
|
||||
%.dtmp===.
|
||||
.=0
|
||||
sect
|
||||
.iif nb len, len==.
|
||||
.=%.dtmp
|
||||
.endc
|
||||
.endm
|
||||
|
||||
; Text accumulation macros. TXTINT creates a text segment of the
|
||||
; specified name. APPEND appends text to that segment. To insert the
|
||||
; accumulated text into the assembly merely use the segment's name.
|
||||
|
||||
.macro txtint name
|
||||
.macro name op1,op2,op3
|
||||
op1'op2
|
||||
op3
|
||||
.endm name
|
||||
.endm txtint
|
||||
|
||||
.macro append name,newcft
|
||||
.nlist
|
||||
name ^|.macro name op1,op2,op3
|
||||
op1|,^|newcft'op2
|
||||
op3|,.endm
|
||||
.list
|
||||
.endm append
|
||||
|
||||
.sbttl Flow of control macros
|
||||
|
||||
; IF macro: Generates code that executes the if clause
|
||||
; if the specified conditon is true, the else clause if
|
||||
; it is false. The else clause is not required. Example:
|
||||
; if eq,<
|
||||
; mov r0,r1
|
||||
; mov (r1)+,r2
|
||||
; >
|
||||
; else <
|
||||
; jsr pc,foo
|
||||
; >
|
||||
|
||||
.macro if cond,code
|
||||
.nlist
|
||||
gncnt===gncnt+1
|
||||
.irp foo,\gncnt
|
||||
.iif p1, .word 0
|
||||
.else
|
||||
%.itmp===<g'foo-<.+2>>/2
|
||||
.iif gt %.itmp-377, .error Branch out of range
|
||||
.iif lt %.itmp+377, .error Branch out of range
|
||||
.iif eq <b'cond>&400, <b'cond>+%.itmp+400
|
||||
.ielse <b'cond>+%.itmp-400
|
||||
.endc
|
||||
code
|
||||
g'foo===.
|
||||
ifcnt===foo
|
||||
.endm .irp
|
||||
.list
|
||||
.endm if
|
||||
|
||||
.macro else code
|
||||
gncnt===gncnt+1
|
||||
.irp foo,\ifcnt
|
||||
.irp bar,\gncnt
|
||||
br g'bar
|
||||
g'foo===.
|
||||
code
|
||||
g'bar===.
|
||||
.endm
|
||||
.endm
|
||||
.endm else
|
||||
|
||||
gncnt===777 ; gensym count
|
||||
|
||||
|
||||
; LOOP macro allows loops without labels. Use RPTL and EXITL
|
||||
; to repeat loop and exit loop. Both take branch condition arguments.
|
||||
; If condition arg is null, then BR is used, i.e. unconditional.
|
||||
; End of CODE falls out of loop unless specific RPTL is used.
|
||||
|
||||
; Example of LOOP macro:
|
||||
; loop < cmpb r0,(r1)+ ; found char yet?
|
||||
; exitl eq ; exit loop on equal
|
||||
; inc r2 ; not found
|
||||
; cmp r2,r5 ; too many?
|
||||
; rptl lt ; no, keep going
|
||||
; jmp error ; too many
|
||||
; >
|
||||
; ; EXITL comes here
|
||||
|
||||
; LOOP defines two lables around the code argument,
|
||||
; the first for looping back via the RPTL macro, the
|
||||
; second for exiting the loop via the EXITL macro.
|
||||
; Labels are of the form %Ln or %Xn where n signifies
|
||||
; that this is the nth use of the LOOP macro. %Yv
|
||||
; gives the loop number of the v'th level of nesting.
|
||||
; Up to 7 levels of nesting are allowed.
|
||||
%level===0
|
||||
%loopn===0
|
||||
.macro loop code
|
||||
%loopn===%loopn+1
|
||||
.if gt %loopn-7777
|
||||
.error Too many loops (maximum of 4095)
|
||||
.mexit
|
||||
.endc
|
||||
%level===%level+1
|
||||
.if gt %level-7
|
||||
.error Loop depth exceeds 7
|
||||
.mexit
|
||||
.endc
|
||||
.irp n,\%level
|
||||
%y'n===%loopn
|
||||
.endm
|
||||
.irp n,\%loopn
|
||||
%l'n===. ; loop back to here
|
||||
code
|
||||
%x'n===. ; exit to here
|
||||
.endm
|
||||
%level===%level-1
|
||||
.endm loop
|
||||
|
||||
.macro rptl cond
|
||||
.if eq %level
|
||||
.error RPTL not inside LOOP
|
||||
.mexit
|
||||
.endc
|
||||
.irp n1,\%level
|
||||
.irp n2,\%y'n1
|
||||
.iif b cond, br %l'n2
|
||||
.ielse b'cond %l'n2
|
||||
.endm
|
||||
.endm
|
||||
.endm rptl
|
||||
|
||||
; SORL expands into a SOB instruction back to the last LOOP
|
||||
; point. SORL takes one arg, a register to use with the SOB
|
||||
; instruction.
|
||||
.macro sorl r
|
||||
.if eq %level
|
||||
.error SORL not inside LOOP
|
||||
.mexit
|
||||
.endc
|
||||
.irp n1,\%level
|
||||
.irp n2,\%y'n1
|
||||
sob r,%l'n2
|
||||
.endm
|
||||
.endm
|
||||
.endm sorl
|
||||
|
||||
|
||||
.macro exitl cond
|
||||
.if eq %level
|
||||
.error EXITL not inside LOOP
|
||||
.mexit
|
||||
.endc
|
||||
.irp n1,\%level
|
||||
.irp n2,\%y'n1
|
||||
.iif b cond, br %x'n2
|
||||
.ielse b'cond %x'n2
|
||||
.endm
|
||||
.endm
|
||||
.endm exitl
|
||||
|
||||
.sbttl Literal macros
|
||||
|
||||
; Literal macros -- deposit literals into contants area which
|
||||
; will have length %.clen.
|
||||
.iif p1, %.clen===0 ; start off length 0
|
||||
|
||||
|
||||
; .LITRL macro will store a literal -- a block of code that
|
||||
; is the first argument to .LITRL. The literal is stored in
|
||||
; the constant area at %.CONSTA, and will be forced to an even
|
||||
; address. If there is no second argument the pointer to the
|
||||
; literal will be stored inline; if there is a second arg the
|
||||
; second arg will be set to the literal's pointer value.
|
||||
; For example:
|
||||
; The following stores a pointer to a string of bytes (0,1,2...)
|
||||
; at location foo:
|
||||
; foo: .litrl ^"
|
||||
; .byte 0,1,2,3,4,5"
|
||||
; The following sets foo to a pointer to a block of words and
|
||||
; bytes (0,1,2,...):
|
||||
; .litrl ^"
|
||||
; .word 0,1,2
|
||||
; .byte 3,4,5",foo
|
||||
|
||||
.macro .litrl litarg,litptr
|
||||
.nlist
|
||||
.if p1
|
||||
%.ctmp===.
|
||||
.even
|
||||
litarg ; stick literal here now so can find its length
|
||||
%.clen===<<%.clen+1>&177776>+.-<<%.ctmp+1>&177776>
|
||||
.=%.ctmp
|
||||
.iff
|
||||
%.ctmp===.
|
||||
.=%.consta
|
||||
.even
|
||||
%.cadr===.
|
||||
litarg ; actual storage of literal
|
||||
%.consta===.
|
||||
.=%.ctmp
|
||||
.endc
|
||||
.if b litptr
|
||||
.even
|
||||
.word %.cadr-. ; deposit ptr to literal
|
||||
.iff
|
||||
litptr==%.cadr ; set ptr to pt to literal
|
||||
.endc
|
||||
.list
|
||||
.endm
|
||||
|
||||
|
||||
; The .STRING macro stores an asciz string in the constants area,
|
||||
; at %.CONSTA, and either stores the pointer to that string
|
||||
; at the .STRING, or sets a value (if there is a second arg).
|
||||
; For example, the following stores, at FOO, a relative pointer
|
||||
; to the asciz string "hello":
|
||||
; FOO: .string ^"hello"
|
||||
; The following sets foo to a pointer to asciz string "hello":
|
||||
; .string ^"hello",foo
|
||||
|
||||
.macro .string text,strptr
|
||||
.nlist
|
||||
.if p1
|
||||
%.clen===%.clen+.length ^ïtext¬+1
|
||||
.iff
|
||||
%.ctmp===.
|
||||
.=%.consta
|
||||
%.cadr===.
|
||||
.asciz ïtextŠ
|
||||
%.consta===.
|
||||
.=%.ctmp
|
||||
.endc
|
||||
.if b strptr
|
||||
.word %.cadr-.
|
||||
.iff
|
||||
strptr==%.cadr
|
||||
.endc
|
||||
.list
|
||||
.endm
|
||||
|
||||
; CONSTANTS causes space to be allocated for the constants
|
||||
; generated by .LITRL and .STRING
|
||||
|
||||
.macro constants
|
||||
.nlist
|
||||
.even
|
||||
%.consta===. ; constants will be assembled here.
|
||||
.=.+%.clen ; reserve space for them.
|
||||
.even
|
||||
|
||||
.if p1
|
||||
.if gt %.clen
|
||||
.print "
|
||||
Constants area "
|
||||
typval \%.clen
|
||||
.print " bytes,
|
||||
From "
|
||||
typval \%.consta
|
||||
.print " to "
|
||||
typval \.-1
|
||||
.print " inclusive.
|
||||
"
|
||||
.endc
|
||||
.endc
|
||||
.list
|
||||
.endm constants
|
||||
3741
src/pdp11/rug.526
Normal file
3741
src/pdp11/rug.526
Normal file
File diff suppressed because it is too large
Load Diff
411
src/pdp11/sadisk.28
Normal file
411
src/pdp11/sadisk.28
Normal file
@@ -0,0 +1,411 @@
|
||||
; -*-PALX-*-
|
||||
.sbttl Disk i/o
|
||||
|
||||
.iif ndf asmpr, asmpr==0 ; assume we can't print if we don't know how
|
||||
|
||||
.if eq sysdsk-drk
|
||||
lblk==512. ; no. of bytes per sector
|
||||
nsecto==12. ; no. of sectors per track
|
||||
ntrack==406. ; no. of tracks per disk
|
||||
.endc
|
||||
.if eq sysdsk-drl
|
||||
lblk==256. ; no. of bytes per sector
|
||||
nsecto==40. ; no. of sectors per track
|
||||
ntrack==256. ; no. of tracks per disk
|
||||
.endc
|
||||
.if ne nrx
|
||||
lblk==128. ; no. of bytes per sector
|
||||
nsecto==26. ; no. of sectors per track
|
||||
ntrack==77. ; no. of tracks per disk
|
||||
.endc
|
||||
|
||||
|
||||
; DOPENR sets up for reading from disk.
|
||||
dopenr: mov 2(sp),dblock ; set block no. to first block to read
|
||||
clr dbufc ; no characters in buffer yet
|
||||
pop (sp) ; remove arg from stack
|
||||
rts r5
|
||||
|
||||
|
||||
; DOPENW sets up for writing to disk.
|
||||
dopenw: mov 2(sp),dblock ; set block no. to first block to write
|
||||
mov #lblk,dbufc ; room for 512 (or 256) characters in block
|
||||
mov pc,-(sp) ; set DBUFP to DBUF
|
||||
add #dbuf-.,(sp) ; ...
|
||||
mov (sp)+,dbufp ; ...
|
||||
pop (sp) ; remove arg from stack
|
||||
rts r5
|
||||
|
||||
|
||||
; DCLSW finishes up writing to the disk.
|
||||
dclsw: cmp dbufc,#lblk ; something in buffer?
|
||||
if ne,<
|
||||
loop < clrb @dbufp ; clear remainder of buffer
|
||||
inc dbufp
|
||||
dec dbufc
|
||||
rptl ne
|
||||
>
|
||||
push dblock ; DKWRIT arg: block no.
|
||||
jsr r5,dkwrit ; write out block
|
||||
>
|
||||
rts r5
|
||||
|
||||
|
||||
; DGETW reads a word from the disk.
|
||||
dgetw: push (sp) ; make room for return val
|
||||
jsr r5,dgetb ; read low byte
|
||||
movb (sp)+,2(sp)
|
||||
jsr r5,dgetb ; read high byte
|
||||
movb (sp)+,3(sp)
|
||||
rts r5
|
||||
|
||||
; DGETB reads a byte from the disk.
|
||||
dgetb: push (sp) ; make room for return val
|
||||
dec dbufc ; characters left to read in this block?
|
||||
if mi,< ; none left, read next block
|
||||
push dblock ; DKREAD args: block no.
|
||||
jsr r5,dkread ; read block
|
||||
inc dblock ; increment block no.
|
||||
mov #lblk-1,dbufc ; 511 (or 255) bytes left to read
|
||||
mov pc,-(sp) ; set DBUFP to DBUF
|
||||
add #dbuf-.,(sp) ; ...
|
||||
mov (sp)+,dbufp ; ...
|
||||
>
|
||||
clr 2(sp) ; so high byte will be zero
|
||||
movb @dbufp,2(sp) ; get character
|
||||
inc dbufp ; move ptr to next
|
||||
rts r5
|
||||
|
||||
; DPUTW writes a word to the disk.
|
||||
dputw: push 2(sp) ; DPUTB arg: byte
|
||||
jsr r5,dputb ; write low byte
|
||||
swab 2(sp) ; switch bytes and fall through
|
||||
; to write high byte
|
||||
|
||||
; DPUTB writes one byte to the disk.
|
||||
dputb: movb 2(sp),@dbufp ; store character in buffer
|
||||
inc dbufp ; move ptr to next character slot
|
||||
dec dbufc ; buffer filled?
|
||||
if eq,< ; yes, write it out
|
||||
push dblock ; DKWRIT args: block no.
|
||||
jsr r5,dkwrit ; write out this block
|
||||
inc dblock ; increment block no.
|
||||
mov #lblk,dbufc ; room for 512 (or 256) more characters
|
||||
sub #lblk,dbufp ; set DBUFP to DBUF
|
||||
>
|
||||
pop (sp) ; remove arg from stack
|
||||
rts r5
|
||||
|
||||
.if eq sysdsk-drk
|
||||
dkread: push (sp)
|
||||
mov #5,2(sp)
|
||||
br rkrw
|
||||
|
||||
dkwrit: push (sp)
|
||||
mov #3,2(sp)
|
||||
br rkrw
|
||||
.endc
|
||||
.if eq sysdsk-drl
|
||||
dkread: push (sp)
|
||||
mov #14,2(sp)
|
||||
br rlrw
|
||||
|
||||
dkwrit: push (sp)
|
||||
mov #12,2(sp)
|
||||
br rlrw
|
||||
.endc
|
||||
.if ne nrx
|
||||
dkread: br rxread
|
||||
|
||||
dkwrit: br rxwrit
|
||||
.endc
|
||||
|
||||
|
||||
|
||||
.sbttl RL11 read/write
|
||||
; RLRW
|
||||
;
|
||||
; ARGS: VALS:
|
||||
; SP ->op code (none)
|
||||
; block number
|
||||
|
||||
.if eq sysdsk-drl
|
||||
rlrw: jsr r5,save6 ; save registers
|
||||
mov 20(sp),r1 ; get block number
|
||||
clr r0 ; clear track counter
|
||||
mov #40.,r2 ; there are 40. blocks per track
|
||||
div r2,r0 ; get number of tracks in r0
|
||||
ash #6,r0 ; mov into place for Cylinder address
|
||||
bis r1,r0 ; merge sector (in r1) with track
|
||||
mov r0,20(sp) ; save converted disk address
|
||||
mov pc,r1 ; pointer to DBUF
|
||||
add #dbuf-.,r1 ; ...
|
||||
mov #7,r4 ; number of times to try recoverable errors
|
||||
;
|
||||
; reset the drive
|
||||
;
|
||||
|
||||
loop < mov #rlcsr,r5 ; get address of CSR
|
||||
mov #13,4(r5) ; do a get status/reset drive
|
||||
mov #4,(r5) ; perform function
|
||||
loop < tstb (r5) ; has drive finished yet??
|
||||
rptl pl ; no yet
|
||||
>
|
||||
tst (r5) ; check for errors
|
||||
bmi rlerr ; go handle them
|
||||
jsr pc,rlseek ; seek to the right track
|
||||
|
||||
; Now we can finally do the read/write operation!!!!!!!!!
|
||||
|
||||
mov #-<lblk/2>,6(r5) ; set word count
|
||||
mov r1,2(r5) ; set bus address
|
||||
mov 20(sp),4(r5) ; set disk address
|
||||
mov 16(sp),(r5) ; perform function
|
||||
loop < tstb (r5) ; is the controller finished???
|
||||
rptl pl ; not yet if plus
|
||||
>
|
||||
tst (r5) ; test for errors
|
||||
exitl pl ; no error, we're through
|
||||
bit #140000,(r5) ; see if a disk error
|
||||
bne rlerr ; check out disk errors
|
||||
sorl r4 ; try a few more times
|
||||
br rlerr
|
||||
>
|
||||
jsr r5,rest6 ; restore registers
|
||||
pop (sp),(sp) ; remove args from stack
|
||||
rts r5
|
||||
|
||||
; perform a seek on the disk to the right track
|
||||
|
||||
rlseek: push r0,r1,r2 ; save registers
|
||||
mov #10,(r5) ; execute read headers function
|
||||
loop < tstb (r5) ; has drive finished yet????
|
||||
rptl pl ; not yet
|
||||
>
|
||||
mov 6(r5),r0 ; get current disk address
|
||||
mov 20+10(sp),r1 ; get desired disk address
|
||||
bic #77,r1 ; clear sector bits
|
||||
bic #177,r0 ; clear sector and surface bits
|
||||
mov r1,r2 ; copy desired disk address
|
||||
bic #177677,r2 ; isolate surface bit
|
||||
ash #-2,r2 ; position it for difference word in seek
|
||||
bic #100,r1 ; remove surface bit
|
||||
sub r1,r0 ; find difference word for seek operation
|
||||
bcc 1$ ; if CC actual >= desired position
|
||||
neg r0 ; make positive difference
|
||||
bis #4,r0 ; set bit to indicate move towards disk center
|
||||
1$: inc r0 ; set marker bit
|
||||
bis r2,r0 ; merge in surface bit
|
||||
mov r0,4(r5) ; put difference word into RLDAR
|
||||
mov #6,(r5) ; perform a seek function
|
||||
loop < tstb (r5) ; has controller finished
|
||||
rptl pl ; not yet
|
||||
>
|
||||
pop r2,r1,r0 ; restore registers
|
||||
rts pc
|
||||
|
||||
; perform error checking on the disk drive
|
||||
|
||||
rlerr:
|
||||
.if ne asmpr
|
||||
print ^"
|
||||
RL01 disk error -- operation aborted
|
||||
"
|
||||
.endc
|
||||
jmp dskerr
|
||||
|
||||
.endc ;eq sysdsk-drl
|
||||
|
||||
|
||||
|
||||
; RKRW performs disk transfers of one sector. It takes two args:
|
||||
; the block no. and operation code (3 for write, 5 for read).
|
||||
|
||||
; ARGS: VALS:
|
||||
; SP -> op code (none)
|
||||
; block no.
|
||||
|
||||
.if eq sysdsk-drk
|
||||
rkrw: jsr r5,save6 ; save regs
|
||||
clr r0 ; divide block no. by 12
|
||||
mov 20(sp),r1 ; ...
|
||||
div #12.,r0 ; ...
|
||||
ash #4,r0 ; multiply quotient by 16
|
||||
add r1,r0 ; add remainder to get DAR
|
||||
bis rknum,r0 ; put in disk no.
|
||||
mov pc,r1 ; ptr to DBUF
|
||||
add #dbuf-.,r1 ; ...
|
||||
mov #7,r5 ; no. of times to retry recoverable errors
|
||||
loop < mov #rkcsr,r4 ; ptr to RKCSR
|
||||
mov #1,(r4) ; controller reset
|
||||
loop < tstb (r4) ; wait for done
|
||||
rptl pl
|
||||
>
|
||||
mov #rkdar+2,r4 ; ptr to RKDAR + 2
|
||||
mov r0,-(r4) ; set RKDAR
|
||||
mov r1,-(r4) ; set RKBAR
|
||||
mov #-<lblk/2>,-(r4) ; set RKWCR
|
||||
mov 16(sp),-(r4) ; set RKCSR, i.e. perform operation
|
||||
loop < tstb (r4) ; wait for done
|
||||
rptl pl
|
||||
>
|
||||
tst (r4) ; errors?
|
||||
exitl pl
|
||||
bit #166340,-(r4) ; recoverable error?
|
||||
if eq,<
|
||||
sorl r5 ; yes, try a few times
|
||||
>
|
||||
.if ne asmpr
|
||||
print ^"
|
||||
Disk Error -- operation aborted
|
||||
"
|
||||
.endc
|
||||
jmp dskerr
|
||||
>
|
||||
jsr r5,rest6 ; restore regs
|
||||
pop (sp),(sp) ; remove args from stack
|
||||
rts r5
|
||||
|
||||
rknum: .word 0 ; Using disk number zero because
|
||||
; disk no. 1 (fixed) is not formatted
|
||||
.endc
|
||||
|
||||
.sbttl RX11 read/write
|
||||
|
||||
.if ne nrx
|
||||
; RXREAD
|
||||
|
||||
; ARGS: VALS:
|
||||
; SP -> block no. (none)
|
||||
|
||||
rxread: push r0,r1,r2 ; save regs
|
||||
mov #rxcs,r0 ; get bus address of RX11 controller
|
||||
push 10(sp),#7 ; RXRW args: block no., op code
|
||||
bis rxnum,(sp) ; yes, set unit select in op code
|
||||
jsr r5,rxrw ; initiate read
|
||||
loop < bit #40,(r0) ; wait for Done
|
||||
rptl eq
|
||||
>
|
||||
tst (r0) ; Error?
|
||||
bmi rxer
|
||||
mov #10,r2 ; no. of times to retry parity errors in Empty
|
||||
loop < mov #3,(r0) ; send Empty command
|
||||
mov pc,r1 ; ptr to buffer
|
||||
add #dbuf-.,r1 ; ...
|
||||
loop < bitb #240,(r0) ; test Transfer Request and Done bits
|
||||
rptl eq ; wait for one to set
|
||||
exitl pl ; Done?
|
||||
movb 2(r0),(r1)+ ; no, Transfer Request, copy data byte
|
||||
rptl
|
||||
>
|
||||
tst (r0) ; Error (parity error in transfer from buffer)?
|
||||
exitl pl
|
||||
sorl r2 ; retry Empty operation
|
||||
br rxer
|
||||
>
|
||||
pop r2,r1,r0,(sp) ; restore regs, remove arg from stack
|
||||
rts r5
|
||||
|
||||
|
||||
; RXWRIT writes a block on the floppy.
|
||||
|
||||
; ARGS: VALS:
|
||||
; SP -> block no. (none)
|
||||
|
||||
rxwrit: push r0,r1,r2 ; save regs
|
||||
mov #rxcs,r0 ; get bus address of RX11 controller
|
||||
mov #10,r2 ; no. of times to retry parity errors in Fill
|
||||
loop < mov #1,(r0) ; send Fill command
|
||||
mov pc,r1 ; get ptr to buffer
|
||||
add #dbuf-.,r1 ; ...
|
||||
loop < bitb #240,(r0) ; test Transfer Request and Done bits
|
||||
rptl eq
|
||||
exitl pl ; Done?
|
||||
movb (r1)+,2(r0) ; no, Transfer Request, load data byte
|
||||
rptl
|
||||
>
|
||||
tst (r0) ; Error (parity error in transfer to buffer)?
|
||||
exitl pl
|
||||
sorl r3 ; retry Fill
|
||||
br rxer
|
||||
>
|
||||
push 10(sp),#5 ; RXRW args: block no., op code
|
||||
bis rxnum,(sp) ; yes, set unit select in op code
|
||||
jsr r5,rxrw ; initiate write
|
||||
loop < bit #40,(r0) ; wait for Done
|
||||
rptl eq
|
||||
>
|
||||
tst (r0) ; Error?
|
||||
bmi rxer
|
||||
pop r2,r1,r0,(sp) ; restore regs, remove arg from stack
|
||||
rts r5
|
||||
|
||||
|
||||
|
||||
; RXRW issues a read or write command to the RX11. If writing, the RX11
|
||||
; buffer should already be filled with the stuff to be written. If reading
|
||||
; the RX11 buffer should be emptied afterward. RXRW does not wait for the
|
||||
; read or write operation to complete.
|
||||
|
||||
; ARGS: VALS:
|
||||
; SP -> op code (none)
|
||||
; block no.
|
||||
|
||||
rxrw: push r2,r3 ; save regs
|
||||
clr r2 ; divide block no. by 26 to get track
|
||||
mov 10(sp),r3 ; and sector addresses
|
||||
div #nsecto,r2 ; perform the division
|
||||
asl r3
|
||||
cmp r3,#nsecto
|
||||
if his,<
|
||||
sub #nsecto-1,r3
|
||||
>
|
||||
inc r3 ; make sector address one based
|
||||
loop < bit #40,(r0) ; wait for Done
|
||||
rptl eq
|
||||
>
|
||||
mov 6(sp),(r0) ; send read or write command
|
||||
loop < tstb (r0) ; wait for Transfer Request
|
||||
rptl pl
|
||||
>
|
||||
mov r3,2(r0) ; send Sector address
|
||||
loop < tstb (r0) ; wait for Transfer Request
|
||||
rptl pl
|
||||
>
|
||||
mov r2,2(r0) ; send Track address
|
||||
pop r3,r2,(sp),(sp) ; restore regs, remove args from stack
|
||||
rts r5
|
||||
|
||||
rxer: mov @#rxdb,r0
|
||||
bit #1,r0
|
||||
if ne,<
|
||||
.if ne asmpr
|
||||
print ^"
|
||||
CRC error detected reading diskette."
|
||||
.endc
|
||||
>
|
||||
bit #2,r0
|
||||
if ne,<
|
||||
.if ne asmpr
|
||||
print ^"
|
||||
Parity error detected on command or address data being transfered to RX01."
|
||||
.endc
|
||||
>
|
||||
.if ne asmpr
|
||||
jmp dskerr
|
||||
.iff
|
||||
pop r2,r1,r0,(sp)
|
||||
rts r5
|
||||
.endc
|
||||
|
||||
rxnum: .word 0 ; disk no.
|
||||
|
||||
.endc ; ne nrx
|
||||
|
||||
dbuf: .blkb lblk ; disk sector buffer
|
||||
dblock: .word 0 ; block no. for next disk i/o
|
||||
dbufp: .word 0 ; ptr to next byte in disk buffer to read/write
|
||||
dbufc: .word 0 ; read: no. of characters remaining in buffer
|
||||
; write: room left in buffer
|
||||
|
||||
| ||||