Annotation of 41BSD/cmd/csh/doprnt.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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