4.3BSD release version
[unix-history] / usr / src / sys / vax / vax / emulate.s
CommitLineData
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
63Lcrc_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
74Lcrc_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
91Lmovtc_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
100Lmovtc_2loop:
101 movb r11,(r5)+
102 decl r4
103 jneq Lmovtc_2loop
104Lmovtc_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
121Lmovtuc_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
133Lmovtuc_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
151Lmatchc_loop:
152 cmpb (r10),(r3)
153 jneq Lmatchc_fail
154 movl r3,r1
155 movl r10,r0
156Lmatchc_2loop:
157 cmpl r0,r11
158 jeql Lmatchc_succ
159 cmpb (r0)+,(r1)+
160 jeql Lmatchc_2loop
161Lmatchc_fail:
162 incl r3
163 decl r2
164 jneq Lmatchc_loop
165 movl r10,r1
166 subl3 r10,r11,r0
167 jbr Lmatchc_out
168Lmatchc_succ:
169 movl r11,r1
170 clrl r0
171Lmatchc_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
184Lspanc_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
192Lspanc_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
206Lscanc_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
214Lscanc_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
227Lskpc_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
234Lskpc_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
246Llocc_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
253Llocc_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
265Lcmpc3_loop:
266 cmpb (r1),(r3)
267 jneq Lcmpc3_out
268 incl r1
269 incl r3
270 decl r0
271 jneq Lcmpc3_loop
272Lcmpc3_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
287Lcmpc5_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
297Lcmpc5_str2:
298 tstl r2
299 jeql Lcmpc5_out
300Lcmpc5_str2loop:
301 cmpb r11,(r3)
302 jneq Lcmpc5_out
303 incl r3
304 decl r2
305 jneq Lcmpc5_str2loop
306 jbr Lcmpc5_out
307Lcmpc5_str1loop:
308 cmpb (r1),r11
309 jneq Lcmpc5_out
310 incl r1
311 decl r0
312 jneq Lcmpc5_str1loop
313Lcmpc5_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
351L111:
352 insv NEGATIVE,$0,$4,(r3)
353L112:
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
361L113:
362 movl NEGATIVE,r2
363L114:
364 cmpl r11,r9 # if source is longer than destination
365 jleq L115
366 movl r9,r11 # set source length == destination length
367L115:
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
376Laddp4_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
387L121:
388 clrl r9 # r9 == carry = 0
389L122:
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
396L119:
397 jgeq L117 # if negative result
398 mnegl $1,r1 # r1 == carry = -1
399 addl2 $10,r9 # r9 == result += 10
400 jbr L118 # else
401L117:
402 clrl r1 # r1 == carry = 0
403L118:
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
410Laddp4_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
418L127: # else
419 clrl r9 # r9 == carry = 0
420L128:
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
429L129:
430 clrl r1
431L130:
432 insv r9,$4,$4,(r3) # store result
433 bisl2 r9,r2
434Laddp4_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
445L132:
446 insv NEGATIVE,$0,$4,(r3)
447L133:
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
451L137:
452 movl $9,r1
453Laddp4_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
465L135:
466 movl $9,r9
467L136:
468 insv r1,$0,$4,(r3)
469 extzv $4,$4,(r3),r0 # high nibble = (9 + carry) - high nibble
470 subl2 r0,r9
471L134:
472 cmpl r9,$9
473 jleq L137
474 clrl r9
475 movl $10,r1
476 jbr Laddp4_diff_norm
477
478Laddp4_same: # operands are of the same sign
479 clrl r2
480 addl2 r1,r9
481 jbr L139
482Laddp4_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
494L141: # else
495 clrl r9 # r9 == carry = 0
496L142:
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
503L139:
504 cmpl r9,$9
505 jleq L143
506 movl $1,r1
507 subl2 $10,r9
508 jbr L144
509L143:
510 clrl r1
511L144:
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
518Laddp4_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
527L147:
528 clrl r9
529L148:
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
539L149:
540 clrl r1
541L150:
542 insv r9,$4,$4,(r3)
543 bisl2 r9,r2
544Laddp4_same_carry:
545 cmpl r3,r10
546 jneq Laddp4_same_cloop
547
548Laddp4_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
555L151: # 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
561Laddp4_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
580Lmovp_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
585Lmovp_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
593Lmovp_neg: # source was negative
594 mnegl r2,r2
595Lmovp_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
601Lmovp_zero:
602 movb POSITIVE,(r3) # otherwise, make result zero and positive
603Lmovp_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
677L169:
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
683L170:
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
692L9998:
693 setnegative
694 setsign($45) # sign character is '-'
695 jbr L175
696L172:
697 setzero
698L175:
699 arguw(1,r2) # (1) source length == r2
700Ledit_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
706L180:
707 jbc $6,r11,L181 # "shift" those commands > 64 to 16 and up
708 subl2 $48,r11
709L181:
710 caseb r11,$0,$0x18 # "do" the command
711 # r11 is available for use, r1 has "count" in it
712Lcaseb_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
737Le_end:
738 arguw(1,r0)
739 argl(2,r1)
740 clrl r2
741 decl r3
742 setpsl(r4)
743 clrl r4
744 return
745
746Le_end_float:
747 jbs SIGNIFBIT,r4,Ledit_case # if significance not set
748 putsign # drop in the sign
749 # fall into...
750Le_set_signif:
751 setsignif
752 jbr Ledit_case
753
754Le_clear_signif:
755 clsignif
756 jbr Ledit_case
757
758Le_store_sign:
759 putsign
760 jbr Ledit_case
761
762Le_load_fill:
763 setfill((r3)+)
764 jbr Ledit_case
765
766Le_load_plus:
767 jbs NEGATIVEBIT,r4,Lpattern_inc # if non-negative
768 # fall into...
769Le_load_sign:
770 setsign((r3)+)
771 jbr Ledit_case
772
773Le_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
778Le_insert:
779 jbc SIGNIFBIT,r4,L196 # if significance set, put next byte
780 movb (r3)+,(r5)+
781 jbr Ledit_case
782L196: # else put in fill character
783 putfill
784 # and throw away character in pattern
785Le_replace_sign: # we don't do anything with
786Lpattern_inc: # replace sign `cause we don't
787 incl r3 # get negative zero
788 jbr Ledit_case
789
790Le_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
795L200:
796 putfill # with fill character
797 decl r11
798 jneq L200
799 jbr Ledit_case
800
801Le_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
805L204: # 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
812L206:
813 bitb $0xf,(r10) # low nibble
814 jeql L209
815 setsignif
816 setoverflow
817L209:
818 incl r10 # increment to next byte
819L208:
820 decl r2 # decrement source length
821 incl r11 # continue `till we're out of excess
822 jlss L204
823 jbr Ledit_case
824
825Le_fill:
826 tstl r1 # put (count in r1) fill characters
827 jeql Ledit_case
828Le_fill_loop:
829 putfill
830 decl r1
831 jneq Le_fill_loop
832 jbr Ledit_case
833
834Le_move:
835 tstl r1 # move (count in r1) characters
836 jeql Ledit_case # from source to destination
837L214:
838 jlbc r2,L215 # read a nibble
839 extzv $4,$4,(r10),r11
840 jbr L216
841L215:
842 extzv $0,$4,(r10),r11
843 incl r10
844L216:
845 decl r2 # source length CAN go negative here...
846 tstl r11
847 jeql L218 # if non-zero
848 setsignif # set significance
849L218:
850 jbc SIGNIFBIT,r4,L219 # if significance set
851 addb3 $48,r11,(r5)+ # put '0' + digit into destination
852 jbr L220
853L219: # else put fill character
854 putfill
855L220:
856 decl r1
857 jneq L214
858 jbr Ledit_case
859
860Le_float: # move with floating sign character
861 tstl r1
862 jeql Ledit_case
863L221:
864 jlbc r2,L222
865 extzv $4,$4,(r10),r11
866 jbr L223
867L222:
868 extzv $0,$4,(r10),r11
869 incl r10
870L223:
871 decl r2 # source length CAN go negative here...
872 tstl r11
873 jeql L225
874 jbs SIGNIFBIT,r4,L226
875 putsign
876L226:
877 setsignif
878L225:
879 jbc SIGNIFBIT,r4,L227
880 addb3 $48,r11,(r5)+
881 jbr L228
882L227:
883 putfill
884L228:
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
916Lashp_neg:
917 movb NEGATIVE,(r6)
918L245: # 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
926Lashp_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
933L249:
934 extzv $0,$4,(r1),r0
935 addl2 r0,r2 # round = last nibble to be shifted off + round
936Lashp_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
942Lashp_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
945L257:
946 decl r3 # move to next nibble in destination, but
947 jneq L258 # don't go beyond the end.
948 incl r3
949L258:
950 decl r11
951Lashp_left: # while scale is positive
952 jneq Lashp_zloop
953 incl r11 # r11<0> is flip-plop ... (incl sets it to one)
954Lashp_noround:
955 clrl r2 # no more rounding
956Lashp_shift:
957 clrl arg4 # arg4 will be used for result condition codes
958 tstl r10
959 jeql Lashp_sethigh
960Lashp_shloop:
961 jlbc r11,L260
962 extzv $4,$4,(r1),r0
963 jbr L261
964L260:
965 decl r1
966 extzv $0,$4,(r1),r0
967L261:
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
975L262: # else
976 movl r2,arg5 # store result and round = 0
977 clrl r2
978L263:
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
986Lashp_noovfl: # else
987 jlbs r3,L264
988 insv arg5,$4,$4,(r6) # put the result into destination (high or low)
989 jbr L265
990L264:
991 decl r6
992 insv arg5,$0,$4,(r6)
993L265:
994 decl r10 # loop for length of source
995 jneq Lashp_shloop
996
997Lashp_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
1001L266:
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
1007Lashp_zerofill:
1008 cvtlb r2,-(r6) # fill up MSNs of destination with carry or zero
1009 clrl r2
1010L267:
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)
1022Lashp_out:
1023 clrl r0
1024 argl(3,r6) # restore r6 from stack
1025 return
1026Lashp_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
1049Lcvtlp_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
1055Lcvtlp_cvt:
1056 insv r2,$4,$4,(r3) # store least significant digit
1057 tstl r11
1058 jeql Lcvtlp_zloop
1059Lcvtlp_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
1072Lcvtlp_zloop: # fill any remaining bytes with zeros
1073 decl r10
1074 jeql Lcvtlp_out
1075 clrb -(r3)
1076 jbr Lcvtlp_zloop
1077Lcvtlp_over:
1078 overflowpsl
1079Lcvtlp_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
1094Lcvtpl_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
1104Lcvtpl_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
1114Lcvtpl_neg: # source was negative - negate destination
1115 mnegl r3,r3
1116 savepsl
1117Lcvtpl_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
1257SCBVEC(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
1271noemulate:
1272 addl2 $48,sp # adjust stack for
1273 .word 0xffff # "reserved instruction fault"
1274SCBVEC(emulateFPD):
1275 .word 0xffff # "reserved instruction fault"
1276#endif