Annotation of 43BSD/lib/libc/vax/stdio/doprnt.c, revision 1.1.1.1

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