|
|
1.1 root 1: # 1 "doprnt.nS"
2:
3: # C library -- conversions
4:
5: .globl __doprnt
6: .globl __flsbuf
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29: .set ch.zer,'0 # cpp doesn't like single appostrophes
30: .set ch.per,'% # I'm convinced BE
31:
32: .align 2
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51: strfoo:
52: clrl r4 # fix interrupt race
53: jbr strok # and try again
54: strmore:
55: movzbl (r1)+,r2 # one char
56:
57: jeql stresc2 # BE
58: cmpl r2,$ch.per # BE
59: jeql stresc2 # bad guy in disguise (outbuf is full)
60: strout2: # enter here to force out r2; r0,r1 must be set
61:
62: movq r0,-(sp) # BE
63: pushl -4(fp) # FILE
64: pushl r2 # the char
65: calls $2,__flsbuf # please empty the buffer and handle 1 char
66: tstl r0 # successful?
67: jgeq strm1 # yes
68: jbcs $31,-16(fp),strm1 # turn on -17(fp) bit of -16(fp) to signify error
69: strm1:
70: incl -16(fp) # count the char
71:
72: movq r0,(sp)+ # BE
73: strout: # enter via bsb with (r0,r1)=input descriptor
74:
75: movq *-4(fp),r4 # output descriptor
76: jbs $31,r4,strfoo # negative count is a no no
77: strok:
78: addl2 r0,-16(fp) # we intend to move this many chars
79:
80: clrl r2
81: tstl r0
82: bleq movdon
83: movlp:
84: tstl r4
85: bleq movdon
86: movzbl (r1)+,r3
87:
88: beql 2f # BE
89: cmpl r3,$ch.per # BE
90: bneq 1f
91: 2: # BE
92: mnegl $1,r2
93: decl r1
94: brb movdon
95: 1:
96: movb r3,(r5)+
97: decl r4
98: sobgtr r0,movlp
99:
100:
101:
102:
103: movdon: movq r4,*-4(fp)
104: subl2 r0,-16(fp) # some chars not moved
105: jbs $1,r2,stresc # terminated by escape?
106: sobgeq r0,strmore # no; but out buffer might be full
107: stresc:
108: rsb
109: stresc2:
110: incl r0 # fix the length
111: decl r1 # and the addr
112: movl $1<1,r2 # fake condition codes
113: rsb
114:
115: errdone:
116: jbcs $31,-16(fp),prdone # set error bit
117: prdone:
118: movl -16(fp),r0
119: ret
120:
121: .align 1
122: __doprnt:
123: .word 0xfc0 # uses r11-r6
124: movab -256(sp),sp # work space
125: movl 4(ap),r11 # addr of format string
126: movl 12(ap),-4(fp) # output FILE ptr
127: movl 8(ap),ap # addr of first arg
128: clrl -16(fp) # number of chars transferred
129: loop:
130: movzwl $65535,r0 # pseudo length
131: movl r11,r1 # fmt addr
132: # comet sucks.
133: movq *-4(fp),r4
134: subl3 r1,r5,r2
135: jlss lp1
136: cmpl r0,r2
137: jleq lp1
138: movl r2,r0
139: lp1:
140: #
141: bsbw strout # copy to output, stop at null or percent
142: movl r1,r11 # new fmt
143: jbc $1,r2,loop # if no escape, then very long fmt
144: tstb (r11)+ # escape; null or percent?
145: jeql prdone # null means end of fmt
146:
147: movl sp,r5 # reset output buffer pointer
148: clrq r9 # r9; r10
149: clrq r6 # r6,r7
150: longorunsg: # we can ignore both of these distinctions
151: short:
152: L4a:
153: movzbl (r11)+,r0 # so capital letters can tail merge
154: L4: caseb r0,$' ,$'x-' # format char
155: L5:
156: .word space-L5 # space
157: .word fmtbad-L5 # !
158: .word fmtbad-L5 # "
159: .word sharp-L5 # #
160: .word fmtbad-L5 # $
161: .word fmtbad-L5 # %
162: .word fmtbad-L5 # &
163: .word fmtbad-L5 # '
164: .word fmtbad-L5 # (
165: .word fmtbad-L5 # )
166: .word indir-L5 # *
167: .word plus-L5 # +
168: .word fmtbad-L5 # ,
169: .word minus-L5 # -
170: .word dot-L5 # .
171: .word fmtbad-L5 # /
172: .word gnum0-L5 # 0
173: .word gnum-L5 # 1
174: .word gnum-L5 # 2
175: .word gnum-L5 # 3
176: .word gnum-L5 # 4
177: .word gnum-L5 # 5
178: .word gnum-L5 # 6
179: .word gnum-L5 # 7
180: .word gnum-L5 # 8
181: .word gnum-L5 # 9
182: .word fmtbad-L5 # :
183: .word fmtbad-L5 # ;
184: .word fmtbad-L5 # <
185: .word fmtbad-L5 # =
186: .word fmtbad-L5 # >
187: .word fmtbad-L5 # ?
188: .word fmtbad-L5 # @
189: .word fmtbad-L5 # A
190: .word fmtbad-L5 # B
191: .word fmtbad-L5 # C
192: .word decimal-L5 # D
193: .word capital-L5 # E
194: .word fmtbad-L5 # F
195: .word capital-L5 # G
196: .word fmtbad-L5 # H
197: .word fmtbad-L5 # I
198: .word fmtbad-L5 # J
199: .word fmtbad-L5 # K
200: .word fmtbad-L5 # L
201: .word fmtbad-L5 # M
202: .word fmtbad-L5 # N
203: .word octal-L5 # O
204: .word fmtbad-L5 # P
205: .word fmtbad-L5 # Q
206: .word fmtbad-L5 # R
207: .word fmtbad-L5 # S
208: .word fmtbad-L5 # T
209: .word unsigned-L5 # U
210: .word fmtbad-L5 # V
211: .word fmtbad-L5 # W
212: .word capital-L5 # X
213: .word fmtbad-L5 # Y
214: .word fmtbad-L5 # Z
215: .word fmtbad-L5 # [
216: .word fmtbad-L5 # \
217: .word fmtbad-L5 # ]
218: .word fmtbad-L5 # ^
219: .word fmtbad-L5 # _
220: .word fmtbad-L5 # `
221: .word fmtbad-L5 # a
222: .word fmtbad-L5 # b
223: .word charac-L5 # c
224: .word decimal-L5 # d
225: .word scien-L5 # e
226: .word float-L5 # f
227: .word general-L5 # g
228: .word short-L5 # h
229: .word fmtbad-L5 # i
230: .word fmtbad-L5 # j
231: .word fmtbad-L5 # k
232: .word longorunsg-L5 # l
233: .word fmtbad-L5 # m
234: .word fmtbad-L5 # n
235: .word octal-L5 # o
236: .word fmtbad-L5 # p
237: .word fmtbad-L5 # q
238: .word fmtbad-L5 # r
239: .word string-L5 # s
240: .word fmtbad-L5 # t
241: .word unsigned-L5 # u
242: .word fmtbad-L5 # v
243: .word fmtbad-L5 # w
244: .word hex-L5 # x
245: fmtbad:
246: movb r0,(r5)+ # print the unfound character
247: jeql errdone # dumb users who end the format with a %
248: jbr prbuf
249: capital:
250: bisl2 $1<6,r10 # note that it was capitalized
251: xorb2 $'a^'A,r0 # make it small
252: jbr L4 # and try again
253:
254: string:
255: movl r8,r0
256: jbs $1,r10,L20 # max length was specified
257: mnegl $1,r0 # default max length
258: L20: movl (ap)+,r2 # addr first byte
259: locc $0,r0,(r2) # find the zero at the end
260: movl r1,r5 # addr last byte +1
261: movl r2,r1 # addr first byte
262: jbr prstr
263:
264: htab: .byte '0,'1,'2,'3,'4,'5,'6,'7,'8,'9,'a,'b,'c,'d,'e,'f
265: Htab: .byte '0,'1,'2,'3,'4,'5,'6,'7,'8,'9,'A,'B,'C,'D,'E,'F
266:
267: octal:
268: movl $30,r2 # init position
269: movl $3,r3 # field r9
270: movab htab,r7 # translate table
271: jbr L10
272:
273: hex:
274: movl $28,r2 # init position
275: movl $4,r3 # field r9
276: movab htab,r7 # translate table
277: jbc $6,r10,L10
278: movab Htab,r7
279: L10: mnegl r3,r6 # increment
280: clrl r1
281: addl2 $4,r5 # room for left affix (2) and slop [forced -17(fp)?]
282: movl (ap)+,r0 # fetch arg
283: L11: extzv r2,r3,r0,r1 # pull out a digit
284: movb (r7)[r1],(r5)+ # convert to character
285: L12: acbl $0,r6,r2,L11 # continue until done
286: clrq r6 # r6, r7
287: clrb (r5) # flag end
288: skpc $'0,$11,4(sp) # skip over leading zeroes
289: jbc $5,r10,prn3 # easy if no left affix
290: tstl -4(ap) # original value
291: jeql prn3 # no affix on 0, for some reason
292: cmpl r3,$4 # were we doing hex or octal?
293: jneq L12a # octal
294: movb $'x,r0
295: jbc $6,r10,L12b
296: movb $'X,r0
297: L12b: movb r0,-(r1)
298: movl $2,r7 # leading 0x for hex is an affix
299: L12a: movb $'0,-(r1) # leading zero for octal is a digit, not an affix
300: jbr prn3 # omit -17(fp) (plus, 7) massaging
301:
302: unsigned:
303: lunsigned:
304: bicl2 $1<4|1<7,r10 # omit -17(fp) (plus, 7) massaging
305: extzv $1,$31,(ap),r0 # right shift logical 1 bit
306: cvtlp r0,$10,(sp) # convert [n/2] to packed
307: movp $10,(sp),8(sp) # copy packed
308: addp4 $10,8(sp),$10,(sp) # 2*[n/2] in packed, at (sp)
309: blbc (ap)+,L14 # n was even
310: addp4 $1,pone,$10,(sp) # n was odd
311: jbr L14
312:
313: patdec: # editpc pattern for decimal printing
314: .byte 0xAA # eo$float 10
315: .byte 0x01 # eo$end_float
316: .byte 0 # eo$end
317:
318: decimal:
319: cvtlp (ap)+,$10,(sp) # 10 digits max
320: jgeq L14
321: incl r7 # minus -17(fp) is a left affix
322: L14: editpc $10,(sp),patdec,8(sp) # ascii at 8(sp); r5=end+1
323: skpc $' ,$11,8(sp) # skip leading blanks; r1=first
324:
325: prnum: # r1=addr first byte, r5=addr last byte +1, r7=size of signs
326: # -1(r1) vacant, for forced -17(fp)
327: tstl r7
328: jneq prn3 # already some left affix, dont fuss
329: jbc $4,r10,prn2
330: movb $'+,-(r1) # needs a plus sign
331: jbr prn4
332: prn2: jbc $7,r10,prn3
333: movb $' ,-(r1) # needs a blank sign
334: prn4: incl r7
335: prn3: jbs $1,r10,prn1
336: movl $1,r8 # default precision is 1
337: prn1: subl3 r1,r5,r6 # raw r9
338: subl2 r7,r6 # number of digits
339: subl2 r6,r8 # number of leading zeroes needed
340: jleq prstr # none
341: addl2 r7,r1 # where current digits start
342: pushl r1 # movcx gobbles registers
343: # check bounds on users who say %.300d
344: movab 32(r5)[r8],r2
345: subl2 fp,r2
346: jlss prn5
347: subl2 r2,r8
348: prn5:
349: #
350: movc3 r6,(r1),(r1)[r8] # make room in middle
351: movc5 $0,(r1),$ch.zer,r8,*(sp) # '0 fill
352: subl3 r7,(sp)+,r1 # first byte addr
353: addl3 r6,r3,r5 # last byte addr +1
354:
355: prstr: # r1=addr first byte; r5=addr last byte +1
356: # r9=minimum r9; r7=len. left affix
357: # r8=<avail>
358: subl3 r1,r5,r8 # raw r9
359: subl3 r8,r9,r0 # pad length
360: jleq padlno # in particular, no left padding
361: jbs $3,r10,padlno
362: # extension for %0 flag causing left zero padding to field r9
363: jbs $2,r10,padlz
364: # this bsbb needed even if %0 flag extension is removed
365: bsbb padb # 7 pad on left
366: jbr padnlz
367: padlz:
368: movl r7,r0
369: jleq padnlx # left zero pad requires left affix first
370: subl2 r0,r8 # part of total length will be transferred
371: subl2 r0,r9 # and will account for part of minimum r9
372: bsbw strout # left affix
373: padnlx:
374: subl3 r8,r9,r0 # pad length
375: bsbb padz # zero pad on left
376: padnlz:
377: # end of extension for left zero padding
378: padlno: # remaining: root, possible right padding
379: subl2 r8,r9 # root reduces minimum r9
380: movl r8,r0 # root length
381: p1: bsbw strout # transfer to output buffer
382: p3: jbc $1,r2,padnpct # percent -17(fp) (or null byte via %c) ?
383: decl r0 # yes; adjust count
384: movzbl (r1)+,r2 # fetch byte
385: movq *-4(fp),r4 # output buffer descriptor
386: sobgeq r4,p2 # room at the out [inn] ?
387: bsbw strout2 # no; force it, then try rest
388: jbr p3 # here we go 'round the mullberry bush, ...
389: p2: movb r2,(r5)+ # hand-deposit the percent or null
390: incl -16(fp) # count it
391: movq r4,*-4(fp) # store output descriptor
392: jbr p1 # what an expensive hiccup!
393: padnpct:
394: movl r9,r0 # size of pad
395: jleq loop
396: bsbb padb
397: jbr loop
398:
399: padz:
400: movb $'0,r2
401: jbr pad
402: padb:
403: movb $' ,r2
404: pad:
405: subl2 r0,r9 # pad r9 decreases minimum r9
406: pushl r1 # save non-pad addr
407: movl r0,r7 # remember r9 of pad
408: subl2 r0,sp # allocate
409: movc5 $0,(r0),r2,r7,(sp) # create pad string
410: movl r7,r0 # length
411: movl sp,r1 # addr
412: bsbw strout
413: addl2 r7,sp # deallocate
414: movl (sp)+,r1 # recover non-pad addr
415: rsb
416:
417: pone: .byte 0x1C # packed 1
418:
419: charac:
420: movl (ap)+,r0 # word containing the char
421: movb r0,(r5)+ # one byte, that's all
422:
423: prbuf:
424: movl sp,r1 # addr first byte
425: jbr prstr
426:
427: space: bisl2 $1<7,r10 # constant r9 e fmt, no plus -17(fp)
428: jbr L4a
429: sharp: bisl2 $1<5,r10 # 'self identifying', please
430: jbr L4a
431: plus: bisl2 $1<4,r10 # always print -17(fp) for floats
432: jbr L4a
433: minus: bisl2 $1<3,r10 # left justification, please
434: jbr L4a
435: gnum0: jbs $0,r10,gnum
436: jbs $1,r10,gnump # ignore when reading precision
437: bisl2 $1<2,r10 # leading zero fill, please
438: gnum: jbs $1,r10,gnump
439: moval (r9)[r9],r9 # r9 *= 5;
440: movaw -ch.zer(r0)[r9],r9 # r9 = 2*witdh + r0 - '0';
441: jbr gnumd
442: gnump: moval (r8)[r8],r8 # r8 *= 5;
443: movaw -ch.zer(r0)[r8],r8 # r8 = 2*r8 + r0 - '0';
444: gnumd: bisl2 $1<0,r10 # digit seen
445: jbr L4a
446: dot: clrl r8 # start on the precision
447: bisl2 $1<1,r10
448: bicl2 $1<0,r10
449: jbr L4a
450: indir:
451: jbs $1,r10,in1
452: movl (ap)+,r9 # r9 specified by parameter
453: jgeq gnumd
454: xorl2 $1<3,r10 # parameterized left adjustment
455: mnegl r9,r9
456: jbr gnumd
457: in1:
458: movl (ap)+,r8 # precision specified by paratmeter
459: jgeq gnumd
460: mnegl r8,r8
461: jbr gnumd
462:
463: float:
464: jbs $1,r10,float1
465: movl $6,r8 # default # digits to right of decpt.
466: float1: bsbw fltcvt
467: addl3 -8(fp),r8,r7
468: movl r7,r6 # for later "underflow" checking
469: bgeq fxplrd
470: clrl r7 # poor programmer planning
471: fxplrd: cmpl r7,$31 # expressible in packed decimal?
472: bleq fnarro # yes
473: movl $31,r7
474: fnarro: subl3 $17,r7,r0 # where to round
475: ashp r0,$17,(sp),$5,r7,16(sp) # do it
476: bvc fnovfl
477: # band-aid for microcode error (spurious overflow)
478: # clrl r0 # assume even length result
479: # jlbc r7,fleven # right
480: # movl $4,r0 # odd length result
481: #fleven: cmpv r0,$4,16(sp),$0 # top digit zero iff true overflow
482: # bneq fnovfl
483: # end band-aid
484: aobleq $0,r6,fnovfl # if "underflow" then jump
485: movl r7,r0
486: incl -8(fp)
487: incl r7
488: ashp r0,$1,pone,$0,r7,16(sp)
489: ashl $-1,r7,r0 # displ to last byte
490: bisb2 -17(fp),16(sp)[r0] # insert -17(fp)
491: fnovfl:
492: movab 16(sp),r1 # packed source
493: movl r7,r6 # packed length
494: pushab prnum # goto prnum after fall-through call to fedit
495:
496:
497: # enter via bsb
498: # r1=addr of packed source
499: # 16(r1) used to unpack source
500: # 48(r1) used to construct pattern to unpack source
501: # 48(r1) used to hold result
502: # r6=length of packed source (destroyed)
503: # -8(fp)=# digits to left of decimal point (destroyed)
504: # r8=# digits to right of decimal point (destroyed)
505: # -17(fp)=1 if negative, 0 otherwise
506: # stack will be used for work space for pattern and unpacked source
507: # exits with
508: # r1=addr of punctuated result
509: # r5=addr of last byte +1
510: # r7=1 if minus -17(fp) inserted, 0 otherwise
511: fedit:
512: pushab 48(r1) # save result addr
513: movab 48(r1),r3 # pattern addr
514: movb $0x03,(r3)+ # eo$set_signif
515: movc5 $0,(r1),$0x91,r6,(r3) # eo$move 1
516: clrb (r3) # eo$end
517: editpc r6,(r1),48(r1),16(r1) # unpack 'em all
518: subl3 r6,r5,r1 # addr unpacked source
519: movl (sp),r3 # punctuated output placed here
520: clrl r7
521: jlbc -17(fp),f1
522: movb $'-,(r3)+ # negative
523: incl r7
524: f1: movl -8(fp),r0
525: jgtr f2
526: movb $'0,(r3)+ # must have digit before decimal point
527: jbr f3
528: f2: cmpl r0,r6 # limit on packed length
529: jleq f4
530: movl r6,r0
531: f4: subl2 r0,r6 # eat some digits
532: subl2 r0,-8(fp) # from the exponent
533: movc3 r0,(r1),(r3) # (most of the) digits to left of decimal point
534: movl -8(fp),r0 # need any more?
535: jleq f3
536: movc5 $0,(r1),$'0,r0,(r3) # '0 fill
537: f3: movl r8,r0 # # digits to right of decimal point
538: jgtr f5
539: jbs $5,r10,f5 # no decimal point unless forced
540: jbcs $9,r10,f6 # no decimal point
541: f5: movb $'.,(r3)+ # the decimal point
542: f6: mnegl -8(fp),r0 # "leading" zeroes to right of decimal point
543: jleq f9
544: cmpl r0,r8 # cant exceed this many
545: jleq fa
546: movl r8,r0
547: fa: subl2 r0,r8
548: movc5 $0,(r1),$'0,r0,(r3)
549: f9: movl r8,r0
550: cmpl r0,r6 # limit on packed length
551: jleq f7
552: movl r6,r0
553: f7: subl2 r0,r8 # eat some digits from the fraction
554: movc3 r0,(r1),(r3) # (most of the) digits to right of decimal point
555: movl r8,r0 # need any more?
556: jleq f8
557: # check bounds on users who say %.300f
558: movab 32(r3)[r0],r2
559: subl2 fp,r2
560: jlss fb
561: subl2 r2,r0 # truncate, willy-nilly
562: movl r0,r8 # and no more digits later, either
563: fb:
564: #
565: subl2 r0,r8 # eat some digits from the fraction
566: movc5 $0,(r1),$'0,r0,(r3) # '0 fill
567: f8: movl r3,r5 # addr last byte +1
568: popr $1<1 # [movl (sp)+,r1] addr first byte
569: rsb
570:
571: patexp: .byte 0x03 # eo$set_signif
572: .byte 0x44,'e # eo$insert 'e
573: .byte 0x42,'+ # eo$load_plus '+
574: .byte 0x04 # eo$store_sign
575: .byte 0x92 # eo$move 2
576: .byte 0 # eo$end
577:
578: scien:
579: incl r8
580: jbs $1,r10,L23
581: movl $7,r8
582: L23: bsbw fltcvt # get packed digits
583: movl r8,r7
584: cmpl r7,$31 # expressible in packed decimal?
585: jleq snarro # yes
586: movl $31,r7
587: snarro: subl3 $17,r7,r0 # rounding position
588: ashp r0,$17,(sp),$5,r7,16(sp) # shift and round
589: bvc snovfl
590: # band-aid for microcode error (spurious overflow)
591: # clrl r0 # assume even length result
592: # jlbc r8,sceven # right
593: # movl $4,r0 # odd length result
594: #sceven: cmpv r0,$4,16(sp),$0 # top digit zero iff true overflow
595: # bneq snovfl
596: # end band-aid
597: incl -8(fp) # rounding overflowed to 100...
598: subl3 $1,r7,r0
599: ashp r0,$1,pone,$0,r7,16(sp)
600: ashl $-1,r7,r0 # displ to last byte
601: bisb2 -17(fp),16(sp)[r0] # insert -17(fp)
602: snovfl:
603: jbs $8,r10,gfmt # %g format
604: movab 16(sp),r1
605: bsbb eedit
606: eexp:
607: movl r1,r6 # save fwa from destruction by cvtlp
608: subl3 $1,-12(fp),r0 # 1P exponent
609: cvtlp r0,$2,(sp) # packed
610: editpc $2,(sp),patexp,(r5)
611: movl r6,r1 # fwa
612: jbc $6,r10,prnum
613: xorb2 $'e^'E,-4(r5)
614: jbr prnum
615:
616: eedit:
617: movl r7,r6 # packed length
618: decl r8 # 1 digit before decimal point
619: movl -8(fp),-12(fp) # save from destruction
620: movl $1,-8(fp) # and pretend
621: jbr fedit
622:
623: gfmt:
624: addl3 $3,-8(fp),r0 # -8(fp) is 1 more than e
625: jlss gfmte # (e+1)+3<0, e+4<=-1, e<=-5
626: subl2 $3,r0 # -8(fp) [==(e+1)]
627: cmpl r0,r8
628: jgtr gfmte # e+1>n, e>=n
629: gfmtf:
630: movl r7,r6
631: subl2 r0,r8 # n-e-1
632: movab 16(sp),r1
633: bsbw fedit
634: g1: jbs $5,r10,g2
635: jbs $9,r10,g2 # dont strip if no decimal point
636: g3: cmpb -(r5),$'0 # strip trailing zeroes
637: jeql g3
638: cmpb (r5),$'. # and trailing decimal point
639: jeql g2
640: incl r5
641: g2: jbc $8,r10,eexp
642: jbr prnum
643: gfmte:
644: movab 16(sp),r1 # packed source
645: bsbw eedit
646: jbsc $8,r10,g1 # 8 now means "use %f" [hence no exponent]
647:
648: general:
649: jbs $1,r10,gn1
650: movl $6,r8 # default precision is 6 significant digits
651: gn1: tstl r8 # cannot allow precision of 0
652: jgtr gn2
653: movl $1,r8 # change 0 to 1, willy-nilly
654: gn2: jbcs $8,r10,L23
655: jbr L23 # safety net
656:
657: # convert double-floating at (ap) to 17-digit packed at (sp),
658: # set 'sign' and 'exp', advance ap.
659: fltcvt:
660: clrb -17(fp)
661: movd (ap)+,r5
662: jeql fzero
663: bgtr fpos
664: mnegd r5,r5
665: incb -17(fp)
666: fpos:
667: extzv $7,$8,r5,r2 # exponent of 2
668: movab -0200(r2),r2 # unbias
669: mull2 $59,r2 # 59/196: 3rd convergent continued frac of log10(2)
670: jlss eneg
671: movab 196(r2),r2
672: eneg:
673: movab -98(r2),r2
674: divl2 $196,r2
675: bsbw expten
676: cmpd r0,r5
677: bgtr ceil
678: incl r2
679: ceil: movl r2,-8(fp)
680: mnegl r2,r2
681: cmpl r2,$29 # 10^(29+9) is all we can handle
682: bleq getman
683: muld2 ten16,r5
684: subl2 $16,r2
685: getman: addl2 $9,r2 # -ceil(log10(x)) + 9
686: jsb expten
687: emodd r0,r4,r5,r0,r5 # (r0+r4)*r5; r0=int, r5=frac
688: fz1: cvtlp r0,$9,16(sp) # leading 9 digits
689: ashp $8,$9,16(sp),$0,$17,4(sp) # as top 9 of 17
690: emodd ten8,$0,r5,r0,r5
691: cvtlp r0,$8,16(sp) # trailing 8 digits
692: # if precision >= 17, must round here
693: movl r8,r7 # so figure out what precision is
694: pushab scien
695: cmpl (sp)+,(sp)
696: jleq gm1 # who called us?
697: addl2 -8(fp),r7 # float; adjust for exponent
698: gm1: cmpl r7,$17
699: jlss gm2
700: cmpd r5,$0d0.5 # must round here; check fraction
701: jlss gm2
702: bisb2 $0x10,8+4(sp) # increment l.s. digit
703: gm2: # end of "round here" code
704: addp4 $8,16(sp),$17,4(sp) # combine leading and trailing
705: bisb2 -17(fp),12(sp) # and insert -17(fp)
706: rsb
707: fzero: clrl r0
708: movl $1,-8(fp) # 0.000e+00 and 0.000 rather than 0.000e-01 and .000
709: jbr fz1
710:
711: .align 2
712: lsb: .long 0x00010000 # lsb in the crazy floating-point format
713:
714: # return 10^r2 as a double float in r0||r1 and 8 extra bits of precision in r4
715: # preserve r2, r5||r6
716: expten:
717: movd $0d1.0,r0 # begin computing 10^exp10
718: clrl r4 # bit counter
719: movad ten1,r3 # table address
720: tstl r2
721: bgeq e10lp
722: mnegl r2,r2 # get absolute value
723: jbss $6,r2,e10lp # flag as negative
724: e10lp: jbc r4,r2,el1 # want this power?
725: muld2 (r3),r0 # yes
726: el1: addl2 $8,r3 # advance to next power
727: aobleq $5,r4,e10lp # through 10^32
728: jbcc $6,r2,el2 # correct for negative exponent
729: divd3 r0,$0d1.0,r0 # by taking reciprocal
730: cmpl $28,r2
731: jneq enm28
732: addl2 lsb,r1 # 10**-28 needs lsb incremented
733: enm28: mnegl r2,r2 # original exponent of 10
734: el2: addl3 $5*8,r2,r3 # negative bit positions are illegal?
735: jbc r3,xlsbh-5,eoklsb
736: subl2 lsb,r1 # lsb was too high
737: eoklsb:
738: movzbl xprec[r2],r4 # 8 extra bits
739: rsb
740:
741: # powers of ten
742: .align 2
743: ten1: .word 0x4220,0,0,0
744: ten2: .word 0x43c8,0,0,0
745: ten4: .word 0x471c,0x4000,0,0
746: ten8: .word 0x4dbe,0xbc20,0,0
747: ten16: .word 0x5b0e,0x1bc9,0xbf04,0
748: ten32: .word 0x759d,0xc5ad,0xa82b,0x70b6
749:
750: # whether lsb is too high or not
751: .byte 1:0,1:0,1:0,1:0,1:1,1:0,1:1,1:0 # -40 thru -33
752: .byte 1:0,1:1,1:0,1:0,1:0,1:0,1:1,1:0 # -32 thru -25
753: .byte 1:0,1:0,1:1,1:1,1:1,1:1,1:0,1:0 # -24 thru -17
754: .byte 1:0,1:1,1:0,1:0,1:1,1:1,1:1,1:1 # -16 thru -9
755: .byte 1:1,1:1,1:1,1:0,1:0,1:0,1:0,1:1 # -8 thru -1
756: xlsbh:
757: .byte 1:0,1:0,1:0,1:0,1:0,1:0,1:0,1:0 # 0 thru 7
758: .byte 1:0,1:0,1:0,1:0,1:0,1:0,1:0,1:0 # 8 thru 15
759: .byte 1:0,1:0,1:0,1:0,1:0,1:0,1:0,1:0 # 16 thru 23
760: .byte 1:0,1:1,1:1,1:0,1:1,1:1,1:1,1:1 # 24 thru 31
761: .byte 1:1,1:1,1:1,1:1,1:1,1:1,1:1 # 32 thru 38
762:
763: # bytes of extra precision
764: .byte 0x56,0x76,0xd3,0x88,0xb5,0x62 # -38 thru -33
765: .byte 0xba,0xf5,0x32,0x3e,0x0e,0x48,0xdb,0x51 # -32 thru -25
766: .byte 0x53,0x27,0xb1,0xef,0xeb,0xa5,0x07,0x49 # -24 thru -17
767: .byte 0x5b,0xd9,0x0f,0x13,0xcd,0xff,0xbf,0x97 # -16 thru -9
768: .byte 0xfd,0xbc,0xb6,0x23,0x2c,0x3b,0x0a,0xcd # -8 thru -1
769: xprec:
770: .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 # 0 thru 7
771: .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 # 8 thru 15
772: .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 # 16 thru 23
773: .byte 0x00,0xa0,0xc8,0x3a,0x84,0xe4,0xdc,0x92 # 24 thru 31
774: .byte 0x9b,0x00,0xc0,0x58,0xae,0x18,0xef # 32 thru 38
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.