Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
; MDS-800 Cold Start Loader for MP/M 2.0
;
; VERSION 2.0 09/1481
;
mpmldrb equ 0100h ;base of MP/M loader
;
org 3000h ;loaded here by hardware
;
ntrks equ 2 ;tracks to read
mpmldr0 equ 25 ;# on track 0
mpmldr1 equ 26 ;# on track 1
;
rmon80 equ 0ff0fh ;restart location for mon80
base equ 078h ;'base' used by controller
rtype equ base+1 ;result type
rbyte equ base+3 ;result byte
reset equ base+7 ;reset controller
;
dstat equ base ;disk status port
ilow equ base+1 ;low iopb address
ihigh equ base+2 ;high iopb address
bsw equ 0ffh ;boot switch
readf equ 4h ;disk read function
stack equ 100h ;use end of boot for stack
;
rstart:
lxi sp,stack;in case of call to mon80
; clear disk status
in rtype
in rbyte
; check if boot switch is off
coldstart:
in bsw
ani 02h ;switch on?
jnz coldstart
; clear the controller
out reset ;logic cleared
;
;
mvi b,ntrks ;number of tracks to read
lxi h,iopb0
;
start:
;
; read first/next track into cpmb
mov a,l
out ilow
mov a,h
out ihigh
wait0: in dstat
ani 4
jz wait0
;
; check disk status
in rtype
ani 11b
cpi 2
;
jnc rstart ;retry the load
;
in rbyte ;i/o complete, check status
; if not ready, then go to mon80
ral
cc rmon80 ;not ready bit set
rar ;restore
ani 11110b ;overrun/addr err/seek/crc/xxxx
;
jnz rstart ;retry the load
;
;
lxi d,iopbl ;length of iopb
dad d ;addressing next iopb
dcr b ;count down tracks
jnz start
;
;
; jmp to the MP/M loader
jmp mpmldrb
;
; parameter blocks
iopb0: db 80h ;iocw, no update
db readf ;read function
db mpmldr0 ;# sectors to read trk 0
db 0 ;track 0
db 2 ;start with sector 2, trk 0
dw mpmldrb ;start at base of bdos
iopbl equ $-iopb0
;
iopb1: db 80h
db readf
db mpmldr1 ;sectors to read on track 1
db 1 ;track 1
db 1 ;sector 1
dw mpmldrb+mpmldr0*128 ;base of second read
end


View File

@@ -0,0 +1,15 @@
; MACRO LIBRARY FOR PEDESTRIAN PUSHBUTTONS
;
CWINP EQU 00H ;INPUT PORT FOR CROSSWALK
;
PUSH? MACRO IFTRUE
;; "PUSH?" JUMPS TO LABEL "IFTRUE" WHEN ANY ONE
;; OF THE CROSSWALK SWITCHES IS DEPRESSED. THE
;; VALUE HAS BEEN LATCHED, AND READING THE PORT
;; CLEARS THE LATCHED VALUES
IN CWINP ;;READ THE CROSSWALK SWITCHES
ANI (1 SHL CWCNT) - 1 ;;BUILD MASK
JNZ IFTRUE ;;ANY SWITCHES SET?
;; CONTINUE ON FALSE CONDITION
ENDM


View File

@@ -0,0 +1,59 @@
; MACRO LIBRARY FOR 8-BIT COMPARISON OPERATION
;
TEST? MACRO X,Y
;; UTILTITY MACRO TO GENERATE CONDITION CODES
IF NOT NUL X ;;THEN LOAD X
LDA X ;;X ASSUMED TO BE IN MEMORY
ENDIF
IRPC ?Y,Y ;;Y MAY BE CONSTANT OPERAND
TDIG? SET '&?Y'-'0' ;;FIRST CHAR DIGIT?
EXITM ;;STOP IRPC AFTER FIRST CHAR
ENDM
IF TDIG? <= 9 ;;Y NUMERIC?
SUI Y ;;YES, SO SUB IMMEDIATE
ELSE
LXI H,Y ;;Y NOT NUMERIC
SUB M ;;SO SUB FROM MEMORY
ENDM
;
LSS MACRO X,Y,TL
;; X LSS THAN Y TEST,
;; TRANSFER TO TL (TRUE LABEL) IF TRUE,
;; CONTINUE IF TEST IS FALSE
TEST? X,Y ;;SET CONDITION CODES
JC TL
ENDM
;
LEQ MACRO X,Y,TL
;; X LESS THAN OR EQUAL TO Y TEST
LSS X,Y,TL
JZ TL
ENDM
;
EQL MACRO X,Y,TL
;; X EQUAL TO Y TEST
TEST? X,Y
JZ TL
ENDM
;
NEQ MACRO X,Y,TL
;; X NOT EQUAL TO Y TEST
TEST? X,Y
JNZ TL
ENDM
;
GEQ MACRO X,Y,TL
;; X GREATER THAN OR EQUAL TO Y TEST
TEST? X,Y
JNC TL
ENDM
;
GTR MACRO X,Y,TL
;; X GREATER THAN Y TEST
LOCAL FL ;;FALSE LABEL
TEST? X,Y
JC FL
DCR A
JNC TL
FL: ENDM


View File

@@ -0,0 +1,388 @@
;*********************************************************
;* *
;* Sector Deblocking Algorithms for MP/M II V2.0 *
;* *
;*********************************************************
;
; utility macro to compute sector mask
smask macro hblk
;; compute log2(hblk), return @x as result
;; (2 ** @x = hblk on return)
@y set hblk
@x set 0
;; count right shifts of @y until = 1
rept 8
if @y = 1
exitm
endif
;; @y is not 1, shift right one position
@y set @y shr 1
@x set @x + 1
endm
endm
;
;*****************************************************
;* *
;* MP/M to host disk constants *
;* *
;*****************************************************
blksiz equ 2048 ;MP/M allocation size
hstsiz equ 512 ;host disk sector size
hstspt equ 20 ;host disk sectors/trk
hstblk equ hstsiz/128 ;MP/M sects/host buff
cpmspt equ hstblk * hstspt ;MP/M sectors/track
secmsk equ hstblk-1 ;sector mask
smask hstblk ;compute sector mask
secshf equ @x ;log2(hstblk)
;
;*****************************************************
;* *
;* BDOS constants on entry to write *
;* *
;*****************************************************
wrall equ 0 ;write to allocated
wrdir equ 1 ;write to directory
wrual equ 2 ;write to unallocated
;
;*****************************************************
;* *
;* The BDOS entry points given below show the *
;* code which is relevant to deblocking only. *
;* *
;*****************************************************
;
; DISKDEF macro, or hand coded tables go here
dpbase equ $ ;disk param block base
;
boot:
wboot:
;enter here on system boot to initialize
xra a ;0 to accumulator
sta hstact ;host buffer inactive
sta unacnt ;clear unalloc count
ret
;
home:
;home the selected disk
lda hstwrt ;check for pending write
ora a
jnz homed
sta hstact ;clear host active flag
homed:
ret
;
seldsk:
;select disk
mov a,c ;selected disk number
sta sekdsk ;seek disk number
mov l,a ;disk number to HL
mvi h,0
rept 4 ;multiply by 16
dad h
endm
lxi d,dpbase ;base of parm block
dad d ;hl=.dpb(curdsk)
ret
;
settrk:
;set track given by registers BC
mov h,b
mov l,c
shld sektrk ;track to seek
ret
;
setsec:
;set sector given by register c
mov a,c
sta seksec ;sector to seek
ret
;
setdma:
;set dma address given by BC
mov h,b
mov l,c
shld dmaadr
ret
;
sectran:
;translate sector number BC
mov h,b
mov l,c
ret
;
;*****************************************************
;* *
;* The READ entry point takes the place of *
;* the previous BIOS defintion for READ. *
;* *
;*****************************************************
read:
;read the selected MP/M sector
xra a
sta unacnt ;unacnt = 0
inr a
sta readop ;read operation
sta rsflag ;must read data
mvi a,wrual
sta wrtype ;treat as unalloc
jmp rwoper ;to perform the read
;
;*****************************************************
;* *
;* The WRITE entry point takes the place of *
;* the previous BIOS defintion for WRITE. *
;* *
;*****************************************************
write:
;write the selected MP/M sector
xra a ;0 to accumulator
sta readop ;not a read operation
mov a,c ;write type in c
sta wrtype
ani wrual ;write unallocated?
jz chkuna ;check for unalloc
;
; write to unallocated, set parameters
mvi a,blksiz/128 ;next unalloc recs
sta unacnt
lda sekdsk ;disk to seek
sta unadsk ;unadsk = sekdsk
lhld sektrk
shld unatrk ;unatrk = sectrk
lda seksec
sta unasec ;unasec = seksec
;
chkuna:
;check for write to unallocated sector
lda unacnt ;any unalloc remain?
ora a
jz alloc ;skip if not
;
; more unallocated records remain
dcr a ;unacnt = unacnt-1
sta unacnt
lda sekdsk ;same disk?
lxi h,unadsk
cmp m ;sekdsk = unadsk?
jnz alloc ;skip if not
;
; disks are the same
lxi h,unatrk
call sektrkcmp ;sektrk = unatrk?
jnz alloc ;skip if not
;
; tracks are the same
lda seksec ;same sector?
lxi h,unasec
cmp m ;seksec = unasec?
jnz alloc ;skip if not
;
; match, move to next sector for future ref
inr m ;unasec = unasec+1
mov a,m ;end of track?
cpi cpmspt ;count MP/M sectors
jc noovf ;skip if no overflow
;
; overflow to next track
mvi m,0 ;unasec = 0
lhld unatrk
inx h
shld unatrk ;unatrk = unatrk+1
;
noovf:
;match found, mark as unnecessary read
xra a ;0 to accumulator
sta rsflag ;rsflag = 0
jmp rwoper ;to perform the write
;
alloc:
;not an unallocated record, requires pre-read
xra a ;0 to accum
sta unacnt ;unacnt = 0
inr a ;1 to accum
sta rsflag ;rsflag = 1
;
;*****************************************************
;* *
;* Common code for READ and WRITE follows *
;* *
;*****************************************************
rwoper:
;enter here to perform the read/write
xra a ;zero to accum
sta erflag ;no errors (yet)
lda seksec ;compute host sector
rept secshf
ora a ;carry = 0
rar ;shift right
endm
sta sekhst ;host sector to seek
;
; active host sector?
lxi h,hstact ;host active flag
mov a,m
mvi m,1 ;always becomes 1
ora a ;was it already?
jz filhst ;fill host if not
;
; host buffer active, same as seek buffer?
lda sekdsk
lxi h,hstdsk ;same disk?
cmp m ;sekdsk = hstdsk?
jnz nomatch
;
; same disk, same track?
lxi h,hsttrk
call sektrkcmp ;sektrk = hsttrk?
jnz nomatch
;
; same disk, same track, same buffer?
lda sekhst
lxi h,hstsec ;sekhst = hstsec?
cmp m
jz match ;skip if match
;
nomatch:
;proper disk, but not correct sector
lda hstwrt ;host written?
ora a
cnz writehst ;clear host buff
;
filhst:
;may have to fill the host buffer
lda sekdsk
sta hstdsk
lhld sektrk
shld hsttrk
lda sekhst
sta hstsec
lda rsflag ;need to read?
ora a
cnz readhst ;yes, if 1
xra a ;0 to accum
sta hstwrt ;no pending write
;
match:
;copy data to or from buffer
lda seksec ;mask buffer number
ani secmsk ;least signif bits
mov l,a ;ready to shift
mvi h,0 ;double count
rept 7 ;shift left 7
dad h
endm
; hl has relative host buffer address
lxi d,hstbuf
dad d ;hl = host address
xchg ;now in DE
lhld dmaadr ;get/put MP/M data
mvi c,128 ;length of move
lda readop ;which way?
ora a
jnz rwmove ;skip if read
;
; write operation, mark and switch direction
mvi a,1
sta hstwrt ;hstwrt = 1
xchg ;source/dest swap
;
rwmove:
;C initially 128, DE is source, HL is dest
ldax d ;source character
inx d
mov m,a ;to dest
inx h
dcr c ;loop 128 times
jnz rwmove
;
; data has been moved to/from host buffer
lda wrtype ;write type
ani wrdir ;to directory?
lda erflag ;in case of errors
rz ;no further processing
;
; clear host buffer for directory write
ora a ;errors?
rnz ;skip if so
xra a ;0 to accum
sta hstwrt ;buffer written
call writehst
lda erflag
ret
;
;*****************************************************
;* *
;* Utility subroutine for 16-bit compare *
;* *
;*****************************************************
sektrkcmp:
;HL = .unatrk or .hsttrk, compare with sektrk
xchg
lxi h,sektrk
ldax d ;low byte compare
cmp m ;same?
rnz ;return if not
; low bytes equal, test high 1s
inx d
inx h
ldax d
cmp m ;sets flags
ret
;
;*****************************************************
;* *
;* WRITEHST performs the physical write to *
;* the host disk, READHST reads the physical *
;* disk. *
;* *
;*****************************************************
writehst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. write "hstsiz" bytes
;from hstbuf and return error flag in erflag.
;return erflag non-zero if error
ret
;
readhst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. read "hstsiz" bytes
;into hstbuf and return error flag in erflag.
ret
;
;*****************************************************
;* *
;* Unitialized RAM data areas *
;* *
;*****************************************************
;
sekdsk: ds 1 ;seek disk number
sektrk: ds 2 ;seek track number
seksec: ds 1 ;seek sector number
;
hstdsk: ds 1 ;host disk number
hsttrk: ds 2 ;host track number
hstsec: ds 1 ;host sector number
;
sekhst: ds 1 ;seek shr secshf
hstact: ds 1 ;host active flag
hstwrt: ds 1 ;host written flag
;
unacnt: ds 1 ;unalloc rec cnt
unadsk: ds 1 ;last unalloc disk
unatrk: ds 2 ;last unalloc track
unasec: ds 1 ;last unalloc sector
;
erflag: ds 1 ;error reporting
rsflag: ds 1 ;read sector flag
readop: ds 1 ;1 if read operation
wrtype: ds 1 ;write operation type
dmaadr: ds 2 ;last dma address
hstbuf: ds hstsiz ;host buffer
;
;*****************************************************
;* *
;* The ENDEF macro invocation goes here *
;* *
;*****************************************************
end


