mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 17:04:19 +00:00
304 lines
6.3 KiB
Plaintext
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
|
|
|
|
|
|
;****************************************************
|
|
;****************************************************
|
|
|
|
|
|
|
|
|