-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy path6809_DIV16.s
248 lines (245 loc) · 6.55 KB
/
6809_DIV16.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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
.macro CLC
ANDCC #$FE
.endm
.macro SEC
ORCC #1
.endm
; Title: 16-bit division
;
; Name: SDIV16, UDIV16, SREM16, UREM16
; Purpose:
; SDIV16 Divide 2 signed 16-bit words and return a 16-bit signed quotient.
; UDIV16 Divide 2 unsigned 16-bit words and return a 16-bit unsigned quotient
; SREM16 Divide 2 signed 16-bit words and return a 16-bit signed remainder
; UREM16 Divide 2 unsigned 16-bit words and return a 16-bit unsigned remainder
;
; Entry:
;
; TOP OF STACK
; High byte of return address
; Low byte of return address
; High byte of divisor
; Low byte of divisor
; High byte of dividend
; Low byte of dividend
;
; Exit:
;
; TOP OF STACK
; High byte of result
; Low byte of result
;
; If no errors then
; Carry := 0
; else
; divide by zero error
; Carry := 1
; quotient := 0
; remainder := 0
;
; Registers Used: A,B,CC,X,Y
;
; Time: Approximately 955 cycles
;
; Size:
; Program 145 bytes
; Data 3 stack bytes
;
; SIGNED DIVISION, RETURNS REMAINDER
;
SREM16:
LDA #$FF ; INDICATE REMAINDER TO BE RETURNED
STA ,-S ; SAVE INDICATOR ON STACK
BRA CHKSGN ; GO CHECK SIGNS
; SIGNED DIVISION, RETURNS QUOTIENT
;
SDIV16:
CLR ,-S ; INDICATE QUOTIENT TO BE RETURNED
;
; IF DIVISOR IS NEGATIVE, TAKE ITS ABSOLUTE VALUE AND INDICATE
; THAT QUOTIENT IS NEGATIVE
;
CHKSGN:
LDD #0 ; INDICATE QUOTIENT, REMAINDER POSITIVE
PSHS D ; SAVE INDICATOR ON STACK LEAX 5,8 POINT TO DIVISOR
TST ,X ; CHECK IF DIVISOR IS POSITIVE
BPL CHKDVD ; BRANCH IF DIVISOR IS POSITIVE
SUBD ,X ; ELSE TAKE ABSOLUTE VALUE OF DIVISOR
STD ,X
COM 1,S ; INDICATE QUOTIENT IS NEGATIVE
BRA CHKZRO
;
; IF DIVIDEND IS NEGATIVE,
; TAKE ITS ABSOLUTE VALUE,
; INDICATE THAT REMAINDER IS NEGATIVE,
; AND INVERT SIGN OF QUOTIENT
;
CHKDVD: LEAX 2,X ; POINT TO HIGH BYTE OF DIVIDEND
TST ,X ; CHECK IF DIVIDEND IS POSITIVE
BPL CHKZRO ; BRANCH IF DIVIDEND IS POSITIVE
LDD #0 ; ELSE TAKE ABSOLUTE VALUE OF DIVIDEND
SUBD ,X
COM ,S ; INDICATE REMAINDER IS NEGATIVE
COM 1,S ; INVERT SIGN OF QUOTIENT
;
; UNSIGNED 16-BIT DIVISION, RETURNS QUOTIENT
;
UDIV16: CLR ,-S ; INDICATE QUOTIENT TO BE RETURNED
BRA CLRSGN
;
; UNSIGNED 16-BIT DIVISION, RETURNS REMAINDER
;
UREM16:
LDA #$FF ; INDICATE REMAINDER TO BE RETURNED
STA ,-S
;
; UNSIGNED DIVISION, INDICATE QUOTIENT, REMAINDER BOTH POSITIVE
;
CLRSGN:
LDD #0 ; INDICATE QUOTIENT, REMAINDER POSITIVE
PSHS D
;
; CHECK FOR ZERO DIVISOR
; EXIT, INDICATING ERROR, IF FOUND
;
CHKZRO:
LEAX 5,S ; POINT TO DIVISOR
LDD ,X ; TEST DIVISOR
BNE STRTDV ; BRANCH IF DIVISOR NOT ZERO
STD 2,X ; DIVISOR IS ZERO, SO MAKE RESULT ZERO
;-- SEC ; INDICATE DIVIDE BY ZERO ERROR
BRA EXITDV ; EXIT INDICATING ERROR
;
; DIVIDE UNSIGNED DIVIDEND BY UNSIGNED DIVISOR
; MEMORY ADDRESSES HOLD BOTH DIVIDEND AND QUOTIENT.
; EACH TIME WE SHIFT THE DIVIDEND ONE BIT LEFT,
; WE ALSO SHIFT A BIT OF THE
; QUOTIENT IN FROM THE CARRY AT THE FAR RIGHT
; AT THE END, THE QUOTIENT HAS REPLACED THE DIVIDEND IN MEMORY
; AND THE REMAINDER IS LEFT IN REGISTER D
;
STRTDV: LDD #0 ; EXTEND DIVIDEND TO 32 BITS WITH 0
LDY #16 ; BIT COUNT = 16
;-- CLC ; START CARRY AT ZERO
;
; SHIFT DIVIDEND LEFT WITH ENTERING AT FAR RIGHT
;
DIV16:
ROL 3,X ; SHIFT LOW BYTE OF DIVIDEND
; QUOTIENT BIT ENTERS FROM CARRY
ROL 2,X ; SHIFT NEXT BYTE OF DIVIDEND
ROLB ; SHIFT NEXT BYTE OF DIVIDEND
ROLA ; SHIFT HIGH BYTE OF DIVIDEND
;
; DO A TRIAL SUBTRACTION OF DIVISOR FROM DIVIDEND
; IF DIFFERENCE IS NON-NEGATIVE, SET NEXT BIT OF QUOTIENT.
; PERFORM ACTUAL SUBTRACTION, REPLACING QUOTIENT WITH DIFFERENCE.
; IF DIFFERENCE IS NEGATIVE, CLEAR NEXT BIT OF QUOTIENT
;
CMPD ,X ; TRIAL SUBTRACTION OF DIVISOR
BCS CLRCRY ; BRANCH IF SUBTRACTION FAILS
SUBD ,X ; TRIAL SUBTRACTION SUCCEEDED,
; SO SUBTRACT DIVISOR FROM
; DIVIDEND
;-- SEC ; SET NEXT BIT OF QUOTIENT TO 1
BRA DECCNT
CLRCRY:
;-- CLC ; TRIAL SUBTRACTION FAILED, SO
; SET NEXT BIT OF QUOTIENT TO 0
;
; UPDATE BIT COUNTER
; CONTINUE THROUGH 16 BITS
;
DECCNT: LEAY -1,Y ; CONTINUE UNTIL ALL BITS DONE
BNE DIV16
;
; SHIFT LAST CARRY INTO QUOTIENT
;
ROL 3,X ; SHIFT LAST CARRY INTO QUOTIENT
ROL 2,X ; INCLUDING MORE SIGNIFICANT BYTE
;
; SAVE REMAINDER IN STACK
; NEGATE REMAINDER IF INDICATOR SHOWS IT IS NEGATIVE
;
STD ,X ; SAVE REMAINDER IN STACK
TST ,S ; CHECK IF REMAINDER IS POSITIVE
BEQ TSTQSN
; BRANCH IF REMAINDER IS POSITIVE
LDD #0 ; ELSE NEGATE IT
STD ,X ; SAVE NEGATIVE REMAINDER
;
; NEGATE QUOTIENT IF INDICATOR SHOWS IT IS NEGATIVE
;
TSTQSN: TST 1,S ; CHECK IF QUOTIENT IS POSITIVE
BEQ TSTRTN ; BRANCH IF QUOTIENT IS POSITIVE LDD #0 ELSE NEGATE IT
SUBD 7,S
STD 7,S ; SAVE NEGATIVE QUOTIENT
;
; SAVE QUDTIENT OR REMAINDER, DEPENDING ON FLAG IN STACK
;
TSTRTN:
;-- CLC ; INDICATE NO DIVIDEBYZERO ERROR
TST 2,S ; TEST QUOTIENT/REMAINDER FLAG
BEQ EXITDV ; BRANCH TO RETURN QUOTIENT
LDD ,X ; REPLACE QUOTIENT WITH REMAINDER
STD 7,S
; REMOVE PARAMETERS FROM STACK AND EXIT
;
EXITDV: LDX 3,S ; SAVE RETURN ADDRESS
LEAS 7,S ; REMOVE PARAMETERS FROM STACK
JMP ,X ; EXIT TO RETURN ADDRESS
;
; SAMPLE EXECUTION
;
SC3B:
;
; SIGNED DIVIDE, OPRND1 / OPRND2, STORE QUOTIENT AT QUOTNT
;
LDY OPRND1 ; GET DIVIDEND
LDX OPRND2 ; GET DIVISOR
PSHS X,Y ; SAVE PARAMETERS IN STACK
JSR SDIV16 ; SIGNED DIVIDE, RETURN QUOTIENT
PULS X ; GET QUOTIENT
STX QUOTNT ; QUOTNT RESULT OF -1023 / 123 = -8
; IN MEMORY QUOTNT = FF HEX
; QUOTNT +1 = F8 HEX
; UNSIGNED DIVIDE, OPRND1 / OPRND2, STORE QUOTIENT AT QUOTNT
;
LDY OPRND1 ; GET DIVIDEND
LDX OPRND2 ; GET DIVISOR
PSHS X,Y ; SAVE PARAMETERS IN STACK
JSR UDIV16 ; UNSIGNED DIVIDE, RETURN QUOTIENT
PULS X ; GET QUOTIENT
STX QUOTNT ; RESULT OF 64513 / 123 = 524
; IN MEMORY QUOTNT = 02 HEX
; QUOTNT +1 = 0C HEX
;
; SIGNED DIVIDE, OPRND1 / OPRND2, STORE REMAINDER AT REMNDR
;
LDY OPRND1 ; GET DIVIDEND
LDX OPRND2 ; GET DIVISOR
PSHS X,Y ; SAVE PARAMETERS IN STACK
JSR SREM16 ; SIGNED DIVIDE, RETURN REMAINDER
PULS X ; GET REMAINDER
STX REMNDR ; REMAINDER OF -1023 / 123 = -39
; IN MEMORY REMNDR = FF HEX
; REMNDR + 1 = C7 HEX
;
; UNSIGNED DIVIDE, OPRND1 / OPRND2, STORE REMAINDER AT REMNDR
;
LDY OPRND1 ; GET DIVIDEND
LDX OPRND2 ; GET DIVISOR
PSHS X,Y ; SAVE PARAMETERS IN STACK
JSR UREM16 ; UNSIGNED DIVIDE, RETURN REMAINDER
PULS X ; GET QUOTIENT
STX REMNDR ; RESULT OF 64513 / 123 = 61
; IN MEMORY REMNDR = D0 HEX
; REMNDR + 1 = 3D HEX
;
; DATA
;
OPRND1 FDB -1023 ; DIVIDEND (64513 UNSIGNED)
OPRND2 FDB 123 ; DIVISOR
QUOTNT RMB 2 ; QUOTIENT
REMNDR RMB 2 ; REMAINDER
END