View File

@@ -0,0 +1,35 @@
File: Contents:
RMAC.COM "RMAC" Relocating Macro Assembler
LINK.COM Linkage Editor
LIB.COM Library Manager
XREF.COM Cross Reference Utility
I8085.LIB Simple macros for 8085 RIM/SIM instructions
Z80.LIB Macro lirary for Z80 operation codes
Z80.DOC Documentation for the Z80.LIB file
INTER.LIB Traffic light intersection library (see manual)
TREADLES.LIB Library for traffic treadles
BUTTONS.LIB Library for pedestrian pushbuttons
SIMPIO.LIB Simple BDOS I/O Library
SEQIO.LIB Sequential file I/O library
STACK.LIB Simple stack machine library
DSTACK.LIB Complete stack machine library
COMPARE.LIB Library for simple 8-bit comparison operations
NCOMPARE.LIB 8-bit comparisons with negation
WHEN.LIB Macros for the WHEN construct (see manual)
DOWHILE.LIB Macros for the DOWHILE contstruct
SELECT.LIB Macros for the SELECT construct
LDRBIOS.ASM Sample Loader BIOS for MP/M II MPMLDR
BOOT.ASM Sample Boot for MP/M II
DEBLOCK.ASM Sample Deblocking algorithm for MP/M II
TODCNV.ASM Sample Time & Date Conversion for MP/M II
RESXIOS.ASM Sample Resident XIOS for MP/M II
DUMP.ASM Sample PRL for MP/M II
EXTRN.ASM Sample External module for DUMP.ASM


View File

@@ -0,0 +1,257 @@
; MP/M II V2.0 disk re-definition library
;
; Copyright (c) 1979, 1980, 1981
; Digital Research
; Box 579
; Pacific Grove, CA
; 93950
;
; MP/M II logical disk drives are defined using the
; macros given below, where the sequence of calls
; is:
;
; disks n
; diskdef parameter-list-0
; diskdef parameter-list-1
; ...
; diskdef parameter-list-n
; endef
;
; where n is the number of logical disk drives attached
; to the MP/M II system, and parameter-list-i defines the
; characteristics of the ith drive (i=0,1,...,n-1)
;
; each parameter-list-i takes the form
; dn,fsc,lsc,[skf],bls,dks,dir,cks,ofs,[k16],[prm]
; where
; dn is the disk number 0,1,...,n-1
; fsc is the first sector number (usually 0 or 1)
; lsc is the last sector number on a track
; skf is optional "skew factor" for sector translate
; bls is the data block size (1024,2048,...,16384)
; dks is the disk size in bls increments (word)
; dir is the number of directory elements (word)
; cks is the number of dir elements to checksum
; ofs is the number of tracks to skip (word)
; k16 is an optional 0 which forces 16K/directory entry
; prm is an optional 0 which marks drive as permanent
;
; for convenience, the form
; dn,dm
; defines disk dn as having the same characteristics as
; a previously defined disk dm.
;
; a standard four drive MP/M II system is defined by
; disks 4
; diskdef 0,1,26,6,1024,243,64,64,2
; dsk set 0
; rept 3
; dsk set dsk+1
; diskdef %dsk,0
; endm
; endef
;
; the value of "begdat" at the end of assembly defines the
; beginning of the uninitialize ram area above the bios,
; while the value of "enddat" defines the next location
; following the end of the data area. the size of this
; area is given by the value of "datsiz" at the end of the
; assembly. note that the allocation vector will be quite
; large if a large disk size is defined with a small block
; size.
;
dskhdr macro dn
;; define a single disk header list
dpe&dn: dw xlt&dn,0000h ;translate table
dw 0000h,0000h ;scratch area
dw dirbuf,dpb&dn ;dir buff,parm block
dw csv&dn,alv&dn ;check, alloc vectors
endm
;
disks macro nd
;; define nd disks
ndisks set nd ;;for later reference
dpbase equ $ ;base of disk parameter blocks
;; generate the nd elements
dsknxt set 0
rept nd
dskhdr %dsknxt
dsknxt set dsknxt+1
endm
endm
;
dpbhdr macro dn
dpb&dn equ $ ;disk parm block
endm
;
ddb macro data,comment
;; define a db statement
db data comment
endm
;
ddw macro data,comment
;; define a dw statement
dw data comment
endm
;
gcd macro m,n
;; greatest common divisor of m,n
;; produces value gcdn as result
;; (used in sector translate table generation)
gcdm set m ;;variable for m
gcdn set n ;;variable for n
gcdr set 0 ;;variable for r
rept 65535
gcdx set gcdm/gcdn
gcdr set gcdm - gcdx*gcdn
if gcdr = 0
exitm
endif
gcdm set gcdn
gcdn set gcdr
endm
endm
;
diskdef macro dn,fsc,lsc,skf,bls,dks,dir,cks,ofs,k16,prm
;; generate the set statements for later tables
if nul lsc
;; current disk dn same as previous fsc
dpb&dn equ dpb&fsc ;equivalent parameters
als&dn equ als&fsc ;same allocation vector size
css&dn equ css&fsc ;same checksum vector size
xlt&dn equ xlt&fsc ;same translate table
else
cksz set (cks)/4
secmax set lsc-(fsc) ;;sectors 0...secmax
sectors set secmax+1;;number of sectors
als&dn set (dks)/8 ;;size of allocation vector
if ((dks) mod 8) ne 0
als&dn set als&dn+1
endif
css&dn set cksz ;;number of checksum elements
;; generate the block shift value
blkval set bls/128 ;;number of sectors/block
blkshf set 0 ;;counts right 0's in blkval
blkmsk set 0 ;;fills with 1's from right
rept 16 ;;once for each bit position
if blkval=1
exitm
endif
;; otherwise, high order 1 not found yet
blkshf set blkshf+1
blkmsk set (blkmsk shl 1) or 1
blkval set blkval/2
endm
;; generate the extent mask byte
blkval set bls/1024 ;;number of kilobytes/block
extmsk set 0 ;;fill from right with 1's
rept 16
if blkval=1
exitm
endif
;; otherwise more to shift
extmsk set (extmsk shl 1) or 1
blkval set blkval/2
endm
;; may be double byte allocation
if (dks) > 256
extmsk set (extmsk shr 1)
endif
;; may be optional [0] in last position
if not nul k16
extmsk set k16
endif
;; now generate directory reservation bit vector
dirrem set dir ;;# remaining to process
dirbks set bls/32 ;;number of entries per block
dirblk set 0 ;;fill with 1's on each loop
rept 16
if dirrem=0
exitm
endif
;; not complete, iterate once again
;; shift right and add 1 high order bit
dirblk set (dirblk shr 1) or 8000h
if dirrem > dirbks
dirrem set dirrem-dirbks
else
dirrem set 0
endif
endm
dpbhdr dn ;;generate equ $
ddw %sectors,<;sec per track>
ddb %blkshf,<;block shift>
ddb %blkmsk,<;block mask>
ddb %extmsk,<;extnt mask>
ddw %(dks)-1,<;disk size-1>
ddw %(dir)-1,<;directory max>
ddb %dirblk shr 8,<;alloc0>
ddb %dirblk and 0ffh,<;alloc1>
if nul prm
ddw %(cks)/4,<;check size>
else
ddw 8000h+cksz,<;permanent disk with check size>
endif
ddw %ofs,<;offset>
;; generate the translate table, if requested
if nul skf
xlt&dn equ 0 ;no xlate table
else
if skf = 0
xlt&dn equ 0 ;no xlate table
else
;; generate the translate table
nxtsec set 0 ;;next sector to fill
nxtbas set 0 ;;moves by one on overflow
gcd %sectors,skf
;; gcdn = gcd(sectors,skew)
neltst set sectors/gcdn
;; neltst is number of elements to generate
;; before we overlap previous elements
nelts set neltst ;;counter
xlt&dn equ $ ;translate table
rept sectors ;;once for each sector
if sectors < 256
ddb %nxtsec+(fsc)
else
ddw %nxtsec+(fsc)
endif
nxtsec set nxtsec+(skf)
if nxtsec >= sectors
nxtsec set nxtsec-sectors
endif
nelts set nelts-1
if nelts = 0
nxtbas set nxtbas+1
nxtsec set nxtbas
nelts set neltst
endif
endm
endif ;;end of nul fac test
endif ;;end of nul bls test
endm
;
defds macro lab,space
lab: ds space
endm
;
lds macro lb,dn,val
defds lb&dn,%val&dn
endm
;
endef macro
;; generate the necessary ram data areas
begdat equ $
dirbuf: ds 128 ;directory access buffer
dsknxt set 0
rept ndisks ;;once for each disk
lds alv,%dsknxt,als
lds csv,%dsknxt,css
dsknxt set dsknxt+1
endm
enddat equ $
datsiz equ $-begdat
force: db 0 ;force out last byte in hex file
endm
;


View File

@@ -0,0 +1,41 @@
; MACRO LIBRARY FOR "DOWHILE" CONSTRUCT
;
GENDTST MACRO TST,X,Y,NUM
;; GENERATE A "DOWHILE" TEST
TST X,Y,,ENDD&NUM
ENDM
;
GENDLAB MACRO LAB,NUM
;; PRODUCE THE LABEL LAB & NUM
;; FOR DOWHILE ENTRY OR EXIT
LAB&NUM:
ENDM
;
GENDJMP MACRO NUM
;; GENERATE JUMP TO DOWHILE TEST
JMP DTEST&NUM
ENDM
;
DOWHILE MACRO XV,REL,YV
;; INITIALIZE COUNTER
DOCNT SET 0 ;NUMBER OF DOWHILES
;;
DOWHILE MACRO X,R,Y
;; GENERATE THE DOWHILE ENTRY
GENDLAB DTEST,%DOCNT
;; GENERATE THE CONDITIONAL TEST
GENDTST R,X,Y,%DOCNT
DOLEV SET DOCNT ;;NEXT ENDD TO GENERATE
DOCNT SET DOCNT+1
ENDM
DOWHILE XV,REL,YV
ENDM
;
ENDDO MACRO
;; GENERATE THE JUMP TO THE TEST
GENDJMP %DOLEV
;; GENERATE THE END OF A DOWHILE
GENDLAB ENDD,%DOLEV
DOLEV SET DOLEV-1
ENDM


View File

