-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprogram2.PANDA_ASM
More file actions
267 lines (225 loc) · 6.52 KB
/
Copy pathprogram2.PANDA_ASM
File metadata and controls
267 lines (225 loc) · 6.52 KB
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# void robertson_mul_2_num(int8 A, int8 B, int8* upper, int8* lower)
# {
# // SPECIAL CASE: The algorithm fails for A = -128.
# // The one case the swap-workaround can't fix is -128 * -128.
# // -128 * -128 = 16384 (0x4000 in 16-bit)
# if (A == -128 && B == -128)
# {
# *upper = 0x40;
# *lower = 0x00;
# return; // Exit early
# }
# // WORKAROUND: Booth's N-bit algorithm fails when multiplicand A is -2^(N-1) (-128).
# // Since A*B = B*A, we just swap them if A is -128.
# // (This is now safe because we've already handled the A=-128, B=-128 case)
# if (A == -128)
# {
# int8 temp = A;
# A = B;
# B = temp;
# }
# int8 P = 0; // accumulator (upper 8 bits)
# int8 Q = B; // multiplier
# int8 Qm1 = 0; // Q-1, starts at 0
# for (int8 i = 0; i < 8; i++)
# {
# int8 Q0 = Q & 1; // current LSB of Q
# // Step 1: add/subtract depending on (Q0, Qm1)
# if (Q0 == 1 && Qm1 == 0)
# {
# // P = P - A
# P = P - A;
# }
# else if (Q0 == 0 && Qm1 == 1)
# {
# // P = P + A
# P = P + A;
# }
# // Step 2: arithmetic right shift of (P, Q, Qm1)
# int8 newQm1 = Q & 1; // save old Q0 before shift
# // Shift right Q, bring in P's LSB
# // We must do a logical shift right, so we mask with 0x7F
# Q = (Q >> 1) & 0x7F;
# if (P & 1)
# {
# Q |= 0x80; // bring P LSB into Q MSB if it was 1
# }
# // Arithmetic shift right P
# // (P >>= 1) is arithmetic for signed types, but this is a
# // 100% portable way to guarantee it.
# int8 signP = P & 0x80;
# P >>= 1;
# if (signP) P |= 0x80; // keep sign bit
# // Update Qm1
# Qm1 = newQm1;
# }
# *upper = P;
# *lower = Q;
# }
# Constants
.IMM_0x00->0x00
.IMM_0x01->0x01
.IMM_0x02->0x02
.IMM_0x03->0x03
.IMM_0x08->0x08
.IMM_0x40->0x40
.IMM_0x80->0x80
# Note: 0x80 is -128 in 8-bit two's complement
# Register Mapping:
# R0: A (Multiplicand)
# R1: B (Multiplier) / Q
# R2: P (Accumulator)
# R3: Qm1
# R4: i (Loop Counter)
# R5: Temp / Constant -128 / Loop Limit
# R6: Q0 (Temp LSB)
# R7: P_LSB (Temp LSB)
# R8: Memory Address Pointers
# R9: Scratch / Constants
# =============================================================
# 1. Load Inputs
# =============================================================
# Load A from Mem[0] into R0
LOAD_IMMEDIATE .IMM_0x00
MOV R0, IM
LOAD R0, R0
# Load B from Mem[1] into R1
LOAD_IMMEDIATE .IMM_0x01
MOV R1, IM
LOAD R1, R1
# =============================================================
# 2. Special Case & Swap Logic
# =============================================================
# Load -128 (0x80) into R5 for comparison
LOAD_IMMEDIATE .IMM_0x80
MOV R5, IM
# Check if A == -128
CMP R0, R5
BEQ @LCheckBForSpecial
# If A != -128, we skip all special logic (no swap needed either)
# Unconditional Jump to InitLoop
CMP R0, R0
BEQ @LInitLoop
@LCheckBForSpecial:
# Here A is -128. Check B.
CMP R1, R5
BEQ @LHandleFixedResult
# If A == -128 AND B != -128, we must SWAP A and B
# Unconditional Jump to Swap
CMP R0, R0
BEQ @LDoSwap
@LHandleFixedResult:
# Case: A == -128 && B == -128
# Result is 0x4000 (16384)
# Store Upper (0x40) to Mem[3]
LOAD_IMMEDIATE .IMM_0x03
MOV R8, IM
LOAD_IMMEDIATE .IMM_0x40
MOV R9, IM
STORE R8, R9
# Store Lower (0x00) to Mem[2]
LOAD_IMMEDIATE .IMM_0x02
MOV R8, IM
LOAD_IMMEDIATE .IMM_0x00
MOV R9, IM
STORE R8, R9
HALT
@LDoSwap:
# Swap R0 (A) and R1 (B)
MOV R6, R0
MOV R0, R1
MOV R1, R6
# Fall through to InitLoop
# =============================================================
# 3. Algorithm Initialization
# =============================================================
@LInitLoop:
# P (R2) = 0
LOAD_IMMEDIATE .IMM_0x00
MOV R2, IM
# Q (R1) is already set to B (or A if swapped)
# Qm1 (R3) = 0
MOV R3, IM
# i (R4) = 0
MOV R4, IM
# Loop Limit (R5) = 8
LOAD_IMMEDIATE .IMM_0x08
MOV R5, IM
# =============================================================
# 4. Main Loop
# =============================================================
@LLoop:
# ---------------------------------------------------------
# Step 1: Check Q0 vs Qm1
# ---------------------------------------------------------
# Get Q0 = Q & 1. Store in R6.
MOV R6, R1
LOAD_IMMEDIATE .IMM_0x01
MOV R9, IM
AND R6, R9
# Compare Q0 (R6) vs Qm1 (R3)
CMP R6, R3
BGT @LSubOp # If Q0=1, Qm1=0 -> Subtract
CMP R6, R3
BLT @LAddOp # If Q0=0, Qm1=1 -> Add
# If Equal, Skip Add/Sub, jump to Shift
CMP R0, R0
BEQ @LShiftOp
@LSubOp:
# P = P - A
SUB R2, R0
CMP R0, R0
BEQ @LShiftOp
@LAddOp:
# P = P + A
ADD R2, R0
# Fall through to Shift
# ---------------------------------------------------------
# Step 2: Combined Shift
# ---------------------------------------------------------
@LShiftOp:
# We need to perform: (P, Q) >> 1
# P is Arithmetic Shift (Keep sign)
# Q is Logical Shift, but inherits P's LSB in its MSB
# 1. Save P's LSB (It will move to Q's MSB)
MOV R7, R2
LOAD_IMMEDIATE .IMM_0x01
MOV R9, IM
AND R7, R9 # R7 = P & 1
# 2. Logical Shift Q Right (R1)
# This shifts R1 >> 1 and puts a 0 in the MSB
SHIFT_RIGHT_LOGICAL R1
# 3. If P's LSB (R7) was 1, we must set Q's MSB to 1
# Check if R7 == 1
CMP R7, R9
BLT @LShiftP # If R7 < 1 (is 0), skip the OR
# OR Q with 0x80 to set MSB
LOAD_IMMEDIATE .IMM_0x80
MOV R9, IM
OR R1, R9
@LShiftP:
# 4. Arithmetic Shift P Right (R2)
# This preserves the sign bit of P
SHIFT_RIGHT_ARITHMETIC R2
# ---------------------------------------------------------
# Step 3: Loop Maintenance
# ---------------------------------------------------------
# Update Qm1 (R3) = Old Q0 (which we stored in R6)
MOV R3, R6
# Increment i (R4)
INC R4
# Compare i < 8
CMP R4, R5
BLT @LLoop
# =============================================================
# 5. Store Results
# =============================================================
# Store Upper (P / R2) to Mem[3], Mem[3] = MSB
LOAD_IMMEDIATE .IMM_0x03
MOV R8, IM
STORE R8, R2
# Store Lower (Q / R1) to Mem[2], Mem[2] = LSB
LOAD_IMMEDIATE .IMM_0x02
MOV R8, IM
STORE R8, R1
HALT