Annotation of 40BSD/libc/stdio/doprnt.s, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.