@@ -0,0 +1,468 @@
; MACRO LIBRARY FOR A ZERO ADDRESS MACHINE
; *****************************************
; * BEGIN TRACE/DUMP UTILITIES *
; *****************************************
BDOS EQU 0005H ;SYSTEM ENTRY
RCHAR EQU 1 ;READ A CHARACTER
WCHAR EQU 2 ;WRITE CHARACTER
WBUFF EQU 9 ;WRITE BUFFER
TRAN EQU 100H ;TRANSIENT PROGRAM AREA
DATA EQU 1100H ;DATA AREA
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
;
DEBUGT SET 0 ;;TRACE DEBUG SET FALSE
DEBUGP SET 0 ;;PRINT DEBUG SET FALSE
;
PRN MACRO PR
;; PRINT MESSAGE 'PR' AT CONSOLE
IF DEBUGP ;;PRINT DEBUG ON?
LOCAL PMSG,MSG ;;LOCAL MESSAGE
JMP PMSG ;;AROUND MESSAGE
MSG: DB CR,LF ;;RETURN CARRIAGE
DB '&PR$' ;;LITERAL MESSAGE
PMSG: PUSH H ;;SAVE TOP ELEMENT OF STACK
LXI D,MSG ;;LOCAL MESSAGE ADDRESS
MVI C,WBUFF ;;WRITE BUFFER 'TIL $
CALL BDOS ;;PRINT IT
POP H ;;RESTORE TOP OF STACK
ENDIF ;;END TEST DEBUGP
ENDM
;
UGEN MACRO
;; GENERATE UTILITIES FOR TRACE OR DUMP
LOCAL PSUB
JMP PSUB ;;JUMP PAST SUBROUTINES
@CH: ;;WRITE CHARACTER IN REG-A
MOV E,A
MVI C,WCHAR
JMP BDOS ;;RETURN THRU BDOS
;;
@NB: ;;WRITE NIBBLE IN REG-A
ADI 90H
DAA
ACI 40H
DAA
JMP @CH ;;RETURN THRU @CH
;;
@HX: ;;WRITE HEX VALUE IN REG-A
PUSH PSW ;;SAVE LOW BYTE
RRC
RRC
RRC
RRC
ANI 0FH ;;MASK HIGH NIBBLE
CALL @NB ;;PRINT HIGH NIBBLE
POP PSW
ANI 0FH
JMP @NB ;;PRINT LOW NIBBLE
;;
@AD ;;WRITE ADDRESS VALUE IN HL
PUSH H ;;SAVE VALUE
MVI A,' ' ;;LEADING BLANK
CALL @CH ;;AHEAD OF ADDRESS
POP H ;;HIGH BYTE TO A
MOV A,H
PUSH H ;;COPY BACK TO STACK
CALL @HX ;;WRITE HIGH BYTE
POP H
MOV A,L ;;LOW BYTE
JMP @HX ;;WRITE LOW BYTE
;
@IN: ;;READ HEX VALUE TO HL FROM CONSOLE
MVI A,' ' ;;LEADING SPACE
CALL @CH ;;TO CONSOLE
LXI H,0 ;;STARTING VALUE
@IN0: PUSH H ;;SAVE IT FOR CHAR READ
MVI C,RCHAR ;;READ CHARACTER FUNCTION
CALL BDOS ;;READ TO ACCUMULATOR
POP H ;;VALUE BEING BUILT IN HL
SUI '0' ;;NORMALIZE TO BINARY
CPI 10 ;;DECIMAL?
JC @IN1 ;;CARRY IF 0,1,...,9
;; MAY BE HEXADECIMAL A,...,F
SUI 'A'-'0'-10
CPI 16 ;;A THROUGH F?
RNC ;;RETURN WITH ASSUMED CR
@IN1: ;;IN RANGE, MULTIPLY BY 4 AND ADD
REPT 4
DAD H ;;SHIFT 4
ENDM
ORA L ;;ADD DIGIT
MOV L,A ;;AND REPLACE VALUE
JMP @IN0 ;;FOR ANOTHER DIGIT
;;
PSUB:
UGEN MACRO
;; REDEF TO INCLUDE ONCE
ENDM
UGEN ;;GENERATE FIRST TIME
ENDM
; *****************************************
; * END OF TRACE/DUMP UTILITIES *
; * BEGIN TRACE(ONLY) UTILITIES *
; *****************************************
TRACE MACRO CODE,MNAME
;; TRACE MACRO GIVEN BY MNAME,
;; AT LOCATION GIVEN BY CODE
LOCAL PSUB
UGEN ;;GENERATE UTILITIES
JMP PSUB
@T1: DS 2 ;;TEMP FOR REG-1
@T2: DS 2 ;;TEMP FOR REG-2
;;
@TR: ;;TRACE MACRO CALL
;; BC=CODE ADDRESS, DE=MESSAGE
SHLD @T1 ;;STORE TOP REG
POP H ;;RETURN ADDRESS
XTHL ;;REG-2 TO TOP
SHLD @T2 ;;STORE TO TEMP
PUSH PSW ;;SAVE FLAGS
PUSH B ;;SAVE RET ADDRESS
MVI C,WBUFF ;;PRINT BUFFER FUNC
CALL BDOS ;;PRINT MACRO NAME
POP H ;;CODE ADDRESS
CALL @AD ;;PRINTED
LHLD @T1 ;;TOP OF STACK
CALL @AD ;;PRINTED
LHLD @T2 ;;TOP-1
CALL @AD ;;PRINTED
POP PSW ;;FLAGS RESTORED
POP D ;;RETURN ADDRESS
LHLD @T2 ;;TOP-1
PUSH H ;;RESTORED
PUSH D ;;RETURN ADDRESS
LHLD @T1 ;;TOP OF STACK
RET
;;
PSUB: ;;PAST SUBROUTINES
;;
TRACE MACRO C,M
;; REDEFINED TRACE, USES @TR
LOCAL PMSG,MSG
JMP PMSG
MSG: DB CR,LF ;;CR,LF
DB '&M$' ;;MAC NAME
PMSG:
LXI B,C ;;CODE ADDRESS
LXI D,MSG ;;MACRO NAME
CALL @TR ;;TO TRACE IT
ENDM
;; BACK TO ORIGINAL MACRO LEVEL
TRACE CODE,MNAME
ENDM
;
TRT MACRO F
;; TURN ON FLAG "F"
DEBUG&F SET 1 ;;PRINT/TRACE ON
ENDM
;
TRF MACRO F
;; TURN OFF FLAG "F"
DEBUG&F SET 0 ;;TRACE/PRINT OFF
ENDM
;
?TR MACRO M
;; CHECK DEBUGT TOGGLE BEFORE TRACE
IF DEBUGT
TRACE %$,M
ENDM
; *****************************************
; * END TRACE (ONLY) UTILITIES *
; * BEGIN DUMP(ONLY) UTILITIES *
; *****************************************
DMP MACRO VNAME,N
;; DUMP VARIABLE VNAME FOR
;; N ELEMENTS (DOUBLE BYTES)
LOCAL PSUB ;;PAST SUBROUTINES
UGEN ;;GEN INLINE ROUTINES
JMP PSUB ;;PAST LOCAL SUBROUTINES
@DM: ;;DUMP UTILITY PROGRAM
;; DE=MSG ADDRESS, C=ELEMENT COUNT
;; HL=BASE ADDRESS TO PRINT
PUSH H ;;BASE ADDRESS
PUSH B ;;ELEMENT COUNT
MVI C,WBUFF ;;WRITE BUFFER FUNC
CALL BDOS ;;MESSAGE WRITTEN
@DM0: POP B ;;RECALL COUNT
POP H ;;RECALL BASE ADDRESS
MOV A,C ;;END OF LIST?
ORA A
RZ ;;RETURN IF SO
DCR C ;;DECREMENT COUNT
MOV E,M ;;NEXT ITEM (LOW)
INX H
MOV D,M ;;NEXT ITEM (HIGH)
INX H ;;READY FOR NEXT ROUND
PUSH H ;;SAVE PRINT ADDRESS
PUSH B ;;SAVE COUNT
XCHG ;;DATA READY
CALL @AD ;;PRINT ITEM VALUE
JMP @DM0 ;;FOR ANOTHER VALUE
;;
@DT: ;;DUMP TOP OF STACK ONLY
PRN <(TOP)=> ;;"(TOP)="
PUSH H
CALL @AD ;;VALUE OF HL
POP H ;;TOP RESTORED
RET
;;
PSUB:
;;
DMP MACRO ?V,?N
;; REDEFINE DUMP TO USE @DM UTILITY
LOCAL PMSG,MSG
;; SPECIAL CASE IF NULL PARAMETERS
IF NUL VNAME
;; DUMP THE TOP OF THE STACK ONLY
CALL @DT
EXITM
ENDIF
;; OTHERWISE DUMP VARIABLE NAME
JMP PMSG
MSG: DB CR,LF ;;CRLF
DB '&?V=$' ;;MESSAGE
PMSG: ADR ?V ;;HL=ADDRESS
ACTIVE SET 0 ;;CLEAR ACTIVE FLAG
LXI D,MSG ;;MESSAGE TO PRINT
IF NUL ?N ;;USE LENGTH 1
MVI C,1
ELSE
MVI C,?N
ENDIF
CALL @DM ;;TO PERFORM THE DUMP
ENDM ;;END OF REDEFINITION
DMP VNAME,N
ENDM
;
; *****************************************
; * END DUMP (ONLY) UTILITIES, *
; * BEGIN STACK MACHINE OPCODES *
; *****************************************
ACTIVE SET 0 ;ACTIVE REGISTER FLAG
;
SIZ MACRO SIZE
ORG TRAN ;;SET TO TRANSIENT AREA
;; CREATE A STACK WHEN "XIT" ENCOUNTERED
@STK SET SIZE ;;SAVE FOR DATA AREA
LXI SP,STACK
ENDM
;
SAVE MACRO
;; CHECK TO ENSURE "ENTER" PROPERLY SET UP
IF STACK ;;IS IT PRESENT?
ENDIF
SAVE MACRO ;;REDEFINE AFTER INITIAL REFERENCE
IF ACTIVE ;;ELEMENT IN HL
PUSH H ;;SAVE IT
ENDIF
ACTIVE SET 1 ;;SET ACTIVE
ENDM
SAVE
ENDM
;
REST MACRO
;; RESTORE THE TOP ELEMENT
IF NOT ACTIVE
POP H ;;RECALL TO HL
ENDIF
ACTIVE SET 1 ;;MARK AS ACTIVE
ENDM
;
CLEAR MACRO
;; CLEAR THE TOP ACTIVE ELEMENT
REST ;;ENSURE ACTIVE
ACTIVE SET 0 ;;CLEARED
ENDM
;
DCL MACRO VNAME,SIZE
;; LABEL THE DECLARATION
VNAME:
IF NUL SIZE
DS 2 ;;ONE WORD REQ'D
ELSE
DS SIZE*2 ;;DOUBLE WORDS
ENDM
;
LIT MACRO VAL
;; LOAD LITERAL VALUE TO TOP OF STACK
SAVE ;;SAVE IF ACTIVE
LXI H,VAL ;;LOAD LITERAL
?TR LIT
ENDM
;
ADR MACRO BASE,INX,CON
;; LOAD ADDRESS OF BASE, INDEXED BY INX,
;; WITH CONSTANT OFFSET GIVEN BY CON
SAVE ;;PUSH IF ACTIVE
IF NUL INX&CON
LXI H,BASE ;;ADDRESS OF BASE
EXITM ;;SIMPLE ADDRESS
ENDIF
;; MUST BE INX AND/OR CON
IF NUL INX
LXI H,CON*2 ;;CONSTANT
ELSE
LHLD INX ;;INDEX TO HL
DAD H ;;DOUBLE PRECISION INX
IF NOT NUL CON
LXI D,CON*2 ;;DOUBLE CONST
DAD D ;;ADDED TO INX
ENDIF ;;NOT NUL CON
ENDIF ;;NUL INX
LXI D,BASE ;;READY TO ADD
DAD D ;;BASE+INX*2+CON*2
ENDM
;
VAL MACRO B,I,C
;; GET VALUE OF B+I+C TO HL
;; CHECK SIMPLE CASE OF B ONLY
IF NUL I&C
SAVE ;;PUSH IF ACTIVE
LHLD B ;;LOAD DIRECTLY
ELSE
;; "ADR" PUSHES ACTIVE REGISTERS
ADR B,I,C ;;ADDRESS IN HL
MOV E,M ;;LOW ORDER BYTE
INX H
MOV D,M ;;HIGH ORDER BYTE
XCHG ;;BACK TO HL
ENDIF
?TR VAL ;;TRACE SET?
ENDM
;
STO MACRO B,I,C
;; STORE THE VALUE OF THE TOP OF STACK
;; LEAVING THE TOP ELEMENT ACTIVE
IF NUL I&C
REST ;;ACTIVATE STACK
SHLD B ;;STORED DIRECTLY TO B
ELSE
ADR B,I,C
POP D ;;VALUE IS IN DE
MOV M,E ;;LOW BYTE
INX H
MOV M,D ;;HIGH BYTE
ENDIF
CLEAR ;;MARK EMPTY
?TR STO ;;TRACE?
ENDM
;
SUM MACRO
REST ;;RESTORE IF SAVED
;; ADD THE TOP TWO STACK ELEMENTS
POP D ;;TOP-1 TO DE
DAD D ;;BACK TO HL
?TR SUM
ENDM
;
DIF MACRO
;; COMPUTE DIFFERENCE BETWEEN TOP ELEMENTS
REST ;;RESTORE IF SAVED
POP D ;;TOP-1 TO DE
MOV A,E ;;TOP-1 LOW BYTE TO A
SUB L ;;LOW ORDER DIFFERENCE
MOV L,A ;;BACK TO L
MOV A,D ;;TOP-1 HIGH BYTE
SBB H ;;HIGH ORDER DIFFERENCE
MOV H,A ;;BACK TO H
;; CARRY FLAG MAY BE SET UPON RETURN
?TR DIF
ENDM
;
LSR MACRO LEN
;; LOGICAL SHIFT RIGHT BY LEN
REST ;;ACTIVATE STACK
REPT LEN ;;GENERATE INLINE
XRA A ;;CLEAR CARRY
MOV A,H
RAR ;;ROTATE WITH HIGH 0
MOV H,A
MOV A,L
RAR
MOV L,A ;;BACK WITH HIGH BIT
ENDM
ENDM
;
GEQ MACRO LAB
;; JUMP TO LAB IF (TOP-1) IS GREATER OR
;; EQUAL TO (TOP) ELEMENT.
DIF ;;COMPUTE DIFFERENCE
CLEAR ;;CLEAR ACTIVE
?TR GEQ
JNC LAB ;;NO CARRY IF GREATER
ORA H ;;BOTH BYTES ZERO?
JZ LAB ;;ZERO IF EQUAL
;; DROP THROUGH IF NEITHER
ENDM
;
DUP MACRO
;; DUPLICATE THE TOP ELEMENT IN THE STACK
REST ;;ENSURE ACTIVE
PUSH H
?TR DUP
ENDM
;
BRN MACRO ADDR
;; BRANCH TO ADDRESS
JMP ADDR
ENDM
;
XIT MACRO
?TR XIT ;;TRACE ON?
JMP 0 ;;RESTART AT 0000
ORG DATA ;;START DATA AREA
DS @STK*2 ;;OBTAINED FROM "SIZ"
STACK: ENDM
;
; *****************************************
; * MEMORY MAPPED I/O SECTION *
; *****************************************
; INPUT VALUES WHICH ARE READ AS IF IN MEMORY
ADC0 EQU 1080H ;A-D CONVERTER 0
ADC1 EQU 1082H ;A-D CONVERTER 1
ADC2 EQU 1084H ;A-D CONVERTER 2
ADC3 EQU 1086H ;A-D CONVERTER 3
;
DAC0 EQU 1090H ;D-A CONVERTER 0
DAC1 EQU 1092H ;D-A CONVERTER 1
DAC2 EQU 1094H ;D-A CONVERTER 2
DAC3 EQU 1096H ;D-A CONVERTER 3
;
RWTRACE MACRO MSG,ADR
;; READ OR WRITE TRACE WITH MESSAGE
;; GIVEN BY "MSG" TO/FROM "ADR"
PRN <MSG AT ADR>
ENDM
;
RDM MACRO ?C
;; READ A-D CONVERTER NUMBER "?C"
SAVE ;;CLEAR THE STACK
IF DEBUGP ;;STOP EXECUTION IN DDT
RWTRACE <A-D INPUT >,% ADC&?C
UGEN ;;ENSURE @IN IS PRESENT
CALL @IN ;;VALUE TO HL
SHLD ADC&?C ;;SIMULATE MEMORY INPUT
ELSE
;; READ FROM MEMORY MAPPED INPUT ADDRESS
LHLD ADC&?C
ENDIF
?TR RDM ;;TRACING?
ENDM
;
WRM MACRO ?C
;; WRITE D-A CONVERTER NUMBER "?C"
REST ;;RESTORE STACK
IF DEBUGP ;;TRACE THE OUTPUT
RWTRACE <D-A OUTPUT>,% DAC&?C
UGEN ;;INCLUDE SUBROUTINES
CALL @AD ;;WRITE THE VALUE
ENDIF
SHLD DAC&?C
?TR WRM ;;TRACING OUTPUT?
CLEAR ;;REMOVE THE VALUE
ENDM
; *****************************************
; * END OF MACRO LIBRARY *
; *****************************************


