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