Commit | Line | Data |
---|---|---|
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. | |
8 | WORD_715827882 | |
9 | ||
10 | # Divisor, also chosen for a unique, visually recognizable bit pattern. | |
11 | WORD_65534 | |
12 | IM_1 | |
13 | ADD | |
14 | ||
15 | # The stack is initialized. Time to run the program. | |
16 | JSR>divide | |
17 | HALT | |
18 | ||
19 | ########################################################################################## | |
20 | generatesignflag | |
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 | ########################################################################################## | |
55 | negate | |
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 | ########################################################################################## | |
73 | absolutevalue | |
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 | ########################################################################################## | |
95 | subtract | |
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 | ########################################################################################## | |
122 | divide | |
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 |