View File

@@ -0,0 +1,242 @@
; NOTE:
; In order to execute this sample DUMP utility you
; must assemble EXTRN.ASM and then link DUMP and EXTRN to
; create the DUMP.PRL file. This is shown below:
;
; 0A>RMAC dump
; 0A>RMAC extrn
; 0A>LINK dump,extrn[op]
;
title 'File Dump Program'
cseg
; File dump program, reads an input file and
; prints in hex
;
; Copyright (C) 1975, 1976, 1977, 1978, 1979, 1980, 1981
; Digital Research
; Box 579, Pacific Grove
; California, 93950
;
; Externals
extrn bdos
extrn fcb
extrn buff
;
cons equ 1 ;read console
typef equ 2 ;type function
printf equ 9 ;buffer print entry
brkf equ 11 ;break key function
openf equ 15 ;file open
readf equ 20 ;read function
;
; non graphic characters
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
;
; file control block definitions
;fcbdn equ fcb+0 ;disk name
;fcbfn equ fcb+1 ;file name
;fcbft equ fcb+9 ;disk file type (3 characters)
;fcbrl equ fcb+12 ;file's current reel number
;fcbrc equ fcb+15 ;file's record count (0 to 128)
;fcbcr equ fcb+32 ;current (next) record number
;fcbln equ fcb+33 ;fcb length
;
dump:
; set up stack
lxi h,0
dad sp
; entry stack pointer in hl from the ccp
shld oldsp
; set sp to local stack area (restored at finis)
lxi sp,stktop
; print sign on message
lxi d,signon
call prntmsg
; read and print successive buffers
call setup ;set up input file
cpi 255 ;255 if file not present
jnz openok ;skip if open is ok
;
; file not there, give error message and return
lxi d,opnmsg
call prntmsg
jmp finis ;to return
;
openok: ;open operation ok, set buffer index to end
mvi a,80h
sta ibp ;set buffer pointer to 80h
; hl contains next address to print
lxi h,0 ;start with 0000
;
gloop:
push h ;save line position
call gnb
pop h ;recall line position
jc finis ;carry set by gnb if end file
mov b,a
; print hex values
; check for line fold
mov a,l
ani 0fh ;check low 4 bits
jnz nonum
; print line number
call crlf
;
; check for break key
call break
; accum lsb = 1 if character ready
rrc ;into carry
jc purge ;don't print any more
;
mov a,h
call phex
mov a,l
call phex
nonum:
inx h ;to next line number
mvi a,' '
call pchar
mov a,b
call phex
jmp gloop
;
purge:
mvi c,cons
call bdos
finis:
; end of dump, return to ccp
; (note that a jmp to 0000h reboots)
call crlf
lhld oldsp
sphl
; stack pointer contains ccp's stack location
ret ;to the ccp
;
;
; subroutines
;
break: ;check break key (actually any key will do)
push h! push d! push b; environment saved
mvi c,brkf
call bdos
pop b! pop d! pop h; environment restored
ret
;
pchar: ;print a character
push h! push d! push b; saved
mvi c,typef
mov e,a
call bdos
pop b! pop d! pop h; restored
ret
;
crlf:
mvi a,cr
call pchar
mvi a,lf
call pchar
ret
;
;
pnib: ;print nibble in reg a
ani 0fh ;low 4 bits
cpi 10
jnc p10
; less than or equal to 9
adi '0'
jmp prn
;
; greater or equal to 10
p10: adi 'A' - 10
prn: call pchar
ret
;
phex: ;print hex char in reg a
push psw
rrc
rrc
rrc
rrc
call pnib ;print nibble
pop psw
call pnib
ret
;
prntmsg: ;print message
; d,e addresses message ending with "$"
mvi c,printf ;print buffer function
jmp bdos
; ret
;
;
gnb: ;get next byte
lda ibp
cpi 80h
jnz g0
; read another buffer
;
;
call diskr
ora a ;zero value if read ok
jz g0 ;for another byte
; end of data, return with carry set for eof
stc
ret
;
g0: ;read the byte at buff+reg a
mov e,a ;ls byte of buffer index
mvi d,0 ;double precision index to de
inr a ;index=index+1
sta ibp ;back to memory
; pointer is incremented
; save the current file address
lxi h,buff
dad d
; absolute character address is in hl
mov a,m
; byte is in the accumulator
ora a ;reset carry bit
ret
;
setup: ;set up file
; open the file for input
xra a ;zero to accum
sta fcb+32 ;clear current record
;
; open the file in R/O mode
lxi h,fcb+6
mov a,m
ori 80h
mov m,a ;set f6' on
lxi d,fcb
mvi c,openf
call bdos
; 255 in accum if open error
ret
;
diskr: ;read disk file record
push h! push d! push b
lxi d,fcb
mvi c,readf
call bdos
pop b! pop d! pop h
ret
;
; fixed message area
signon:
db 'MP/M II V2.0 File Dump'
db cr,lf,'$'
opnmsg:
db cr,lf,'No input file present on disk$'
; variable area
ibp: ds 2 ;input buffer pointer
oldsp: ds 2 ;entry sp value from ccp
;
; stack area
ds 64 ;reserve 32 level stack
stktop:
;
end dump


View File

@@ -0,0 +1,14 @@
title 'External Reference Module'
bdos equ 0005h
fcb equ 005ch
tfcb equ 006ch
buff equ 0080h
public bdos
public fcb
public tfcb
public buff
end


View File

@@ -0,0 +1,17 @@
; INTEL 8085 MACRO LIBRARY
;
; THE SIM (SET INTERRUPT MASK),
; AND RIM (READ INTERRUPT MASK)
; ARE DEFINED BY THE FOLLOWING MACROS:
;
SIM MACRO
;; SET INTERRUPT MASK FROM REG-A VALUE
DB 30H ;;OPCODE FOR SIM
ENDM
;
RIM MACRO
;; READ INTERRUPT MASK TO REG-A
DB 20H ;;OPCODE FOR RIM
ENDM
;


View File

@@ -0,0 +1,80 @@
; MACRO LIBRARY FOR BASIC INTERSECTION
;
; GLOBAL DEFINITIONS FOR DEBUG PROCESSING
TRUE EQU 0FFFFH ;VALUE OF TRUE
FALSE EQU NOT TRUE;VALUE OF FALSE
DEBUG SET FALSE ;INITIALLY FALSE
BDOS EQU 5 ;ENTRY TO CP/M BDOS
RCHAR EQU 1 ;READ CHARACTER FUNCTION
WBUFF EQU 9 ;WRITE BUFFER FUNCTION
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
;
; INPUT/OUTPUT PORTS FOR LIGHT AND CLOCK
LIGHT EQU 00H ;TRAFFIC LIGHT CONTROL
CLOCK EQU 03H ;24 HOUR CLOCK (0,1,...,23)
;
; BIT POSITIONS FOR TRAFFIC LIGHT CONTROL
NSBITS EQU 4 ;NORTH SOUUTH BITS
EWBITS EQU 0 ;EAST WEST BITS
;
; CONSTANT VALUES FOR THE LIGHT CONTROL
OFF EQU 0 ;TURN LIGHT OFF
RED EQU 1 ;VALUE FOR RED LIGHT
YELLOW EQU 2 ;VALUE FOR YELLOW LIGHT
GREEN EQU 3 ;GREEN LIGHT
;
SETLITE MACRO DIR,COLOR
;; SET LIGHT GIVEN BY "DIR" TO COLOR GIVEN BY "COLOR"
IF DEBUG ;;PRINT INFO AT CONSOLE
LOCAL SETMSG,PASTMSG
MVI C,WBUFF ;;WRITE BUFFER FUNCTION
LXI D,SETMSG
CALL BDOS ;;WRITE THE TRACE INFO
JMP PASTMSG
SETMSG: DB CR,LF
DB '&DIR CHANGING TO &COLOR$'
PASTMSG:
EXITM
ENDIF
MVI A,COLOR SHL DIR&BITS ;;READIED
OUT LIGHT ;;SENT IN PROPER BIT POSITION
ENDM
;
TIMER MACRO SECONDS
;; CONSTRUCT INLINE TIME-OUT LOOP
LOCAL T1,T2,T3 ;;LOOP ENTRIES
MVI D,4*SECONDS ;;BASIC LOOP CONTROL
T1: MVI B,250 ;;250MSEC *4 = 1 SEC
T2: MVI C,182 ;;182*5.5USEC = 1MSEC
T3: DCR C ;;1 CY = .5 USEC
JNZ T3 ;;+10 CY = 5.5 USEC
DCR B ;;COUNT 250,249...
JNZ T2 ;;LOOP ON B REGISTER
DCR D ;;BASIC LOOP CONTROL
JNZ T1 ;;LOOP ON D REGISTER
;; ARRIVE HERE WITH APPROXIMATELY "SECONDS"
;; TIMEOUT, CONTINUE PROCESSING.
ENDM
;
CLOCK? MACRO LOW,HIGH,IFTRUE
;; CHECK FOR REAL-TIME CLOCK GREATER THAN OR
;; EQUAL TO "LOW." AND LESS THAN "HIGH."
;; CONTINUE AT "IFTRUE" WHEN BETWEEN THESE
;; TIMES.
LOCAL IFFALSE ;;ALTERNATE TO TRUE CASE
IN CLOCK ;;READ REAL-TIME CLOCK
IF NOT NUL HIGH ;;CHECK HIGH CLOCK
CPI HIGH ;;EQUAL OR GREATER?
JNC IFFALSE ;;SKIP TO END IF SO
ENDIF
CPI LOW ;;LESS THAN LOW VALUE?
JNC IFTRUE ;;SKIP TO LABEL IF NOT
IFFALSE:
ENDM
;
RETRY MACRO GOLABEL
;; CONTINUE EXECUTION AT "GOLABEL"
JMP GOLABEL
ENDM


View File

