-
Notifications
You must be signed in to change notification settings - Fork 8
/
6809_MPDMUL.s
204 lines (197 loc) · 5.58 KB
/
6809_MPDMUL.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
.macro CLC
ANDCC #$FE
.endm
; Title: Multiple-precision Decimal Multiplication
; Name: MPDMUL
; Purpose: Multiply 2 arrays of BCD bytes
; Multiplicand := Multiplicand * multiplier
; Entry: TOP 0F STACK
; High byte of return address
; Low byte of return address
; Length of the arrays in bytes
; High byte of multiplicand address
; Low byte of multiplicand address
; High byte of multiplier address
; Low byte of multiplier address
; The arrays are unsigned BCD numbers
; with a maximum Length of 255 bytes,
; ARRAY[0] is the least significant byte,
; and ARRAY[LENGTH1] is the most significant byte.
;
; Exit: Multiplicand := Multiplicand * multiplier
;
; Registers Used: All
;
; Time: Assuming average digit value of multiplicand
; is 5, then the time is approximately
; (170 * Length^2)+ (370 * length) + 80 cycles
; Size:
; Program 164 bytes
; Data 511 bytes plus 3 stack bytes
;
; TEST LENGTH OF OPERANDS
; EXIT IF LENGTH IS ZERO
;
MPDMUL:
LDB 2,S ; GET LENGTH OF OPERANDS IN BYTES L
BEQ EXITML ; BRANCH (EXIT) IF LENGTH IS ZERO
;
; SAVE DIGIT COUNTER AND UPPER/LOWER DIGIT FLAG ON STACK,
; MAKE ROOM FOR NEXT DIGIT OF MULTIPLICAND ON STACK
;
CLRA ; CLEAR DIGIT FLAG INITIALLY (LOWER DIGIT)
PSHS A,B ; SAVE LENGTH, DIGIT FLAG ON STACK
LEAS -1,S ; RESERVE SPACE ON STACK FOR NEXT DIGIT
; OF MULTIPLICAND
;
; SAVE MULTIPLICAND IN TEMPORARY BUFFER (MCAND)
; CLEAR PARTIAL PRODUCT CONSISTING OF UPPER BYTES
; STARTING AT PROD AND LOWER BYTES REPLACING
; MULTIPLICAND
;
LDX 6,S ; GET BASE ADDRESS OF MULTIPLICAND
LDY #MCAND ; GET BASE ADDRESS OF TEMPORARY BUFFER
LDU #PROD ; GET BASE ADDRESS OF UPPER PRODUCT
INITLP:
LDA ,X ; MOVE BYTE OF MULTIPLICAND TO TEMPORARY BUFFER
STA ,Y+
CLRA
STA ,X+ ; CLEAR BYTE OF LOWER PRODUCT
STA ,U+ ; CLEAR BYTE OF UPPER PRODUCT
DECB
BNE INITLP ; CONTINUE THROUGH ALL BYTES
STA ,U ; CLEAR OVERFLOW BYTE ALSO
;
; LOOP THROUGH ALL BYTES OF MULTIPLICAND
; USE EACH DIGIT TO DETERMINE HOW MANY TIMES
; TO ADD MULTIPLIER TO PARTIAL PRODUCT
LDU #MCAND ; POINT TO FIRST BYTE OF MULTIPLICAND
;
; LOOP THROUGH 2 DIGITS PER BYTE
; DURING LOWER DIGIT, DIGIT FLAG = 0
; DURING UPPER DIGIT, DIGIT FLAG = FF HEX
PROCDG:
LDA ,U ; GET BYTE OF MULTIPLICAND
LDY 1,S ; GET DIGIT FLAG
BEQ MASKDG ; BRANCH IF ON LGWER DIGIT
LSRA ; SHIFT UPPER DIGIT TO LOWER DIGIT
LSRA
LSRA
LSRA
MASKDG:
ANDA #$0F ; MASK OFF CURRENT DIGIT
BEQ MOVDIG ; BRANCH(SKIP ADDITION) IF DIGIT IS ZERO
STA ,S ; SAVE DIGIT ON STACK
;
; ADD MULTIPLIER TO PRODUCT NUMBER OF TIMES GIVEN BY DIGIT OF MULTIPLICAND
;
ADMULT:
LDB 5,S ; GET LENGTH OF OPERANDS
LDY #PROD ; GET BASE ADDRESS OF PRODUCT
LDX 8,S ; GET BASE ADDRESS OF MULTIPLIER
CLC ; CLEAR CARRY INITIALLY
ADBYTE:
LDA ,X+ ; GET NEXT BYTE OF MULTIPLIER
ADCA ,Y ; ADD TO BYTE OF UPPER PRODUCT
DAA ; MAKE SUM DECIMAL
STA ,Y+ ; STORE AS NEW PRODUCT
DECB ; DECREMENT LOOP COUNTER
BNE ADBYTE ; CONTINUE UNTIL LOOP COUNTER = 0
LDA ,Y ; ADD CARRY TO OVERFLOW BYTE
ADCA #0
DAA ; MAKE SUM DECIMAL
STA ,Y ; SAVE NEW OVERFLOW BYTE
DEC ,S ; DECREMENT NUMBER OF ADDITIONS
BNE ADMULT ; CONTINUE UNITL ALL ADDITIONS DONE
;
; STORE THE LEAST SIGNIFICANT DIGIT OF UPPER PRODUCT AS
; THE NEXT DIGIT OF MULTIPLICAND
;
MOVDIG:
LDX 6,S ; GET BASE ADDRESS OF MULTIPLICAND
LDY #PROD ; GET BASE ADDRESS OF UPPER PRODUCT
LDB ,Y ; GET LEAST SIGNIFICANT BYTE OF PRODUCT
ANDB #$0F ; MASK OFF LOWER DIGIT
LDA 1,S ; GET DIGIT FLAG
BEQ LOWDGT ; BRANCH IF ON LOWER DIGIT
ASLB ; ELSE SHIFT PRODUCT DIGIT TO UPPER DIGIT
ASLB
ASLB
ASLB
ADDB ,X ; ADD TO UPPER DIGIT OF MULTIPLICAND BYTE
STB ,X+
BRA SHFPRD ; BRANCH TO SHIFT PRODUCT
LOWDGT:
STB ,X ; STORE DIGIT IN MULTIPLICAND
;
; SHIFT PARTIAL PRODUCT RIGHT 1 DIGIT (4 BITS)
SHFPRD:
LDA #4 ; SHIFT ONE DIGIT (4 BITS)
SETSHF:
LDB 5,S ; GET LENGTH
INCB ; SHIFT LENGTH+1 BYTES TO INCLUDE OVERFLOW
LDY #PROD ; POINT TO PARTIAL PRODUCT
LEAY B,Y ; POINT PAST OVERFLOW BYTE
CLC ; CLEAR CARRY INTO OVERFLOW
SHFARY:
ROR ,-Y ; SHIFT BYTE OF PRODUCT RIGHT
DECB ; CONTINUE THROUGH ALL BYTES
BNE SHFARY ; DECREMENT SHIFT COUNT
DECA SETSHF ; CONTINUE THROUGH 4 1-BIT SHIFTS
;
; CHANGE OVER TO NEXT
; DIGIT IF ON LOWER DIGIT
;
LDA #$FF ; GET UPPER DIGIT MARKER
CMPA 1,S ; COMPARE TO DIGIT FLAG
BEQ HIDIG ; BRANCH IF ON UPPER DIGIT
STA 1,S ; ELSE SET DIGIT FLAG TO UPPER DIGIT
BRA PROCDG ;T PROCESS NEXT DIGIT
;
; MOVE ON TO NEXT BYTE IF ON UPPER DIGIT
;
HIDIG:
CLR 1,S ; CLEAR DIGIT FLAG TO INDICATE LOW DIGIT
LEAU 1,U ; PROCEED TO NEXT BYTE OF MULTIPLICAND
LDD 6,S ; GET MULTIPLICAND POINTER
ADDD #1 ; POINT TO NEXT BYTE
STD 6,S ; SAVE MULTIPLICAND POINTER
DEC 2,S ; DECREMENT DIGIT COUNTER
BNE PROCDG ; PROCESS NEXT DIGIT
LEAS 3,S ; REMOVE TEMPORARY STORAGE FROM STACK
;
; REMOVE PARAMETERS FROM STACK AND EXIT
;
EXITML:
LDU ,S ; GET RETURN ADDRESS
LEAS 7,S ; REMOVE PARAMETERS FROM STACK
JMP ,U ; EXIT TO RETURN ADDRESS
;
; DATA
;
PROD: RMB 256 ; PRODUCT BUFFER WITH OVERFLOW BYTE
MCAND: RMB 255 ; MULTIPLICAND BUFFER
;
; SAMPLE EXECUTION
;
SC3J:
LDX AY1ADR ; GET MULTIPLICAND
LDY AY2ADR ; GET MULTIPLIER
LDA #SZAYS ; GET LENGTH OF ARRAYS IN BYTES
PSHS A,X,Y ; SAVE PARAMETERS IN STACK
JSR MPDMUL ; MULTIPLE-PRECISION DECIMAL MULTIPLICATION
; RESULT OF 1234H
; 5718H = 7056012H
; IN MEMORY
; AY1 = 12H
; AY1+1 = 60H
; AY1+2 = 05H
; AY1+3 = 07H
; AY1+6 = 00H
BRA SC3J ; REPEAT TEST
SZAYS EQU 7 ; LENGTH OF ARRAYS IN BYTES
AY1ADR FDB AY1 ; BASE ADDRESS OF ARRAY 1
AY2ADR FDB AY2 ; BASE ADDRESS OF ARRAY 2
AY1: FCB $34,$12,0,0,0,0,0
AY2: FCB $18,$57,0,0,0,0,0
END