mirror of
https://github.com/PDP-10/its.git
synced 2026-03-10 12:48:25 +00:00
RUG - PDP-11 debugger.
This commit is contained in:
4
Makefile
4
Makefile
@@ -25,12 +25,12 @@ SRC = syseng sysen1 sysen2 sysen3 sysnet kshack dragon channa \
|
||||
tensor transl wgd zz graphs lmlib pratt quux scheme gsb ejs mudsys \
|
||||
draw wl taa tj6 budd sharem ucode rvb kldcp math as imsrc gls demo \
|
||||
macsym lmcons dmcg hack hibou agb gt40 rug maeda ms kle aap common \
|
||||
fonts zork 11logo kmp info aplogo bkph bbn
|
||||
fonts zork 11logo kmp info aplogo bkph bbn pdp11 chsncp
|
||||
DOC = info _info_ sysdoc sysnet syshst kshack _teco_ emacs emacs1 c kcc \
|
||||
chprog sail draw wl pc tj6 share _glpr_ _xgpr_ inquir mudman system \
|
||||
xfont maxout ucode moon acount alan channa fonts games graphs humor \
|
||||
kldcp libdoc lisp _mail_ midas quux scheme manual wp chess ms macdoc \
|
||||
aplogo _klfe_
|
||||
aplogo _klfe_ pdp11 chsncp cbf rug
|
||||
BIN = sys2 emacs _teco_ lisp liblsp alan inquir sail comlap c decsys \
|
||||
moon graphs draw datdrw fonts fonts1 fonts2 games macsym maint imlac \
|
||||
_www_ hqm
|
||||
|
||||
@@ -1105,6 +1105,15 @@ expect ":KILL"
|
||||
respond "*" ":midas sys1; ts gtload_syseng; gtload\r"
|
||||
expect ":KILL"
|
||||
|
||||
# RUG, PDP-11 debugger.
|
||||
respond "*" ":cwd pdp11\r"
|
||||
respond "*" ":palx rug\r"
|
||||
respond "?" "2\r"
|
||||
respond "?" "100000\r"
|
||||
respond "?" "1\r"
|
||||
respond "?" "1\r"
|
||||
expect ":KILL"
|
||||
|
||||
# URUG, GT40 debugger.
|
||||
respond "*" ":palx sysbin;_sysen2;urug\r"
|
||||
respond "=YES" "1\r"
|
||||
|
||||
12
doc/cbf/rug.featur
Normal file
12
doc/cbf/rug.featur
Normal file
@@ -0,0 +1,12 @@
|
||||
Rug fixes not mentioned before
|
||||
1) .TTYTYP -1 means glass TTY
|
||||
2) "ab and 'a with lower case chars is no longer spuriously
|
||||
uppercasd
|
||||
3) $" typeout mode now prints low byte high byte, which allow
|
||||
strings to come out right and is consistent with the way
|
||||
typein always was.
|
||||
|
||||
To do:
|
||||
Src Dst opening commands
|
||||
^P
|
||||
$X ?
|
||||
200
doc/cbf/rugord.1
Normal file
200
doc/cbf/rugord.1
Normal file
@@ -0,0 +1,200 @@
|
||||
|
||||
Brief user documentation for Rug.
|
||||
|
||||
The order of things in this document is pretty random. Someday
|
||||
someone should fix it.
|
||||
|
||||
Basically Rug expects a symbolic expression followed by a command
|
||||
which operates on the expression, e.g. "FOO+5=" where "FOO+5" is
|
||||
the symbolic expression and "=" is the command. Commands may be
|
||||
one letter (e.g. "="), one letter following an escape (e.g. "$L"
|
||||
where escape will echo as a dollar sign), or a colon followed by
|
||||
up to six letters (such as ":HELP").
|
||||
|
||||
Symbolic expressions may contain any defined symbol, octal number,
|
||||
or decimal number (digit-string terminated with a period, e.g.
|
||||
"143." whereas "143" without the "." would be octal) connected
|
||||
with the arithmetic operators "+", "-", or space (which is
|
||||
equivalent to "+" for convenience). $Q (Escape Q) is a special
|
||||
symbol whose value is the last quantity that rug typed out.
|
||||
Further, the user can generate ascii or rad50 codes for characters
|
||||
and use these numbers in any symbolic expression: Typing
|
||||
single-quote followed by one letter produces the 16-bit quantity
|
||||
containing the letter in the low byte and zero in the high byte.
|
||||
Typing double-quote followed by two ascii letters will produce the
|
||||
16-bit quantity containing the first letter in the low byte and
|
||||
the second in the high byte. Typing "&" followed by three letters
|
||||
produces the 16-bit rad50 equivalent of the letters.
|
||||
|
||||
If the user types an undefined symbol in an expression, Rug will
|
||||
beep, generally allowing the user to rubout and correct the
|
||||
symbol. When the expression is done an error will usually result
|
||||
(unless the command doesn't care) if there was any undefined
|
||||
symbol within the expression. There is one exception to the
|
||||
beep-rule: if the first symbol in the expression is undefined,
|
||||
then the expression will be terminated immediately, not allowing
|
||||
the user to correct it.
|
||||
|
||||
Many commands will produce different results depending on certain
|
||||
modes that the user can set. Most modes have "temporary" and
|
||||
"permanent" settings: temporary modes act until Rug prompts with a
|
||||
"*". The "*" prompt indicates that all modes have been reset to
|
||||
their permanent settings.
|
||||
|
||||
There are several symbols with predefined values. These are
|
||||
listed below (note that "user" refers to the user program being
|
||||
run, e.g. "user R0" means the programs R0):
|
||||
|
||||
. Contains the last address opened.
|
||||
%0 - %7 Standard register definitions (user regs).
|
||||
.M Mask for searches:
|
||||
.M has the 16-bit mask.
|
||||
.M+1 has the 16-bit low address.
|
||||
.M+2 has the 16-bit hi address.
|
||||
.STBEG Location containing pointer to bottom (low
|
||||
address) of symbol table.
|
||||
.STEND Address of bottom of predefined RUG symbol table.
|
||||
.START Address of RUG's starting address.
|
||||
.MXOFF Initially 200. A value must be within this distance
|
||||
symbol to be printed as that symbol+offset.
|
||||
|
||||
ESCAPE COMMANDS (<arg> is symbolic expression):
|
||||
|
||||
$Q Value of last quantity typed out
|
||||
|
||||
$G Start execution at default start address.
|
||||
<arg>$G Start execution of user program at <arg>.
|
||||
<arg>$$G Set default start addr to <arg> and start execution.
|
||||
|
||||
<arg>$W Search from low-address (.M+1 contents) to high-address
|
||||
(.M+2 contents) for <arg> masked by contents of .M.
|
||||
Each match found will be shown by printing location and
|
||||
contents. Any type-in by user will stop the search.
|
||||
|
||||
<arg>$E Same as W but effective address search. I.e. BR FOO
|
||||
will match an arg of FOO.
|
||||
|
||||
<arg>$B Set a breakpoint at <arg>. (There are 8 breakpoints
|
||||
available. Use :LISTB to see where breakpoints are
|
||||
currently set.)
|
||||
|
||||
<arg>$P Proceed user program after hitting breakpoint. If no
|
||||
<arg>, proceed until hitting any breakpoint. If <arg>
|
||||
then set this breakpoint's count to <arg> and proceed.
|
||||
If a breakpoint has a count, then it will only break
|
||||
after being hit count many times.
|
||||
|
||||
<arg>$U Remove breakpoint at <arg>. If no <arg> then remove
|
||||
all breakpoints.
|
||||
|
||||
$C Set temporary type-out mode "contants", i.e. type
|
||||
contents of open locations as octal numbers.
|
||||
|
||||
$S Set temp type-out mode "symbols", i.e. type open
|
||||
location contents as symbols.
|
||||
|
||||
$I Set temp type-out mode "instructions", i.e. type
|
||||
open location contents as instructions.
|
||||
|
||||
$R Set temp type-out mode "relative addresses", i.e.
|
||||
type addresses as symbolic references, INC FOO.
|
||||
|
||||
$A Set temp type-out mode "absolute addresses", i.e.
|
||||
type addresses as octal numbers, INC 14345.
|
||||
|
||||
$" Set temp word type-out mode to "ascii", i.e. when
|
||||
opening words, type out ascii characters.
|
||||
|
||||
$' Set byte word type-out mode to "ascii", ie. when
|
||||
opening words, type out ascii characters.
|
||||
|
||||
Note that examining a location in Ascii mode that
|
||||
contains control characters will cause them to be
|
||||
shown as the usual ^<char> representation, (or $ for
|
||||
escape) except that Space, CR, LF and Bell will
|
||||
actually be sent to the terminal, Tab will cause the
|
||||
correct number of spaces to be sent,and FF will
|
||||
clear the screens on displays and CRLF on theirs.
|
||||
|
||||
$& Set temp type out mode to radix 50.
|
||||
ASCII A - Z $ . % 0 - 9
|
||||
Radix 50 (in octal) 1 - 32 33 34 35 36 - 47
|
||||
|
||||
$$C $$S $$I $$R $$A $$" $$' $$&
|
||||
Like $C $S $I $R $A $" $' and $& but set permanent
|
||||
type-out modes.
|
||||
|
||||
$L Load program. Source loaded from depends on how
|
||||
this RUG was assembled and environment its running in.
|
||||
For stand alone disk system, takes block number after
|
||||
the L.
|
||||
|
||||
$Y Dump program. Only meaningful in standalone disk
|
||||
system thus far. Takes arg of lblock number after
|
||||
the Y.
|
||||
|
||||
$Z Zero all of core. I will change this to $$Z to be less
|
||||
dangerous soon.
|
||||
|
||||
|
||||
SINGLE-LETTER COMMANDS:
|
||||
|
||||
<symbol>: Define <symbol> to be . (i.e. current location).
|
||||
|
||||
<arg>= Print value of <arg>.
|
||||
|
||||
<arg>><symbol> Define <symbol> to be <arg>, e.g. 1234>FOO defines
|
||||
FOO to be 1234.
|
||||
|
||||
<arg>/ Open location <arg> as word.
|
||||
|
||||
<arg>\ Open location <arg> as byte.
|
||||
|
||||
<arg><CR> (Carriage-return) Deposit <arg> into current location
|
||||
if it is open and then close the location and prompt.
|
||||
No <arg> means no change to current location.
|
||||
|
||||
<arg><LF> (Line-feed) Deposit <arg> into current location if
|
||||
open, then open next location. No <arg> means no
|
||||
change to current location.
|
||||
|
||||
<arg>^ Deposit <arg> and open previous location. No change
|
||||
if no <arg>.
|
||||
|
||||
<arg>] Open location <arg> as symbol.
|
||||
|
||||
<arg>[ Open location <arg> as number.
|
||||
|
||||
<symbol>$K Half-kill <symbol> so that it won't be used for
|
||||
printing symbolic addresses.
|
||||
|
||||
$$K Kill all symbols in program.
|
||||
|
||||
^L Clear screen.
|
||||
|
||||
<arg>^N Proceed program in single-step mode: no <arg> means
|
||||
execute one instruction;q <arg> means execute <arg>
|
||||
instructions then return to RUG.
|
||||
|
||||
_ Type out <arg> in symbolic mode, but don't set
|
||||
either the temporary or permanent modes.
|
||||
|
||||
; Type out <arg> in the last specified temporary
|
||||
or permanent mode (see $A, $C, $I, $R, $S).
|
||||
|
||||
$; Like ; but also set the temporary mode to the
|
||||
last specified temporary or permanent mode.
|
||||
|
||||
$$; Like $; but set permanent mode instead of
|
||||
temporary mode.
|
||||
|
||||
@ Open location addressed by PC in instruction mode
|
||||
|
||||
COLON COMMANDS:
|
||||
|
||||
:HELP List the colon commands.
|
||||
|
||||
:LISTB List all breakpoints set, and their counts.
|
||||
|
||||
:EXIT Exists Rug
|
||||
|
||||
3
doc/chsncp/-read-.-this-
Normal file
3
doc/chsncp/-read-.-this-
Normal file
@@ -0,0 +1,3 @@
|
||||
This directory is used for the development of CHAOS Network
|
||||
NCP software for PDP-11s. Please do not delete any files
|
||||
from here without consulting with JLK, LSP, or OTA.
|
||||
4
doc/pdp11/-read-.-this-
Normal file
4
doc/pdp11/-read-.-this-
Normal file
@@ -0,0 +1,4 @@
|
||||
Don't delete anything out of this directory unless you know what you are doing...
|
||||
For more information on the programs in this directory, please contact RLL@MC.
|
||||
|
||||
-RLL April 13, 1980
|
||||
@@ -203,6 +203,7 @@
|
||||
- RIPDEV, replacement for MLDEV for no-longer-existing machines.
|
||||
- RMAIL, mail reading client.
|
||||
- RMTDEV, MLDEV for non-ITS hosts.
|
||||
- RUG, PDP-11 debugger.
|
||||
- SALV, old file system tool for KA and KL.
|
||||
- SCAN, TEX output to XGP SCAN file.
|
||||
- SCANDL, TTY output spy.
|
||||
|
||||
203
doc/rug/rug.doc2
Normal file
203
doc/rug/rug.doc2
Normal file
@@ -0,0 +1,203 @@
|
||||
.XGP
|
||||
.double
|
||||
.fill
|
||||
|
||||
Rug is a symbolic debugger which runs on the pdp11.
|
||||
There are three basic output modes which affect how the
|
||||
contents of a location get printed.
|
||||
.nofill
|
||||
$C causes the location contents to be printed as a number.
|
||||
$S causes the location to be printed as a symbol.
|
||||
$I causes the location to be printed as an instruction.
|
||||
Also there are two minor mode changes:
|
||||
$A inhibits the printing of symbols (like in an instruction).
|
||||
$R reverses the action of $A.
|
||||
.fill
|
||||
|
||||
By typing two alt modes, the mode gets more permanently changed,
|
||||
but can be changed back, of course by switching to a different mode.
|
||||
|
||||
To open a location type / or \.
|
||||
This opens it in word or byte mode respectively.
|
||||
However if an odd location is opened, it will be in byte
|
||||
mode even if / was typed.
|
||||
|
||||
After a location is opened, a number can be placed into it numerically,
|
||||
symbolically, or as an instruction. For instance if FOO is defined,all of the following are legal:
|
||||
.nofill
|
||||
100/ 53 MOV @FOO+.(%2),(%3)+
|
||||
100/ 53 FOO+352-10
|
||||
100/ 53 6
|
||||
.fill
|
||||
To open a register, type %5/ and %5 will be opened as expected
|
||||
(or if it is a defined symbol
|
||||
just type its name)
|
||||
|
||||
When typing an instruction, type
|
||||
the operation code followed by a space or tab.
|
||||
Extra tabs and spaces are ignored here.
|
||||
Then type the next field. Follow it by a comma if
|
||||
there is another field. Then type the other field.
|
||||
When inputting a symbol, the arithmetic operations
|
||||
are +, -, *, and ! for add, subtract multiply
|
||||
and divide respectively.
|
||||
Important note: when typing in
|
||||
condition codes, type SE CZ, for example. in other words, type
|
||||
SE(space) or CL(space), depending on whether you
|
||||
wish to clear or set the flags, then follow it with all the
|
||||
flags you wish to modify by the instruction.
|
||||
|
||||
After a location is opened, carriage return will close it, placing
|
||||
in it any value that might have been typed directly before the return,
|
||||
unless some operations were performed, in which case it will not change
|
||||
the contents.
|
||||
Line feed will open the next word or byte, depending
|
||||
on whether the previous location were opened in word or byte mode.
|
||||
if the previous location were opened in instruction mode, line feed
|
||||
will open the next instruction. (it will skip over to the end of
|
||||
a multiple lenth instruction.
|
||||
^ will go to either one word or one byte ahead of the opened location.
|
||||
being in instuction mode does not change this.
|
||||
/ opens the last memory location mentioned
|
||||
(like JMP FOO,MOV BAR,FOO or TSTB @FOO all open FOO)
|
||||
_ opens second last memory location mentioned
|
||||
(MOV BAR,FOO opens BAR with an extra slash)
|
||||
tab (contrl i) opens the location which is the
|
||||
value of the number in the location opened.
|
||||
|
||||
< will return to the sequence interrupted by extra tabs
|
||||
|
||||
.center
|
||||
breakpoints
|
||||
To set a breakpoint, type FOO$B
|
||||
This sets a breakpoint at location FOO.
|
||||
To delete a breakpoint, type FOO$D.
|
||||
To delete all breakpoints, type $D.
|
||||
|
||||
To see which locations have breakpoints in them,
|
||||
type .B/. This will contain either a random location within rug,
|
||||
indicating that that breakpoint is not set, or a location which
|
||||
would be where that breakpoint is.
|
||||
If line feed is typed, you can see where B1 is.
|
||||
If another line feed is typed, you can see where B2 is, etc.
|
||||
up to B7. Or type .B+6 to examine breakpoint 6.
|
||||
To examine the count number of each
|
||||
breakpoint, type .C+n/ to examine the count of breakpoint n.
|
||||
(The count is how many times you are to proceed through that
|
||||
breakpoint before stopping.)
|
||||
|
||||
|
||||
|
||||
.center
|
||||
running the program
|
||||
.nofill
|
||||
FOO$G starts it at location FOO
|
||||
$P lets it proceed from where it left off
|
||||
n$P causes it to stop after looping through the last breakpoint
|
||||
n times.
|
||||
.fill
|
||||
The breakpoint repeat counts can be inpected and modified
|
||||
by opening .B and typing 9 line feeds.
|
||||
The repeat count for breakpoint 0 will then be typed.
|
||||
The repeat counts for breakpoints 1 through 7 follow in sequence.
|
||||
.center
|
||||
|
||||
single step mode
|
||||
by typing ^N, you can execute one more instruction.
|
||||
Rug will type SS;adr, where adr is the address of the
|
||||
next instruction to be executed.
|
||||
To execute 5 instructions, type 5^N, etc.
|
||||
Breakpoints are disabled in single instruction mode.
|
||||
By typing 400^N, it is very likely you might skip a few
|
||||
breakpoints.
|
||||
|
||||
|
||||
.S is a defined symbol which is the user status.
|
||||
.P is a defined symbol which is the user priority
|
||||
|
||||
.center
|
||||
defining symbols
|
||||
To define a symbol, type 100,FOO:
|
||||
This defines FOO as location 100.
|
||||
It is perfectly legal to redefine symbols.
|
||||
All radix 50 chars are legal in a symbol.
|
||||
Symbol names longer than 6 characters get automatically chopped.
|
||||
Also, FOO: defines FOO as . (address of the open
|
||||
location)
|
||||
|
||||
To half kill an already defined symbol type FOO^k.
|
||||
To unhalf kill a symbol you accidentally half killed, just
|
||||
redefine it (type FOO,FOO)
|
||||
|
||||
A string of numbers will be considered
|
||||
as octal unless there is a decimal point somewhere in it
|
||||
or it contains an 8 or 9.
|
||||
.break
|
||||
|
||||
& causes radix 50 to be input (&abc is like typing the numeric
|
||||
quantity which is abc in radix 50 packed with a on the left)
|
||||
spaces are zero radix 50
|
||||
|
||||
.break
|
||||
[ will type the two ascii bytes in the opened word
|
||||
.break
|
||||
|
||||
.break
|
||||
] performs a radix 50 mode unpack of the opened word.
|
||||
.break
|
||||
|
||||
' causes the ascii value of the next character to be input
|
||||
(mov ##'F,R2 is legal)
|
||||
.break
|
||||
" causes the next two char.'s ascii value to be packed into a word
|
||||
|
||||
.center
|
||||
loading a file
|
||||
To load a file from the paper tape reader,
|
||||
type $LP:. If it is on multiple tapes, the debugger
|
||||
halts at the end of each tape and hitting "continue"
|
||||
causes the next tape to be read.
|
||||
Use RADIA;PUNCH BIN on the PDP10 to punch out a
|
||||
debugger-loadable tape, which is an absolute loader
|
||||
binary of the program which gets loaded directly onto
|
||||
disk, followed by an absolute loader tape of the
|
||||
symbol table which gets loaded directly into core.
|
||||
|
||||
To load a file from the PDP10's disk, type $LT: <user;file name>,
|
||||
where <user;file name> is the ITS file specification for the file to be
|
||||
loaded.When it is done loading you'll be back
|
||||
in the debugger.
|
||||
To load a program without first zeroing
|
||||
core, type $^L instead of $L.
|
||||
Symbols are always loaded with the program.
|
||||
|
||||
To save the debugger on disk type $^D. To get it back type $^U.
|
||||
To load a program of disk #<n>, type $L<n>:<file name>. To save it (dump it)
|
||||
type $Y<n>:<file name>. If a file with the name <file name> exists already,
|
||||
rug will type FILE EXISTS DELETE?. If you then type Y, rug will delete the old
|
||||
file, and dump core into a new file with <file name>. If you type anything else,
|
||||
the file is not dumped.
|
||||
.center
|
||||
zeroing core and initializing the symbol table.
|
||||
To zero all of core and initialize the symbol table, type $$Z. To just
|
||||
reinitialize the symbol table, type $Z.
|
||||
.center
|
||||
interacting with programs
|
||||
Programs should leave locations 157000-160000 alone.
|
||||
That is the resident portion of rug.
|
||||
If a program is running and you wish to get to the debugger,
|
||||
halt the program and start at location 157000.
|
||||
Rug should swap the program out and itself in.
|
||||
Proceed is disabled when the debugger is
|
||||
started with the switches as opposed to trapping there.
|
||||
(the program executes "3")
|
||||
Aside from the the 300 locations already mentioned, the program
|
||||
can use all 28k of core.
|
||||
However, currently only up to 157500 (the
|
||||
absolute loader) is swapped in and out.
|
||||
Maximum symbol table size is about 2000 symbols
|
||||
(logo is well under the limit.)
|
||||
To find out how much symbol table room is used,
|
||||
type "..B="
|
||||
The mimumum allowed value of ..B is 10000.
|
||||
|
||||
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
|
||||
|
||||
| ||||