page 255 .z80 public mmuinit public bnk2log,bnk2phy,hwl2phy,phy2log public isv_sw public b_ld_a,b_ld_hl,b_st_a,b_st_hl extrn @cbnk extrn ijphl maclib z180reg.inc maclib config.inc ;---------------------------------------------------------------------- ; Memory Map 1: ; ; Common CAStart .. 0FFFF ; Bank 0 00000 .. CAStart-1 ; Bank 1 10000 .. ; Bank 2 ; ; Memory Map 2: ; ; Common 18000 .. 1BFFF BANK1 ; ; Bank 0 00000 .. 0BFFF 0 ; Bank 1 0C000 .. 17FFF 1*BNK_SIZE ; Bank 2 1C000 .. 27FFF 2*BNK_SIZE + CMN_SIZE ; Bank 3 28000 .. 33FFF 3*BNK_SIZE + CMN_SIZE ; Bank n n*BNK_SIZE + (n < 2) ? 0 : CMN_SIZE ; ;---------------------------------------------------------------------- cseg mmuinit: ld a,USR$CBAR out0 (cbar),a ret ;-------------------------------------------------------------------- ; Return the BBR value for the given bank number ; ; in a: Bank number ; out a: bbr value if 0 ; Memory Map 1 bnk2log: or a ; ret z ; Bank 0 is at physical address 0 dec a ; push bc ; ld c,a ; ld b,BNK_SIZE ; mlt bc ; bank size * bank number ld a,c ; add a,10h ; add bank0 + common pop bc ; ret ; else ; Memory Map 2 bnk2log: or a ret z ; Bank 0 is at physical address 0 push bc ld c,a ; ld b,BNK_SIZE ; mlt bc ; bank size * bank number cp 2 ; ld a,c ; pop bc ret c add a,CMN_SIZE ret endif if 0 ; table version push hl ld hl,bnk_table ; add a,l ; ld l,a ; jr nc,$+3 ; inc h ; ld a,(hl) ; pop hl ret endif ;-------------------------------------------------------------- ;in hl: Log. Address ; a: Bank number ; ;out ahl: Phys. (linear) Address bnk2phy: push bc ld c,a ld a,h and a,0f0h cp CA*16 ld a,c pop bc jr c,b2p_banked ; address is in common if 0 ; Memory Map 1 ld a,0 ; base is 0 else ; Memory Map 2 ld a,1 ; same as bank1 endif b2p_banked: call bnk2log ; get address base ; fall thru ;-------------------------------------------------------------- ; ; hl: Log. Address ; a: Bank base (bbr) ; ; 2 0 0 ; 0 6 8 0 ; hl hhhhhhhhllllllll ; a + bbbbbbbb ; ; OP: ahl = (a<<12) + (h<<8) + l ; ;out ahl: Phys. (linear) Address log2phy: push bc ; l2p_i: ld c,a ; ld b,16 ; mlt bc ; bc = a<<4 ld a,c ; add a,h ; ld h,a ; ld a,b ; adc a,0 ; pop bc ; ret ; ;-------------------------------------------------------------- ; ; hl: Log. Address ; ; ; OP: ahl = (bankbase<<12) + (h<<8) + l ; ;out ahl: Phys. (linear) Address hwl2phy: push bc ; in0 c,(cbar) ; ld a,h ; or 00fh ; log. addr in common1? cp c jr c,hlp_1 in0 a,(cbr) ; yes, cbr is address base jr hl2p_x hlp_1: ld b,16 ; log. address in baked area? mlt bc ld a,h cp c jr c,hlp_2 in0 a,(bbr) ; yes, bbr is address base jr hl2p_x hlp_2: xor a ; common1 hl2p_x: jr nz,l2p_i pop bc ; bank part is 0, no translation ret ; ;-------------------------------------------------------------- ; return logical bank 0 address for given physical address. ; ; in: ahl: pyhsical addres (20 bit) ; out hl: logical address. ; logical address is in bank 0 or common, no bank number returned ; phy2log: or a ret z push bc push hl ld l,h ld h,0 ld bc,-16*SYS$CBR add hl,bc ld h,l pop bc ld l,c pop bc ret ;-------------------------------------------------------------- ; Trampoline for routines in banked ram. ; Switch stack pointer to "system" stack in top ram ; Save cbar ; cseg ; common! public _b0call if 0 _b0call: push af in0 a,(bbr) jr nz,b0c_doit pop af ex (sp),hl ;16 push de ld e,(hl) inc hl ld d,(hl) inc hl ld (b0c_fast_go),de pop de ex (sp),hl ;16 b0c_fast_go equ $+1 jp 0 b0c_doit: ld (b0_save_hl),hl ld (b0_save_de),de pop hl ld (b0_save_af),hl pop de ;get ptr to 'function address' in de ld hl,2 add hl,de push hl ;put return address on stack if 0 ; link80 ld hl,0 add hl,sp ; ld a,h cp high (bs$stack-bs$stack$size) ;link80 can't process this jr nc,$ + 5 ;skip if stack allready in common bios ram else ld hl,bs$stack-bs$stack$size ld a,h dec a ld hl,0 add hl,sp ; cp h jr c,$ + 5 ;skip if stack allready in common bios ram endif ld sp,bs$stack ; push hl ;save user stack pointer in0 h,(bbr) ; push hl ; ld hl,b0c_ret push hl xor a out0 (bbr),a ; ex de,hl ;ptr ld e,(hl) ;get 'function address' inc hl ; ld d,(hl) ; push de ;put on (switched) stack ld hl,(b0_save_af) ;get back users registers push hl pop af ld de,(b0_save_de) ld hl,(b0_save_hl) ret ;go to function b0c_ret: ld (b0_save_hl),hl pop hl ; out0 (bbr),h ; pop hl ; ld sp,hl ; ld hl,(b0_save_hl) ret ; else _b0call: push af ld (b0_save_hl),hl ld (b0_save_de),de pop hl ld (b0_save_af),hl pop de ;get ptr to 'function address' in de ld hl,2 add hl,de push hl ;put return address on stack if 0 ; link80 ld hl,0 add hl,sp ; ld a,h cp high (bs$stack-bs$stack$size) ;link80 can't process this jr nc,$ + 5 ;skip if stack allready in common bios ram else ld hl,bs$stack-bs$stack$size ld a,h dec a ld hl,0 add hl,sp ; cp h jr c,$ + 5 ;skip if stack allready in common bios ram endif ld sp,bs$stack ; push hl ;save user stack pointer in0 h,(bbr) ; push hl ; ld hl,b0c_ret push hl xor a out0 (bbr),a ; ex de,hl ;ptr ld e,(hl) ;get 'function address' inc hl ; ld d,(hl) ; push de ;put on (switched) stack ld hl,(b0_save_af) ;get back users registers push hl pop af ld de,(b0_save_de) ld hl,(b0_save_hl) ret ;go to function b0c_ret: ld (b0_save_hl),hl pop hl ; out0 (bbr),h ; pop hl ; ld sp,hl ; ld hl,(b0_save_hl) ret ; endif b0_save_hl: dw 0 b0_save_de: dw 0 b0_save_af: dw 0 ;-------------------------------------------------------------------- ; Trampoline for interrupt routines in banked ram. ; Switch stack pointer to "system" stack in top ram ; Save bbr cseg if 0 isv_sw: ; ex (sp),hl ;save hl, 'return adr' in hl push de ; push af ; ex de,hl ;'return address' in de if 0 if 0 ; link80 ld hl,0 add hl,sp ; ld a,h cp high (bs$stack-bs$stack$size) ;link80 can't process this jr nc,$ + 5 ;skip if stack allready in common bios ram else ld hl,bs$stack-bs$stack$size ld a,h dec a ld hl,0 add hl,sp ; cp h jr c,$ + 5 ;skip if stack allready in common bios ram endif ld sp,bs$stack ; else ld hl,0 add hl,sp ld sp,istack endif push hl ;save user stack pointer in0 h,(bbr) ; push hl ; xor a ; out0 (bbr),a ; ex de,hl ; ld e,(hl) ; inc hl ; ld d,(hl) ; ex de,hl ; push bc ; call ijphl ; pop bc ; pop hl ; out0 (bbr),h ; pop hl ; ld sp,hl ; pop af ; pop de ; pop hl ; ei ; ret ; else isv_sw: ; ex (sp),hl ;save hl, 'return adr' in hl ld (i$stack),sp ;save user stack pointer ld sp,i$stack push de ; push bc ; push af ; in0 a,(bbr) ; push af ; xor a ; out0 (bbr),a ; ld e,(hl) ; inc hl ; ld d,(hl) ; ex de,hl ; call ijphl ; pop af ; out0 (bbr),a ; pop af ; pop bc ; pop de ; ld sp,(i$stack) ; pop hl ; ei ; ret ; endif public i$stack rept 24 db '|' endm i$stack: dw 0 dseg ;-------------------------------------------------------------------- ; Load byte/word from user ram ; ; de: src address in users bank ; return ; a: value (byte) ; hl: value (word) b_ld_a: push hl or a ; clear carry == byte store jr $+3 b_ld_hl: scf ; set carry == word store push af ; save flag push hl ; make space on stack ld a,(@cbnk) ld b,a ; b = src bank ld hl,0 ld a,l ld c,l ; c = dst bank (0) add hl,sp ; hl = dst adc a,1 ; a = count ex de,hl call dma_move ex de,hl pop hl pop af ret c ld a,l pop hl ret ;-------------------------------------------------------------------- ; Store byte/word to user ram ; ; de: dst address in users bank ; a: value (byte) ; hl: value (word) b_st_a: push hl ld l,a or a ; clear carry == byte store jr $+3 b_st_hl: scf ; set carry == word store push af ; save flag push hl ; put value on stack ld a,(@cbnk) ; ld c,a ; c = dst bank ld a,0 ld l,a ld h,a ld b,a ; b = src bank (0) add hl,sp ; hl = src adc a,1 ; a = count call dma_move pop hl ; restore value pop af ; carry ret c pop hl ret ;-------------------------------------------------------------------- ; ; hl: src ; de: dst ; b: src bank ; c: dst bank ; a: count dma_move: out0 (bcr0l),a ; setup DMA count xor a out0 (bcr0h),a push hl ld a,b call bnk2phy out0 (sar0l),l ; setup DMA src address out0 (sar0h),h out0 (sar0b),a ld l,e ld h,d ld a,c call bnk2phy out0 (dar0l),l ; setup DMA dst address out0 (dar0h),h out0 (dar0b),a ld a,M_MMOD ; DMA burst mode out0 (dmode),a ld a,M_DE0+M_NDWE1 ; enable DMA0 out0 (dstat),a ; move ... pop hl ret ;==================================================================== cseg if 0 ;-------------------------------------------------------------------- ; Return the BBR value for the given bank number bnk2bbr: or a ; 4 ret z ; 5/10 | 11 14 push bc ;11 | 11 ld b,a ; 4 ld c,CA ; 6 mlt bc ;17 >45 ld a,c ; 4 add a,10h ; 6 pop bc ; 9 | 10 ret ; 9 | 10 76 push ix ;2 / 14 | 15 ld ix,bnktbl ;4 / 12 | 14 ld ($+3+2),a ;3 / 15 | 19 ld a,(ix+0) ;3 / 14 | 19 pop ix ;2 / 12 | 14 ret ;1 / 9 | 10 15 / 76|91 push hl ;1 / 11 | 11 ld hl,bnktbl ;3 / 9 | 10 add a,l ;1 / 4 | 4 ld l,a ;1 / 4 | 4 ld a,0 ;1 / 6 | 7 adc a,h ;1 / 4 | 4 ld h,a ;1 / 4 | 4 ld a,(hl) ;1 / 6 | 7 pop hl ;1 / 9 | 10 ret ;1 / 9 | 10 12 / 66|71 push hl ;1 / 11 | 11 add a,low bnktbl ;2 / 6 | 7 ld l,a ;1 / 4 | 4 ld a,0 ;1 / 6 | 7 adc a,high bnktbl ;2 / 6 | 7 ld h,a ;1 / 4 | 4 ld a,(hl) ;1 / 6 | 7 pop hl ;1 / 9 | 10 ret ;1 / 9 | 10 11 / 61|67 endif cseg public bs$stack rept bs$stack$size db '|' endm bs$stack: end