Commit | Line | Data |
---|---|---|
9d2503c6 | 1 | /* |
0880b18e | 2 | * @(#)emulate.s 7.1 (Berkeley) %G% |
9d2503c6 BK |
3 | */ |
4 | ||
5 | #ifdef VAX630 | |
6 | /* | |
7 | * String instruction emulation - MicroVAX only. These routines are called | |
8 | * from locore.s when an "emulate" fault occurs on the MicroVAX. They are | |
9 | * called with the stack set up as follows: | |
10 | * | |
11 | * (sp): Return address of trap handler | |
12 | * 4(sp): Instruction Opcode (also holds PSL result from emulator) | |
13 | * 8(sp): Instruction PC | |
14 | * 12(sp): Operand 1 | |
15 | * 16(sp): Operand 2 | |
16 | * 20(sp): Operand 3 | |
17 | * 24(sp): Operand 4 | |
18 | * 28(sp): Operand 5 | |
19 | * 32(sp): Operand 6 | |
20 | * 36(sp): old Register 11 | |
21 | * 40(sp): old Register 10 | |
22 | * 44(sp): Return PC | |
23 | * 48(sp): Return PSL | |
24 | * 52(sp): TOS before instruction | |
25 | * | |
26 | * R11 and r10 are available for use. If any routine needs to use r9-r1 | |
27 | * they need to save them first (unless those registers are SUPPOSED to be | |
28 | * messed with by the "instruction"). These routines leave their results | |
29 | * in registers 0-5 explicitly, as needed, and use the macros defined below | |
30 | * to link up with calling routine. | |
31 | */ | |
32 | ||
33 | #define return rsb | |
34 | #define savepsl movpsl 4(sp) | |
35 | #define setpsl(reg) movl reg,4(sp) | |
36 | #define overflowpsl movl $2,4(sp) | |
37 | #define arg1 12(sp) | |
38 | #define arg2 16(sp) | |
39 | #define arg3 20(sp) | |
40 | #define arg4 24(sp) | |
41 | #define arg5 28(sp) | |
42 | #define arg6 32(sp) | |
43 | #define argub(num,reg) movzbl 8+4*num(sp),reg | |
44 | #define arguw(num,reg) movzwl 8+4*num(sp),reg | |
45 | #define argul(num,reg) movl 8+4*num(sp),reg | |
46 | #define argb(num,reg) cvtbl 8+4*num(sp),reg | |
47 | #define argw(num,reg) cvtwl 8+4*num(sp),reg | |
48 | #define argl(num,reg) movl 8+4*num(sp),reg | |
49 | #define toarg(reg,num) movl reg,8+4*num(sp) | |
50 | ||
51 | ||
52 | .text | |
53 | .align 1 | |
54 | .globl _EMcrc | |
55 | _EMcrc: | |
56 | argl(1,r11) # (1) table address == r11 | |
57 | argl(2,r0) # (2) initial crc == r0 | |
58 | toarg(r8,1) # save r8 in arg1 spot | |
59 | argl(4,r8) # (4) source address == r8 | |
60 | toarg(r1,4) # save r1 in arg4 spot | |
61 | tstl arg3 # (3) source length == "arg3" | |
62 | jeql Lcrc_out | |
63 | Lcrc_loop: | |
64 | xorb2 (r8)+,r0 | |
65 | extzv $0,$4,r0,r10 | |
66 | extzv $4,$28,r0,r1 | |
67 | xorl3 r1,(r11)[r10],r0 | |
68 | extzv $0,$4,r0,r10 | |
69 | extzv $4,$28,r0,r1 | |
70 | xorl3 r1,(r11)[r10],r0 | |
71 | decl arg3 | |
72 | jneq Lcrc_loop | |
73 | tstl r0 | |
74 | Lcrc_out: | |
75 | savepsl | |
76 | argl(1,r8) | |
77 | argl(4,r1) | |
78 | return | |
79 | ||
80 | ||
81 | .align 1 | |
82 | .globl _EMmovtc | |
83 | _EMmovtc: | |
84 | arguw(1,r0) # (1) source length == r0 | |
85 | argl(2,r1) # (2) source address == r1 | |
86 | argub(3,r11) # (3) fill character == r11 | |
87 | argl(4,r3) # (4) table address == r3 | |
88 | argl(6,r5) # (6) destination address == r5 | |
89 | arguw(5,r4) # (5) destination length == r4 | |
90 | jeql Lmovtc_out | |
91 | Lmovtc_loop: | |
92 | tstl r0 | |
93 | jeql Lmovtc_2loop | |
94 | movzbl (r1)+,r2 | |
95 | movb (r3)[r2],(r5)+ | |
96 | decl r0 | |
97 | decl r4 | |
98 | jeql Lmovtc_out | |
99 | jbr Lmovtc_loop | |
100 | Lmovtc_2loop: | |
101 | movb r11,(r5)+ | |
102 | decl r4 | |
103 | jneq Lmovtc_2loop | |
104 | Lmovtc_out: | |
105 | cmpl r4,r0 | |
106 | savepsl | |
107 | clrl r2 | |
108 | return | |
109 | ||
110 | ||
111 | .align 1 | |
112 | .globl _EMmovtuc | |
113 | _EMmovtuc: | |
114 | arguw(1,r0) # (1) source length == r0 | |
115 | argl(2,r1) # (2) source address == r1 | |
116 | argub(3,r11) # (3) escape character == r11 | |
117 | argl(4,r3) # (4) table address == r3 | |
118 | argl(6,r5) # (6) destination address == r5 | |
119 | arguw(5,r4) # (5) destination length == r4 | |
120 | jeql Lmovtuc_out | |
121 | Lmovtuc_loop: | |
122 | tstl r0 | |
123 | jeql Lmovtuc_out | |
124 | movzbl (r1),r2 | |
125 | movzbl (r3)[r2],r2 | |
126 | cmpl r2,r11 | |
127 | jeql Lmovtuc_out | |
128 | movzbl (r1)+,r2 | |
129 | movb (r3)[r2],(r5)+ | |
130 | decl r0 | |
131 | decl r4 | |
132 | jneq Lmovtuc_loop | |
133 | Lmovtuc_out: | |
134 | cmpl r4,r0 | |
135 | savepsl | |
136 | clrl r2 | |
137 | return | |
138 | ||
139 | ||
140 | .align 1 | |
141 | .globl _EMmatchc | |
142 | _EMmatchc: | |
143 | argl(2,r10) # (2) substring address == r10 | |
144 | arguw(3,r2) # (3) source length == r2 | |
145 | argl(4,r3) # (4) source address == r3 | |
146 | arguw(1,r11) # (1) substring length == r11 | |
147 | jeql Lmatchc_out # temp source address == r1 | |
148 | addl2 r10,r11 # temp substring address == r0 | |
149 | tstl r2 | |
150 | jeql Lmatchc_out | |
151 | Lmatchc_loop: | |
152 | cmpb (r10),(r3) | |
153 | jneq Lmatchc_fail | |
154 | movl r3,r1 | |
155 | movl r10,r0 | |
156 | Lmatchc_2loop: | |
157 | cmpl r0,r11 | |
158 | jeql Lmatchc_succ | |
159 | cmpb (r0)+,(r1)+ | |
160 | jeql Lmatchc_2loop | |
161 | Lmatchc_fail: | |
162 | incl r3 | |
163 | decl r2 | |
164 | jneq Lmatchc_loop | |
165 | movl r10,r1 | |
166 | subl3 r10,r11,r0 | |
167 | jbr Lmatchc_out | |
168 | Lmatchc_succ: | |
169 | movl r11,r1 | |
170 | clrl r0 | |
171 | Lmatchc_out: | |
172 | savepsl | |
173 | return | |
174 | ||
175 | ||
176 | .align 1 | |
177 | .globl _EMspanc | |
178 | _EMspanc: | |
179 | argl(2,r1) # (2) string address == r1 | |
c475a6e1 JB |
180 | argl(3,r3) # (3) table address == r3 |
181 | argub(4,r2) # (4) character-mask == r2 | |
9d2503c6 BK |
182 | arguw(1,r0) # (1) string length == r0 |
183 | jeql Lspanc_out | |
184 | Lspanc_loop: | |
185 | movzbl (r1),r11 | |
c475a6e1 JB |
186 | mcomb (r3)[r11],r11 |
187 | bicb3 r11,r2,r11 | |
9d2503c6 BK |
188 | jeql Lspanc_out |
189 | incl r1 | |
190 | decl r0 | |
191 | jneq Lspanc_loop | |
192 | Lspanc_out: | |
193 | savepsl | |
194 | clrl r2 | |
195 | return | |
196 | ||
197 | ||
198 | .align 1 | |
199 | .globl _EMscanc | |
200 | _EMscanc: | |
201 | argl(2,r1) # (2) string address == r1 | |
c475a6e1 JB |
202 | argl(3,r3) # (3) table address == r3 |
203 | argub(4,r2) # (4) character-mask == r2 | |
9d2503c6 BK |
204 | arguw(1,r0) # (1) string length == r0 |
205 | jeql Lscanc_out | |
206 | Lscanc_loop: | |
207 | movzbl (r1),r11 | |
c475a6e1 JB |
208 | mcomb (r3)[r11],r11 |
209 | bicb3 r11,r2,r11 | |
9d2503c6 BK |
210 | jneq Lscanc_out |
211 | incl r1 | |
212 | decl r0 | |
213 | jneq Lscanc_loop | |
214 | Lscanc_out: | |
215 | savepsl | |
216 | clrl r2 | |
217 | return | |
218 | ||
219 | ||
220 | .align 1 | |
221 | .globl _EMskpc | |
222 | _EMskpc: | |
223 | argub(1,r11) # (1) character == r11 | |
224 | argl(3,r1) # (3) string address == r1 | |
225 | arguw(2,r0) # (2) string length == r0 | |
226 | incl r0 | |
227 | Lskpc_loop: | |
228 | decl r0 | |
229 | jeql Lskpc_out | |
230 | cmpb (r1)+,r11 | |
231 | jeql Lskpc_loop | |
232 | decl r1 | |
c475a6e1 | 233 | tstl r0 |
9d2503c6 BK |
234 | Lskpc_out: |
235 | savepsl | |
236 | return | |
237 | ||
238 | ||
239 | .align 1 | |
240 | .globl _EMlocc | |
241 | _EMlocc: | |
242 | argub(1,r11) # (1) character == r11 | |
243 | argl(3,r1) # (3) string address == r1 | |
244 | arguw(2,r0) # (2) string length == r0 | |
245 | incl r0 | |
246 | Llocc_loop: | |
247 | decl r0 | |
248 | jeql Llocc_out | |
249 | cmpb (r1)+,r11 | |
250 | jneq Llocc_loop | |
251 | decl r1 | |
c475a6e1 | 252 | tstl r0 |
9d2503c6 BK |
253 | Llocc_out: |
254 | savepsl | |
255 | return | |
256 | ||
257 | ||
258 | .align 1 | |
259 | .globl _EMcmpc3 | |
260 | _EMcmpc3: | |
261 | argl(2,r1) # (2) string1 address == r1 | |
262 | argl(3,r3) # (3) string2 address == r3 | |
263 | arguw(1,r0) # (1) strings' length == r0 | |
264 | jeql Lcmpc3_out | |
265 | Lcmpc3_loop: | |
266 | cmpb (r1),(r3) | |
267 | jneq Lcmpc3_out | |
268 | incl r1 | |
269 | incl r3 | |
270 | decl r0 | |
271 | jneq Lcmpc3_loop | |
272 | Lcmpc3_out: | |
273 | savepsl | |
274 | movl r0,r2 | |
275 | return | |
276 | ||
277 | ||
278 | .align 1 | |
279 | .globl _EMcmpc5 | |
280 | _EMcmpc5: | |
281 | argl(2,r1) # (2) string1 address == r1 | |
282 | argub(3,r11) # (1) fill character == r11 | |
283 | arguw(4,r2) # (1) string2 length == r2 | |
284 | argl(5,r3) # (3) string2 address == r3 | |
285 | arguw(1,r0) # (1) string1 length == r0 | |
286 | jeql Lcmpc5_str2 | |
287 | Lcmpc5_loop: | |
288 | tstl r2 | |
289 | jeql Lcmpc5_str1loop | |
290 | cmpb (r1),(r3) | |
291 | jneq Lcmpc5_out | |
292 | incl r1 | |
293 | incl r3 | |
294 | decl r2 | |
295 | decl r0 | |
296 | jneq Lcmpc5_loop | |
297 | Lcmpc5_str2: | |
298 | tstl r2 | |
299 | jeql Lcmpc5_out | |
300 | Lcmpc5_str2loop: | |
301 | cmpb r11,(r3) | |
302 | jneq Lcmpc5_out | |
303 | incl r3 | |
304 | decl r2 | |
305 | jneq Lcmpc5_str2loop | |
306 | jbr Lcmpc5_out | |
307 | Lcmpc5_str1loop: | |
308 | cmpb (r1),r11 | |
309 | jneq Lcmpc5_out | |
310 | incl r1 | |
311 | decl r0 | |
312 | jneq Lcmpc5_str1loop | |
313 | Lcmpc5_out: | |
314 | savepsl | |
315 | return | |
316 | ||
317 | ||
318 | /* | |
319 | * Packed Decimal string operations | |
320 | */ | |
321 | ||
322 | #define POSITIVE $12 | |
323 | #define NEGATIVE $13 | |
324 | #define NEGATIVEalt $11 | |
325 | ||
326 | ||
327 | .align 1 | |
328 | .globl _EMaddp4 | |
329 | _EMaddp4: | |
330 | toarg(r9,6) # save register r9 in arg6 spot | |
331 | arguw(1,r11) # (1) source length == r11 | |
332 | argl(2,r10) # (2) source address == r10 | |
333 | arguw(3,r9) # (3) destination length == r9 | |
334 | argl(4,r3) # (4) destination address == r3 | |
335 | # arg4 will be needed later | |
336 | # arg5 holds destination address of LSNibble temporarily | |
337 | ashl $-1,r11,r11 | |
338 | addl2 r11,r10 # source address of LSNibble | |
339 | incl r11 # source length is in bytes | |
340 | ashl $-1,r9,r9 | |
341 | addl2 r9,r3 # r3 = destination address of LSNibble | |
342 | incl r9 # destination length is in bytes | |
343 | toarg(r3,5) # stored in arg5 spot | |
344 | extzv $0,$4,(r3),r2 # set standard +/- indicators in destination | |
345 | cmpl r2,NEGATIVE | |
346 | jeql L112 | |
347 | cmpl r2,NEGATIVEalt | |
348 | jeql L111 | |
349 | insv POSITIVE,$0,$4,(r3) | |
350 | jbr L112 | |
351 | L111: | |
352 | insv NEGATIVE,$0,$4,(r3) | |
353 | L112: | |
354 | extzv $0,$4,(r10),r2 # r2 = standard +/- of source | |
355 | cmpl r2,NEGATIVE | |
356 | jeql L114 | |
357 | cmpl r2,NEGATIVEalt | |
358 | jeql L113 | |
359 | movl POSITIVE,r2 | |
360 | jbr L114 | |
361 | L113: | |
362 | movl NEGATIVE,r2 | |
363 | L114: | |
364 | cmpl r11,r9 # if source is longer than destination | |
365 | jleq L115 | |
366 | movl r9,r11 # set source length == destination length | |
367 | L115: | |
368 | extzv $4,$4,(r3),r9 # r9 = LSDigit of destination | |
369 | extzv $4,$4,(r10),r1 # r1 = LSDigit of source | |
370 | extzv $0,$4,(r3),r0 | |
371 | cmpl r0,r2 # if signs of operands are not equal | |
372 | jeql Laddp4_same # do a subtraction | |
373 | clrl r2 # r2 is non-zero if result is non-zero | |
374 | subl2 r1,r9 # r9 = "addition" of operands' high nibble | |
375 | jbr L119 # jump into addition loop | |
376 | Laddp4_diff_loop: | |
377 | decl r3 | |
378 | extzv $0,$4,(r3),r0 | |
379 | addl2 r0,r1 # r1 = carry + next (low) nibble of source | |
380 | decl r10 | |
381 | extzv $0,$4,(r10),r0 | |
382 | subl2 r0,r1 # r1 -= next (low) nibble of destination | |
383 | jgeq L121 # if negative result | |
384 | mnegl $1,r9 # r9 == carry = -1 | |
385 | addl2 $10,r1 # r1 == result += 10 | |
386 | jbr L122 # else | |
387 | L121: | |
388 | clrl r9 # r9 == carry = 0 | |
389 | L122: | |
390 | insv r1,$0,$4,(r3) # store result low nibble | |
391 | bisl2 r1,r2 | |
392 | extzv $4,$4,(r3),r0 | |
393 | addl2 r0,r9 # r9 = carry + next (high) nibble of source | |
394 | extzv $4,$4,(r10),r0 | |
395 | subl2 r0,r9 # r9 -= next (high) nibble of destination | |
396 | L119: | |
397 | jgeq L117 # if negative result | |
398 | mnegl $1,r1 # r1 == carry = -1 | |
399 | addl2 $10,r9 # r9 == result += 10 | |
400 | jbr L118 # else | |
401 | L117: | |
402 | clrl r1 # r1 == carry = 0 | |
403 | L118: | |
404 | insv r9,$4,$4,(r3) # store result high nibble | |
405 | bisl2 r9,r2 # r2 is non-zero if result is non-zero | |
406 | decl r11 # while (--source length) | |
407 | jneq Laddp4_diff_loop | |
408 | argl(4,r10) # r10 = address of destination MSNibble | |
409 | jbr Laddp4_diff_carry | |
410 | Laddp4_diff_carlop: | |
411 | decl r3 | |
412 | extzv $0,$4,(r3),r0 | |
413 | addl2 r0,r1 # r1 == carry += next (low) nibble | |
414 | jgeq L127 # if less than zero | |
415 | movl r1,r9 # r9 == carry (must be -1) | |
416 | movl $9,r1 # r1 == result = 9 | |
417 | jbr L128 | |
418 | L127: # else | |
419 | clrl r9 # r9 == carry = 0 | |
420 | L128: | |
421 | insv r1,$0,$4,(r3) # store result | |
422 | bisl2 r1,r2 | |
423 | extzv $4,$4,(r3),r0 | |
424 | addl2 r0,r9 # r9 == carry += next (high) nibble | |
425 | jgeq L129 # if less than zero | |
426 | movl r9,r1 # r1 == carry (must be -1) | |
427 | movl $9,r9 # r9 == result = 9 | |
428 | jbr L130 | |
429 | L129: | |
430 | clrl r1 | |
431 | L130: | |
432 | insv r9,$4,$4,(r3) # store result | |
433 | bisl2 r9,r2 | |
434 | Laddp4_diff_carry: | |
435 | cmpl r3,r10 | |
436 | jneq Laddp4_diff_carlop | |
437 | tstl r1 # if carry out of MSN then fix up result | |
438 | jeql Laddp4_add_done | |
439 | argl(5,r3) # r3 == address of LSN of destination | |
440 | extzv $0,$4,(r3),r0 | |
441 | cmpl r0,NEGATIVE # switch sign of result | |
442 | jneq L132 | |
443 | insv POSITIVE,$0,$4,(r3) | |
444 | jbr L133 | |
445 | L132: | |
446 | insv NEGATIVE,$0,$4,(r3) | |
447 | L133: | |
448 | extzv $4,$4,(r3),r0 # normalize result (carry out of MSN into LSN) | |
449 | subl3 r0,$10,r9 # r9 = 10 - destination LSNibble | |
450 | jbr L134 | |
451 | L137: | |
452 | movl $9,r1 | |
453 | Laddp4_diff_norm: | |
454 | insv r9,$4,$4,(r3) | |
455 | cmpl r3,r10 # while (not at MSNibble) | |
456 | jeql Laddp4_add_done | |
457 | decl r3 | |
458 | extzv $0,$4,(r3),r0 # low nibble = (9 + carry) - low nibble | |
459 | subl2 r0,r1 | |
460 | cmpl r1,$9 | |
461 | jleq L135 | |
462 | clrl r1 | |
463 | movl $10,r9 | |
464 | jbr L136 | |
465 | L135: | |
466 | movl $9,r9 | |
467 | L136: | |
468 | insv r1,$0,$4,(r3) | |
469 | extzv $4,$4,(r3),r0 # high nibble = (9 + carry) - high nibble | |
470 | subl2 r0,r9 | |
471 | L134: | |
472 | cmpl r9,$9 | |
473 | jleq L137 | |
474 | clrl r9 | |
475 | movl $10,r1 | |
476 | jbr Laddp4_diff_norm | |
477 | ||
478 | Laddp4_same: # operands are of the same sign | |
479 | clrl r2 | |
480 | addl2 r1,r9 | |
481 | jbr L139 | |
482 | Laddp4_same_loop: | |
483 | decl r3 | |
484 | extzv $0,$4,(r3),r0 | |
485 | addl2 r0,r1 # r1 == carry += next (low) nibble of dest | |
486 | decl r10 | |
487 | extzv $0,$4,(r10),r0 | |
488 | addl2 r0,r1 # r1 += next (low) nibble of source | |
489 | cmpl r1,$9 # if result > 9 | |
490 | jleq L141 | |
491 | movl $1,r9 # r9 == carry = 1 | |
492 | subl2 $10,r1 # r1 == result -= 10 | |
493 | jbr L142 | |
494 | L141: # else | |
495 | clrl r9 # r9 == carry = 0 | |
496 | L142: | |
497 | insv r1,$0,$4,(r3) # store result | |
498 | bisl2 r1,r2 | |
499 | extzv $4,$4,(r10),r0 | |
500 | addl2 r0,r9 # ditto for high nibble | |
501 | extzv $4,$4,(r3),r0 | |
502 | addl2 r0,r9 | |
503 | L139: | |
504 | cmpl r9,$9 | |
505 | jleq L143 | |
506 | movl $1,r1 | |
507 | subl2 $10,r9 | |
508 | jbr L144 | |
509 | L143: | |
510 | clrl r1 | |
511 | L144: | |
512 | insv r9,$4,$4,(r3) | |
513 | bisl2 r9,r2 | |
514 | decl r11 # while (--source length) | |
515 | jneq Laddp4_same_loop | |
516 | argl(4,r10) # r10 = destination address of MSNibble | |
517 | jbr Laddp4_same_carry | |
518 | Laddp4_same_cloop: | |
519 | decl r3 | |
520 | extzv $0,$4,(r3),r0 # propagate carry up to MSNibble of destination | |
521 | addl2 r0,r1 | |
522 | cmpl r1,$10 | |
523 | jneq L147 | |
524 | movl $1,r9 | |
525 | clrl r1 | |
526 | jbr L148 | |
527 | L147: | |
528 | clrl r9 | |
529 | L148: | |
530 | insv r1,$0,$4,(r3) | |
531 | bisl2 r1,r2 | |
532 | extzv $4,$4,(r3),r0 | |
533 | addl2 r0,r9 | |
534 | cmpl r9,$10 | |
535 | jneq L149 | |
536 | movl $1,r1 | |
537 | clrl r9 | |
538 | jbr L150 | |
539 | L149: | |
540 | clrl r1 | |
541 | L150: | |
542 | insv r9,$4,$4,(r3) | |
543 | bisl2 r9,r2 | |
544 | Laddp4_same_carry: | |
545 | cmpl r3,r10 | |
546 | jneq Laddp4_same_cloop | |
547 | ||
548 | Laddp4_add_done: | |
549 | argl(5,r3) # r3 = destination address of LSNibble | |
550 | tstl r2 # if zero result | |
551 | jneq L151 | |
552 | savepsl # remember that for condition codes | |
553 | insv POSITIVE,$0,$4,(r3) # make sure sign of result is positive | |
554 | jbr Laddp4_out | |
555 | L151: # else | |
556 | extzv $0,$4,(r3),r0 | |
557 | cmpl r0,NEGATIVE # if result is negative | |
558 | jneq Laddp4_out | |
559 | mnegl r2,r2 # remember THAT in Cond Codes | |
560 | savepsl | |
561 | Laddp4_out: | |
562 | argl(4,r3) | |
563 | argl(2,r1) | |
564 | clrl r0 | |
565 | clrl r2 | |
566 | argl(6,r9) # restore r9 from stack | |
567 | return | |
568 | ||
569 | ||
570 | .align 1 | |
571 | .globl _EMmovp | |
572 | _EMmovp: | |
573 | arguw(1,r11) # (1) string length == r11 | |
574 | argl(2,r10) # (1) source address == r10 | |
575 | argl(3,r3) # (1) destination address == r3 | |
576 | # we will need arg2 and arg3 later | |
577 | clrl r2 # r2 == non-zero if source is non-zero | |
578 | ashl $-1,r11,r11 # length is number of bytes, not nibbles | |
579 | jeql Lmovp_zlen | |
580 | Lmovp_copy: | |
581 | bisb2 (r10),r2 # keep track of non-zero source | |
582 | movb (r10)+,(r3)+ # move two nibbles | |
583 | decl r11 # loop for length of source | |
584 | jneq Lmovp_copy | |
585 | Lmovp_zlen: | |
586 | extzv $4,$4,(r10),r0 # look at least significant nibble | |
587 | bisl2 r0,r2 | |
588 | extzv $0,$4,(r10),r0 # check sign nibble | |
589 | cmpl r0,NEGATIVEalt | |
590 | jeql Lmovp_neg | |
591 | cmpl r0,NEGATIVE | |
592 | jneq Lmovp_pos | |
593 | Lmovp_neg: # source was negative | |
594 | mnegl r2,r2 | |
595 | Lmovp_pos: | |
596 | tstl r2 # set condition codes | |
597 | savepsl | |
598 | jeql Lmovp_zero | |
599 | movb (r10),(r3) # move last byte if non-zero result | |
600 | jbr Lmovp_out | |
601 | Lmovp_zero: | |
602 | movb POSITIVE,(r3) # otherwise, make result zero and positive | |
603 | Lmovp_out: | |
604 | clrl r0 | |
605 | argl(2,r1) | |
606 | clrl r2 | |
607 | argl(3,r3) | |
608 | return | |
609 | ||
610 | ||
611 | /* | |
612 | * Definitions for Editpc instruction | |
613 | * | |
614 | * Here are the commands and their corresponding hex values: | |
615 | * | |
616 | * EPend 0x00 | |
617 | * EPend_float 0x01 | |
618 | * EPclear_signif 0x02 | |
619 | * EPset_signif 0x03 | |
620 | * EPstore_sign 0x04 | |
621 | * EPload_fill 0x40 | |
622 | * EPload_sign 0x41 | |
623 | * EPload_plus 0x42 | |
624 | * EPload_minus 0x43 | |
625 | * EPinsert 0x44 | |
626 | * EPblank_zero 0x45 | |
627 | * EPreplace_sign 0x46 | |
628 | * EPadjust_input 0x47 | |
629 | * EPfill 0x80 | |
630 | * EPmove 0x90 | |
631 | * EPfloat 0xa0 | |
632 | * | |
633 | * | |
634 | * r4 is carved up as follows: | |
635 | * | |
636 | * ------------------------------------------- | |
637 | * | N Z V C | | |
638 | * ------------------------------------------- | |
639 | * | |
640 | * fill character is stuffed into arg5 space | |
641 | * sign character is stuffed into arg6 space | |
642 | */ | |
643 | ||
644 | #define SIGNIFBIT $0 | |
645 | #define setsignif bisl2 $1,r4 | |
646 | #define clsignif bicl2 $1,r4 | |
647 | #define OVERFLOWBIT $1 | |
648 | #define setoverflow bisl2 $2,r4 | |
649 | #define cloverflow bicl2 $2,r4 | |
650 | #define ZEROBIT $2 | |
651 | #define setzero bisl2 $4,r4 | |
652 | #define clzero bicl2 $4,r4 | |
653 | #define NEGATIVEBIT $3 | |
654 | #define setnegative bisl2 $8,r4 | |
655 | #define clnegative bicl2 $8,r4 | |
656 | #define putfill movb arg5,(r5)+ | |
657 | #define setfill(reg) movb reg,arg5 | |
658 | #define putsign movb arg6,(r5)+ | |
659 | #define setsign(reg) movb reg,arg6 | |
660 | ||
661 | ||
662 | .align 1 | |
663 | .globl _EMeditpc | |
664 | _EMeditpc: | |
665 | arguw(1,r11) # (1) source length == r11 | |
666 | argl(2,r10) # (2) source address == r10 | |
667 | argl(3,r3) # (3) pattern address == r3 | |
668 | argl(4,r5) # (4) destination address == r5 | |
669 | # we will need arg1 and arg2 later | |
670 | # arg5 and arg6 are used for fill and sign - r0 is free | |
671 | setfill($32) # fill character is ' ' | |
672 | setsign($32) # sign character is ' ' | |
673 | clrl r4 # clear flags | |
674 | ashl $-1,r11,r11 # source length / 2 | |
675 | addl3 r11,r10,r2 | |
676 | extzv $4,$4,(r2),r1 # r1 == least significant nibble of source | |
677 | L169: | |
678 | cmpl r2,r10 | |
679 | jeql L170 | |
680 | tstb -(r2) # loop over source packed decimal number | |
681 | jeql L169 | |
682 | incl r1 # r1 is non-zero if source is non-zero | |
683 | L170: | |
684 | addl3 r11,r10,r2 | |
685 | tstl r1 | |
686 | jeql L172 # source is zero - set flags | |
687 | extzv $0,$4,(r2),r11 | |
688 | cmpl r11,NEGATIVEalt | |
689 | jeql L9998 # source is negative - set sign and flags | |
690 | cmpl r11,NEGATIVE | |
691 | jneq L175 | |
692 | L9998: | |
693 | setnegative | |
694 | setsign($45) # sign character is '-' | |
695 | jbr L175 | |
696 | L172: | |
697 | setzero | |
698 | L175: | |
699 | arguw(1,r2) # (1) source length == r2 | |
700 | Ledit_case: | |
701 | movzbl (r3)+,r11 # get next edit command (pattern) | |
702 | cmpl r11,$128 | |
703 | jlss L180 | |
704 | extzv $0,$4,r11,r1 # command has a "count" arg - into r1 | |
705 | ashl $-4,r11,r11 # and shift over | |
706 | L180: | |
707 | jbc $6,r11,L181 # "shift" those commands > 64 to 16 and up | |
708 | subl2 $48,r11 | |
709 | L181: | |
710 | caseb r11,$0,$0x18 # "do" the command | |
711 | # r11 is available for use, r1 has "count" in it | |
712 | Lcaseb_label: | |
713 | .word Le_end - Lcaseb_label # 00 | |
714 | .word Le_end_float - Lcaseb_label # 01 | |
715 | .word Le_clear_signif - Lcaseb_label # 02 | |
716 | .word Le_set_signif - Lcaseb_label # 03 | |
717 | .word Le_store_sign - Lcaseb_label # 04 | |
718 | .word Le_end - Lcaseb_label # 05 | |
719 | .word Le_end - Lcaseb_label # 06 | |
720 | .word Le_end - Lcaseb_label # 07 | |
721 | .word Le_fill - Lcaseb_label # 80 | |
722 | .word Le_move - Lcaseb_label # 90 | |
723 | .word Le_float - Lcaseb_label # a0 | |
724 | .word Le_end - Lcaseb_label # b0 | |
725 | .word Le_end - Lcaseb_label # c0 | |
726 | .word Le_end - Lcaseb_label # d0 | |
727 | .word Le_end - Lcaseb_label # e0 | |
728 | .word Le_end - Lcaseb_label # f0 | |
729 | .word Le_load_fill - Lcaseb_label # 40 | |
730 | .word Le_load_sign - Lcaseb_label # 41 | |
731 | .word Le_load_plus - Lcaseb_label # 42 | |
732 | .word Le_load_minus - Lcaseb_label # 43 | |
733 | .word Le_insert - Lcaseb_label # 44 | |
734 | .word Le_blank_zero - Lcaseb_label # 45 | |
735 | .word Le_replace_sign - Lcaseb_label # 46 | |
736 | .word Le_adjust_input - Lcaseb_label # 47 | |
737 | Le_end: | |
738 | arguw(1,r0) | |
739 | argl(2,r1) | |
740 | clrl r2 | |
741 | decl r3 | |
742 | setpsl(r4) | |
743 | clrl r4 | |
744 | return | |
745 | ||
746 | Le_end_float: | |
747 | jbs SIGNIFBIT,r4,Ledit_case # if significance not set | |
748 | putsign # drop in the sign | |
749 | # fall into... | |
750 | Le_set_signif: | |
751 | setsignif | |
752 | jbr Ledit_case | |
753 | ||
754 | Le_clear_signif: | |
755 | clsignif | |
756 | jbr Ledit_case | |
757 | ||
758 | Le_store_sign: | |
759 | putsign | |
760 | jbr Ledit_case | |
761 | ||
762 | Le_load_fill: | |
763 | setfill((r3)+) | |
764 | jbr Ledit_case | |
765 | ||
766 | Le_load_plus: | |
767 | jbs NEGATIVEBIT,r4,Lpattern_inc # if non-negative | |
768 | # fall into... | |
769 | Le_load_sign: | |
770 | setsign((r3)+) | |
771 | jbr Ledit_case | |
772 | ||
773 | Le_load_minus: | |
774 | jbs NEGATIVEBIT,r4,Le_load_sign # if negative load the sign | |
775 | incl r3 # else increment pattern | |
776 | jbr Ledit_case | |
777 | ||
778 | Le_insert: | |
779 | jbc SIGNIFBIT,r4,L196 # if significance set, put next byte | |
780 | movb (r3)+,(r5)+ | |
781 | jbr Ledit_case | |
782 | L196: # else put in fill character | |
783 | putfill | |
784 | # and throw away character in pattern | |
785 | Le_replace_sign: # we don't do anything with | |
786 | Lpattern_inc: # replace sign `cause we don't | |
787 | incl r3 # get negative zero | |
788 | jbr Ledit_case | |
789 | ||
790 | Le_blank_zero: | |
791 | jbc ZEROBIT,r4,Lpattern_inc # if zero | |
792 | movzbl (r3)+,r11 # next byte is a count | |
793 | jeql Ledit_case | |
794 | subl2 r11,r5 # to back up over output and replace | |
795 | L200: | |
796 | putfill # with fill character | |
797 | decl r11 | |
798 | jneq L200 | |
799 | jbr Ledit_case | |
800 | ||
801 | Le_adjust_input: | |
802 | movzbl (r3)+,r0 # get count of nibbles from pattern | |
803 | subl3 r2,r0,r11 | |
804 | jgeq Ledit_case # if length of source is > this number | |
805 | L204: # discard digits in source | |
806 | jlbc r2,L206 # use low bit of length to choose nibble | |
807 | bitb $0xf0,(r10) # high nibble | |
808 | jeql L208 | |
809 | setsignif # set significance and overflow if | |
810 | setoverflow # wasted digit is non-zero | |
811 | jbr L208 | |
812 | L206: | |
813 | bitb $0xf,(r10) # low nibble | |
814 | jeql L209 | |
815 | setsignif | |
816 | setoverflow | |
817 | L209: | |
818 | incl r10 # increment to next byte | |
819 | L208: | |
820 | decl r2 # decrement source length | |
821 | incl r11 # continue `till we're out of excess | |
822 | jlss L204 | |
823 | jbr Ledit_case | |
824 | ||
825 | Le_fill: | |
826 | tstl r1 # put (count in r1) fill characters | |
827 | jeql Ledit_case | |
828 | Le_fill_loop: | |
829 | putfill | |
830 | decl r1 | |
831 | jneq Le_fill_loop | |
832 | jbr Ledit_case | |
833 | ||
834 | Le_move: | |
835 | tstl r1 # move (count in r1) characters | |
836 | jeql Ledit_case # from source to destination | |
837 | L214: | |
838 | jlbc r2,L215 # read a nibble | |
839 | extzv $4,$4,(r10),r11 | |
840 | jbr L216 | |
841 | L215: | |
842 | extzv $0,$4,(r10),r11 | |
843 | incl r10 | |
844 | L216: | |
845 | decl r2 # source length CAN go negative here... | |
846 | tstl r11 | |
847 | jeql L218 # if non-zero | |
848 | setsignif # set significance | |
849 | L218: | |
850 | jbc SIGNIFBIT,r4,L219 # if significance set | |
851 | addb3 $48,r11,(r5)+ # put '0' + digit into destination | |
852 | jbr L220 | |
853 | L219: # else put fill character | |
854 | putfill | |
855 | L220: | |
856 | decl r1 | |
857 | jneq L214 | |
858 | jbr Ledit_case | |
859 | ||
860 | Le_float: # move with floating sign character | |
861 | tstl r1 | |
862 | jeql Ledit_case | |
863 | L221: | |
864 | jlbc r2,L222 | |
865 | extzv $4,$4,(r10),r11 | |
866 | jbr L223 | |
867 | L222: | |
868 | extzv $0,$4,(r10),r11 | |
869 | incl r10 | |
870 | L223: | |
871 | decl r2 # source length CAN go negative here... | |
872 | tstl r11 | |
873 | jeql L225 | |
874 | jbs SIGNIFBIT,r4,L226 | |
875 | putsign | |
876 | L226: | |
877 | setsignif | |
878 | L225: | |
879 | jbc SIGNIFBIT,r4,L227 | |
880 | addb3 $48,r11,(r5)+ | |
881 | jbr L228 | |
882 | L227: | |
883 | putfill | |
884 | L228: | |
885 | decl r1 | |
886 | jneq L221 | |
887 | jbr Ledit_case | |
888 | ||
889 | ||
890 | .align 1 | |
891 | .globl _EMashp | |
892 | _EMashp: | |
893 | argb(1,r11) # (1) scale (number to shift) == r11 | |
894 | arguw(2,r10) # (2) source length == r10 | |
895 | argl(3,r1) # (3) source address == r1 | |
896 | argub(4,r2) # (4) rounding factor == r2 | |
897 | arguw(5,r3) # (5) destination length == r3 | |
898 | toarg(r6,3) # arg3 holds register 6 from caller | |
899 | argl(6,r6) # (6) destination address == r6 | |
900 | # we need arg6 for later | |
901 | # arg1 is used for temporary storage | |
902 | # arg4 is used as general storage | |
903 | # arg5 is used as general storage | |
904 | ashl $-1,r3,r0 # destination length is number of bytes | |
905 | addl2 r0,r6 # destination address == least sig nibble | |
906 | toarg(r6,1) # save in arg1 spot for later | |
907 | ashl $-1,r10,r0 | |
908 | addl2 r0,r1 # source address == least sig nibble | |
909 | extzv $0,$4,(r1),r0 # determine sign of source | |
910 | cmpl r0,NEGATIVEalt | |
911 | jeql Lashp_neg | |
912 | cmpl r0,NEGATIVE | |
913 | jeql Lashp_neg | |
914 | movb POSITIVE,(r6) | |
915 | jbr L245 | |
916 | Lashp_neg: | |
917 | movb NEGATIVE,(r6) | |
918 | L245: # r3<0> counts digits going into destination | |
919 | bisl2 $1,r3 # and is flip-flop for which nibble to | |
920 | tstl r11 # write in destination (1 = high, 0 = low) | |
921 | jgeq Lashp_left # (it must start out odd) | |
922 | addl2 r11,r10 # scale is negative (right shift) | |
923 | jgeq Lashp_right | |
924 | clrl r10 # test for shifting whole number out | |
925 | jbr Lashp_setround | |
926 | Lashp_right: | |
927 | divl3 $2,r11,r0 | |
928 | addl2 r0,r1 # source address == MSNibble to be shifted off | |
929 | jlbc r11,L249 | |
930 | extzv $4,$4,(r1),r0 | |
931 | addl2 r0,r2 # round = last nibble to be shifted off + round | |
932 | jbr Lashp_setround | |
933 | L249: | |
934 | extzv $0,$4,(r1),r0 | |
935 | addl2 r0,r2 # round = last nibble to be shifted off + round | |
936 | Lashp_setround: # r11<0> now is flip-flop for which nibble to | |
937 | incl r11 # read from source (1 == high, 0 == low) | |
938 | cmpl r2,$9 # set rounding factor to one if nibble shifted | |
939 | jleq Lashp_noround # off + round argument was 10 or greater | |
940 | movl $1,r2 | |
941 | jbr Lashp_shift | |
942 | Lashp_zloop: | |
943 | jlbs r3,L257 # don't need to clear high nibble twice | |
944 | clrb -(r6) # clear low (and high) nib of next byte in dest | |
945 | L257: | |
946 | decl r3 # move to next nibble in destination, but | |
947 | jneq L258 # don't go beyond the end. | |
948 | incl r3 | |
949 | L258: | |
950 | decl r11 | |
951 | Lashp_left: # while scale is positive | |
952 | jneq Lashp_zloop | |
953 | incl r11 # r11<0> is flip-plop ... (incl sets it to one) | |
954 | Lashp_noround: | |
955 | clrl r2 # no more rounding | |
956 | Lashp_shift: | |
957 | clrl arg4 # arg4 will be used for result condition codes | |
958 | tstl r10 | |
959 | jeql Lashp_sethigh | |
960 | Lashp_shloop: | |
961 | jlbc r11,L260 | |
962 | extzv $4,$4,(r1),r0 | |
963 | jbr L261 | |
964 | L260: | |
965 | decl r1 | |
966 | extzv $0,$4,(r1),r0 | |
967 | L261: | |
968 | incl r11 # flip the source nibble flip/flop | |
969 | addl2 r0,r2 # round += next nibble | |
970 | cmpl r2,$10 # if round == 10 | |
971 | jneq L262 | |
972 | clrl arg5 # then result = 0 and round = 1 | |
973 | movl $1,r2 | |
974 | jbr L263 | |
975 | L262: # else | |
976 | movl r2,arg5 # store result and round = 0 | |
977 | clrl r2 | |
978 | L263: | |
979 | bisl2 arg5,arg4 # remember if result was nonzero in arg4 | |
980 | decl r3 # move to next nibble early to check | |
981 | jgeq Lashp_noovfl # if we've moved passed destination limits | |
982 | clrl r3 # test the result for possible overflow | |
983 | tstl arg5 # ignore zero nibbles | |
984 | jeql L265 # if the nibble was non-zero, overflow | |
985 | jbr Lashp_overfl | |
986 | Lashp_noovfl: # else | |
987 | jlbs r3,L264 | |
988 | insv arg5,$4,$4,(r6) # put the result into destination (high or low) | |
989 | jbr L265 | |
990 | L264: | |
991 | decl r6 | |
992 | insv arg5,$0,$4,(r6) | |
993 | L265: | |
994 | decl r10 # loop for length of source | |
995 | jneq Lashp_shloop | |
996 | ||
997 | Lashp_sethigh: | |
998 | jlbc r3,L266 # if we haven't set the high nibble, | |
999 | insv r2,$4,$4,(r6) # carry the round into the high nibble | |
1000 | clrl r2 | |
1001 | L266: | |
1002 | argl(1,r10) # r10 = address of destination LSNibble | |
1003 | argl(6,r3) # r3 = address of destination MSNibble | |
1004 | movl arg4,r11 # r11 = non-zero if destination == non-zero | |
1005 | savepsl | |
1006 | jbr L267 | |
1007 | Lashp_zerofill: | |
1008 | cvtlb r2,-(r6) # fill up MSNs of destination with carry or zero | |
1009 | clrl r2 | |
1010 | L267: | |
1011 | cmpl r3,r6 | |
1012 | jneq Lashp_zerofill | |
1013 | tstl r2 # if carry beyond destination, overflow | |
1014 | jneq Lashp_overfl | |
1015 | extzv $0,$4,(r10),r0 # test for negative result | |
1016 | cmpl r0,NEGATIVE | |
1017 | jneq Lashp_out | |
1018 | mnegl r11,r11 | |
1019 | savepsl | |
1020 | jneq Lashp_out # turn -0 into 0 | |
1021 | insv POSITIVE,$0,$4,(r10) | |
1022 | Lashp_out: | |
1023 | clrl r0 | |
1024 | argl(3,r6) # restore r6 from stack | |
1025 | return | |
1026 | Lashp_overfl: # do overflow | |
1027 | clrl r2 | |
1028 | overflowpsl | |
1029 | jbr Lashp_out | |
1030 | ||
1031 | ||
1032 | .align 1 | |
1033 | .globl _EMcvtlp | |
1034 | _EMcvtlp: | |
1035 | arguw(2,r10) # (2) destination length == r10 | |
1036 | argl(3,r3) # (3) destination address == r3 | |
1037 | ashl $-1,r10,r10 | |
1038 | addl2 r10,r3 # destination address points to Least Sig byte | |
1039 | incl r10 # length is # of bytes, not nibbles | |
1040 | argl(1,r11) # (1) source == r11 | |
1041 | savepsl | |
1042 | jgeq Lcvtlp_pos | |
1043 | movb NEGATIVE,(r3) # source is negative | |
1044 | divl3 $10,r11,r0 | |
1045 | mull3 $10,r0,r1 | |
1046 | subl3 r11,r1,r2 # r2 = source mod 10 | |
1047 | mnegl r0,r11 # source = -(source / 10) | |
1048 | jbr Lcvtlp_cvt | |
1049 | Lcvtlp_pos: | |
1050 | movb POSITIVE,(r3) # source is non-negative | |
1051 | divl3 $10,r11,r0 | |
1052 | mull3 $10,r0,r1 | |
1053 | subl3 r1,r11,r2 # r2 = source mod 10 | |
1054 | movl r0,r11 # source = source / 10 | |
1055 | Lcvtlp_cvt: | |
1056 | insv r2,$4,$4,(r3) # store least significant digit | |
1057 | tstl r11 | |
1058 | jeql Lcvtlp_zloop | |
1059 | Lcvtlp_loop: # while source is non-zero | |
1060 | decl r10 # and for length of destination ... | |
1061 | jeql Lcvtlp_over | |
1062 | divl3 $10,r11,r1 # r1 = source / 10 | |
1063 | mull3 $10,r1,r0 | |
1064 | subl2 r0,r11 # source = source mod 10 | |
1065 | movb r11,-(r3) # store low "nibble" in next significant byte | |
1066 | divl3 $10,r1,r11 # source = r1 / 10 | |
1067 | mull3 $10,r11,r0 | |
1068 | subl2 r0,r1 # r1 = source mod 10 | |
1069 | insv r1,$4,$4,(r3) # store high nibble | |
1070 | tstl r11 | |
1071 | jneq Lcvtlp_loop # quit if source becomes zero | |
1072 | Lcvtlp_zloop: # fill any remaining bytes with zeros | |
1073 | decl r10 | |
1074 | jeql Lcvtlp_out | |
1075 | clrb -(r3) | |
1076 | jbr Lcvtlp_zloop | |
1077 | Lcvtlp_over: | |
1078 | overflowpsl | |
1079 | Lcvtlp_out: | |
1080 | clrl r1 # r0 is already zero | |
1081 | clrl r2 | |
1082 | return | |
1083 | ||
1084 | ||
1085 | .align 1 | |
1086 | .globl _EMcvtpl | |
1087 | _EMcvtpl: | |
1088 | arguw(1,r11) # (1) source length == r11 | |
1089 | argl(2,r10) # (2) source address == r10 | |
1090 | clrl r3 # r3 == destination | |
1091 | movl r10,r1 # r1 set up now for return | |
1092 | ashl $-1,r11,r11 # source length is number of bytes | |
1093 | jeql Lcvtpl_zero | |
1094 | Lcvtpl_loop: # for source length | |
1095 | mull2 $10,r3 # destination *= 10 | |
1096 | extzv $4,$4,(r10),r0 | |
1097 | addl2 r0,r3 # destination += high nibble | |
1098 | mull2 $10,r3 # destination *= 10 | |
1099 | extzv $0,$4,(r10),r0 | |
1100 | addl2 r0,r3 # destination += low nibble | |
1101 | incl r10 | |
1102 | decl r11 | |
1103 | jneq Lcvtpl_loop | |
1104 | Lcvtpl_zero: # least significant byte | |
1105 | mull2 $10,r3 | |
1106 | extzv $4,$4,(r10),r0 | |
1107 | addl2 r0,r3 # dest = 10 * dest + high nibble | |
1108 | savepsl | |
1109 | extzv $0,$4,(r10),r2 # test sign nibble | |
1110 | cmpl r2,NEGATIVE | |
1111 | jeql Lcvtpl_neg | |
1112 | cmpl r2,NEGATIVEalt | |
1113 | jneq Lcvtpl_out | |
1114 | Lcvtpl_neg: # source was negative - negate destination | |
1115 | mnegl r3,r3 | |
1116 | savepsl | |
1117 | Lcvtpl_out: | |
1118 | toarg(r3,3) | |
1119 | clrl r0 | |
1120 | clrl r2 | |
1121 | clrl r3 | |
1122 | return | |
1123 | ||
1124 | ||
1125 | .align 1 | |
1126 | .globl _EMcvtps | |
1127 | _EMcvtps: | |
1128 | return | |
1129 | ||
1130 | ||
1131 | .align 1 | |
1132 | .globl _EMcvtsp | |
1133 | _EMcvtsp: | |
1134 | return | |
1135 | ||
1136 | ||
1137 | .align 1 | |
1138 | .globl _EMaddp6 | |
1139 | _EMaddp6: | |
1140 | return | |
1141 | ||
1142 | ||
1143 | .align 1 | |
1144 | .globl _EMsubp4 | |
1145 | _EMsubp4: | |
1146 | return | |
1147 | ||
1148 | ||
1149 | .align 1 | |
1150 | .globl _EMsubp6 | |
1151 | _EMsubp6: | |
1152 | return | |
1153 | ||
1154 | ||
1155 | .align 1 | |
1156 | .globl _EMcvtpt | |
1157 | _EMcvtpt: | |
1158 | return | |
1159 | ||
1160 | ||
1161 | .align 1 | |
1162 | .globl _EMmulp | |
1163 | _EMmulp: | |
1164 | return | |
1165 | ||
1166 | ||
1167 | .align 1 | |
1168 | .globl _EMcvttp | |
1169 | _EMcvttp: | |
1170 | return | |
1171 | ||
1172 | ||
1173 | .align 1 | |
1174 | .globl _EMdivp | |
1175 | _EMdivp: | |
1176 | return | |
1177 | ||
1178 | ||
1179 | .align 1 | |
1180 | .globl _EMcmpp3 | |
1181 | _EMcmpp3: | |
1182 | return | |
1183 | ||
1184 | ||
1185 | .align 1 | |
1186 | .globl _EMcmpp4 | |
1187 | _EMcmpp4: | |
1188 | return | |
1189 | ||
1190 | ||
1191 | #endif UVAXII | |
1192 | ||
1193 | ||
1194 | #ifdef notdef | |
1195 | /* | |
1196 | * Emulation OpCode jump table: | |
1197 | * ONLY GOES FROM 0xf8 (-8) TO 0x3B (59) | |
1198 | */ | |
1199 | #define EMUTABLE 0x43 | |
1200 | #define NOEMULATE .long noemulate | |
1201 | #define EMULATE(a) .long _EM/**/a | |
1202 | .globl _emJUMPtable | |
1203 | _emJUMPtable: | |
1204 | /* f8 */ EMULATE(ashp); EMULATE(cvtlp); NOEMULATE; NOEMULATE | |
1205 | /* fc */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1206 | /* 00 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1207 | /* 04 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1208 | /* 08 */ EMULATE(cvtps); EMULATE(cvtsp); NOEMULATE; EMULATE(crc) | |
1209 | /* 0c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1210 | /* 10 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1211 | /* 14 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1212 | /* 18 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1213 | /* 1c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1214 | /* 20 */ EMULATE(addp4); EMULATE(addp6); EMULATE(subp4); EMULATE(subp6) | |
1215 | /* 24 */ EMULATE(cvtpt); EMULATE(mulp); EMULATE(cvttp); EMULATE(divp) | |
1216 | /* 28 */ NOEMULATE; EMULATE(cmpc3); EMULATE(scanc); EMULATE(spanc) | |
1217 | /* 2c */ NOEMULATE; EMULATE(cmpc5); EMULATE(movtc); EMULATE(movtuc) | |
1218 | /* 30 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE | |
1219 | /* 34 */ EMULATE(movp); EMULATE(cmpp3); EMULATE(cvtpl); EMULATE(cmpp4) | |
1220 | /* 38 */ EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc) | |
1221 | ||
1222 | /* | |
1223 | * The following is called with the stack set up as follows: | |
1224 | * | |
1225 | * (sp): Opcode | |
1226 | * 4(sp): Instruction PC | |
1227 | * 8(sp): Operand 1 | |
1228 | * 12(sp): Operand 2 | |
1229 | * 16(sp): Operand 3 | |
1230 | * 20(sp): Operand 4 | |
1231 | * 24(sp): Operand 5 | |
1232 | * 28(sp): Operand 6 | |
1233 | * 32(sp): Operand 7 (unused) | |
1234 | * 36(sp): Operand 8 (unused) | |
1235 | * 40(sp): Return PC | |
1236 | * 44(sp): Return PSL | |
1237 | * 48(sp): TOS before instruction | |
1238 | * | |
1239 | * Each individual routine is called with the stack set up as follows: | |
1240 | * | |
1241 | * (sp): Return address of trap handler | |
1242 | * 4(sp): Opcode (will get return PSL) | |
1243 | * 8(sp): Instruction PC | |
1244 | * 12(sp): Operand 1 | |
1245 | * 16(sp): Operand 2 | |
1246 | * 20(sp): Operand 3 | |
1247 | * 24(sp): Operand 4 | |
1248 | * 28(sp): Operand 5 | |
1249 | * 32(sp): Operand 6 | |
1250 | * 36(sp): saved register 11 | |
1251 | * 40(sp): saved register 10 | |
1252 | * 44(sp): Return PC | |
1253 | * 48(sp): Return PSL | |
1254 | * 52(sp): TOS before instruction | |
1255 | */ | |
1256 | ||
1257 | SCBVEC(emulate): | |
1258 | movl r11,32(sp) # save register r11 in unused operand | |
1259 | movl r10,36(sp) # save register r10 in unused operand | |
1260 | cvtbl (sp),r10 # get opcode | |
1261 | addl2 $8,r10 # shift negative opcodes | |
1262 | subl3 r10,$EMUTABLE,r11 # forget it if opcode is out of range | |
1263 | bcs noemulate | |
1264 | movl _emJUMPtable[r10],r10 # call appropriate emulation routine | |
1265 | jsb (r10) # routines put return values into regs 0-5 | |
1266 | movl 32(sp),r11 # restore register r11 | |
1267 | movl 36(sp),r10 # restore register r10 | |
1268 | insv (sp),$0,$4,44(sp) # and condition codes in Opcode spot | |
1269 | addl2 $40,sp # adjust stack for return | |
1270 | rei | |
1271 | noemulate: | |
1272 | addl2 $48,sp # adjust stack for | |
1273 | .word 0xffff # "reserved instruction fault" | |
1274 | SCBVEC(emulateFPD): | |
1275 | .word 0xffff # "reserved instruction fault" | |
1276 | #endif |