Skip to content

Saturday Double Dabble

April 18, 2015

I’m putting this aside to steep for a while but the latest double dabble routine i’ve tested is below. This incorporates Charles’ latest demo work bodged by me to work with the compiler. It handles both 16 and 32 bit unsigned numbers. I’m also including Charles’ baseline demo routine and his writeup.
For the record, the 32 bit 12345 benchmark conversion takes 830 instructions.

; **********************************
; R15 - saved pointer to end of buffer, return value pointer to ascii result
; R10 - BINARY BIT COUNT
; R8  - POINTER TO BINARY NUMBER BEING CONVERTED
; R9  - UPPER BYTE IS PART OF BINARY NUMBER
; R9  - LOWER BYTE IS BYTE SHIFT COUNT
; R12 - INDEX REGISTER
; R13 - LOW BYTE STORES LOCAL LOOP COUNTER
; R13 - HIGH BYTE SAVES CURRENT BCD DIGIT
; R14 - LOW BYTE STORES ACTIVE BCD DIGIT COUNT
; R14 - HIGH BYTE SAVES CARRY VALUE (DF)
; **********************************
_uitoa:	;unsigned 16 bit binary to ascii conversion
ldax R15,R13,6	;point r15 to end of supplied buffer
ldi 0		;0
str R15		;terminate the result buffer
dec R15		;point to the units position
pushr R12	;save our 2 byte number
cpy2 R8,sp	;point to the work area
reserve 2	;dec the stack pointer twice more to synch with 32 bit cleanup
; -----------------
; *** SET BINARY BIT COUNT IN LOW BYTE OF R10
LDI     16           ;LOWER R10 = TOTAL BIT COUNT
PLO     R10
; -----------------
; *** COUNTER FOR UPPER BYTES
LDI     1
PLO     R13
br ddcore	;go do the core conversion