@@ -0,0 +1,417 @@
; MP/M 2.0 Loader BIOS
; (modified CP/M 2.2 BIOS)
; MDS I/O drivers for CP/M 2.2
; (single drive, single density)
; -or-
; (single drive, double density)
; Version 2.0 -- Sept 81
vers equ 20 ;version 2.0
; Copyright (C) 1980, 1981
; Digital Research
; Box 579, Pacific Grove
; California, 93950
false equ 0
true equ not false
asm equ true
mac equ not asm
sgl equ true
dbl equ not sgl
if mac
maclib diskdef
numdsks equ 1 ;number of drives available
endif
ram$top equ 1d00h ; top address+1
bios equ ram$top-0600h ; basic input/output system
bdos equ bios-0e00h ; base of the bdos
org bios
buff equ 0080h ;default buffer address
retry equ 10 ;max retries on disk i/o before error
; jump vector for indiviual routines
jmp boot
wboote: jmp wboot
jmp const
jmp conin
jmp conout
jmp list
jmp punch
jmp reader
jmp home
jmp seldsk
jmp settrk
jmp setsec
jmp setdma
jmp read
jmp write
jmp list$st ; list status poll
jmp sect$tran ; sector translation
; we also assume the MDS system has four disk drives
numdisks equ 1 ;number of drives available
revrt equ 0fdh ;interrupt revert port
intc equ 0fch ;interrupt mask port
icon equ 0f3h ;interrupt control port
inte equ 0111$1110b ;enable rst 0(warm boot), rst 7 (monitor)
; MDS monitor equates
rmon80 equ 0ff0fh ;restart mon80 (boot error)
; disk ports and commands
base equ 78h ;base of disk command io ports
dstat equ base ;disk status (input)
rtype equ base+1 ;result type (input)
rbyte equ base+3 ;result byte (input)
ilow equ base+1 ;iopb low address (output)
ihigh equ base+2 ;iopb high address (output)
readf equ 4h ;read function
writf equ 6h ;write function
recal equ 3h ;recalibrate drive
iordy equ 4h ;i/o finished mask
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
boot:
wboot:
gocpm:
ret
crtin: ; crt: input
in 0f7h ! ani 2 ! jz crtin
in 0f6h ! ani 7fh
ret
crtout: ; crt: output
in 0f7h ! ani 1 ! jz crtout
mov a,c ! out 0f6h
ret
crtst: ; crt: status
in 0f7h ! ani 2 ! rz
ori 0ffh
ret
ttyin: ; tty: input
in 0f5h ! ani 2 ! jz ttyin
in 0f4h ! ani 7fh
ret
ttyout: ; tty: output
in 0f5h ! ani 1 ! jz ttyout
mov a,c ! out 0f4h
ret
;ttyst:
; in 0f5h ! ani 2 ! rz
; ori -1
; ret
lptout: ; lpt: output
in 0fbh ! ani 1 ! jz lptout
mov a,c ! cma ! out 0fah
ret
lpt$st:
in 0fbh ! ani 1 ! rz
ori 0ffh
ret
conin equ crtin
const equ crtst
conout equ crtout
reader equ ttyin
punch equ ttyout
list equ lptout
listst equ lptst
seldsk: ;select disk given by register c
lxi h, 0 ! mov a,c ! cpi num$disks ! rnc ; first, insure good select
ani 2 ! sta dbank ; then save it
lxi h,sel$table ! mvi b,0 ! dad b ! mov a,m ! sta iof
mov h,b ! mov l,c
dad h ! dad h ! dad h ! dad h ; times 16
lxi d,dpbase ! dad d
ret
home: ;move to home position
; treat as track 00 seek
mvi c,0
;
settrk: ;set track address given by c
lxi h,iot
mov m,c
ret
;
setsec: ;set sector number given by c
mov a,c ;sector number to accum
sta ios ;store sector number to iopb
ret
;
setdma: ;set dma address given by regs b,c
mov l,c
mov h,b
shld iod
ret
sect$tran: ; translate the sector # in <c> if needed
mov h,b ! mov l,c ! inx h ; in case of no translation
mov a, d ! ora e ! rz
xchg ! dad b ; point to physical sector
mov l,m ! mvi h,0
ret
read: ;read next disk record (assuming disk/trk/sec/dma set)
mvi c,readf ;set to read function
jmp setfunc
;
write: ;disk write function
mvi c,writf
;
setfunc:
; set function for next i/o (command in reg-c)
lxi h,iof ;io function address
mov a,m ;get it to accumulator for masking
ani 1111$1000b ;remove previous command
ora c ;set to new command
mov m,a ;replaced in iopb
; single density drive 1 requires bit 5 on in sector #
; mask the bit from the current i/o function
ani 0010$0000b ;mask the disk select bit
lxi h,ios ;address the sector select byte
ora m ;select proper disk bank
mov m,a ;set disk select bit on/off
;
waitio:
mvi c,retry ;max retries before perm error
rewait:
; start the i/o function and wait for completion
call intype ;in rtype
call inbyte ;clears the controller
lda dbank ;set bank flags
ora a ;zero if drive 0,1 and nz if 2,3
mvi a,iopb and 0ffh ;low address for iopb
mvi b,iopb shr 8 ;high address for iopb
jnz iodr1 ;drive bank 1?
out ilow ;low address to controller
mov a,b
out ihigh ;high address
jmp wait0 ;to wait for complete
iodr1: ;drive bank 1
out ilow+10h ;88 for drive bank 10
mov a,b
out ihigh+10h
wait0: call instat ;wait for completion
ani iordy ;ready?
jz wait0
; check io completion ok
call intype ;must be io complete (00) unlinked
; 00 unlinked i/o complete, 01 linked i/o complete (not used)
; 10 disk status changed 11 (not used)
cpi 10b ;ready status change?
jz wready
; must be 00 in the accumulator
ora a
jnz werror ;some other condition, retry
; check i/o error bits
call inbyte
ral
jc wready ;unit not ready
rar
ani 11111110b ;any other errors? (deleted data ok)
jnz werror
; read or write is ok, accumulator contains zero
ret
wready: ;not ready, treat as error for now
call inbyte ;clear result byte
jmp trycount
werror: ;return hardware malfunction (crc, track, seek, etc.)
; the MDS controller has returned a bit in each position
; of the accumulator, corresponding to the conditions:
; 0 - deleted data (accepted as ok above)
; 1 - crc error
; 2 - seek error
; 3 - address error (hardware malfunction)
; 4 - data over/under flow (hardware malfunction)
; 5 - write protect (treated as not ready)
; 6 - write error (hardware malfunction)
; 7 - not ready
; (accumulator bits are numbered 7 6 5 4 3 2 1 0)
trycount:
; register c contains retry count, decrement 'til zero
dcr c
jnz rewait ;for another try
; cannot recover from error
mvi a,1 ;error code
ret
; intype, inbyte, instat read drive bank 00 or 10
intype: lda dbank
ora a
jnz intyp1 ;skip to bank 10
in rtype
ret
intyp1: in rtype+10h ;78 for 0,1 88 for 2,3
ret
inbyte: lda dbank
ora a
jnz inbyt1
in rbyte
ret
inbyt1: in rbyte+10h
ret
instat: lda dbank
ora a
jnz insta1
in dstat
ret
insta1: in dstat+10h
ret
; utility subroutines
prmsg: ;print message at h,l to 0
mov a,m ! ora a ! rz
push h ! mov c,a ! call conout ! pop h
inx h ! jmp prmsg
; data areas (must be in ram)
dbank: db 0 ;disk bank 00 if drive 0,1
; 10 if drive 2,3
iopb: ;io parameter block
db 80h ;normal i/o operation
iof: db readf ;io function, initial read
ion: db 1 ;number of sectors to read
iot: db 2 ;track number
ios: db 1 ;sector number
iod: dw buff ;io address
;
;
sel$table:
if sgl
db 00h, 30h, 00h, 30h ; drive select bits
endif
if dbl
db 00h, 10h, 00h, 30h ; drive select bits
endif
if mac and sgl
disks numdisks ; generate drive tables
diskdef 0,1,26,6,1024,243,64,64,2
endef
endif
if mac and dbl
disks numdisks ; generate drive tables
diskdef 0,1,52,,2048,243,128,128,2,0
endef
endif
if asm
dpbase equ $ ;base of disk param blks
dpe0: dw xlt0,0000h ;translate table
dw 0000h,0000h ;scratch area
dw dirbuf,dpb0 ;dir buff, parm block
dw csv0,alv0 ;check, alloc vectors
dpb0 equ $ ;disk param block
endif
if asm and sgl
dw 26 ;sec per track
db 3 ;block shift
db 7 ;block mask
db 0 ;extnt mask
dw 242 ;disk size-1
dw 63 ;directory max
db 192 ;alloc0
db 0 ;alloc1
dw 16 ;check size
dw 2 ;offset
xlt0 equ $ ;translate table
db 1
db 7
db 13
db 19
db 25
db 5
db 11
db 17
db 23
db 3
db 9
db 15
db 21
db 2
db 8
db 14
db 20
db 26
db 6
db 12
db 18
db 24
db 4
db 10
db 16
db 22
endif
if asm and dbl
xlt0 equ 0
endif
if asm
begdat equ $
dirbuf: ds 128 ;directory access buffer
alv0: ds 31
csv0: ds 16
endif
if asm and dbl
ds 16
endif
if asm
enddat equ $
datsiz equ $-begdat
endif
end


View File

@@ -0,0 +1,77 @@
; MACRO LIBRARY FOR 8-BIT COMPARISON OPERATION
;
TEST? MACRO X,Y
;; UTILTITY MACRO TO GENERATE CONDITION CODES
IF NOT NUL X ;;THEN LOAD X
LDA X ;;X ASSUMED TO BE IN MEMORY
ENDIF
IRPC ?Y,Y ;;Y MAY BE CONSTANT OPERAND
TDIG? SET '&?Y'-'0' ;;FIRST CHAR DIGIT?
EXITM ;;STOP IRPC AFTER FIRST CHAR
ENDM
IF TDIG? <= 9 ;;Y NUMERIC?
SUI Y ;;YES, SO SUB IMMEDIATE
ELSE
LXI H,Y ;;Y NOT NUMERIC
SUB M ;;SO SUB FROM MEMORY
ENDM
;
LSS MACRO X,Y,TL,FL
;; X LSS THAN Y TEST,
;; IF TL IS PRESENT, ASSUME TRUE TEST
;; IF TL IS ABSENT, THEN INVERT TEST
IF NUL TL
GEQ X,Y,FL
ELSE
TEST? X,Y ;;SET CONDITION CODES
JC TL
ENDM
;
LEQ MACRO X,Y,TL,FL
;; X LESS THAN OR EQUAL TO Y TEST
IF NUL TL
GEQ X,Y,FL
ELSE
LSS X,Y,TL
JZ TL
ENDM
;
EQL MACRO X,Y,TL,FL
;; X EQUAL TO Y TEST
IF NUL TL
NEQ X,Y,FL
ELSE
TEST? X,Y
JZ TL
ENDM
;
NEQ MACRO X,Y,TL,FL
;; X NOT EQUAL TO Y TEST
IF NUL TL
EQL X,Y,FL
ELSE
TEST? X,Y
JNZ TL
ENDM
;
GEQ MACRO X,Y,TL,FL
;; X GREATER THAN OR EQUAL TO Y TEST
IF NUL TL
LSS X,Y,FL
ELSE
TEST? X,Y
JNC TL
ENDM
;
GTR MACRO X,Y,TL,FL
;; X GREATER THAN Y TEST
IF NUL TL
LEQ X,Y,FL
ELSE
LOCAL GFL ;;FALSE LABEL
TEST? X,Y
JC GFL
DCR A
JNC TL
GFL: ENDM


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
; MACRO LIBRARY FOR "SELECT" CONSTRUCT
;
; LABEL GENERATORS
GENSLXI MACRO NUM
;; LOAD HL WITH ADDRESS OF CASE LIST
LXI H,SELV&NUM
ENDM
;
GENCASE MACRO NUM,ELT
;; GENERATE JMP TO END OF CASES
IF ELT GT 0
JMP ENDS&NUM ;;PAST ADDR LIST
ENDIF
;; GENERATE LABEL FOR THIS CASE
CASE&NUM&@&ELT:
ENDM
;
GENELT MACRO NUM,ELT
;; GENERATE ONE ELEMENT OF CASE LIST
DW CASE&NUM&@&ELT
ENDM
;
GENSLAB MACRO NUM,ELTS
;; GENERATE CASE LIST
SELV&NUM:
ECNT SET 0 ;;COUNT ELEMENTS
REPT ELTS ;;GENERATE DW'S
GENELT NUM,%ECNT
ECNT SET ECNT+1
ENDM ;;END OF DW'S
;; GENERATE END OF CASE LIST LABEL
ENDS&NUM:
ENDM
;
SELNEXT MACRO
;; GENERATE THE NEXT CASE
GENCASE %CCNT,%ECNT
;; INCREMENT THE CASE ELEMENT COUNT
ECNT SET ECNT+1
ENDM
;
SELECT MACRO VAR
;; GENERATE CASE SELECTION CODE
CCNT SET 0 ;;COUNT "SELECTS"
SELECT MACRO V ;;REDEFINITION OF SELECT
;; SELECT ON V OR ACCUMULATOR CONTENTS
IF NOT NUL V
LDA V ;;LOAD SELECT VARIABLE
ENDIF
GENSLXI %CCNT ;;GENERATE THE LXI H,SELV#
MOV E,A ;;CREATE DOUBLE PRECISION
MVI D,0 ;;V IN D,E PAIR
DAD D ;;SINGLE PREC INDEX
DAD D ;;DOUBLE PREC INDEX
MOV E,M ;;LOW ORDER BRANCH ADDR
INX H ;;TO HIGH ORDER BYTE
MOV D,M ;;HIGH ORDER BRANCH INDEX
XCHG ;;READY BRANCH ADDRESS IN HL
PCHL ;;GONE TO THE PROPER CASE
ECNT SET 0 ;;ELEMENT COUNTER RESET
SELNEXT ;;SELECT CASE 0
ENDM
;; INVOKE REDEFINED SELECT THE FIRST TIME
SELECT VAR
ENDM
;
ENDSEL MACRO
;; END OF SELECT, GENERATE CASE LIST
GENCASE %CCNT,%ECNT ;;LAST CASE
GENSLAB %CCNT,%ECNT ;;CASE LIST
;; INCREMENT "SELECT" COUNT
CCNT SET CCNT+1
ENDM


View File

