1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2026-04-20 10:16:47 +00:00

Completed, tested, debugged, and documented module bitlib

This commit is contained in:
Curtis F Kaylor
2020-10-04 22:17:09 -04:00
parent 0fbbc6dce2
commit d816bd1273
6 changed files with 423 additions and 25 deletions
+70
View File
@@ -0,0 +1,70 @@
Bit Manipulation Functions for C02 Programs
This module contains functions to shift and rotate the bits in a byte,
and to extract, combine, swap and duplicate nybbles in a byte.
At the beginning of the program use the directives
#include <stddef.h02>
#include <bitlib.h02>
The following functions are defined:
r = shiftl(b,n) Shifts byte b by n bits to the left and returns
the result in r. If n is 0, the byte is not
shifted, and if n greater than 8, the returned
value will be 0.
r = shiftr(b,n) Shifts byte b by n bits to the right and returns
the result in r. If n is 0, the byte is not
shifted, and if n greater than 8, the returned
value will be 0.
r = rotl(b,n) Rotate byte b by n bits to the left and returns
the result in r, with the high bit rotated into
the low bit on each rotation. If n is 0, the
byte is not rotated, and any value of n greater
than 8, will return the same result as n modulo 8.
r = rotr(b,n) Rotate byte b by n bits to the right and returns
the result in r, with the high bit rotated into
the low bit on each rotation. If n is 0, the
byte is not rotated, and any value of n greater
than 8, will return the same result as n modulo 8.
b = pack(l,r); Packs the low nybbles of bytes l and r into a
single byte, with l becoming the left (or high)
nybble and r becoming the right (or low) nybble.
and returns the packed byte in b.
l,r = unpack(b); Unpacks byte b, returning the left (or high)
nybble in l, and the right (or low) nybble in r.
d = dupl(b); Duplicates the low nybble of byte b into the
high nybble and returns the new byte in d.
Note: Executes function pack() with b as both
arguments.
d = swap(b); Swaps the left (or high) and right (or low)
nybbles of byte b and returns the new byte in d.
Note: Executes function rotl() with the arguments
b and 4.
c,d,e = func(a,&d); Stores the input value a and the address of d
in memory.
Returns three bytes read from memory.
Note: Writes argument a to variable arg0,
the address of d to variables adr0 and adr1,
and returns the values of variables var0,
var1, and var2.
Note: This library expects the following external variables to be defined:
temp0: Temporary Variable
+103
View File
@@ -0,0 +1,103 @@
; C02 Module bitlib.h02 Assembly Language Subroutines
; Requires external location TEMP0 (system header)
SUBROUTINE BITLIB
;dupl(nybble) - Duplicate Low Order Nybble
;Args: A = Left Nybble
;Destroys: TEMP0
;Affects: Y
;Returns: A = Byte Containing Byte
DUPL: TAY ;Copy Left Nybble to Right
BEQ PACK ;If Zero, Return
;pack(nybble,nybble) - Pack Two Low Order Nybbles into Single Byte
;Args: A = Left Nybble
; Y = Right Nybble
;Destroys: TEMP0
;Returns: A = Packed Byte
PACK: ASL ;Shift Right Nybble to High Order
ASL
ASL
ASL
STA TEMP0 ;and Save It
TYA ;Get Right Nybble
AND #$0F ;Isolate Right Nybble
ORA TEMP0 ;Copy in Left Nybble
RTS
;unpack(byte) - Unpack Byte into Two Low Order Nybbles
;Args: A = Byte to Unpack
;Returns: A = Left Nybble
; Y = Right Nybble
UNPACK: PHA ;Save Byte
AND #$0F ;Isolate Right Nybble
TAY ;and Copy to Y Register
PLA ;Retrieve Byte
LSR ;and Shift Left Nybble to Low Order
LSR
LSR
LSR
RTS
;swap(byte) - Swap Low and High Nybbles in Byte
;Args: A = Byte to Swap
;Affects Y,N,Z,C
;Returns: A = Swapped Byte
SWAP: LDY #4 ;Set Count to 4 and Rotate Left
;rotl(byte,count) - Rotate byte by count Bits to the Left
;Args = Byte to Rotate
;Y = Number of Bits to Rotate
;Affects Y,N,Z,C
;Returns: A = Rotated Byte
ROTL: CPY #0 ;If Number of Bits is 0
BEQ .RETURN ; Return
.LOOPRL CLC ;Bit 0 will be 0
ROL ;Rotate Left
ADC #0 ; Copy Carry to Bit 0
DEY ;Decrement Counter
BNE .LOOPRL ; and Loop if Not 0
.RETURN RTS
;rotr(byte,count) - Shift byte by count Bits to the Right
;Args = Byte to Rotate
;Y = Number of Bits to Rotate
;Affects Y,N,Z,C
;Returns: A = Rotated Byte
ROTR: CPY #0 ;If Number of Bits is 0
BEQ .RETURN ; Return
.LOOPRR CLC ;Bit 7 will be 0
ROR ;Rotate Right
BCC .SKIPRR ;If Bit 0 was Set
ORA #$80 ; Set Bit 8
.SKIPRR DEY ;Decrement Counter
BNE .LOOPRR ; and Loop if Not 0
RTS
;shiftl(byte,count) - Shift byte by Count bits to the Left
;Args = Byte to Shift
;Y = Number of Bits to Rotate
;Affects Y,N,Z,C
;Returns: A = Shifted Byte
SHIFTL: CPY #0 ;If Number of Bits is 0
BEQ .RETURN ; Return
.LOOPSL ASL ;Shift Byte to Left
DEY ;Decrement Counter
BNE .LOOPSL ; and Loop if Not 0
RTS
;shiftr(byte,count) - Shift byte by Count bits to the Right
;Args = Byte to Shift
;Y = Number of Bits to Rotate
;Affects Y,N,Z,C
;Returns: A = Shifted Byte
SHIFTR: CPY #0 ;If Number of Bits is 0
BEQ .RETURN ; Return
.LOOPSR LSR ;Shift Byte to Right
DEY ;Decrement Counter
BNE .LOOPSR ; and Loop if Not 0
RTS
ENDSUBROUTINE
+50
View File
@@ -0,0 +1,50 @@
/**********************************************
* bitlib - Bit Manipulation Routines for C02 *
**********************************************/
/* Duplicate Low Order Nybble in Byte *
* Args: char b - Byte to Duplicate *
* Returns: char d - Duplicated Byte */
char dupl();
/* Pack Nybbles into Single Byte *
* Args: char l - Left Nybble *
* char r - Right Nybble *
* Returns: char b - Packed Byte */
char pack();
/* Rotate Byte Left *
* Args: char b - Byte to Rotate *
* char n - Number of Bits *
* Returns: char r - Rotated Byte */
char rotl();
/* Rotate Byte Right *
* Args: char b - Byte to Rotate *
* char n - Number of Bits *
* Returns: char r - Rotated Byte */
char rotr();
/* Shift Byte Left *
* Args: char b - Byte to Shift *
* char n - Number of Bits *
* Returns: char r - Shifted Byte */
char shiftl();
/* Shift Byte Right *
* Args: char b - Byte to Shift *
* char n - Number of Bits *
* Returns: char r - Shifted Byte */
char shiftr();
/* Swap Nybbles in Byte *
* Args: char b - Byte to Swap *
* Returns: char d - Swapped Byte */
char swap();
/* Unpack Byte into Separate Nybbles *
* Args: char b - Byte to Unpack *
* Returns: char l - Left Nybble *
* char r - Right Nybble */
char unpack();
+128
View File
@@ -0,0 +1,128 @@
/*********************************
* BITTEST - Test Module bitlib *
*********************************/
//Specify System Header using -H option
#include <stddef.h02>
#include <bitlib.h02>
const char detail = #FALSE;
char argone,argtwo,expone,exptwo,resone,restwo;
char high,low,left,right;
void pr1arg() {putchr(' ');prbyte(argone);putchr('=');prbyte(resone);}
void pr2arg() {putchr(' ');prbyte(argone);putchr(',');prbyte(argtwo);
putchr('=');prbyte(resone);}
void pr2res() {putchr(' ');prbyte(argone);putchr('=');
prbyte(resone);putchr(',');prbyte(restwo);}
void prtok() {putstr(" OK"); newlin();}
main:
putstr("DUPL():");
high = 0; low = 0;
for (argone = 0; argone < $10; argone++) {
expone = high | low; high = high + 16; low++;
resone = dupl(argone); if (detail) pr1arg();
if (resone <> expone) goto er1arg;
}
prtok();
putstr("PACK():");
high = 0;
for (argone = 0; argone < $10; argone++) {
low = 0;
for (argtwo = 0; argtwo < $10; argtwo++) {
expone = high | low; low++;
resone = pack(argone,argtwo); if (detail) pr2arg();
if (resone <> expone) goto er2arg;
}
high = high + 16;
}
prtok();
putstr("UNPACK():");
high = 0;
for (expone = 0; expone < $10; expone++) {
low = 0;
for (exptwo = 0; exptwo < $10; exptwo++) {
argone = high | low; low++;
resone, restwo = unpack(argone); if (detail) pr2res();
if (resone <> expone or restwo <> exptwo) goto er2arg;
}
high = high + 16;
}
prtok();
putstr("SWAP():");
high = 0;
for (right = 0; right < $10; right++) {
low = 0; left = 0;
do {
argone = high | low; low++;
expone = left | right; left = left + 16;
resone = swap(argone); if (detail) pr1arg();
if (resone <> expone) goto er1arg;
} while (left);
high = high + 16;
}
prtok();
putstr("ROTL():");
argone = %10101010; expone = argone;
for (argtwo = 0; argtwo < 9; argtwo++) {
resone = rotl(argone, argtwo); if (detail) pr2arg();
if (resone <> expone) goto er2arg;
high = expone & $80; expone<<; if (high) expone++;
}
prtok();
putstr("ROTR():");
argone = %10101010; expone = argone;
for (argtwo = 0; argtwo < 9; argtwo++) {
resone = rotr(argone, argtwo); if (detail) pr2arg();
if (resone <> expone) goto er2arg;
low = expone & $01; expone>>; if (low) expone = expone | $80;
}
prtok();
putstr("SHIFTL():");
argone = %10101010; expone = argone;
for (argtwo = 0; argtwo < 9; argtwo++) {
resone = shiftl(argone, argtwo); if (detail) pr2arg();
if (resone <> expone) goto er2arg;
expone<<;
}
prtok();
putstr("SHIFTR():");
argone = %10101010; expone = argone;
for (argtwo = 0; argtwo < 9; argtwo++) {
resone = shiftr(argone, argtwo); if (detail) pr2arg();
if (resone <> expone) goto er2arg;
expone>>;
}
prtok();
goto exit;
er1arg:
if (detail) newlin();
putstr(" ARG $"); prbyte(argone); putstr(" RESULT $"); prbyte(resone);
putstr(" EXPECTED $"); prbyte(expone); newlin();
goto exit;
er2arg:
if (detail) newlin();
putstr(" ARGS $"); prbyte(argone); putstr(",$"); prbyte(argtwo);
putstr(" RESULT $"); prbyte(resone);
putstr(" EXPECTED $"); prbyte(expone); newlin();
goto exit;
er2res:
if (detail) newlin();
putstr(" ARG $"); prbyte(argone); putstr(" RESULT $"); prbyte(resone);
putstr(" EXPECTED $"); prbyte(expone); putstr(",$"); prbyte(exptwo);
newlin();
goto exit;
+16
View File
@@ -0,0 +1,16 @@
cleared iocb for channel 0
cleared iocb for channel 1
cleared iocb for channel 2
cleared iocb for channel 3
cleared iocb for channel 4
cleared iocb for channel 5
cleared iocb for channel 6
cleared iocb for channel 7
cleared iocb for channel 8
cleared iocb for channel 9
cleared iocb for channel 10
cleared iocb for channel 11
cleared iocb for channel 12
cleared iocb for channel 13
cleared iocb for channel 14
cleared iocb for channel 15
+56 -25
View File
@@ -8,11 +8,19 @@
char aa,xx,yy; //Function Arguments
char i; //Loop Index
char r,h,l; //Register#, MSB, LSB
int v; //Register Contents
const char rvals = {$0F,$F0, $1E,$E1, $2D,$D2, $3C,$C3, $4B,$B4, $5A,$A5, $69,$96, $78,$87,
$80,$08, $91,$19, $A2,$2A, $B3,$B3, $C4,$4C, $D5,$5D, $E6,$6E, $F7,$7F};
char rcomp[32];
void clrabi() {for (i=0; i<=@rvals; i++) abi[i] = 0;}
void prword() {putchr('$'); prbyte(y); prbyte(x); putchr(' ');}
void putlin() {putstr(); newlin();}
void error() {putlin(); goto exit;}
void passed() {putlin("PASSED");}
void prtadr(aa,yy,xx) {
putchr('$');
if (yy) prbyte(yy);
@@ -22,32 +30,55 @@ void prtadr(aa,yy,xx) {
main:
//Print Register Addresses
putstr("R0 "); prtadr(&R0); putstr(" R0L "); prtadr(&R0L); putstr(" R0H "); prtadr(&R0H); newlin();
putstr("R1 "); prtadr(&R1); putstr(" R1L "); prtadr(&R1L); putstr(" R1H "); prtadr(&R1H); newlin();
putstr("R2 "); prtadr(&R2); putstr(" R2L "); prtadr(&R2L); putstr(" R2H "); prtadr(&R2H); newlin();
putstr("R3 "); prtadr(&R3); putstr(" R3L "); prtadr(&R3L); putstr(" R3H "); prtadr(&R3H); newlin();
putstr("R4 "); prtadr(&R4); putstr(" R4L "); prtadr(&R4L); putstr(" R4H "); prtadr(&R4H); newlin();
putstr("R5 "); prtadr(&R5); putstr(" R5L "); prtadr(&R5L); putstr(" R5H "); prtadr(&R5H); newlin();
putstr("R6 "); prtadr(&R6); putstr(" R6L "); prtadr(&R6L); putstr(" R6H "); prtadr(&R6H); newlin();
putstr("R7 "); prtadr(&R7); putstr(" R7L "); prtadr(&R7L); putstr(" R7H "); prtadr(&R7H); newlin();
putstr("R8 "); prtadr(&R8); putstr(" R8L "); prtadr(&R8L); putstr(" R8H "); prtadr(&R8H); newlin();
putstr("R9 "); prtadr(&R9); putstr(" R9L "); prtadr(&R9L); putstr(" R9H "); prtadr(&R9H); newlin();
putstr("R10 "); prtadr(&R10); putstr(" R10L "); prtadr(&R10L); putstr(" R10H "); prtadr(&R10H); newlin();
putstr("R11 "); prtadr(&R11); putstr(" R11L "); prtadr(&R11L); putstr(" R11H "); prtadr(&R11H); newlin();
putstr("R12 "); prtadr(&R12); putstr(" R12L "); prtadr(&R12L); putstr(" R12H "); prtadr(&R12H); newlin();
putstr("R13 "); prtadr(&R13); putstr(" R13L "); prtadr(&R13L); putstr(" R13H "); prtadr(&R13H); newlin();
putstr("R14 "); prtadr(&R14); putstr(" R14L "); prtadr(&R14L); putstr(" R14H "); prtadr(&R14H); newlin();
putstr("R15 "); prtadr(&R15); putstr(" R15L "); prtadr(&R15L); putstr(" R15H "); prtadr(&R15H); newlin();
putstr("R0 "); prtadr(&abi.r0); putstr(" R0L "); prtadr(&abi.r0.lo); putstr(" R0H "); prtadr(&abi.r0.hi); newlin();
putstr("R1 "); prtadr(&abi.r1); putstr(" R1L "); prtadr(&abi.r1.lo); putstr(" R1H "); prtadr(&abi.r1.hi); newlin();
putstr("R2 "); prtadr(&abi.r2); putstr(" R2L "); prtadr(&abi.r2.lo); putstr(" R2H "); prtadr(&abi.r2.hi); newlin();
putstr("R3 "); prtadr(&abi.r3); putstr(" R3L "); prtadr(&abi.r3.lo); putstr(" R3H "); prtadr(&abi.r3.hi); newlin();
putstr("R4 "); prtadr(&abi.r4); putstr(" R4L "); prtadr(&abi.r4.lo); putstr(" R4H "); prtadr(&abi.r4.hi); newlin();
putstr("R5 "); prtadr(&abi.r5); putstr(" R5L "); prtadr(&abi.r5.lo); putstr(" R5H "); prtadr(&abi.r5.hi); newlin();
putstr("R6 "); prtadr(&abi.r6); putstr(" R6L "); prtadr(&abi.r6.lo); putstr(" R6H "); prtadr(&abi.r6.hi); newlin();
putstr("R7 "); prtadr(&abi.r7); putstr(" R7L "); prtadr(&abi.r7.lo); putstr(" R7H "); prtadr(&abi.r7.hi); newlin();
putstr("R8 "); prtadr(&abi.r8); putstr(" R8L "); prtadr(&abi.r8.lo); putstr(" R8H "); prtadr(&abi.r8.hi); newlin();
putstr("R9 "); prtadr(&abi.r9); putstr(" R9L "); prtadr(&abi.r9.lo); putstr(" R9H "); prtadr(&abi.r9.hi); newlin();
putstr("R10 "); prtadr(&abi.r10); putstr(" R10L "); prtadr(&abi.r10.lo); putstr(" R10H "); prtadr(&abi.r10.hi); newlin();
putstr("R11 "); prtadr(&abi.r11); putstr(" R11L "); prtadr(&abi.r11.lo); putstr(" R11H "); prtadr(&abi.r11.hi); newlin();
putstr("R12 "); prtadr(&abi.r12); putstr(" R12L "); prtadr(&abi.r12.lo); putstr(" R12H "); prtadr(&abi.r12.hi); newlin();
putstr("R13 "); prtadr(&abi.r13); putstr(" R13L "); prtadr(&abi.r13.lo); putstr(" R13H "); prtadr(&abi.r13.hi); newlin();
putstr("R14 "); prtadr(&abi.r14); putstr(" R14L "); prtadr(&abi.r14.lo); putstr(" R14H "); prtadr(&abi.r14.hi); newlin();
putstr("R15 "); prtadr(&abi.r15); putstr(" R15L "); prtadr(&abi.r15.lo); putstr(" R15H "); prtadr(&abi.r15.hi); newlin();
//Test setabi() and getabi()
for (i=0; i<=@rvals; i++) r0l[i] = 0; //Clear ABI Registers
//inline $ff;
setabi(@rvals, rvals); //Write to ABI Registers
for (i=0; i<@rvals; i++) {
if (!i&7) newlin();
if (!i&1) putstr(" $");
prbyte(R0l[i]);
if (R0l[i] <> rvals[i]) {putstr("ERROR!"); goto exit;}
putstr("SETABI(), GETABI() ");
clrabi(); //Clear Registers
i = 0;
for (r=0; r<16; r++) {
l = r | 16; h = r | 32;
setabi(r, h, l);
xx = abi[i]; i++;
yy = abi[i]; i++;
v = getabi(r);
//newlin(); prhex(r); putchr(':'); prword(.,h,l); prword(.,yy,xx); prword(v);
if (xx<>l or yy<>h) error("SETABI: WRITE ERROR");
if (<v<>l or >v<>h) error("GETABI: READ ERROR");
}
passed();
goto exit;
//Test setabi() and getabi()
putstr("SETABR(), GETABR() ");
for (i=0; i<=@rvals; i++) {
abi[i] = 0; //Clear ABI Registers
rcomp[i] = 0; //Clear Compare Array
}
//inline $ff;
setabr(@rvals, rvals); //Write to ABI Registers
getabr(@rcomp, rcomp); //Read from ABI Registers
for (i=0; i<@rvals; i++) {
//if (!i&7) newlin(); if (!i&1) putstr(" $"); prbyte(abi[i]);
if (abi[i] <> rvals[i]) error("SETABR() WRITE ERROR");
if (rcomp[i] <> rvals[i]) error("GETABR() READ ERROR");
}
if (abi[@rvals] <> 0) error("SETABR() OVERFLOW");
if (rcomp[@rvals] <> 0) error("GETABR() OVERFLOW");
passed();
goto exit;