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