@@ -0,0 +1,439 @@
; SEQUENTIAL FILE I/O LIBRARY
;
FILERR SET 0000H ;REBOOT AFTER ERROR
@BDOS EQU 0005H ;BDOS ENTRY POINT
@TFCB EQU 005CH ;DEFAULT FILE CONTROL BLOCK
@TBUF EQU 0080H ;DEFAULT BUFFER ADDRESS
;
; BDOS FUNCTIONS
@MSG EQU 9 ;SEND MESSAGE
@OPN EQU 15 ;FILE OPEN
@CLS EQU 16 ;FILE CLOSE
@DIR EQU 17 ;DIRECTORY SEARCH
@DEL EQU 19 ;FILE DELETE
@FRD EQU 20 ;FILE READ OPERATION
@FWR EQU 21 ;FILE WRITE OPERATION
@MAK EQU 22 ;FILE MAKE
@REN EQU 23 ;FILE RENAME
@DMA EQU 26 ;SET DMA ADDRESS
;
@SECT EQU 128 ;SECTOR SIZE
EOF EQU 1AH ;END OF FILE
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
TAB EQU 09H ;HORIZONTAL TAB
;
@KEY EQU 1 ;KEYBOARD
@CON EQU 2 ;CONSOLE DISPLAY
@RDR EQU 3 ;READER
@PUN EQU 4 ;PUNCH
@LST EQU 5 ;LIST DEVICE
;
; KEYWORDS FOR "FILE" MACRO
INFILE EQU 1 ;INPUT FILE
OUTFILE EQU 2 ;OUTPUTFILE
SETFILE EQU 3 ;SETUP NAME ONLY
;
; THE FOLLOWING MACROS DEFINE SIMPLE SEQUENTIAL
; FILE OPERATIONS:
;
FILLNAM MACRO FC,C
;; FILL THE FILE NAME/TYPE GIVEN BY FC FOR C CHARACTERS
@CNT SET C ;;MAX LENGTH
IRPC ?FC,FC ;;FILL EACH CHARACTER
;; MAY BE END OF COUNT OR NUL NAME
IF @CNT=0 OR NUL ?FC
EXITM
ENDIF
DB '&?FC' ;;FILL ONE MORE
@CNT SET @CNT-1 ;;DECREMENT MAX LENGTH
ENDM ;;OF IRPC ?FC
;;
;; PAD REMAINDER
REPT @CNT ;;@CNT IS REMAINDER
DB ' ' ;;PAD ONE MORE BLANK
ENDM ;;OF REPT
ENDM
;
FILLDEF MACRO FCB,?FL,?LN
;; FILL THE FILE NAME FROM THE DEFAULT FCB
;; FOR LENGTH ?LN (9 OR 12)
LOCAL PSUB
JMP PSUB ;;JUMP PAST THE SUBROUTINE
@DEF: ;;THIS SUBROUTINE FILLS FROM THE TFCB (+16)
MOV A,M ;;GET NEXT CHARACTER TO A
STAX D ;;STORE TO FCB AREA
INX H
INX D
DCR C ;;COUNT LENGTH DOWN TO 0
JNZ @DEF
RET
;; END OF FILL SUBROUTINE
PSUB:
FILLDEF MACRO ?FCB,?F,?L
LXI H,@TFCB+?F ;;EITHER @TFCB OR @TFCB+16
LXI D,?FCB
MVI C,?L ;;LENGTH = 9,12
CALL @DEF
ENDM
FILLDEF FCB,?FL,?LN
ENDM
;
FILLNXT MACRO
;; INITIALIZE BUFFER AND DEVICE NUMBERS
@NXTB SET 0 ;;NEXT BUFFER LOCATION
@NXTD SET @LST+1 ;;NEXT DEVICE NUMBER
FILLNXT MACRO
ENDM
ENDM
;
FILLFCB MACRO FID,DN,FN,FT,BS,BA
;; FILL THE FILE CONTROL BLOCK WITH DISK NAME
;; FID IS AN INTERNAL NAME FOR THE FILE,
;; DN IS THE DRIVE NAME (A,B..), OR BLANK
;; FN IS THE FILE NAME, OR BLANK
;; FT IS THE FILE TYPE
;; BS IS THE BUFFER SIZE
;; BA IS THE BUFFER ADDRESS
LOCAL PFCB
;;
;; SET UP THE FILE CONTROL BLOCK FOR THE FILE
;; LOOK FOR FILE NAME = 1 OR 2
@C SET 1 ;;ASSUME TRUE TO BEGIN WITH
IRPC ?C,FN ;;LOOK THROUGH CHARACTERS OF NAME
IF NOT ('&?C' = '1' OR '&?C' = '2')
@C SET 0 ;;CLEAR IF NOT 1 OR 2
ENDM
;; @C IS TRUE IF FN = 1 OR 2 AT THIS POINT
IF @C ;;THEN FN = 1 OR 2
;; FILL FROM DEFAULT AREA
IF NUL FT ;;TYPE SPECIFIED?
@C SET 12 ;;BOTH NAME AND TYPE
ELSE
@C SET 9 ;;NAME ONLY
ENDIF
FILLDEF FCB&FID,(FN-1)*16,@C ;;TO SELECT THE FCB
JMP PFCB ;;PAST FCB DEFINITION
DS @C ;;SPACE FOR DRIVE/FILENAME/TYPE
FILLNAM FT,12-@C ;;SERIES OF DB'S
ELSE
JMP PFCB ;;PAST INITIALIZED FCB
IF NUL DN
DB 0 ;;USE DEFAULT DRIVE IF NAME IS ZERO
ELSE
DB '&DN'-'A'+1 ;;USE SPECIFIED DRIVE
ENDIF
FILLNAM FN,8 ;;FILL FILE NAME
;; NOW GENERATE THE FILE TYPE WITH PADDED BLANKS
FILLNAM FT,3 ;;AND THREE CHARACTER TYPE
ENDIF
FCB&FID EQU $-12 ;;BEGINNING OF THE FCB
DB 0 ;;EXTENT FIELD 00 FOR SETFILE
;; NOW DEFINE THE 3 BYTE FIELD, AND DISK MAP
DS 20 ;;X,X,RC,DM0...DM15,CR FIELDS
;;
IF FID&TYP<=2 ;;IN/OUTFILE
;; GENERATE CONSTANTS FOR INFILE/OUTFILE
FILLNXT ;;@NXTB=0 ON FIRST CALL
IF BS+0<@SECT
;; BS NOT SUPPLIED, OR TOO SMALL
@BS SET @SECT ;;DEFAULT TO ONE SECTOR
ELSE
;; COMPUTE EVEN BUFFER ADDRESS
@BS SET (BS/@SECT)*@SECT
ENDIF
;;
;; NOW DEFINE BUFFER BASE ADDRESS
IF NUL BA
;; USE NEXT ADDRESS AFTER @NXTB
FID&BUF SET BUFFERS+@NXTB
;; COUNT PAST THIS BUFFER
@NXTB SET @NXTB+@BS
ELSE
FID&BUF SET BA
ENDIF
;; FID&BUF IS BUFFER ADDRESS
FID&ADR:
DW FID&BUF
;;
FID&SIZ EQU @BS ;;LITERAL SIZE
FID&LEN:
DW @BS ;;BUFFER SIZE
FID&PTR:
DS 2 ;;SET IN INFILE/OUTFILE
;; SET DEVICE NUMBER
@&FID SET @NXTD ;;NEXT DEVICE
@NXTD SET @NXTD+1
ENDIF ;;OF FID&TYP<=2 TEST
PFCB: ENDM
;
FILE MACRO MD,FID,DN,FN,FT,BS,BA
;; CREATE FILE USING MODE MD:
;; INFILE = 1 INPUT FILE
;; OUTFILE = 2 OUTPUT FILE
;; SETFILE = 3 SETUP FCB
;; (SEE FILLFCB FOR REMAINING PARAMETERS)
LOCAL PSUB,MSG,PMSG
LOCAL PND,EOD,EOB,PNC
;; CONSTRUCT THE FILE CONTROL BLOCK
;;
FID&TYP EQU MD ;;SET MODE FOR LATER REF'S
FILLFCB FID,DN,FN,FT,BS,BA
IF MD=3 ;;SETUP FCB ONLY, SO EXIT
EXITM
ENDIF
;; FILE CONTROL BLOCK AND RELATED PARAMETERS
;; ARE CREATED INLINE, NOW CREATE IO FUNCTION
JMP PSUB ;;PAST INLINE SUBROUTINE
IF MD=1 ;;INPUT FILE
GET&FID:
ELSE
PUT&FID:
PUSH PSW ;;SAVE OUTPUT CHARACTER
ENDIF
LHLD FID&LEN ;;LOAD CURRENT BUFFER LENGTH
XCHG ;;DE IS LENGTH
LHLD FID&PTR ;;LOAD NEXT TO GET/PUT TO HL
MOV A,L ;;COMPUTE CUR-LEN
SUB E
MOV A,H
SBB D ;;CARRY IF NEXT<LENGTH
JC PNC ;;CARRY IF LEN GTR CURRENT
;; END OF BUFFER, FILL/EMPTY BUFFERS
LXI H,0
SHLD FID&PTR ;;CLEAR NEXT TO GET/PUT
PND:
;; PROCESS NEXT DISK SECTOR:
XCHG ;;FID&PTR TO DE
LHLD FID&LEN ;;DO NOT EXCEED LENGTH
;; DE IS NEXT TO FILL/EMPTY, HL IS MAX LEN
MOV A,E ;;COMPUTE NEXT-LEN
SUB L ;;TO GET CARRY IF MORE
MOV A,D
SBB H ;;TO FILL
JNC EOB
;; CARRY GEN'ED, HENCE MORE TO FILL/EMPTY
LHLD FID&ADR ;;BASE OF BUFFERS
DAD D ;;HL IS NEXT BUFFER ADDR
XCHG
MVI C,@DMA ;;SET DMA ADDRESS
CALL @BDOS ;;DMA ADDRESS IS SET
LXI D,FCB&FID ;;FCB ADDRESS TO DE
IF MD=1 ;;READ BUFFER FUNCTION
MVI C,@FRD ;;FILE READ FUNCTION
ELSE
MVI C,@FWR ;;FILE WRITE FUNCTION
ENDIF
CALL @BDOS ;;RD/WR TO/FROM DMA ADDRESS
ORA A ;;CHECK RETURN CODE
JNZ EOD ;;END OF FILE/DISK?
;; NOT END OF FILE/DISK, INCREMENT LENGTH
LXI D,@SECT ;;SECTOR SIZE
LHLD FID&PTR ;;NEXT TO FILL
DAD D
SHLD FID&PTR ;;BACK TO MEMORY
JMP PND ;;PROCESS ANOTHER SECTOR
;;
EOD:
;; END OF FILE/DISK ENCOUNTERED
IF MD=1 ;;INPUT FILE
LHLD FID&PTR ;;LENGTH OF BUFFER
SHLD FID&LEN ;;RESET LENGTH
ELSE
;; FATAL ERROR, END OF DISK
LOCAL EMSG
MVI C,@MSG ;;WRITE THE ERROR
LXI D,EMSG
CALL @BDOS ;;ERROR TO CONSOLE
POP PSW ;;REMOVE STACKED CHARACTER
JMP FILERR ;;USUALLY REBOOTS
EMSG: DB CR,LF
DB 'DISK FULL: &FID'
DB '$'
ENDIF
;;
EOB:
;; END OF BUFFER, RESET DMA AND POINTER
LXI D,@TBUF
MVI C,@DMA
CALL @BDOS
LXI H,0
SHLD FID&PTR ;;NEXT TO GET
;;
PNC:
;; PROCESS THE NEXT CHARACTER
XCHG ;;INDEX TO GET/PUT IN DE
LHLD FID&ADR ;;BASE OF BUFFER
DAD D ;;ADDRESS OF CHAR IN HL
XCHG ;;ADDRESS OF CHAR IN DE
IF MD=1 ;;INPUT PROCESSING DIFFERS
LHLD FID&LEN ;;FOR EOF CHECK
MOV A,L ;;0000?
ORA H
MVI A,EOF ;;END OF FILE?
RZ ;;ZERO FLAG IF SO
LDAX D ;;NEXT CHAR IN ACCUM
ELSE
;; STORE NEXT CHARACTER FROM ACCUMULATOR
POP PSW ;;RECALL SAVED CHAR
STAX D ;;CHARACTER IN BUFFER
ENDIF
LHLD FID&PTR ;;INDEX TO GET/PUT
INX H
SHLD FID&PTR ;;POINTER UPDATED
;; RETURN WITH NON ZERO FLAG IF GET
RET
;;
PSUB: ;;PAST INLINE SUBROUTINE
XRA A ;;ZERO TO ACC
STA FCB&FID+12 ;;CLEAR EXTENT
STA FCB&FID+32 ;;CLEAR CUR REC
LXI H,FID&SIZ ;;BUFFER SIZE
SHLD FID&LEN ;;SET BUFF LEN
IF MD=1 ;;INPUT FILE
SHLD FID&PTR ;;CAUSE IMMEDIATE READ
MVI C,@OPN ;;OPEN FILE FUNCTION
ELSE ;;OUTPUT FILE
LXI H,0 ;;SET NEXT TO FILL
SHLD FID&PTR ;;POINTER INITIALIZED
MVI C,@DEL
LXI D,FCB&FID ;;DELETE FILE
CALL @BDOS ;;TO CLEAR EXISTING FILE
MVI C,@MAK ;;CREATE A NEW FILE
ENDIF
;; NOW OPEN (IF INPUT), OR MAKE (IF OUTPUT)
LXI D,FCB&FID
CALL @BDOS ;;OPEN/MAKE OK?
INR A ;;255 BECOMES 00
JNZ PMSG
MVI C,@MSG ;;PRINT MESSAGE FUNCTION
LXI D,MSG ;;ERROR MESSAGE
CALL @BDOS ;;PRINTED AT CONSOLE
JMP FILERR ;;TO RESTART
MSG: DB CR,LF
IF MD=1 ;;INPUT MESSAGE
DB 'NO &FID FILE'
ELSE
DB 'NO DIR SPACE: &FID'
ENDIF
DB '$'
PMSG:
ENDM
;
PUT MACRO DEV
;; WRITE CHARACTER FROM ACCUM TO DEVICE
IF @&DEV <= @LST
;; SIMPLE OUTPUT
PUSH PSW ;;SAVE CHARACTER
MVI C,@&DEV ;;WRITE CHAR FUNCTION
MOV E,A ;;READY FOR OUTPUT
CALL @BDOS ;;WRITE CHARACTER
POP PSW ;;RESTORE FOR TESTING
ELSE
CALL PUT&DEV
ENDM
;
FINIS MACRO FID
;; CLOSE THE FILE(S) GIVEN BY FID
IRP ?F,<FID>
;; SKIP ALL BUT OUTPUT FILES
IF ?F&TYP=2
LOCAL EOB?,PEOF,MSG,PMSG
;; WRITE ALL PARTIALLY FILLED BUFFERS
EOB?: ;;ARE WE AT THE END OF A BUFFER?
LHLD ?F&PTR ;;NEXT TO FILL
MOV A,L ;;ON BUFFER BOUNDARY?
ANI (@SECT-1) AND 0FFH
JNZ PEOF ;;PUT EOF IF NOT 00
IF @SECT>255
;; CHECK HIGH ORDER BYTE ALSO
MOV A,H
ANI (@SECT-1) SHR 8
JNZ PEOF ;;PUT EOF IF NOT 00
ENDIF
;; ARRIVE HERE IF END OF BUFFER, SET LENGTH
;; AND WRITE ONE MORE BYTE TO CLEAR BUFFS
SHLD ?F&LEN ;;SET TO SHORTER LENGTH
PEOF: MVI A,EOF ;;WRITE ANOTHER EOF
PUSH PSW ;;SAVE ZERO FLAG
CALL PUT&?F
POP PSW ;;RECALL ZERO FLAG
JNZ EOB? ;;NON ZERO IF MORE
;; BUFFERS HAVE BEEN WRITTEN, CLOSE FILE
MVI C,@CLS
LXI D,FCB&?F ;;READY FOR CALL
CALL @BDOS
INR A ;;255 IF ERR BECOMES 00
JNZ PMSG
;; FILE CANNOT BE CLOSED
MVI C,@MSG
LXI D,MSG
CALL @BDOS
JMP PMSG ;;ERROR MESSAGE PRINTED
MSG: DB CR,LF
DB 'CANNOT CLOSE &?F'
DB '$'
PMSG:
ENDIF
ENDM ;;OF THE IRP
ENDM
;
ERASE MACRO FID
;; DELETE THE FILE(S) GIVEN BY FID
IRP ?F,<FID>
MVI C,@DEL
LXI D,FCB&?F
CALL @BDOS
ENDM ;;OF THE IRP
ENDM
;
DIRECT MACRO FID
;; PERFORM DIRECTORY SEARCH FOR FILE
;; SETS ZERO FLAG IF NOT PRESENT
LXI D,FCB&FID
MVI C,@DIR
CALL @BDOS
INR A ;00 IF NOT PRESENT
ENDM
;
RENAME MACRO NEW,OLD
;; RENAME FILE GIVEN BY "OLD" TO "NEW"
LOCAL PSUB,REN0
;; INCLUDE THE RENAME SUBROUTINE ONCE
JMP PSUB
@RENS: ;;RENAME SUBROUTINE, HL IS ADDRESS OF
;;OLD FCB, DE IS ADDRESS OF NEW FCB
PUSH H ;;SAVE FOR RENAME
LXI B,16 ;;B=00,C=16
DAD B ;;HL = OLD FCB+16
REN0: LDAX D ;;NEW FCB NAME
MOV M,A ;;TO OLD FCB+16
INX D ;;NEXT NEW CHAR
INX H ;;NEXT FCB CHAR
DCR C ;;COUNT DOWN FROM 16
JNZ REN0
;; OLD NAME IN FIRST HALF, NEW IN SECOND HALF
POP D ;;RECALL BASE OF OLD NAME
MVI C,@REN ;;RENAME FUNCTION
CALL @BDOS
RET ;;RENAME COMPLETE
PSUB:
RENAME MACRO N,O ;;REDEFINE RENAME
LXI H,FCB&O ;;OLD FCB ADDRESS
LXI D,FCB&N ;;NEW FCB ADDRESS
CALL @RENS ;;RENAME SUBROUTINE
ENDM
RENAME NEW,OLD
ENDM
;
GET MACRO DEV
;; READ CHARACTER FROM DEVICE
IF @&DEV <= @LST
;; SIMPLE INPUT
MVI C,@&DEV
CALL @BDOS
ELSE
CALL GET&DEV
ENDM
;


