This is a cross-referenced version of pack8.plan, to download the unmodified
source try pack8.plan.
#PROGRAM /GFPACK8(15AM,22AM,DBM,EBM)
#PAGE
#INCLUDE STACK(/DEFS)
#PROGRAM
# Pack 8 bit bytes into a buffer
# gf pack8 (int *from, int len, int *to, int pos)
#SET ARGS=0
#DEFINE ARGFROM=ARGS
#SET ARGS=ARGS+1
#DEFINE ARGLEN=ARGS
#SET ARGS=ARGS+1
#DEFINE ARGTO=ARGS
#SET ARGS=ARGS+1
#DEFINE ARGPOS=ARGS
#SET ARGS=ARGS+1
# Stack frame
#SET STFRAME=SXFRAME
# First the arguments:
#DEFINE STFROM=SXPAR1
#SET STFRAME=STFRAME+1
#DEFINE STLEN=SXPAR2
#SET STFRAME=STFRAME+1
#DEFINE STTO=SXPAR3
#SET STFRAME=STFRAME+1
#DEFINE STPOS=SXPAR4
#SET STFRAME=STFRAME+1
# Now local vars:
# Pick up call by value parameters
STACK 2
OBEY ARGLEN(1)
LDX 0 0(3)
STO 0 STLEN(2)
OBEY ARGPOS(1)
LDX 0 0(3)
STO 0 STPOS(2)
# Pick up call by name parameters
OBEY ARGFROM(1)
ARRAY 3 [ arg is array elem or name
STACK 2 [ restore stack top
STO 3 STFROM(2)
OBEY ARGTO(1)
ARRAY 3 [ arg is array elem or name
STACK 2 [ restore stack top
STO 3 STTO(2)
ADN 1 ARGS
# Now Pascal style entry point
#CUE GPPACK8
BEGIN 2 3,1,STFRAME
# X1 - source
# X3 - dest
# X5 - count left
# X7 - pos in word (0, 1, 2)
LDX 5 STLEN(2) [ get bytes to move
BZE 5 BYE [ all done?
LDX 1 STFROM(2) [ get source addr
LDX 3 STTO(2) [ get destination buf
LDX 7 STPOS(2) [ get position to write to
BZE 7 WDS [ optimise frequent case
LDN 0 3
DVS 6 0 [ X7 = pos/3. x6 = remainder
ADX 1 7 [ point to dest word
# Jump if writing to start of word
BZE 6 WDS [ go copy full words
LDX 4 0(3) [ get dest word
# X6 = 1, middle byte, = 2, rightmost byte
SBNC 6 2
BCC RIGHT [ go write to rightmost byte
# Write to middle byte
MID LDX 0 0(1) [ get byte
SLL 0 8 [ move byte to middle
# -4081 = 0xfff00f, reduce shifting needed
NGN 6 4081 [ get mask to X6
SLC 6 4 [ x6 = 0xff00ff
ANDX 4 6 [ carve hole for byte
ORX 4 0 [ or in byte
SBN 5 1 [ decrement bytes to do
BNZ 5 *+3 [ carry on if more
STO 4 0(3) [ save word
BRN BYE [ and exit
ADN 1 1 [ increment input pointer
# Write to rightmost byte
RIGHT LDX 0 0(1) [ get byte
NGN 6 256 [ get mask
ANDX 4 6 [ mask off unwanted
ORX 4 0 [ or in byte
STO 4 0(3) [ save word
SBN 5 1 [ more to do?
BZE 5 BYE
ADN 1 1 [ increment input pointer
ADN 3 1 [ incr output pointer
# Now move full words, don't need to worry
# about previous contents
# get here with X5 = bytes left to do
# use X4 = byte count, X5 = word count
WDS LDN 0 3
DVS 4 0 [ x5 = count/3, x4 = remainder
BZE 5 TRAIL [ go deal with trailing bytes
NXT LDX 0 0(1) [ get leftmost byte
SLL 0 8
ORX 0 1(1) [ get middle byte
SLL 0 8
ORX 0 2(1) [ get rightmost byte
STO 0 0(3) [ save
ADN 1 3 [ bump pointers
ADN 3 1
BCT 5 NXT [ loop back for next word
# Now move any trailing bytes
# X4 = byte count, 0, 1 or 2
TRAIL BZE 4 BYE
LDX 0 0(1) [ get byte
SRC 0 8 [ move to top
NGN 5 256 [ get mask
SRC 5 8 [ x5 = 0x00ffff
ANDX 5 0(3) [ mask in word
ORX 5 0 [ or in byte
SBNC 4 2 [ done?
BCS DONE
LDX 0 1(1) [ get next byte
SLL 0 8 [ move to middle
NGN 6 4081 [ get mask to X6
SLC 6 4 [ x6 = 0xff00ff
ANDX 5 6 [ Carve hole for byte
ORX 5 0 [ or in byte
DONE STO 5 0(3) [ and save
BYE END 2 1,0
#END
#FINISH