_ultoa:	;unsigned 32 bit conversion to ascii
ld2 R15,'O',sp,(2+4); pick up the buffer pointer
ldax R15,R15,11	;point to end of buffer for terminating 0
ldi 0
str R15
dec R15
; *** store binary number on stack and leave address in R8
pushf R13
pushl R12
cpy2 R8,SP
; -----------------
; *** SET BINARY BIT COUNT IN LOW BYTE OF R10
LDI     32           ;LOWER R10 = TOTAL BIT COUNT
PLO     R10
; -----------------
; *** COUNTER FOR UPPER BYTES
LDI     3
PLO     R13
; *** Here the buffer is prepped, R15 points to the end of it
;     R8 points to the binary number to convert and R10.0 has the bit count
;     R13.0 has a count of the upper bytes of the binary number
; *** DDCORE: is the entry point for all uses of the routine
DDCORE:
; *** start X=R12 pointing at units position of bcd number
cpy2 R12,R15
sex R12
; -----------------
; *** HIGH R9 = BYTE OF BINARY NUMBER
DOMORE:         LDA     R8		;pick up next byte of binary number
; -----------------
; *** IF ZERO BYTE, ADJUST R10 SHIFT COUNT AND TRY AGAIN
BNZ     NOMORE	;go check that the last digit is>9
GLO     R10           ;GET SHIFT COUNT
SMI     8            ;SUBTRACT ONE BYTE OF 8 BITS
PLO     R10           ;PUT BACK SHIFT COUNT
DEC     R13
GLO     R13
BNZ     DOMORE       ;LOOP NO MORE THAN 3 TIMES
; -----------------
; *** CHECK LAST BINARY BYTE < 10
LDA     R8           ;GET LAST BINARY BYTE
PHI     R9
SMI     10
BDF     NOMOR2       ;CONTINUE IF LAST BINARY BYTE >= 10
; -----------------
; *** STORE LAST BYTE AS ONLY BCD DIGIT
GHI     R9
STXD
ldi 1	;set digit count to 1
plo R14	;in reg 14
BR      SKPLBL       ;SKIP ENTIRE DOUBLE DABBLE LOOP
; -----------------
; *** RELOAD BINARY BYTE -- RESET COUNT TO 8
NOMORE:         PHI     R9
NOMOR2:         LDI     8
PLO     R9
; -----------------
; *** CURRENT BYTE HAS A ONE BIT
; -----------------
; *** SHIFT OUT HIGH ORDER ZERO BITS OF BINARY NUMBER
SHFOUT:         GHI     R9
SHL
PHI     R9
; -----------------
; *** CHECK FOR BYTE RELOAD
DEC     R9           ;DECREMENT BYTE BIT COUNT
CONTIN:         DEC     R10           ;DECREMENT TOTAL BIT COUNT
BNF     SHFOUT
; -----------------
; *** SET UPPER BYTE OF R10 TO 1
LDI     1
PHI     R10              ;HIGH BYTE OF R10 IS CONSTANT 1
PLO     R14             ;ACTIVE BCD DIGIT COUNT -- STARTS AT 1
; -----------------
; SET LOW-ORDER BCD DIGIT TO 1
STXD
;
;
;
; -----------------
; *** MAIN DOUBLE DABBLE LOOP
NLOOP:
; -----------------
; SHIFT BIT OF BINARY NUMBER INTO DF (CARRY)
; -----------------
GHI     R9
SHL
PHI     R9
; -----------------
; *** CHECK FOR BYTE RELOAD
DEC     R9
GLO     R9
BNZ     SKLOAD
; -----------------
; *** LOAD NEXT BINARY BYTE -- RESET COUNT TO 8
LDA     R8
PHI     R9
LDI     8
PLO     R9
; -----------------
; SET INDEX REGISTER
SKLOAD:         cpy2 R12,R15            ;restore index register
; -----------------
; GET ACTIVE BCD DIGIT COUNT TO LOOP COUNTER R13
GLO     R14             ;GET ACTIVE BCD DIGIT COUNT
PLO     R13             ;STORE LOCAL LOOP COUNT
UNILP:
; -----------------
; *** SAVE DF (CARRY) IN UPPER BYTE OF R14
SHLC                    ;GET CARRY TO LOW-ORDER BIT OF D
PHI     R14             ;SAVE D IN UPPER BYTE OF R14
; ----------------
; *** TEST ONE BYTE FOR PRE-CORRECTION
LDX                     ;LOAD D FROM INDEX ADDRESS
PHI     R13             ;SAVE BCD DIGIT IN UPPER BYTE OF R13
SMI     5               ;IS D > 4
BNF     NOFIX           ;SKIP CORRECTION IF D < 0
; *** PRE-CORRECT BCD DIGIT
ADI     128             ;ADD 3 CORRECTION + 5 RESTORE + 120
PHI     R13             ;SAVE BCD DIGIT IN UPPER BYTE OF R13
NOFIX:
; -----------------
; SHIFT ONE BCD DIGIT
; -----------------
GHI     R14             ;GET CARRY BACK TO D
SHR                     ;PUT CARRY VALUE INTO DF
GHI     R13             ;GET WORKING BCD DIGIT
SHLC                    ;ROTATE D THROUGH CARRY
STXD                    ;STORE D AND DECREMENT INDEX REGISTER
; -----------------
; *** UNILP COUNTER OVERHEAD
DEC     R13             ;DECREMENT CORRECT-SHIFT LOOP COUNTER
GLO     R13             ;D = LOCAL LOOP COUNT
BNZ     UNILP           ;LOOP UNTIL DONE
; -----------------
; *** IF DF = 1, CREATE NEW BCD DIGIT = 1 -- INCREMENT ACTIVE BCD DIGIT COUNT
BNF     SKPDIG          ;IF CARRY IS ZERO, NO NEW BCD DIGIT
INC     R14             ;INCREMENT ACTIVE BCD DIGIT COUNT
GHI     R10              ;GET A BYTE WITH VALUE OF 1
STXD                    ;STORE D IN NEW BCD DIGIT POSITION
; -----------------
; *** MAIN LOOP COUNTER OVERHEAD
SKPDIG:         DEC     R10              ;DECREMENT MASTER LOOP COUNTER
GLO     R10              ;D = BINARY BIT COUNT
BNZ     NLOOP           ;LOOP UNTIL DONE

SKPLBL:                                 ;LABEL TO SKIP DOUBLE DABBLE LOOP
; -----------------
; *** asciize bcd digits
asciize:	ldn R15	;pick up digit
ori 0x30 ;make it ascii
str R15
dec R15  ;back up a digit
dec R14	;reduce digit count
glo R14	;test
bnz asciize ;back for more if needed
inc R15	;reverse last backup

sex SP	;reset X to the stack pointer
release 4 ;release the 4 byte work area
cretn
#include "olduino.h"
#include "nstdlib.h"
#include <cpu1802spd4port7.h>
char * dd32cr1(long int);
char * ultoa(unsigned long int,char *);
char * uitoa(unsigned int,char *);
void	xtoainc(){
asm("\tinclude ddgt32.inc\n"); //ends with a return
}
void main(){
char bcdbuf[12]={10,10,10,10,10,10,10,10,10,10,10,10};
char *bcd;unsigned long binval=21; unsigned int bvali=12345;
int i;

delay(3000);
printf("\rBCD Mule Saturday\r\n");
for (i=10;i>=-1;i--){
binval=i;
printf("%d %lx=%ld=%s=%s\n\r",i,binval,binval,ultoa(binval,bcdbuf),uitoa(i,bcdbuf));
binval--;
}
}
#include "nstdlib.c"
#include "olduino.c"
TITL	"1802 Cross-Assembler Double-Dabble Source"
EJCT	60

