Added 'long division' as new embedded program for NEDsim.
[screensavers] / hacks / NEDsim / ned_programs / long_division.ned_asm
CommitLineData
e9878e80
AT
1# (c) 2021 Aaron Taylor <ataylor at subgeniuskitty dot com>
2# See LICENSE.txt file for copyright and license details.
3
4# This program performs binary long division, halting when complete.
5
6# Dividend, chosen for alternating bit pattern to make it easily identifiable
7# whenever it appears somewhere on the stack.
8WORD_715827882
9
10# Divisor, also chosen for a unique, visually recognizable bit pattern.
11WORD_65534
12IM_1
13ADD
14
15# The stack is initialized. Time to run the program.
16JSR>divide
17HALT
18
19##########################################################################################
20generatesignflag
21##########################################################################################
22# Description:
23# Given a pair of twos-complement signed integers X and Y, generates a sign flag.
24# Flag is non-zero if the product of X and Y would be negative, otherwise flag is zero.
25# Call Stack:
26# Y Operand
27# X Operand
28# Return PC <-- TOS
29# Return Stack:
30# Sign Flag <-- TOS
31##########################################################################################
32 # Place Return PC at bottom of stack.
33 LDSP+2
34 LDSP+1
35 STSP+3
36 STSP+0
37
38 # Stack now looks like:
39 # Return PC
40 # X Operand
41 # Y Operand <-- TOS
42
43 IM_4
44 LOAD
45 AND
46 SWAP
47 IM_4
48 LOAD
49 AND
50 XOR
51 SWAP
52 RTS
53
54##########################################################################################
55negate
56##########################################################################################
57# Description:
58# Returns the additive inverse of a twos-complement operand.
59# Call Stack:
60# Operand
61# Return PC <-- TOS
62# Return Stack:
63# Result <-- TOS
64##########################################################################################
65 SWAP
66 NOT
67 IM_1
68 ADD
69 SWAP
70 RTS
71
72##########################################################################################
73absolutevalue
74##########################################################################################
75# Description:
76# Returns the absolute value of a twos-complement operand.
77# Call Stack:
78# Operand
79# Return PC <-- TOS
80# Return Stack:
81# Result <-- TOS
82##########################################################################################
83 SWAP
84 LDSP+0
85 IM_4
86 LOAD
87 AND
88 BRZ>absolutevaluereturn
89 JSR>negate
90 absolutevaluereturn
91 SWAP
92 RTS
93
94##########################################################################################
95subtract
96##########################################################################################
97# Description:
98# Performs X-Y and returns result on TOS.
99# Call Stack:
100# Y Operand
101# X Operand
102# Return PC <-- TOS
103# Return Stack:
104# Result <-- TOS
105##########################################################################################
106 # Place Return PC at bottom of stack.
107 LDSP+2
108 LDSP+1
109 STSP+3
110 STSP+0
111 # Stack now looks like:
112 # Return PC
113 # X Operand
114 # Y Operand <-- TOS
115
116 JSR>negate
117 ADD
118 SWAP
119 RTS
120
121##########################################################################################
122divide
123##########################################################################################
124# Description:
125# Division with remainder.
126# Halts on zero divisor.
127# Call Stack:
128# Dividend
129# Divisor
130# Return PC <-- TOS
131# Return Stack:
132# Quotient
133# Remainder <-- TOS
134##########################################################################################
135 # Move Return PC to bottom of stack.
136 LDSP+2
137 SWAP
138 STSP+2
139 SWAP
140
141 # Stack now looks like:
142 # Return PC
143 # Dividend
144 # Divisor <-- TOS
145
146 # Check for zero divisor
147 LDSP+0
148 BRZ>divideexception
149
150 # Generate a sign flag and store it behind the operands.
151 LDSP+1
152 LDSP+1
153 JSR>generatesignflag
154 LDSP+2
155 SWAP
156 STSP+2
157
158 # Stack now looks like:
159 # Return PC
160 # Sign flag (nonzero for negative result, 0 for positive result)
161 # Divisor
162 # Dividend <-- TOS
163
164 # Convert both Dividend and Divisor to absolute value.
165 JSR>absolutevalue
166 SWAP
167 JSR>absolutevalue
168
169 # Stack now looks like:
170 # Return PC
171 # Sign flag (nonzero for negative result, 0 for positive result)
172 # ABS(Dividend)
173 # ABS(Divisor) <-- TOS
174
175 # Prepare stack for division algorithm.
176 IM_31 # Cycle Counter - Loop from n-1 -> 0 where n = 32 bits.
177 IM_0 # Quotient
178 IM_0 # Remainder
179
180 # Binary long division
181 divisionloop
182 # Check Cycle Counter for end-of-loop condition (CC = -1).
183 LDSP+2 # Cycle Counter
184 IM_1
185 ADD
186 BRZ>divisionloopend
187
188 # While Cycle Counter >= 0
189
190 # Left-shift Remainder by 1 bit.
191 IM_1
192 IM_4 # Address of 0x80000000 register
193 LOAD
194 OR
195 SHIFT
196
197 # Set LSB of Remainder equal to bit (Cycle Counter) of Dividend.
198 LDSP+4 # Dividend
199 LDSP+3 # Cycle Counter
200 SHIFT
201 IM_1
202 AND
203 OR
204
205 # Check if Remainder >= Divisor
206 LDSP+0 # Remainder
207 LDSP+4 # Divisor
208 BLT>divisionsubloopend
209
210 # If Remainder >= Divisor
211
212 # Set Remainder = Remainder - Divisor
213 LDSP+3 # Divisor
214 SWAP
215 JSR>subtract
216
217 # Set bit (Cycle Counter) of Quotient equal to 1.
218 SWAP
219 IM_1
220 LDSP+3 # Cycle Counter
221 IM_4
222 LOAD
223 OR
224 SHIFT
225 OR
226 SWAP
227
228 divisionsubloopend
229
230 # Decrement Cycle Counter
231 IM_1
232 LDSP+3 # Cycle Counter
233 JSR>subtract
234 STSP+2
235
236 # Loop over next division cycle
237 JMP>divisionloop
238
239 divisionloopend
240
241 # Stack cleanup
242 STSP+1
243 STSP+1
244 STSP+1
245
246 # Stack now looks like:
247 # Return PC
248 # Sign flag (nonzero for negative result, 0 for positive result)
249 # Remainder
250 # Quotient <-- TOS
251
252 # Set sign of results.
253 LDSP+2 # Sign flag
254 BRZ>divisioncleanup
255 JSR>negate
256 SWAP
257 JSR>negate
258 SWAP
259
260 divisioncleanup
261
262 # Clean up and return
263 SWAP
264 LDSP+3 # Return PC
265 SWAP
266 STSP+2
267 SWAP
268 STSP+2
269 RTS
270
271 # For now we can only HALT on errors and let the PC inform our debugging.
272 divideexception
273 HALT
274