View File

@@ -0,0 +1,26 @@
; MACRO LIBRARY FOR SIMPLE I/O
BDOS EQU 0005H ;BDOS ENTRY
CONIN EQU 1 ;CONSOLE INPUT FUNCTION
MSGOUT EQU 9 ;PRINT MESSAGE TIL $
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
;
READ MACRO VAR
;; READ A SINGLE CHARACTER INTO VAR
MVI C,CONIN ;CONSOLE INPUT FUNCTION
CALL BDOS ;CHARACTER IS IN A
STA VAR
ENDM
;
WRITE MACRO MSG
;; WRITE MESSAGE TO CONSOLE
LOCAL MSGL,PMSG
JMP PMSG
MSGL: DB CR,LF ;;LEADING CRLF
DB '&MSG' ;;INLINE MESSAGE
DB '$' ;;MESSAGE TERMINATOR
PMSG: MVI C,MSGOUT ;;PRINT MESSAGE TIL $
LXI D,MSGL
CALL BDOS
ENDM


View File

@@ -0,0 +1,56 @@
SIZ MACRO SIZE
;; SET "ORG" AND CREATE STACK
LOCAL STACK ;;LABEL ON THE STACK
ORG 100H ;;AT BASE OF TPA
LXI SP,STACK
JMP STACK ;;PAST STACK
DS SIZE*2 ;;DOUBLE PRECISION
STACK: ENDM
;
DUP MACRO
;; DUPLICATE TOP OF STACK
PUSH H
ENDM
;
SUM MACRO
;; ADD THE TOP TWO STACK ELEMENTS
POP D ;;TOP-1 TO DE
DAD D ;;BACK TO HL
ENDM
;
LSR MACRO LEN
;; LOGICAL SHIFT RIGHT BY LEN
REPT LEN ;;GENERATE INLINE
XRA A ;;CLEAR CARRY
MOV A,H
RAR ;;ROTATE WITH HIGH 0
MOV H,A
MOV A,L
RAR
MOV L,A ;;BACK WITH HIGH BIT
ENDM
ENDM
;
ADC0 EQU 1080H ;A-D CONVERTER 0
ADC1 EQU 1082H ;A-D CONVERTER 1
ADC2 EQU 1084H ;A-D CONVERTER 2
ADC3 EQU 1086H ;A-D CONVERTER 3
;
DAC0 EQU 1090H ;D-A CONVERTER 0
DAC1 EQU 1092H ;D-A CONVERTER 1
DAC2 EQU 1094H ;D-A CONVERTER 2
DAC3 EQU 1096H ;D-A CONVERTER 3
;
RDM MACRO ?C
;; READ A-D CONVERTER NUMBER "?C"
PUSH H ;;CLEAR THE STACK
;; READ FROM MEMORY MAPPED INPUT ADDRESS
LHLD ADC&?C
ENDM
;
WRM MACRO ?C
;; WRITE D-A CONVERTER NUMBER "?C"
SHLD DAC&?C ;;VALUE WRITTEN
POP H ;;RESTORE STACK
ENDM


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
; MACRO LIBRARY FOR STREET TREADLES
;
TRINP EQU 01H ;TREADLE INPUT PORT
TROUT EQU 01H ;TREADLE OUTPUT PORT
;
TREAD? MACRO TR,IFTRUE
;; "TREAD?" IS INVOKED TO CHECK IF
;; TREADLE GIVEN BY TR HAS BEEN SENSED.
;; IF SO, THE LATCH IS CLEARED AND CONTROL
;; TRANSFERS TO THE LABEL "IFTRUE"
LOCAL IFFALSE ;;IN CASE NOT SET
;;
IN TRINP ;;READ TREADLE SWITCHES
ANI 1 SHL TR ;;MASK PROPER BIT
JZ IFFALSE ;;SKIP RESET IF 0
MVI A,1 SHL TR ;;TO RESET THE BIT
OUT TROUT ;;CLEAR IT
JMP IFTRUE ;;GO TO TRUE LABEL
IFFALSE:
ENDM


View File

@@ -0,0 +1,36 @@
; MACRO LIBRARY FOR "WHEN" CONSTRUCT
;
; "WHEN" COUNTERS
; LABEL GENERATORS
GENWTST MACRO TST,X,Y,NUM
;; GENERATE A "WHEN" TEST (NEGATED FORM),
;; INVOKE MACRO "TST" WITH PARAMETERS
;; X,Y WITH JUMP TO ENDW & NUM
TST X,Y,,ENDW&NUM
ENDM
;
GENLAB MACRO LAB,NUM
;; PRODUCE THE LABEL "LAB" & "NUM"
LAB&NUM:
ENDM
;
; "WHEN" MACROS FOR START AND END
;
WHEN MACRO XV,REL,YV
;; INITIALIZE COUNTERS FIRST TIME
WCNT SET 0 ;;NUMBER OF WHENS
WHEN MACRO X,R,Y
GENWTST R,X,Y,%WCNT
WLEV SET WCNT ;;NEXT ENDW TO GENERATE
WCNT SET WCNT+1 ;;NUMBER OF "WHEN"S
ENDM
WHEN XV,REL,YV
ENDM
;
ENDW MACRO
;; GENERATE THE ENDING CODE FOR A "WHEN"
GENLAB ENDW,%WLEV
WLEV SET WLEV-1 ;;COUNT CURRENT LEVEL DOWN
;; WLEV MUST NOT GO BELOW 0 (NOT CHECKED)
ENDM


View File