CPU	1802

NUMBER		EQU	0

;
; Register Definitions:
;
R0		EQU	0
R1		EQU	1
R2		EQU	2
R3		EQU	3
R4		EQU	4
R5		EQU	5
R6		EQU	6
R7		EQU	7
R8		EQU	8
R9		EQU	9
R10		EQU	10
R11		EQU	11
R12		EQU	12
R13		EQU	13
R14		EQU	14
R15		EQU	15

; **********************************
; R5  - LOW BYTE = LOW BYTE OF INDEX REGISTER VALUE
; R6  - BINARY BIT COUNT
; R8  - POINTER TO BINARY NUMBER
; R9  - UPPER BYTE IS PART OF BINARY NUMBER
; R9  - LOWER BYTE IS BYTE SHIFT COUNT
; R12 - INDEX REGISTER
; R13 - LOW BYTE STORES LOCAL LOOP COUNTER
; R13 - HIGH BYTE SAVES CURRENT BCD DIGIT
; R14 - LOW BYTE STORES ACTIVE BCD DIGIT COUNT
; R14 - HIGH BYTE SAVES CARRY VALUE (DF)
; **********************************

LBR     $100

BGNDIG:         DB      84,129,91,194,132,49,81,49,71
ENDDIG:         DB      191

;CONVRT:         DB      $00,$CE,$ED,$BB         ; DECIMAL 13,561,275
;CONVRT:         DB      $00,$0C,$ED,$BB         ; DECIMAL 847,291
;CONVRT:         DB      $FF,$FF,$FF,$FF         ; DECIMAL 4,294,967,295
;CONVRT:         DB      $00,$08,$00,$00         ; DECIMAL 524,288
;CONVRT:         DB      $00,$00,$7B,$86         ; DECIMAL 31,622
CONVRT:         DB      $00,$FE,$DC,$BA         ; DECIMAL 16,702,650
;CONVRT:         DB      $DE,$AD,$BE,$EF         ; DECIMAL 3,735,928,559
;CONVRT:         DB      $DE,$AD,$FA,$CE         ; DECIMAL 3,735,943,886
;CONVRT:         DB      $00,$00,$00,$09         ; DECIMAL 9
;CONVRT:        DB      $00,$00,$00,$00          ; DECIMAL 0

