412 lines
10 KiB
ArmAsm
412 lines
10 KiB
ArmAsm
"** 01-s1.pdf page 21
|
|
" s4
|
|
|
|
" allocate a free disk block for a file (data or indirect)
|
|
alloc: 0
|
|
-1 " decrement the count
|
|
tad s.nfblks " of free blocks at s.fblks
|
|
spa " any left?
|
|
jmp 1f " no
|
|
dac s.nfblks " Update the count of free block numbers
|
|
tad fblksp " get pointer to last valid entry in s.fblks
|
|
jms laci " fetch the word
|
|
dac 9f+t " save in t0
|
|
jms copyz; dskbuf; 64 " zero dskbuf
|
|
lac 9f+t " get block number back
|
|
jms dskwr " write out the zeros
|
|
dzm .savblk " cancel system block write
|
|
lac 9f+t " get the block number back
|
|
jmp alloc i " Return from routine
|
|
1:
|
|
lac s.nxfblk " next block with list of free blocks
|
|
sna " any?
|
|
jms halt " OUT OF DISK
|
|
dac s.fblks " save as first free block #
|
|
jms dskrd " read the block
|
|
lac dskbuf " get first word (pointer to next in chain)
|
|
dac s.nxfblk " save as new "next"
|
|
jms copy; dskbuf+1; s.fblks+1; 9 " copy remaining 9 as free
|
|
lac d10 " reset free count
|
|
dac s.nfblks
|
|
jmp alloc+1
|
|
|
|
" free the disk block whose number is in AC
|
|
free: 0
|
|
lmq " save block in MQ
|
|
lac s.nfblks " get number of free blocks
|
|
sad d10 " 10?
|
|
jmp 1f " yes
|
|
tad fblksp " no: get addr in s.fblks to store new block in
|
|
dac 9f+t " save pointer
|
|
lacq " get block number
|
|
dac 9f+t i " save it in s.fblks
|
|
dzm .savblk " cancel system block write
|
|
isz s.nfblks " increment free count
|
|
jmp free i " return
|
|
1:
|
|
lac s.nxfblk " get head of free chain
|
|
dac dskbuf " save (as chain ptr) in first word of disk buf
|
|
jms copy; s.fblks+1; dskbuf+1; 9 " with 9 of the 10 free blocks
|
|
lacq " get the newly freed block back
|
|
dac s.nxfblk " save as new head of free chain
|
|
jms dskwr " write dskbuf to the newly freed block
|
|
dzm .savblk " cancel system block write
|
|
lac d1 " reset free count to one
|
|
dac s.nfblks " (the first word in s.fblks)
|
|
jmp free i " Return from the routine
|
|
t = t+1
|
|
|
|
" load AC indirect (without using indirect!)
|
|
" need to avoid use of indirect in interrupt service routines
|
|
" AC/ address
|
|
" jms laci
|
|
" AC/ contents of address
|
|
laci: 0
|
|
and o17777 " clear everything but addr
|
|
tad o200000 " make into "lac addr"
|
|
dac .+1
|
|
lac .. " fetch
|
|
jmp laci i " return
|
|
|
|
"** 01-s1.pdf page 22
|
|
|
|
" skip if AC between two values (inclusive)
|
|
" jms betwen; low_ptr; high_ptr
|
|
" <not between>
|
|
" <between>
|
|
" listing has an alternate written in
|
|
" (which would require 'lac ptr' instead of 'ptr' args?)
|
|
betwen: 0
|
|
lmq cmq " get ~AC in MQ
|
|
lac betwen i " get low_ptr
|
|
dac 9f+t
|
|
isz betwen " skip low_ptr
|
|
lacq " get ~AC (-AC-1) from MQ
|
|
tad 9f+t i " get low-AC-1
|
|
sma " negative (AC >= low)?
|
|
jmp 1f " no, return w/o skip
|
|
lac betwen i " fetch high_ptr
|
|
dac 9f+t
|
|
isz betwen " skip high_ptr
|
|
lacq " get -AC-1
|
|
tad 9f+t i " add to high value (high-AC-1)
|
|
cma " complement (AC-high)
|
|
spa sna " AC-high <= 0?
|
|
1:
|
|
isz betwen " no: give happy (skip) return
|
|
lacq " restore ~AC
|
|
cma " restore AC
|
|
jmp betwen i " return w/o skip
|
|
|
|
" copy memory
|
|
" call:
|
|
" jms copy; src; dest; count
|
|
copy: 0
|
|
-1
|
|
tad copy i
|
|
dac 8
|
|
isz copy
|
|
-1
|
|
tad copy i
|
|
dac 9
|
|
isz copy
|
|
-1
|
|
tad copy i
|
|
cma
|
|
dac 9f+t
|
|
isz copy
|
|
1:
|
|
lac 8 i
|
|
dac 9 i
|
|
isz 9f+t
|
|
jmp 1b
|
|
jmp copy i
|
|
|
|
" copy zeroes (clear memory)
|
|
" call:
|
|
" jms copyz; pointer; count
|
|
copyz: 0
|
|
-1
|
|
tad copyz i " get call PC
|
|
dac 8 " save in index (pre-increments)
|
|
isz copyz " skip pointer
|
|
-1
|
|
tad copyz i " get count-1
|
|
cma " get negative count
|
|
dac 9f+t " save in t0
|
|
isz copyz " skip count
|
|
1:
|
|
dzm 8 i " zero word
|
|
isz 9f+t " done?
|
|
jmp 1b " no: loop
|
|
jmp copyz i " return
|
|
t = t+1
|
|
|
|
" Character queue management routines
|
|
" (CALLED FROM PI: USE OF INDIRECT AVOIDED!)
|
|
|
|
" Queue numbers:
|
|
" 0: free list
|
|
" 1: tty input
|
|
" 2: tty output
|
|
" 3: display keyboard
|
|
" 4: paper tape reader
|
|
" 5: paper tape punch
|
|
|
|
" queue headers are two words: "first" and "last"(??)
|
|
" queue entries are two words: "next" and "char"
|
|
|
|
" put queued character
|
|
" character to store in "char"
|
|
" queue number in AC
|
|
|
|
putchar: 0
|
|
"** 01-s1.pdf page 23
|
|
dac 9f+t " save queue number in t0
|
|
cla " get entry from free list
|
|
jms takeq
|
|
jmp putchar i " none free: return w/o skip
|
|
tad o40001 " turn into "dac addr+1"
|
|
dac .+4
|
|
lac 9f+t " get queue number back
|
|
jms putq " add entry
|
|
lac char " get char
|
|
dac q2+1 .. " save in second word of queue entry
|
|
isz putchar " give skip return
|
|
jmp putchar i
|
|
t = t+1
|
|
|
|
" get queued character
|
|
" queue number in AC
|
|
" returns with skip if something found
|
|
getchar: 0
|
|
jms takeq " get entry from head of queue
|
|
jmp i getchar " nothing there: return w/o skip
|
|
tad o200001 " turn into "lac qentry+1" (fetch stored char)
|
|
dac .+3
|
|
cla
|
|
jms putq " put qentry on free list
|
|
lac q2+1 .. " fetch queued character(!!!)
|
|
isz getchar " give skip return
|
|
jmp i getchar
|
|
|
|
" fetch first entry from a queue
|
|
" queue number in AC
|
|
" returns with skip if something dequeued
|
|
takeq: 0
|
|
rcl " multiply queue number by two
|
|
tad lacq1 " add "lac q1"
|
|
dac .+7
|
|
tad o640000 " turn "lac" into "dac"
|
|
dac .+17
|
|
tad d1 " increment addr
|
|
dac .+14
|
|
tad o500000 " turn "dac" into "sad"
|
|
dac .+5
|
|
lac q1 .. " load queue head
|
|
sna " non-zero?
|
|
jmp takeq i " no: return zero w/o skip
|
|
dac lnkaddr
|
|
sad q1+1 .. " different from tail(??)
|
|
jmp .+5 " no -- (last entry?)
|
|
tad o200000 " yes: turn into lac
|
|
dac .+1 " save lac
|
|
lac q2 .. " get next pointer from queue entry
|
|
jmp .+3
|
|
cla " here with head == tail(??)
|
|
dac q1+1 .. " clear tail
|
|
dac q1 .. " save (clear) head
|
|
isz takeq " give skip return
|
|
lac lnkaddr " return queue entry pointer
|
|
jmp i takeq
|
|
|
|
" save queue entry (at lnkaddr) to a queue (queue number in AC)
|
|
putq: 0
|
|
rcl " multiply by two
|
|
tad dacq1 " turn into "dac qhead"
|
|
dac .+14
|
|
tad d1 " turn into "dac qtail"
|
|
dac .+13
|
|
tad o140000 " turn into "lac qtail"
|
|
dac .+1
|
|
lac q1-1 .. " fetch tail
|
|
"** 01-s1.pdf page 24
|
|
sna " non-zero?
|
|
jmp .+6 " no: is zero
|
|
tad o40000 " turn into "dac qentry" (append to queue)
|
|
dac .+2
|
|
lac lnkaddr " get new entry
|
|
dac q2 .. " append to tail entry
|
|
jmp .+3
|
|
lac lnkaddr " here with tail == 0
|
|
dac q1 .. " save new entry as head
|
|
dac q1+1 .. " save new tail
|
|
jmp putq i
|
|
|
|
" NOTE!! srcdbs, collaps, dskrd, dskwr share the same "temp" vars:
|
|
" "t0" temp!!
|
|
" "t1" contains pointer to (addr, buffer)
|
|
" "t2" contains block number
|
|
|
|
" check if disk block number in AC in memory
|
|
" give skip return if block NOT found
|
|
|
|
srcdbs: 0
|
|
dac 9f+t+2 "* lmq " save block number in t2
|
|
-ndskbs " loop for number of buffers
|
|
dac 9f+t " in t0
|
|
law dskbs "* -1 dac 8 written " get address of first buffer
|
|
dac 9f+t+1 "* lacq " in t1
|
|
1:
|
|
lac 9f+t+2 "** crossed out " get desired block number
|
|
sad 9f+t+1 i "** "8 i" written " match buffer block?
|
|
jmp srcdbs i " yes: return without skip
|
|
law 65 "** crossed out " no: advance to next buffer
|
|
tad 9f+t+1 "** crossed out isz 8 written
|
|
dac 9f+t+1
|
|
isz 9f+t
|
|
jmp 1b
|
|
isz srcdbs " block not found: give skip return
|
|
jmp srcdbs i
|
|
|
|
collapse: 0
|
|
cla " look for free buffer
|
|
jms srcdbs " found?
|
|
jmp 1f " yes
|
|
law dskbs " no: reuse last buffer
|
|
dac 9f+t+1 "** 9f+t+1 crossed out: 8 written in
|
|
1:
|
|
"** written: tad dm1
|
|
"** written: dac 8
|
|
lac 9f+t+1 "** 9f+t+1 crossed out: 8 written in
|
|
dac 0f+1 " save as copy dest
|
|
tad d65 "** crossed out w/ d2 " get start of next buffer
|
|
dac 0f " save as copy src
|
|
cma
|
|
tad d1
|
|
tad edskbsp " subtract from end of buffers
|
|
and o17777 " mask to 13 bits
|
|
sna " non-zero count?
|
|
jmp 0f+3 " no: skip copy
|
|
dac 0f+2 " save as copy length
|
|
jms copy; 0:..; ..; .. " slide buffers up
|
|
-65
|
|
tad edskbsp " get addr of last buffer
|
|
dac 9f+t " save in t0
|
|
tad d1 " get block data pointer
|
|
dac 0f " save as copy dest
|
|
lac dskaddr " get block number
|
|
dac 9f+t i " save in buffer header
|
|
jms copy; dskbuf; 0:..; 64 " copy dskbuf to last buffer
|
|
jmp collapse i
|
|
|
|
" read logical disk block number (2..7999) in AC into dskbuf
|
|
dskrd: 0
|
|
jms betwen; d2; d7999
|
|
|
|
"** 01-s1.pdf page 25
|
|
jms halt " bad block number
|
|
sad dskaddr " block currently in dskbuf
|
|
jmp dskrd i " yes: return
|
|
dac dskaddr " save block address
|
|
jms srcdbs " in memory?
|
|
jmp 1f " yes
|
|
lac dskaddr " no: read from disk
|
|
jms dskio; 06000
|
|
jmp 2f
|
|
1:
|
|
dzm 9f+t+1 i
|
|
law 1
|
|
tad 9f+t+1
|
|
dac .+2
|
|
jms copy; ..; dskbuf; 64
|
|
2:
|
|
jms collapse
|
|
jmp dskrd i
|
|
|
|
" write a file block (data, inode or indirect)
|
|
" AC/ block
|
|
dskwr: 0
|
|
jms betwen; d2; d7999
|
|
jms halt
|
|
jms dskio; 07000
|
|
lac dskaddr
|
|
jms srcdbs
|
|
dzm 9f+t+1 i
|
|
jms collapse
|
|
jmp dskwr i
|
|
t = t+3
|
|
|
|
" called to read/write logical block into "dskbuf"
|
|
" AC/ block
|
|
" jms dskio; DSLD_BITS
|
|
dskio: 0
|
|
dac dskaddr
|
|
cll; idiv; 80
|
|
dac 9f+t
|
|
lacq
|
|
idiv; 10
|
|
dac 9f+t+1
|
|
lls 22
|
|
xor 9f+t+1
|
|
als 8
|
|
dac 9f+t+1
|
|
lac 9f+t
|
|
idiv; 10
|
|
dac 9f+t
|
|
lls 22
|
|
xor 9f+t
|
|
xor 9f+t+1
|
|
xor o200000
|
|
dac 9f+t
|
|
jms dsktrans; -64; dskbuf; 9f+t; dskio
|
|
isz dskio
|
|
jmp dskio i
|
|
t = t+1
|
|
|
|
" perform disk I/O (both filesystem buffer and swapping)
|
|
" passed physical (BCD) disk address
|
|
" called:
|
|
" jms dsktrans; -WC; MAC; addr_ptr; dsld_ptr
|
|
dsktrans: 0
|
|
-10
|
|
dac 9f+t
|
|
1:
|
|
-1
|
|
tad dsktrans
|
|
dac 12
|
|
"** 01-s1.pdf page 26
|
|
dscs " clear status register
|
|
lac 12 i
|
|
dslw " load WC
|
|
lac 12 i
|
|
dslm " load MAC
|
|
lac 12 i
|
|
jms laci
|
|
dsld " load TA & SA
|
|
dzm .dskb
|
|
lac 12 i
|
|
jms laci
|
|
jms laci
|
|
dsls " load status
|
|
lac .dskb " check for interrupt
|
|
sna
|
|
jmp .-2
|
|
lac .dske " get status from interrupt
|
|
sma
|
|
jmp 12 i " return
|
|
isz 9f+t
|
|
jmp 1b
|
|
jms halt " 10 disk errors
|
|
t = t+1
|
|
|
|
halt: 0
|
|
isz 9f+t " spin for a while (process interrupts)
|
|
jmp .-1
|
|
iof " disable interrupts
|
|
hlt " halt
|
|
jms copy; law; 4096; 4096 " continued: copy system up to user memory?
|
|
hlt; jmp .-1 " halt for good
|
|
t = t+1
|
|
|