This is a cross-referenced version of mvch.plan, to download the unmodified
source try mvch.plan.
#PROGRAM /MVCH(15AM,22AM,DBM,EBM)
#PAGE
# MVCH (LEN, FROM, TO)
# Attempts to optimise to word moves when it can
# allows any length to be moved
# Internal use - calling sequence is
# X4 = source (Character address)
# X5 = dest (Character address)
# X6 = chars to move
# CALL 1 MVCHARS
# On exit X4 points after last char moved from
# X5 points after last char moved to
# All other registers may be trashed
#PROGRAM
LDX 0 6 [ get chars to move
SBNC 0 7 [ at least one whole word?
BCS TRAIL [ if not, simple char move
LDX 0 4 [ get source addr
ERX 0 5 [ compare with dest
SLC 0 2 [ move diff in offset to low bits
ANDN 0 #3 [ mask boring
BNZ 0 CHAR [ jump if char offsets different
# Char offsets are same, move 'till word boundary
LDX 0 4
SLC 0 2 [ so just what is the offset, anyway?
ANDN 0 #3
BZE 0 WORD [ jif already on word boundary
LDN 1 4
SBX 1 0 [ move 1..3 chars before word boundary
MVCH 4 0(1)
SBX 6 1 [ amount left to move
WORD LDX 3 6 [ chars left to move
SRL 3 2 [ convert to words
LDX 7 3 [ words to move
W512 SBNC 7 512 [ more than 512 words to move?
BCS REST
MOVE 4 0 [ move 512 words
ADN 4 512 [ increment pointers
ADN 5 512
SBN 6 2048 [ decrement chars left to move
BRN W512
REST MOVE 4 0(3) [ move words
ADX 4 3
ADX 5 3 [ MOVE, unlike MVCH, doesn't update
SLL 3 2 [ How many chars were moved?
SBX 6 3 [ decrement chars left to move
TRAIL BZE 6 BYE [ jump if move finished
STO 6 3
MVCH 4 0(3) [ move trailing chars
BYE EXIT 1 0 [ All done.
# If source and dest don't have same alignment we'll have
# to use MVCH for whole move
CHAR LDX 7 6 [ more than 512 chars?
SBNC 7 512
BCS TRAIL [ no, just do the end bit
MVCH 4 0 [ move 512 chars
STO 7 6
BRN CHAR
#END
#FINISH