START		ORG	100H
; -----------------
; *** SET UP INDEX REGISTER LOAD
SEX     R12
LDI     HIGH(ENDDIG)
PHI     R12
LDI     LOW(ENDDIG)
PLO     R5
PLO     R12
; -----------------
; *** LOAD BINARY NUMBER ADDRESS TO R8
LDI     HIGH(CONVRT)
PHI     R8
LDI     LOW(CONVRT)
PLO     R8
; -----------------
; *** SET BINARY BIT COUNT IN LOW BYTE OF R6
LDI     32           ;LOWER R6 = TOTAL BIT COUNT
PLO     R6
; -----------------
; *** COUNTER FOR FOUR UPPER BYTES
LDI     3
PLO     R13
; -----------------
; *** HIGH R9 = BYTE OF BINARY NUMBER
DOMORE:         LDA     R8
; -----------------
; *** IF ZERO BYTE, ADJUST R6 SHIFT COUNT AND TRY AGAIN
BNZ     NOMORE
GLO     R6           ;GET SHIFT COUNT
SMI     8            ;SUBTRACT ONE BYTE OF 8 BITS
PLO     R6           ;PUT BACK SHIFT COUNT
DEC     R13
GLO     R13
BNZ     DOMORE       ;LOOP NO MORE THAN 3 TIMES
; -----------------
; *** CHECK LAST BINARY BYTE < 10
LDA     R8           ;GET LAST BINARY BYTE
PHI     R9
SMI     10
BDF     NOMOR2       ;CONTINUE IF LAST BINARY BYTE >= 10
; -----------------
; *** STORE LAST BYTE AS ONLY BCD DIGIT
GHI     R9
STXD
BR      SKPLBL       ;SKIP ENTIRE DOUBLE DABBLE LOOP
; -----------------
; *** RELOAD BINARY BYTE -- RESET COUNT TO 8
NOMORE:         PHI     R9
NOMOR2:         LDI     8
PLO     R9
; -----------------
; *** CURRENT BYTE HAS A ONE BIT
; -----------------
; *** SHIFT OUT HIGH ORDER ZERO BITS OF BINARY NUMBER
SHFOUT:         GHI     R9
SHL
PHI     R9
; -----------------
; *** CHECK FOR BYTE RELOAD
DEC     R9           ;DECREMENT BYTE BIT COUNT
CONTIN:         DEC     R6           ;DECREMENT TOTAL BIT COUNT
BNF     SHFOUT
; -----------------
; *** SET UPPER BYTE OF R6 TO 1
LDI     1
PHI     R6              ;HIGH BYTE OF R6 IS CONSTANT 1
PLO     R14             ;ACTIVE BCD DIGIT COUNT -- STARTS AT 1
; -----------------
; SET LOW-ORDER BCD DIGIT TO 1
STXD
;
;
;
; -----------------
; *** MAIN DOUBLE DABBLE LOOP
NLOOP:
; -----------------
; SHIFT BIT OF BINARY NUMBER INTO DF (CARRY)
; -----------------
GHI     R9
SHL
PHI     R9
; -----------------
; *** CHECK FOR BYTE RELOAD
DEC     R9
GLO     R9
BNZ     SKLOAD
; -----------------
; *** RELOAD BINARY BYTE -- RESET COUNT TO 8
LDA     R8
PHI     R9
LDI     8
PLO     R9
; -----------------
; SET INDEX REGISTER (LOW BYTE ONLY)
SKLOAD:         GLO     R5              ;GET INDEX LOW BYTE
PLO     R12             ;STORE IN INDEX REG.
; -----------------
; GET ACTIVE BCD DIGIT COUNT TO LOOP COUNTER R13
GLO     R14             ;GET ACTIVE BCD DIGIT COUNT
PLO     R13             ;STORE LOCAL LOOP COUNT
UNILP:
; -----------------
; *** SAVE DF (CARRY) IN UPPER BYTE OF R14
SHLC                    ;GET CARRY TO LOW-ORDER BIT OF D
PHI     R14             ;SAVE D IN UPPER BYTE OF R14
; ----------------
; *** TEST ONE BYTE FOR PRE-CORRECTION
LDX                     ;LOAD D FROM INDEX ADDRESS
PHI     R13             ;SAVE BCD DIGIT IN UPPER BYTE OF R13
SMI     5               ;IS D > 4
BNF     NOFIX           ;SKIP CORRECTION IF D < 0
; *** PRE-CORRECT BCD DIGIT
ADI     128             ;ADD 3 CORRECTION + 5 RESTORE + 120
PHI     R13             ;SAVE BCD DIGIT IN UPPER BYTE OF R13
NOFIX:
; -----------------
; SHIFT ONE BCD DIGIT
; -----------------
GHI     R14             ;GET CARRY BACK TO D
SHR                     ;PUT CARRY VALUE INTO DF
GHI     R13             ;GET WORKING BCD DIGIT
SHLC                    ;ROTATE D THROUGH CARRY
STXD                    ;STORE D AND DECREMENT INDEX REGISTER
; -----------------
; *** UNILP COUNTER OVERHEAD
DEC     R13             ;DECREMENT CORRECT-SHIFT LOOP COUNTER
GLO     R13             ;D = LOCAL LOOP COUNT
BNZ     UNILP           ;LOOP UNTIL DONE
; -----------------
; *** IF DF = 1, CREATE NEW BCD DIGIT = 1 -- INCREMENT ACTIVE BCD DIGIT COUNT
BNF     SKPDIG          ;IF CARRY IS ZERO, NO NEW BCD DIGIT
INC     R14             ;INCREMENT ACTIVE BCD DIGIT COUNT
GHI     R6              ;GET A BYTE WITH VALUE OF 1
STXD                    ;STORE D IN NEW BCD DIGIT POSITION
; -----------------
; *** MAIN LOOP COUNTER OVERHEAD
SKPDIG:         DEC     R6              ;DECREMENT MASTER LOOP COUNTER
GLO     R6              ;D = BINARY BIT COUNT
BNZ     NLOOP           ;LOOP UNTIL DONE
SKPLBL:                                 ;LABEL TO SKIP DOUBLE DABBLE LOOP
; -----------------
; *** ZERO REMAINING HIGH ORDER BCD DIGITS
GLO     R14             ;GET LAST ACTIVE BCD DIGIT COUNT
SDI     10              ;COMPUTE REMAINING BCD DIGIT COUNT
PLO     R6              ;AND STORE IN LOOP COUNTER
CLEAR:          GLO     R13             ;GET ZERO FROM LOW BYTE OF R13
STXD                    ;STORE ZERO IN UNUSED BCD DIGITS
DEC     R6
GLO     R6
BNZ     CLEAR
; -----------------
IDL
END

Charles’ writeup

Advertisements

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: