msx1: custom user copy routines
authorAlan Cox <alan@linux.intel.com>
Sun, 7 Apr 2019 11:48:46 +0000 (12:48 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 7 Apr 2019 11:48:46 +0000 (12:48 +0100)
We know the kernel side will always be mapped so we can do much simpler user
copiers which is important because the bank switch is so incredibly expensive.

The actual code is from SBCv2 so we should probably unify this into a standard
'always mapped' lib helper

Kernel/platform-msx1/fuzix.lnk
Kernel/platform-msx1/slots.s

index ae7c619..97cdab7 100644 (file)
@@ -44,5 +44,4 @@ vt.rel
 font6x8.rel
 devsys.rel
 usermem.rel
-usermem_std-z80.rel
 -e
index 4b5826a..7ab73d0 100644 (file)
@@ -645,3 +645,143 @@ testram:
 
 _ramtab:
        .ds 6
+
+;
+;      Because the slot changing is so slow and we do bouncing the need
+;      for custom copiers is essential. We carefully lay out things so that
+;      nothing we need to copy is below the common boundary line.
+;
+
+        ; exported symbols
+        .globl __uget
+        .globl __ugetc
+        .globl __ugetw
+
+       .globl outcharhex
+       .globl outhl
+
+        .globl __uput
+        .globl __uputc
+        .globl __uputw
+        .globl __uzero
+
+       .globl  map_process_always
+       .globl  map_kernel
+;
+;      We need these in common as they bank switch
+;
+        .area _COMMONMEM
+
+;
+;      The basic operations are copied from the standard one. Only the
+;      blk transfers are different. uputget is a bit different as we are
+;      not doing 8bit loop pairs.
+;
+uputget:
+        ; load DE with the byte count
+        ld c, 8(ix) ; byte count
+        ld b, 9(ix)
+       ld a, b
+       or c
+       ret z           ; no work
+        ; load HL with the source address
+        ld l, 4(ix) ; src address
+        ld h, 5(ix)
+        ; load DE with destination address (in userspace)
+        ld e, 6(ix)
+        ld d, 7(ix)
+       ret     ;       Z is still false
+
+__uputc:
+       pop bc  ;       return
+       pop de  ;       char
+       pop hl  ;       dest
+       push hl
+       push de
+       push bc
+       call map_process_always
+       ld (hl), e
+uputc_out:
+       jp map_kernel                   ; map the kernel back below common
+
+__uputw:
+       pop bc  ;       return
+       pop de  ;       word
+       pop hl  ;       dest
+       push hl
+       push de
+       push bc
+       call map_process_always
+       ld (hl), e
+       inc hl
+       ld (hl), d
+       jp map_kernel
+
+__ugetc:
+       pop bc  ; return
+       pop hl  ; address
+       push hl
+       push bc
+       call map_process_always
+        ld l, (hl)
+       ld h, #0
+       jp map_kernel
+
+__ugetw:
+       pop bc  ; return
+       pop hl  ; address
+       push hl
+       push bc
+       call map_process_always
+        ld a, (hl)
+       inc hl
+       ld h, (hl)
+       ld l, a
+       jp map_kernel
+
+__uput:
+       push ix
+       ld ix, #0
+       add ix, sp
+       call uputget                    ; source in HL dest in DE, count in BC
+       jr z, uput_out                  ; but count is at this point magic
+       call map_process_always
+       ldir
+uput_out:
+       call map_kernel
+       pop ix
+       ld hl, #0
+       ret
+
+__uget:
+       push ix
+       ld ix, #0
+       add ix, sp
+       call uputget                    ; source in HL dest in DE, count in BC
+       jr z, uput_out                  ; but count is at this point magic
+       call map_process_always
+       ldir
+       jr uput_out
+
+;
+__uzero:
+       pop de  ; return
+       pop hl  ; address
+       pop bc  ; size
+       push bc
+       push hl
+       push de
+       ld a, b ; check for 0 copy
+       or c
+       ret z
+       call map_process_always
+       ld (hl), #0
+       dec bc
+       ld a, b
+       or c
+       jp z, uputc_out
+       ld e, l
+       ld d, h
+       inc de
+       ldir
+       jp uputc_out