@@ -0,0 +1,402 @@
Z-80 Macro Library Documentation
--------------------------------
I.
The purpose of this library is to enable the assembly of the Z-80
instruction set on a CP/M sytem using the CP/M MAC macro assembler.
This library is invoked with the pseudo-op:
" MACLIB Z80 "
II.
The following symbols and notations are used in the individual macro
descriptions;
r - Any of the 8 bit registers: A, B, C, D, E, H, L, or M
rr - Any of the 16 bit register pairs: BC, DE, HL, or SP
nn - 8 bit immediate data (0 through 255)
d - 8 bit signed displacment (-128 through +127)
nnnn - 16 bit address or immediate data (0 through 65535)
b - bit number (0-7, 7 is most significant, 0 is least)
addr - 16 bit address within PC+127 through PC-128
m(zzz) - Memory at address "zzz"
III.
MACLIB ver. Zilog ver TDL ver
-------------- ------------- -------------
LDX r,d LD r,(IX+d) MOV r,d(IX)
Load register from indexed memory (with IX)
LDY r,d LD r,(IY+d) MOV r,d(IY)
Load register from indexed memory (with IY)
STX r,d LD (IX+d),r MOV d(IX),r
Store register to indexed memory (with IX)
STY r,d LD (IY+d),r MOV d(IY),r
Store register to indexed memory (with IY)
MVIX nn,d LD (IX+d),nn MVI d(IX)
Move immediate to indexed memory (with IX)
MVIY nn,d LD (IY+d),nn MVI d(IY)
Move immediate to indexed memory (with IY)
LDAI LD A,I LDAI
Move I to A
LDAR LD A,R LDAR
Move R to A
STAI LD I,A STAI
Move A to I
STAR LD R,A STAR
Move A to R
LXIX nnnn LD IX,nnnn LXI IX,nnnn
Load IX immediate (16 bits)
LXIY nnnn LD IY,nnnn LXI IY,nnnn
Load IY immediate (16 bits)
LBCD nnnn LD BC,(nnnn) LBCD nnnn
Load BC direct (from memory at nnnn)
LDED nnnn LD DE,(nnnn) LDED nnnn
Load DE direct
LSPD nnnn LD SP,(nnnn) LSPD nnnn
Load SP direct
LIXD nnnn LD IX,(nnnn) LIXD nnnn
Load IX direct
LIYD nnnn LD IY,(nnnn) LIYD nnnn
Load IY direct
SBCD nnnn LD (nnnn),BC SBCD nnnn
Store BC direct (to memory at nnnn)
SDED nnnn LD (nnnn),DE SDED nnnn
Store DE direct
SSPD nnnn LD (nnnn),SP SSPD nnnn
Store SP direct
SIXD nnnn LD (nnnn),IX SIXD nnnn
Store IX direct
SIYD nnnn LD (nnnn),IY SIYD nnnn
Store IY direct
SPIX LD SP,IX SPIX
Copy IX to the SP
SPIY LD SP,IY SPIY
Copy IY to the SP
PUSHIX PUSH IX PUSH IX
Push IX into the stack
PUSHIY PUSH IY PUSH IY
Push IY into the stack
POPIX POP IX POP IX
Pop IX from the stack
POPIY POP IY POP IY
Pop IY from the stack
EXAF EX AF,AF' EXAF
Exchange AF and the alternate, AF'
EXX EXX EXX
Exchange BC DE HL with BC' DE' HL'
XTIX EX (SP),IX XTIX
Exchange IX with the top of the stack
XTIY EX (SP),IY XTIY
Exchange IY with the top of the stack
LDI LDI LDI
Move m(HL) to m(DE), increment DE and HL, decrement BC
LDIR LDIR LDIR
Repeat LDI until BC = 0
LDD LDD LDD
Move m(HL) to m(DE), decrement HL, DE, and BC
LDDR LDDR LDDR
Repeat LDD until BC = 0
CCI CPI CCI
Compare A with m(HL), increment HL, decrement BC
CCIR CPIR CCIR
Repeat CCI until BC = 0 or A = m(HL)
CCD CPD CCD
Compare A with m(HL), decrement HL and BC
CCDR CPDR CCDR
Repeat CCD until BC = 0 or A = m(HL)
ADDX d ADD (IX+d) ADD d(IX)
Indexed add to A
ADDY d ADD (IY+d) ADD d(IY)
Indexed add to A
ADCX d ADC (IX+d) ADC d(IX)
Indexed add with carry
ADCY d ADC (IY+d) ADC d(IY)
Indexed add with carry
SUBX d SUB (IX+d) SUB d(IX)
Indexed subtract
SUBY d SUB (IY+d) SUB d(IY)
Indexed Subtract
SBCX d SBC (IX+d) SBB d(IX)
Indexed subtract with "borrow"
SBCY d SBC (IY+d) SBB d(IY)
Indexed subtract with borrow
ANDX d AND (IX+d) ANA d(IX)
Indexed logical and
ANDY d AND (IY+d) ANA d(IY)
Indexed logical and
XORX d XOR (IX+d) XRA d(IX)
Indexed logical exclusive or
XORY d XOR (IY+d) XRA d(IY)
Indexed logical exclusive or
ORX d OR (IX+d) ORA d(IX)
Indexed logical or
ORY d OR (IY+d) ORA d(IY)
Indexed logical exclusive or
CMPX d CP (IX+d) CMP d(IX)
Indexed compare
CMPY d CP (IY+d) CMP d(IY)
Index compare
INRX d INC (IX+d) INR d(IX)
Increment memory at m(IX+d)
INRY d INC (IY+d) INR d(IY)
Increment memory at m(IY+d)
DCRX d INC (IX+d) INR d(IX)
Decrement memory at m(IX+d)
DCRY d DEC (IY+d) DCR d(IY)
Decrement memory at m(IX+d)
NEG NEG NEG
Negate A (two's complement)
IM0 IM0 IM0
Set interrupt mode 0
IM1 IM1 IM1
Set interrupt mode 1
IM2 IM2 IM2
Set interrupt mode 2
DADC rr ADC HL,rr DADC rr
Add with carry rr to HL
DSBC rr SBC HL,rr DSBC rr
Subtract with "borrow" rr from HL
DADX rr ADD IX,rr DADX rr
Add rr to IX (rr may be BC, DE, SP, IX)
DADY rr ADD IY,rr DADY rr
Add rr to IY (rr may be BC, DE, SP, IY)
INXIX INC IX INX IX
Increment IX
INXIY INC IY INX IY
Increment IY
DCXIX DEC IX DCX IX
Decrement IX
DCXIY DEC IY DCX IY
Decrement IY
BIT b,r BIT b,r BIT b,r
Test bit b in register r
SETB b,r SET b,r SET b,r
Set bit b in register r
RES b,r RES b,r RES b,r
Reset bit b in register r
BITX b,d BIT b,(IX+d) BIT b,d(IX)
Test bit b in memory at m(IX+d)
BITY b,d BIT b,(IY+d) BIT b,d(IY)
Test bit b in memory at m(IY+d)
SETX b,d SET b,(IX+d) SET b,d(IX)
Set bit b in memory at m(IX+d)
SETY b,d SET b,(IY+d) SET b,d(IY)
Set bit b in memory at m(IY+d)
RESX b,d RES b,(IX+d) RES b,d(IX)
Reset bit b in memory at m(IX+d)
RESY b,d RES b,(IY+d) RES b,d(IY)
Reset bit b in memory at m(IY+d)
JR addr JR addr-$ JMPR addr
Jump relative unconditional
JRC addr JR C,addr-$ JRC addr
Jump relative if Carry indicator true
JRNC addr JR NC,addr-$ JRNC addr
Jump relative if carry indicator false
JRZ addr JR Z,addr-$ JRC addr
Jump relative if Zero indicator true
JRNZ addr JR NZ,addr-$ JRNZ addr
Jump relative if Zero indicator false
DJNZ addr DJNZ addr-$ DJNZ addr
Decrement B, jump relative if non-zero
PCIX JMP (IX) PCIX
Jump to address in IX ie, Load PC from IX
PCIY JMP (IY) PCIY
Jump to address in IY
RETI RETI RETI
Return from interrupt
RETN RETN RETN
Return from non-maskable interrupt
INP r IN r,(C) INP r
Input from port C to register r
OUTP r OUT (C),r OUTP r
Output from register r to port (C)
INI INI INI
Input from port (C) to m(HL), increment HL, decrement b
INIR INIR INIR
Input from port (C) to m(HL), increment HL, decrement B, repeat if B <> 0
OUTI OTI OUTI
Output from m(HL) to port (C), increment HL, decrement B
OUTIR OTIR OUTIR
Repeat OUTI until B = 0
IND IND IND
Input from port (C) to m(HL), decrement HL & B
INDR INDR INDR
Repeat IND until B = 0
OUTD OTD OUTD
Output from m(HL) to port (C), decrement HL & B
OUTDR OTDR OUTDR
Repeat OUTD until B = 0
RLCR r RLC r RLCR r
Rotate left circular register
RLCX d RLC (IX+d) RLCR d(IX)
Rotate left circular indexed memory
RLCY d RLC (IY+d) RLCR d(IY)
Rotate left circular indexed memory
RALR r RL r RALR r
Rotate left arithmetic register
RALX d RL (IX+d) RALR d(IX)
Rotate left arithmetic indexed memory
RALY d RL (IY+d) RALR d(IY)
Rotate left arithmetic indexed memory
RRCR r RRC r RRCR r
Rotate right circular register
RRCX d RRC (IX+d) RRCR d(IX)
Rotate right circular indexed
RRCY d RRC (IY+d) RRCR d(IY)
Rotate right circular indexed
RARR r RR r RARR r
Rotate right arithmetic register
RARX d RR (IX+d) RARR d(IX)
Rotate right arithmetic indexed memory
RARY d RR (IY+d) RARR d(IY)
Rotate right arithmetic indexed memory
SLAR r SLA r SLAR r
Shift left register
SLAX d SLA (IX+d) SLAR d(IX)
Shift left indexed memory
SLAY d SLA (IY+d) SLAR d(IY)
Shift left indexed memory
SRAR r SRA r SRAR r
Shift right arithmetic register
SRAX d SRA (IX+d) SRAR d(IX)
Shift right arithmetic indexed memory
SRAY d SRA (IY+d) SRAR d(IY)
Shift right arithmetic indexed memory
SRLR r SRL r SRLR r
Shift right logical register
SRLX d SRL (IX+d) SRLR d(IX)
Shift right logical indexed memory
SRLY d SRL (IY+d) SRLR d(IY)
Shift right logical indexed memory
RLD RLD RLD
Rotate left digit
RRD RRD RRD
Rotate right digit


View File

@@ -0,0 +1,457 @@
; @CHK MACRO USED FOR CHECKING 8 BIT DISPLACMENTS
;
@CHK MACRO ?DD ;; USED FOR CHECKING RANGE OF 8-BIT DISP.S
IF (?DD GT 7FH) AND (?DD LT 0FF80H)
'DISPLACEMENT RANGE ERROR - Z80 LIB'
ENDIF
ENDM
LDX MACRO ?R,?D
@CHK ?D
DB 0DDH,?R*8+46H,?D
ENDM
LDY MACRO ?R,?D
@CHK ?D
DB 0FDH,?R*8+46H,?D
ENDM
STX MACRO ?R,?D
@CHK ?D
DB 0DDH,70H+?R,?D
ENDM
STY MACRO ?R,?D
@CHK ?D
DB 0FDH,70H+?R,?D
ENDM
MVIX MACRO ?N,?D
@CHK ?D
DB 0DDH,36H,?D,?N
ENDM
MVIY MACRO ?N,?D
@CHK ?D
DB 0FDH,36H,?D,?N
ENDM
LDAI MACRO
DB 0EDH,57H
ENDM
LDAR MACRO
DB 0EDH,5FH
ENDM
STAI MACRO
DB 0EDH,47H
ENDM
STAR MACRO
DB 0EDH,4FH
ENDM
LXIX MACRO ?NNNN
DB 0DDH,21H
DW ?NNNN
ENDM
LXIY MACRO ?NNNN
DB 0FDH,21H
DW ?NNNN
ENDM
LDED MACRO ?NNNN
DB 0EDH,5BH
DW ?NNNN
ENDM
LBCD MACRO ?NNNN
DB 0EDH,4BH
DW ?NNNN
ENDM
LSPD MACRO ?NNNN
DB 0EDH,07BH
DW ?NNNN
ENDM
LIXD MACRO ?NNNN
DB 0DDH,2AH
DW ?NNNN
ENDM
LIYD MACRO ?NNNN
DB 0FDH,2AH
DW ?NNNN
ENDM
SBCD MACRO ?NNNN
DB 0EDH,43H
DW ?NNNN
ENDM
SDED MACRO ?NNNN
DB 0EDH,53H
DW ?NNNN
ENDM
SSPD MACRO ?NNNN
DB 0EDH,73H
DW ?NNNN
ENDM
SIXD MACRO ?NNNN
DB 0DDH,22H
DW ?NNNN
ENDM
SIYD MACRO ?NNNN
DB 0FDH,22H
DW ?NNNN
ENDM
SPIX MACRO
DB 0DDH,0F9H
ENDM
SPIY MACRO
DB 0FDH,0F9H
ENDM
PUSHIX MACRO
DB 0DDH,0E5H
ENDM
PUSHIY MACRO
DB 0FDH,0E5H
ENDM
POPIX MACRO
DB 0DDH,0E1H
ENDM
POPIY MACRO
DB 0FDH,0E1H
ENDM
EXAF MACRO
DB 08H
ENDM
EXX MACRO
DB 0D9H
ENDM
XTIX MACRO
DB 0DDH,0E3H
ENDM
XTIY MACRO
DB 0FDH,0E3H
ENDM
LDI MACRO
DB 0EDH,0A0H
ENDM
LDIR MACRO
DB 0EDH,0B0H
ENDM
LDD MACRO
DB 0EDH,0A8H
ENDM
LDDR MACRO
DB 0EDH,0B8H
ENDM
CCI MACRO
DB 0EDH,0A1H
ENDM
CCIR MACRO
DB 0EDH,0B1H
ENDM
CCD MACRO
DB 0EDH,0A9H
ENDM
CCDR MACRO
DB 0EDH,0B9H
ENDM
ADDX MACRO ?D
@CHK ?D
DB 0DDH,86H,?D
ENDM
ADDY MACRO ?D
@CHK ?D
DB 0FDH,86H,?D
ENDM
ADCX MACRO ?D
@CHK ?D
DB 0DDH,8EH,?D
ENDM
ADCY MACRO ?D
@CHK ?D
DB 0FDH,8EH,?D
ENDM
SUBX MACRO ?D
@CHK ?D
DB 0DDH,96H,?D
ENDM
SUBY MACRO ?D
@CHK ?D
DB 0FDH,96H,?D
ENDM
SBCX MACRO ?D
@CHK ?D
DB 0DDH,9EH,?D
ENDM
SBCY MACRO ?D
@CHK ?D
DB 0FDH,9EH,?D
ENDM
ANDX MACRO ?D
@CHK ?D
DB 0DDH,0A6H,?D
ENDM
ANDY MACRO ?D
@CHK ?D
DB 0FDH,0A6H,?D
ENDM
XORX MACRO ?D
@CHK ?D
DB 0DDH,0AEH,?D
ENDM
XORY MACRO ?D
@CHK ?D
DB 0FDH,0AEH,?D
ENDM
ORX MACRO ?D
@CHK ?D
DB 0DDH,0B6H,?D
ENDM
ORY MACRO ?D
@CHK ?D
DB 0FDH,0B6H,?D
ENDM
CMPX MACRO ?D
@CHK ?D
DB 0DDH,0BEH,?D
ENDM
CMPY MACRO ?D
@CHK ?D
DB 0FDH,0BEH,?D
ENDM
INRX MACRO ?D
@CHK ?D
DB 0DDH,34H,?D
ENDM
INRY MACRO ?D
@CHK ?D
DB 0FDH,34H,?D
ENDM
DCRX MACRO ?D
@CHK ?D
DB 0DDH,035H,?D
ENDM
DCRY MACRO ?D
@CHK ?D
DB 0FDH,35H,?D
ENDM
NEG MACRO
DB 0EDH,44H
ENDM
IM0 MACRO
DB 0EDH,46H
ENDM
IM1 MACRO
DB 0EDH,56H
ENDM
IM2 MACRO
DB 0EDH,5EH
ENDM
BC EQU 0
DE EQU 2
HL EQU 4
IX EQU 4
IY EQU 4
DADC MACRO ?R
DB 0EDH,?R*8+4AH
ENDM
DSBC MACRO ?R
DB 0EDH,?R*8+42H
ENDM
DADX MACRO ?R
DB 0DDH,?R*8+09H
ENDM
DADY MACRO ?R
DB 0FDH,?R*8+09H
ENDM
INXIX MACRO
DB 0DDH,23H
ENDM
INXIY MACRO
DB 0FDH,23H
ENDM
DCXIX MACRO
DB 0DDH,2BH
ENDM
DCXIY MACRO
DB 0FDH,2BH
ENDM
BIT MACRO ?N,?R
DB 0CBH,?N*8+?R+40H
ENDM
SETB MACRO ?N,?R
DB 0CBH,?N*8+?R+0C0H
ENDM
RES MACRO ?N,?R
DB 0CBH,?N*8+?R+80H
ENDM
BITX MACRO ?N,?D
@CHK ?D
DB 0DDH,0CBH,?D,?N*8+46H
ENDM
BITY MACRO ?N,?D
@CHK ?D
DB 0FDH,0CBH,?D,?N*8+46H
ENDM
SETX MACRO ?N,?D
@CHK ?D
DB 0DDH,0CBH,?D,?N*8+0C6H
ENDM
SETY MACRO ?N,?D
@CHK ?D
DB 0FDH,0CBH,?D,?N*8+0C6H
ENDM
RESX MACRO ?N,?D
@CHK ?D
DB 0DDH,0CBH,?D,?N*8+86H
ENDM
RESY MACRO ?N,?D
@CHK ?D
DB 0FDH,0CBH,?D,?N*8+86H
ENDM
JR MACRO ?N
DB 18H,?N-$-1
ENDM
JRC MACRO ?N
DB 38H,?N-$-1
ENDM
JRNC MACRO ?N
DB 30H,?N-$-1
ENDM
JRZ MACRO ?N
DB 28H,?N-$-1
ENDM
JRNZ MACRO ?N
DB 20H,?N-$-1
ENDM
DJNZ MACRO ?N
DB 10H,?N-$-1
ENDM
PCIX MACRO
DB 0DDH,0E9H
ENDM
PCIY MACRO
DB 0FDH,0E9H
ENDM
RETI MACRO
DB 0EDH,4DH
ENDM
RETN MACRO
DB 0EDH,45H
ENDM
INP MACRO ?R
DB 0EDH,?R*8+40H
ENDM
OUTP MACRO ?R
DB 0EDH,?R*8+41H
ENDM
INI MACRO
DB 0EDH,0A2H
ENDM
INIR MACRO
DB 0EDH,0B2H
ENDM
IND MACRO
DB 0EDH,0AAH
ENDM
INDR MACRO
DB 0EDH,0BAH
ENDM
OUTI MACRO
DB 0EDH,0A3H
ENDM
OUTIR MACRO
DB 0EDH,0B3H
ENDM
OUTD MACRO
DB 0EDH,0ABH
ENDM
OUTDR MACRO
DB 0EDH,0BBH
ENDM
RLCR MACRO ?R
DB 0CBH, 00H + ?R
ENDM
RLCX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 06H
ENDM
RLCY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 06H
ENDM
RALR MACRO ?R
DB 0CBH, 10H+?R
ENDM
RALX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 16H
ENDM
RALY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 16H
ENDM
RRCR MACRO ?R
DB 0CBH, 08H + ?R
ENDM
RRCX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 0EH
ENDM
RRCY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 0EH
ENDM
RARR MACRO ?R
DB 0CBH, 18H + ?R
ENDM
RARX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 1EH
ENDM
RARY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 1EH
ENDM
SLAR MACRO ?R
DB 0CBH, 20H + ?R
ENDM
SLAX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 26H
ENDM
SLAY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 26H
ENDM
SRAR MACRO ?R
DB 0CBH, 28H+?R
ENDM
SRAX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 2EH
ENDM
SRAY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 2EH
ENDM
SRLR MACRO ?R
DB 0CBH, 38H + ?R
ENDM
SRLX MACRO ?D
@CHK ?D
DB 0DDH, 0CBH, ?D, 3EH
ENDM
SRLY MACRO ?D
@CHK ?D
DB 0FDH, 0CBH, ?D, 3EH
ENDM
RLD MACRO
DB 0EDH, 6FH
ENDM
RRD MACRO
DB 0EDH, 67H
ENDM