|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley Software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: .ascii "@(#)doprnt.c 5.2 (Berkeley) 6/6/85"
9: #endif
10:
11: # C library -- conversions
12:
13: .globl __doprnt
14: .globl __strout
15:
16: #define flags r10
17: #define literb 0
18: #define liter 1
19: #define ndfndb 0
20: #define ndfnd 1
21: #define ljustb 1
22: #define ljust 2
23: #define zfillb 2
24: #define zfill 4
25: #define precb 3
26: #define prec 8
27: #define psignb 4
28: #define psign 16
29: #define gflagb 5
30: #define gflag 32
31: #define width r9
32: #define ndigit r8
33: #define fdesc -4(fp)
34: #define exp -8(fp)
35: #define sign -9(fp)
36: .set one,010 # 1.0 in floating immediate
37: .set ch.zer,'0 # cpp doesn't like single appostrophes
38:
39: .align 1
40: __doprnt:
41: .word 0xfc0 # uses r11-r6
42: subl2 $128,sp
43: movl 4(ap),r11 # addr of format string
44: movl 12(ap),fdesc # output FILE ptr
45: movl 8(ap),ap # addr of first arg
46: loop:
47: movl r11,r0 # current point in format
48: bicl2 $liter,flags # no literal characters yet
49: L1: movb (r11)+,width # next character of format
50: beql L2 # end of format string
51: cmpb width,$'%
52: beql L2 # warning character
53: bisl2 $liter,flags # literal character
54: jbr L1
55: L2: blbc flags,L3 # bbc $literb,flags,L3 # no literals in format
56: pushl fdesc # file pointer
57: pushl $0 # no left/right adjust
58: pushl r0 # addr
59: subl3 r0,r11,r1 # length
60: subl3 $1,r1,-(sp) # % or null not part of literal
61: calls $4,__strout # dump the literal
62: L3:
63: blbs width,L4 # % is odd; end of format?
64: ret # yes
65:
66: # htab overlaps last 16 characters of ftab
67: ftab: .byte 0, 0, 0,'c,'d,'e,'f,'g, 0, 0, 0,'+,'l,'-,'.,'o
68: htab: .byte '0,'1,'2,'3,'4,'5,'6,'7,'8,'9,'a,'b,'c,'d,'e,'f
69:
70: L4: movl sp,r5 # reset output buffer pointer
71: clrq r9 # width; flags ljustb,ndfndb,zfillb
72: L4a: movzbl (r11)+,r0 # supposed format
73: extzv $0,$5,r0,r1 # bottom 5 bits
74: L4b: cmpb r0,ftab[r1] # good enough?
75: jneq L6 # no
76: L4c: casel r1,$3,$22 # yes
77: L5: .word charac-L5 # c
78: .word decimal-L5 # d
79: .word scien-L5 # e
80: .word float-L5 # f
81: .word general-L5 # g
82: .word L6-L5 # h
83: .word L6-L5 # i
84: .word L6-L5 # j
85: .word plus-L5 # +
86: .word longorunsg-L5 # l
87: .word minus-L5 # -
88: .word dot-L5 # .
89: .word octal-L5 # o
90: .word gnum0-L5 # 0
91: .word gnum-L5 # 1
92: .word gnum-L5 # 2
93: .word gnum-L5 # 3
94: .word gnum-L5 # 4
95: .word gnum-L5 # 5
96: .word gnum-L5 # 6
97: .word gnum-L5 # 7
98: .word gnum-L5 # 8
99: .word gnum-L5 # 9
100:
101: L6: jbcs $5,r0,L4b # capitals same as small
102: cmpb r0,$'s
103: jeql string
104: cmpb r0,$'x
105: jeql hex
106: cmpb r0,$'u
107: jeql unsigned
108: cmpb r0,$'r
109: jeql remote
110: movzbl -1(r11),r0 # orginal "format" character
111: cmpb r0,$'*
112: jeql indir
113: L9: movb r0,(r5)+ # print the unfound character
114: jbr prbuf
115:
116: nulstr:
117: .byte '(,'n,'u,'l,'l,'),0
118:
119: string:
120: movl ndigit,r0
121: jbs $precb,flags,L20 # max length was specified
122: mnegl $1,r0 # default max length
123: L20: movl (ap)+,r2 # addr first byte
124: bneq L21
125: movab nulstr,r2
126: L21: locc $0,r0,(r2) # find the zero at the end
127: movl r1,r5 # addr last byte +1
128: movl r2,r1 # addr first byte
129: jbr prstr
130:
131:
132: longorunsg:
133: movb (r11)+,r0
134: cmpb r0,$'o
135: jeql loct
136: cmpb r0,$'x
137: jeql lhex
138: cmpb r0,$'d
139: jeql long
140: cmpb r0,$'u
141: jeql lunsigned
142: decl r11
143: jbr unsigned
144:
145: loct:
146: octal:
147: movl $30,r2 # init position
148: movl $3,r3 # field width
149: movl $10,r4 # result length -1
150: jbr L10
151:
152: lhex:
153: hex:
154: movl $28,r2 # init position
155: movl $4,r3 # field width
156: movl $7,r4 # result length -1
157: L10: mnegl r3,r6 # increment
158: clrl r1
159: movl (ap)+,r0 # fetch arg
160: L11: extzv r2,r3,r0,r1 # pull out a digit
161: movb htab[r1],(r5)+ # convert to character
162: L12: acbl $0,r6,r2,L11 # continue until done
163: clrb (r5) # flag end
164: skpc $'0,r4,(sp) # skip over leading zeroes
165: jbr prstr
166:
167: patdec: # editpc pattern for decimal printing
168: .byte 0xA9 # eo$float 9
169: .byte 0x01 # eo$end_float
170: .byte 0x91 # eo$move 1
171: .byte 0 # eo$end
172:
173: long:
174: decimal:
175: cvtlp (ap)+,$10,(sp) # 10 digits max
176: L14: editpc $10,(sp),patdec,8(sp) # ascii at 8(sp); r5=end+1
177: skpc $' ,$10,8(sp) # skip leading blanks; r1=first
178:
179: prstr: # r1=addr first byte; r5=addr last byte +1
180: cvtbl $' ,-(sp) # blank fill
181: jbc $zfillb,flags,L15
182: cvtbl $'0,(sp) # zero fill
183: L15: pushl fdesc # FILE
184: subl2 r1,r5 # r5=actual length=end+1-first
185: subl3 r5,width,r0 # if >0, how much to fill
186: bgeq L24
187: clrl r0 # no fill
188: L24: jbs $ljustb,flags,L25
189: mnegl r0,r0
190: L25: pushl r0 # fill count
191: pushl r1 # addr first byte
192: pushl r5 # length
193: calls $5,__strout
194: jbr loop
195:
196: pone: .byte 0x1C # packed 1
197:
198: unsigned:
199: lunsigned:
200: extzv $1,$31,(ap),r0 # right shift logical 1 bit
201: cvtlp r0,$10,(sp) # convert [n/2] to packed
202: movp $10,(sp),8(sp) # copy packed
203: addp4 $10,8(sp),$10,(sp) # 2*[n/2] in packed, at (sp)
204: blbc (ap)+,L14 # n was even
205: addp4 $1,pone,$10,(sp) # n was odd
206: jbr L14
207:
208: charac:
209: movl $4,r0 # chars per word
210: L18: movb (ap)+,(r5)+ # transfer char
211: bneq L19
212: decl r5 # omit null characters
213: L19: sobgtr r0,L18
214:
215: prbuf:
216: movl sp,r1 # addr first byte
217: jbr prstr
218:
219: plus: bisl2 $psign,flags # always print sign for floats
220: jbr L4a
221: minus: bisl2 $ljust,flags # left justification, please
222: jbr L4a
223: gnum0: jbs $ndfndb,flags,gnum
224: jbs $precb,flags,gnump # ignore when reading precision
225: bisl2 $zfill,flags # leading zero fill, please
226: gnum: jbs $precb,flags,gnump
227: moval (width)[width],width # width *= 5;
228: movaw -ch.zer(r0)[width],width # width = 2*witdh + r0 - '0';
229: jbr gnumd
230: gnump: moval (ndigit)[ndigit],ndigit # ndigit *= 5;
231: movaw -ch.zer(r0)[ndigit],ndigit # ndigit = 2*ndigit + r0 - '0';
232: gnumd: bisl2 $ndfnd,flags # digit seen
233: jbr L4a
234: dot: clrl ndigit # start on the precision
235: bisl2 $prec,flags
236: bicl2 $ndfnd,flags
237: jbr L4a
238: indir: movl (ap)+,ndigit # width specified by parameter
239: jbr gnumd
240: remote: movl (ap)+,ap
241: movl (ap)+,r11
242: jbr loop
243:
244: float:
245: bsbw fltcvt
246: fltg: jbs $ndfndb,flags,float1
247: movl $6,ndigit # default # digits to right of decpt.
248: float1: addl3 exp,ndigit,r7
249: movl r7,r6 # for later "underflow" checking
250: bgeq fxplrd
251: clrl r7 # poor programmer planning
252: fxplrd: cmpl r7,$31 # expressible in packed decimal?
253: bleq fnarro # yes
254: movl $31,r7
255: fnarro: subl3 $17,r7,r0 # where to round
256: ashp r0,$17,(sp),$5,r7,16(sp) # do it
257: bvc fnovfl
258: # band-aid for microcode error (spurious overflow)
259: clrl r0 # assume even length result
260: jlbc r7,fleven # right
261: movl $4,r0 # odd length result
262: fleven: cmpv r0,$4,16(sp),$0 # top digit zero iff true overflow
263: bneq fnovfl
264: # end band-aid
265: aobleq $0,r6,fnovfl # if "underflow" then jump
266: movl r7,r0
267: incl exp
268: incl r7
269: ashp r0,$1,pone,$0,r7,16(sp)
270: ashl $-1,r7,r0 # displ to last byte
271: bisb2 sign,16(sp)[r0] # insert sign
272: fnovfl:
273: movc3 $4,patsci,(sp)
274: clrl r6 # # digits moved so far
275: movl exp,r0
276: bleq fexpng
277: bsbb patmov # digits to left of decpt.
278: fexpng: tstl ndigit
279: jeql fnodp
280: movc3 $2,fpatdp,(r3)
281: tstl exp
282: bgeq fxppos
283: addl3 exp,ndigit,r6
284: bgeq flfakl
285: clrl r6 # it's all fill
286: flfakl: subl3 r6,$31,r6 # fake length for patmov
287: flfill: movc3 $2,fpatzf,(r3) # zero fill to right of dec.pt
288: fxppos: movl ndigit,r0
289: bsbb patmov
290: fnodp: sobgeq r6,fledit # must move at least 1 digit
291: movl $31,r6 # none moved; fake it
292: aobleq $1,ndigit,flfill # with a one-character zero fill
293: fledit: editpc r7,16(sp),(sp),32(sp)
294: jbr prflt
295:
296: patexp: .byte 0x03 # eo$set_signif
297: .byte 0x44,'e # eo$insert 'e
298: .byte 0x42,'+ # eo$load_plus '+
299: .byte 0x04 # eo$store_sign
300: .byte 0x92 # eo$move 2
301: .byte 0 # eo$end
302: patsci: .byte 0x42,'+ # eo$load_plus '+
303: .byte 0x03 # eo$set_signif
304: .byte 0x04 # eo$store_sign
305: .byte 0x91 # eo$move 1
306: fpatdp: .byte 0x44,'. # eo$insert '.
307: fpatzf: .byte 0x40,'0 # eo$load_fill '0
308:
309: # construct pattern at (r3) to move r0 digits in editpc;
310: # r6 digits already moved for this number
311: patmov:
312: movb $0x90,r2 # eo$move
313: subl3 r6,$31,r1 # # digits remaining in packed
314: addl2 r0,r6
315: cmpl r0,r1 # enough digits remaining?
316: bleq patsml # yes
317: tstl exp # zero 'fill'; before or after rest?
318: bgeq pataft # after
319: pushl r1 # # digits remaining
320: movb $0x80,r2 # eo$fill
321: subl3 $31,r6,r0 # number of fill bytes
322: bsbb patsml # recursion!
323: movl (sp)+,r0
324: movb $0x90,r2 # eo$move
325: jbr patsml
326: pataft: movl r1,r0 # last of the 31
327: bsbb patsml # recursion!
328: subl3 $31,r6,r0 # number of fill bytes
329: movb $0x80,r2 # eo$fill
330: patsml: tstl r0
331: bleq patzer # DEC doesn't like repetition counts of 0
332: mnegl $15,r1 # 15 digits at a time
333: subl2 r1,r0 # counteract acbl
334: jbr pattst
335: patmlp: bisb3 r2,$15,(r3)+ # 15
336: pattst: acbl $16,r1,r0,patmlp # until <= 15 left
337: bisb3 r2,r0,(r3)+ # rest
338: patzer: clrb (r3) # eo$end
339: rsb
340:
341: scien:
342: bsbw fltcvt # get packed digits
343: scig: incl ndigit
344: jbs $ndfndb,flags,L23
345: movl $7,ndigit
346: L23: subl3 $17,ndigit,r0 # rounding position
347: ashp r0,$17,(sp),$5,ndigit,16(sp) # shift and round
348: bvc snovfl
349: # band-aid for microcode error (spurious overflow)
350: clrl r0 # assume even length result
351: jlbc ndigit,sceven # right
352: movl $4,r0 # odd length result
353: sceven: cmpv r0,$4,16(sp),$0 # top digit zero iff true overflow
354: bneq snovfl
355: # end band-aid
356: incl exp # rounding overflowed to 100...
357: subl3 $1,ndigit,r0
358: ashp r0,$1,pone,$0,ndigit,16(sp)
359: ashl $-1,ndigit,r0 # displ to last byte
360: bisb2 sign,16(sp)[r0] # insert sign
361: snovfl:
362: jbc $gflagb,flags,enotg # not %g format
363: # find trailing zeroes in packed number
364: ashl $-1,ndigit,r0
365: addl2 r3,r0 # addr of l.s.digit and sign
366: movl $4,r1 # bit position of digit
367: movl ndigit,r7 # current length of packed
368: jbr gtz
369: gtz1: xorl2 $4,r1 # position of next digit
370: bneq gtz # same byte
371: decl r0 # different byte
372: gtz: cmpv r1,$4,(r0),$0 # a trailing zero?
373: jneq gntz
374: sobgtr r7,gtz1
375: incl r7
376: gntz: # r7: minimum width of fraction
377: cmpl exp,$-4
378: jleq eg # small exponents use %e
379: subl3 r7,exp,r0
380: cmpl $5,r0
381: jleq eg # so do (w+5) <= exp
382: tstl r0 # rest use %f
383: jleq fg # did we trim too many trailing zeroes?
384: movl exp,r7 # yes
385: fg: subl3 ndigit,r7,r0
386: ashp r0,ndigit,16(sp),$0,r7,(sp)
387: movp r7,(sp),16(sp)
388: subl3 exp,r7,ndigit # correct ndigit for %f
389: jbr fnovfl
390: eg: subl3 ndigit,r7,r0
391: ashp r0,ndigit,16(sp),$0,r7,(sp)
392: movp r7,(sp),16(sp)
393: movl r7,ndigit # packed number has been trimmed
394: enotg:
395: movc3 $7,patsci,(sp)
396: movl $1,r6 # 1P
397: subl3 $1,ndigit,r0 # digits after dec.pt
398: bsbw patmov
399: editpc ndigit,16(sp),(sp),32(sp) # 32(sp)->result, r5->(end+1)
400: decl exp # compensate: 1 digit left of dec.pt
401: cvtlp exp,$2,(sp) # exponent
402: editpc $2,(sp),patexp,(r5)
403: prflt: movab 32(sp),r1
404: jbs $psignb,flags,prflt1
405: cmpb (r1)+,$'+
406: beql prflt1
407: decl r1
408: prflt1: skpc $' ,$63,(r1)
409: jbr prstr
410:
411: general:
412: jbcs $gflagb,flags,scien
413: jbr scien # safety net
414:
415: # convert double-floating at (ap) to 17-digit packed at (sp),
416: # set 'sign' and 'exp', advance ap.
417: fltcvt:
418: clrb sign
419: movd (ap)+,r5
420: jeql fzero
421: bgtr fpos
422: mnegd r5,r5
423: incb sign
424: fpos:
425: extzv $7,$8,r5,r2 # exponent of 2
426: movaw -0600(r2)[r2],r2 # unbias and mult by 3
427: bgeq epos
428: subl2 $9,r2
429: epos: divl2 $10,r2
430: bsbb expten
431: cmpd r0,r5
432: bgtr ceil
433: incl r2
434: ceil: movl r2,exp
435: mnegl r2,r2
436: cmpl r2,$29 # 10^(29+9) is all we can handle
437: bleq getman
438: muld2 ten16,r5
439: subl2 $16,r2
440: getman: addl2 $9,r2 # -ceil(log10(x)) + 9
441: bsbb expten
442: emodd r0,r4,r5,r0,r5 # (r0+r4)*r5; r0=int, r5=frac
443: fz1: cvtlp r0,$9,16(sp) # leading 9 digits
444: ashp $8,$9,16(sp),$0,$17,4(sp) # as top 9 of 17
445: emodd ten8,$0,r5,r0,r5
446: cvtlp r0,$8,16(sp) # trailing 8 digits
447: addp4 $8,16(sp),$17,4(sp) # combine leading and trailing
448: bisb2 sign,12(sp) # and insert sign
449: rsb
450: fzero: clrl r0
451: movl $1,exp # 0.000e+00 and 0.000 rather than 0.000e-01 and .000
452: jbr fz1
453:
454: # return 10^r2 as a double float in r0||r1 and 8 extra bits of precision in r4
455: # preserve r2, r5||r6
456: expten:
457: movd $one,r0 # begin computing 10^exp10
458: clrl r4 # bit counter
459: movad ten1,r3 # table address
460: tstl r2
461: bgeq e10lp
462: mnegl r2,r2 # get absolute value
463: jbss $6,r2,e10lp # flag as negative
464: e10lp: jbc r4,r2,el1 # want this power?
465: muld2 (r3),r0 # yes
466: el1: addl2 $8,r3 # advance to next power
467: aobleq $5,r4,e10lp # through 10^32
468: jbcc $6,r2,el2 # correct for negative exponent
469: divd3 r0,$one,r0 # by taking reciprocal
470: mnegl r2,r2
471: el2: clrl r4 # 8 extra bits of precision
472: rsb
473:
474: # powers of ten
475: .align 2
476: ten1: .word 0x4220,0,0,0
477: ten2: .word 0x43c8,0,0,0
478: ten4: .word 0x471c,0x4000,0,0
479: ten8: .word 0x4dbe,0xbc20,0,0
480: ten16: .word 0x5b0e,0x1bc9,0xbf04,0
481: ten32: .word 0x759d,0xc5ad,0xa82b,0x70b6
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.