Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/newos/biosmem2.z8k
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

304 lines
6.3 KiB
Plaintext

;************ biosmem2.z8k **************************
;*
;* Memory Management for P-CP/M (tm) BIOS
;* for Olivetti M20 (Z8001) system.
;*
;* 821013 S. Savitzky (Zilog) -- split modules
;* 820913 S. Savitzky (Zilog) -- created.
;*
; 01/12/83 Adapted for Z8002 (DMH, FMZ)
__text: .sect
;****************************************************
;*
;* This module copies data from one memory space
;* to another. The machine-dependent parts of
;* the mapping are well isolated.
;*
;* Segmented operations are well-isolated, and
;* are either the same as their non-segmented
;* counterparts, or constructed using macros.
;*
;****************************************************
.input "biosdefs2.z8k"
;****************************************************
;*
;* Global declarations
;*
;****************************************************
.global _sysseg, _usrseg, _sysstk, _psap
.global _mem_mov, _map_wdw
.global memsc
.global _blkmov
;****************************************************
;*
;* Externals
;*
;****************************************************
.global xfersc
.global _mem_bcp
;****************************************************
;*
;* System/User Memory Access
;*
;* _mem_cpy( source, dest, length)
;* long source, dest, length;
;* _map_adr( addr, space) -> paddr
;* long addr; int space;
;*
;* _map_adr( addr, -1) -> addr
;* sets user seg# from addr
;*
;* _map_adr( addr, -2)
;* control transfer to context at addr.
;*
;* system call: mem_cpy
;* rr6: source
;* rr4: dest
;* rr2: length (0 < length <= 64K)
;* returns
;* registers unchanged
;*
;* system call: map_adr
;* rr6: logical addr
;* r5: space code
;* r4: ignored
;* rr2: 0
;* returns
;* rr6: physical addr
;*
;* space codes:
;* 0: caller data
;* 1: caller program
;* 2: system data
;* 3: system program
;* 4: TPA data
;* 5: TPA program
;*
;* The following does not apply in Z8002 case
;*
;* x+256 x=1, 3, 5 : segmented I-space addr.
;* instead of data access
;*
;* FFFF: set user segment
;*
;****************************************************
memsc: ;memory manager system call
; CALLED FROM SC
; IN SEGMENTED MODE
; rr6: source
; rr4: dest / space
; rr2: length / 0
testl rr2
jr z mem_map
mem_copy: ; copy data.
; rr6: source
; rr4: dest
; rr2: length
push @r15,r3 ; push length as a short!
pushl @r15,rr4 ; push dest
pushl @r15, rr6 ; push source
call _mem_bcp ; call C copy routine
ldl rr6,4(r15) ; get dest into rr6
add r7,8(r15) ; return dest plus length
inc r15,#10 ; restore stack
ret
mem_map: ; map address
; rr6: source
; r4: caller's seg.
; r5: space
; r2: caller's FCW
cp r5,#-2 ; space=-2: xfer
jp eq xfersc
;* ld r4,scseg+co(r15) Not done in Z8002 implementation
ld r2,scfcw+co(r15)
calr map_1
ldl cr6+co(r15),rr6 ; return rr6
ret
map_1: ; dispatch
cp r5,#0FFFFh
jr eq set_usr ; space=-1: user seg
cpb rl5,#0
jr eq call_data
cpb rl5,#1
jr eq call_prog
cpb rl5,#2
jr eq sys_data
cpb rl5,#3
jr eq sys_prog
cpb rl5,#4
jr eq usr_data
cpb rl5,#5
jr eq usr_prog
ret ;default: no mapping
set_usr: ;-1: set user seg.
ld _usrseg,r6
ret
;*
;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT ***
;*
;* rr6= logical address
;* r4 = caller's PC segment - but NOT in the Z8002 implementation!
;* r2 = caller's FCW
;* returns
;* rr6= mapped address
;*
;* This code is much simpler than the corresponding
;* Z8001 code. If the caller's FCW indicates that he
;* was in Normal mode, then _usrseg is returned.
;* Otherwise, pseudo-segment 0 is returned.
;*
call_data:
bit r2,#14 ; System caller?
jr nz sys_data ; yes-- use system seg
ld r6,_usrseg ; no -- use pc segment
ret
call_prog:
bit r2,#14 ; System caller?
jr nz sys_prog ; yes-- use system seg
ld r6,_usrseg ; no 00 use pc segment
jr map_prog ; map prog as data
sys_data:
sys_prog:
ld r6, _sysseg
ret ; assume sys does not
; separate code, data
usr_data:
ld r6, _usrseg
ret
usr_prog:
ld r6, _usrseg
jr map_prog
map_prog: ; map program addr into data
; rr6 = address
and r6,#7F00h ; extract seg bits
; kontron: pseudo-segment 2 is the only one with
; separate I and D spaces, and
; the program space is accessed
; as pseudo-segment 1, data space as pseudo-segment 2
cpb rh6,#2
ret ne
ldb rh6,#1
ret
;*
;* The following routine copies a block of data from one part
;* of the system address space to another. In practice, part
;* of the address space may be windowed, but that is transparent
;* here.
;*
;* The interface is:
;* blkmov(source,dest,length)
;* short source,dest,length;
;*
_blkmov:
ld r5,ARG1(r15) ; r5: source
ld r4,ARG2(r15) ; r4: dest
ld r2,ARG3(r15) ; r2: length (just a word!)
ld r7,r2 ; return value = bytes copied
ldirb @r4,@r5,r2 ; copy!
ret
;****************************************************
;* mem_mov -- C callable block move routine
;* input stack:
;* ret. addr (word)
;* source (word)
;* destination (word)
;* length, bytes (word)
_mem_mov:
ld r5,2(r15) ; pull off source
ld r7,4(r15) ; pull off destination
ld r0,6(r15) ; pull off length
ldirb @r7,@r5,r0 ; block move
ret
;****************************************************
;* map_wdw -- C callable map window routine,
; system dependent.
;* input stack:
;* ret. addr (word)
;* window code (word)
;* 2 means physical block 2
;* 3 means physical block 3
;* x means physical block 1
;*
;* Note: the manual is unclear, but implies that
;* history must be kept concerning the window
;* mapping, if the window was last block 3.
;* That is why I map block one before others.
;* See ECB/C16 Hardware description for details.
_map_wdw:
ld r0,2(r15) ; pull off window code
out 0c000h,r0 ; map physical block 1
cp r0,#2 ; map physical block 2?
jr nz,map_wdw_3 ; No, go for physical block 3.
out 8001h,r0 ; Funny port address, huh?
ret
map_wdw_3:
cp r0,#3 ; map pysical block 3?
ret nz ; no, already mapped to 1.
out 0c001h,r0 ; yes.
ret
;****************************************************
;*
;* Data
;*
;****************************************************
__bss: .sect
_sysseg: .block 2 ;system segment
_usrseg: .block 2 ;user segment
_sysstk: .block 2 ;system stack pointer
_psap: .block 2 ;program status area ptr
;****************************************************
;****************************************************