BSD 4_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 30 Jun 1983 09:29:01 +0000 (01:29 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 30 Jun 1983 09:29:01 +0000 (01:29 -0800)
Work on file usr/src/lib/libc/vax/gen/atof.s
Work on file usr/src/lib/libc/vax/gen/nargs.s
Work on file usr/src/lib/libc/vax/gen/abs.s

Synthesized-from: CSRG/cd1/4.2

usr/src/lib/libc/vax/gen/abs.s [new file with mode: 0644]
usr/src/lib/libc/vax/gen/atof.s [new file with mode: 0644]
usr/src/lib/libc/vax/gen/nargs.s [new file with mode: 0644]

diff --git a/usr/src/lib/libc/vax/gen/abs.s b/usr/src/lib/libc/vax/gen/abs.s
new file mode 100644 (file)
index 0000000..c5be804
--- /dev/null
@@ -0,0 +1,12 @@
+/*     abs.s   4.1     83/06/27        */
+
+/* abs - int absolute value */
+
+#include "DEFS.h"
+
+ENTRY(abs)
+       movl    4(ap),r0
+       bgeq    1f
+       mnegl   r0,r0
+1:
+       ret
diff --git a/usr/src/lib/libc/vax/gen/atof.s b/usr/src/lib/libc/vax/gen/atof.s
new file mode 100644 (file)
index 0000000..3860c1d
--- /dev/null
@@ -0,0 +1,326 @@
+/*     atof.s  4.2     83/06/30        */
+
+#include "DEFS.h"
+
+/*
+ *     atof: convert ascii to floating
+ *
+ *     C usage:
+ *
+ *             double atof (s)
+ *             char *s;
+ *
+ *     Register usage:
+ *
+ *             r0-1:   value being developed
+ *             r2:     first section: pointer to the next character
+ *                     second section: binary exponent
+ *             r3:     flags
+ *             r4:     first section: the current character
+ *                     second section: scratch
+ *             r5:     the decimal exponent
+ *             r6-7:   scratch
+ *
+ *     Flag definitions
+ */
+       .set    msign,0         # mantissa has negative sign
+       .set    esign,1         # exponent has negative sign
+       .set    decpt,2         # decimal point encountered
+
+       .align  2
+two31: .word   0x5000          # 2 ** 31
+       .word   0               # (=2147483648)
+       .word   0               # in floating-point
+       .word   0               # (so atof doesn't have to convert it)
+/*
+ *     Entry point
+ */
+ENTRY(atof)
+       pushl   r6
+       pushl   r7
+/*
+ *     Initialization
+ */
+       clrl    r3              # All flags start out false
+       movl    4(ap),r2        # Address the first character
+       clrl    r5              # Clear starting exponent
+/*
+ *     Skip leading white space
+ */
+sk0:   movzbl  (r2)+,r4        # Fetch the next (first) character
+       cmpb    $' ,r4          # Is it blank?
+       jeql    sk0             #   ...yes
+       cmpb    r4,$8           # 8 is lowest of white-space group
+       jlss    sk1             # Jump if char too low to be white space
+       cmpb    r4,$13          # 13 is highest of white-space group
+       jleq    sk0             # Jump if character is white space
+sk1:
+/*
+ *     Check for a sign
+ */
+       cmpb    $'+,r4          # Positive sign?
+       jeql    cs1             #   ... yes
+       cmpb    $'-,r4          # Negative sign?
+       jneq    cs2             #   ... no
+       bisb2   $1<msign,r3     # Indicate a negative mantissa
+cs1:   movzbl  (r2)+,r4        # Skip the character
+cs2:
+/*
+ *     Accumulate digits, keeping track of the exponent
+ */
+       clrq    r0              # Clear the accumulator
+ad0:   cmpb    r4,$'0          # Do we have a digit?
+       jlss    ad4             #   ... no, too small
+       cmpb    r4,$'9
+       jgtr    ad4             #   ... no, too large
+/*
+ *     We got a digit.  Accumulate it
+ */
+       cmpl    r1,$214748364   # Would this digit cause overflow?
+       jgeq    ad1             #   ... yes
+/*
+ *     Multiply (r0,r1) by 10.  This is done by developing
+ *     (r0,r1)*2 in (r6,r7), shifting (r0,r1) left three bits,
+ *     and adding the two quadwords.
+ */
+       ashq    $1,r0,r6        # (r6,r7)=(r0,r1)*2
+       ashq    $3,r0,r0        # (r0,r1)=(r0,r1)*8
+       addl2   r6,r0           # Add low halves
+       adwc    r7,r1           # Add high halves
+/*
+ *     Add in the digit
+ */
+       subl2   $'0,r4          # Get the digit value
+       addl2   r4,r0           # Add it into the accumulator
+       adwc    $0,r1           # Possible carry into high half
+       jbr     ad2             # Join common code
+/*
+ *     Here when the digit won't fit in the accumulator
+ */
+ad1:   incl    r5              # Ignore the digit, bump exponent
+/*
+ *     If we have seen a decimal point, decrease the exponent by 1
+ */
+ad2:   jbc     $decpt,r3,ad3   # Jump if decimal point not seen
+       decl    r5              # Decrease exponent
+ad3:
+/*
+ *     Fetch the next character, back for more
+ */
+       movzbl  (r2)+,r4        # Fetch
+       jbr     ad0             # Try again
+/*
+ *     Not a digit.  Could it be a decimal point?
+ */
+ad4:   cmpb    r4,$'.          # If it's not a decimal point, either it's
+       jneq    ad5             #   the end of the number or the start of
+                               #   the exponent.
+       jbcs    $decpt,r3,ad3   # If it IS a decimal point, we record that
+                               #   we've seen one, and keep collecting
+                               #   digits if it is the first one.
+/*
+ *     Check for an exponent
+ */
+ad5:   clrl    r6              # Initialize the exponent accumulator
+
+       cmpb    r4,$'e          # We allow both lower case e
+       jeql    ex1             #   ... and ...
+       cmpb    r4,$'E          #   upper-case E
+       jneq    ex7
+/*
+ *     Does the exponent have a sign?
+ */
+ex1:   movzbl  (r2)+,r4        # Get next character
+       cmpb    r4,$'+          # Positive sign?
+       jeql    ex2             #   ... yes ...
+       cmpb    r4,$'-          # Negative sign?
+       jneq    ex3             #   ... no ...
+       bisb2   $1<esign,r3     # Indicate exponent is negative
+ex2:   movzbl  (r2)+,r4        # Grab the next character
+/*
+ *     Accumulate exponent digits in r6
+ */
+ex3:   cmpb    r4,$'0          # A digit is within the range
+       jlss    ex4             # '0' through
+       cmpb    r4,$'9          # '9',
+       jgtr    ex4             # inclusive.
+       cmpl    r6,$214748364   # Exponent outrageously large already?
+       jgeq    ex2             #   ... yes
+       moval   (r6)[r6],r6     # r6 *= 5
+       movaw   -'0(r4)[r6],r6  # r6 = r6 * 2 + r4 - '0'
+       jbr     ex2             # Go 'round again
+ex4:
+/*
+ *     Now get the final exponent and force it within a reasonable
+ *     range so our scaling loops don't take forever for values
+ *     that will ultimately cause overflow or underflow anyway.
+ *     A tight check on over/underflow will be done by ldexp.
+ */
+       jbc     $esign,r3,ex5   # Jump if exponent not negative
+       mnegl   r6,r6           # If sign, negate exponent
+ex5:   addl2   r6,r5           # Add given exponent to calculated exponent
+       cmpl    r5,$-100        # Absurdly small?
+       jgtr    ex6             #   ... no
+       movl    $-100,r5        #   ... yes, force within limit
+ex6:   cmpl    r5,$100         # Absurdly large?
+       jlss    ex7             #   ... no
+       movl    $100,r5         #   ... yes, force within bounds
+ex7:
+/*
+ *     Our number has now been reduced to a mantissa and an exponent.
+ *     The mantissa is a 63-bit positive binary integer in r0,r1,
+ *     and the exponent is a signed power of 10 in r5.  The msign
+ *     bit in r3 will be on if the mantissa should ultimately be
+ *     considered negative.
+ *
+ *     We now have to convert it to a standard format floating point
+ *     number.  This will be done by accumulating a binary exponent
+ *     in r2, as we progressively get r5 closer to zero.
+ *
+ *     Don't bother scaling if the mantissa is zero
+ */
+       movq    r0,r0           # Mantissa zero?
+       jeql    exit            #   ... yes
+
+       clrl    r2              # Initialize binary exponent
+       tstl    r5              # Which way to scale?
+       jleq    sd0             # Scale down if decimal exponent <= 0
+/*
+ *     Scale up by "multiplying" r0,r1 by 10 as many times as necessary,
+ *     as follows:
+ *
+ *     Step 1: Shift r0,r1 right as necessary to ensure that no
+ *     overflow can occur when multiplying.
+ */
+su0:   cmpl    r1,$429496729   # Compare high word to (2**31)/5
+       jlss    su1             # Jump out if guaranteed safe
+       ashq    $-1,r0,r0       # Else shift right one bit
+       incl    r2              #    bump exponent to compensate
+       jbr     su0             #    and go back to test again.
+/*
+ *     Step 2: Multiply r0,r1 by 5, by appropriate shifting and
+ *     double-precision addition
+ */
+su1:   ashq    $2,r0,r6        # (r6,r7) := (r0,r1) * 4
+       addl2   r6,r0           # Add low-order halves
+       adwc    r7,r1           #   and high-order halves
+/*
+ *     Step 3: Increment the binary exponent to take care of the final
+ *     factor of 2, and go back if we still need to scale more.
+ */
+       incl    r2              # Increment the exponent
+       sobgtr  r5,su0          #    and back for more (maybe)
+
+       jbr     cm0             # Merge to build final value
+
+/*
+ *     Scale down.  We must "divide" r0,r1 by 10 as many times
+ *     as needed, as follows:
+ *
+ *     Step 0: Right now, the condition codes reflect the state
+ *     of r5.  If it's zero, we are done.
+ */
+sd0:   jeql    cm0             # If finished, build final number
+/*
+ *     Step 1: Shift r0,r1 left until the high-order bit (not counting
+ *     the sign bit) is nonzero, so that the division will preserve
+ *     as much precision as possible.
+ */
+       tstl    r1              # Is the entire high-order half zero?
+       jneq    sd2             #   ...no, go shift one bit at a time
+       ashq    $30,r0,r0       #   ...yes, shift left 30,
+       subl2   $30,r2          #   decrement the exponent to compensate,
+                               #   and now it's known to be safe to shift
+                               #   at least once more.
+sd1:   ashq    $1,r0,r0        # Shift (r0,r1) left one, and
+       decl    r2              #   decrement the exponent to compensate
+sd2:   jbc     $30,r1,sd1      # If the high-order bit is off, go shift
+/*
+ *     Step 2: Divide the high-order part of (r0,r1) by 5,
+ *     giving a quotient in r1 and a remainder in r7.
+ */
+sd3:   movl    r1,r6           # Copy the high-order part
+       clrl    r7              # Zero-extend to 64 bits
+       ediv    $5,r6,r1,r7     # Divide (cannot overflow)
+/*
+ *     Step 3: Divide the low-order part of (r0,r1) by 5,
+ *     using the remainder from step 2 for rounding.
+ *     Note that the result of this computation is unsigned,
+ *     so we have to allow for the fact that an ordinary division
+ *     by 5 could overflow.  We make allowance by dividing by 10,
+ *     multiplying the quotient by 2, and using the remainder
+ *     to adjust the modified quotient.
+ */
+       addl3   $2,r0,r6        # Dividend is low part of (r0,r1) plus
+       adwc    $0,r7           #  2 for rounding plus
+                               #  (2**32) * previous remainder
+       ediv    $10,r6,r0,r6    # r0 := quotient, r6 := remainder.
+       addl2   r0,r0           # Make r0 result of dividing by 5
+       cmpl    r6,$5           # If remainder is 5 or greater,
+       jlss    sd4             #   increment the adjustted quotient.
+       incl    r0
+/*
+ *     Step 4: Increment the decimal exponent, decrement the binary
+ *     exponent (to make the division by 5 into a division by 10),
+ *     and back for another iteration.
+ */
+sd4:   decl    r2              # Binary exponent
+       aoblss  $0,r5,sd2
+/*
+ *     We now have the following:
+ *
+ *     r0:     low-order half of a 64-bit integer
+ *     r1:     high-order half of the same 64-bit integer
+ *     r2:     a binary exponent
+ *
+ *     Our final result is the integer represented by (r0,r1)
+ *     multiplied by 2 to the power contained in r2.
+ *     We will transform (r0,r1) into a floating-point value,
+ *     set the sign appropriately, and let ldexp do the
+ *     rest of the work.
+ *
+ *     Step 1: if the high-order bit (excluding the sign) of
+ *     the high-order half (r1) is 1, then we have 63 bits of
+ *     fraction, too many to convert easily.  However, we also
+ *     know we won't need them all, so we will just throw the
+ *     low-order bit away (and adjust the exponent appropriately).
+ */
+cm0:   jbc     $30,r1,cm1      # jump if no adjustment needed
+       ashq    $-1,r0,r0       # lose the low-order bit
+       incl    r2              # increase the exponent to compensate
+/*
+ *     Step 2: split the 62-bit number in (r0,r1) into two
+ *     31-bit positive quantities
+ */
+cm1:   ashq    $1,r0,r0        # put the high-order bits in r1
+                               #   and a 0 in the bottom of r0
+       rotl    $-1,r0,r0       # right-justify the bits in r0
+                               #   moving the 0 from the ashq
+                               #   into the sign bit.
+/*
+ *     Step 3: convert both halves to floating point
+ */
+       cvtld   r0,r6           # low-order part in r6-r7
+       cvtld   r1,r0           # high-order part in r0-r1
+/*
+ *     Step 4: multiply the high order part by 2**31 and combine them
+ */
+       muld2   two31,r0        # multiply
+       addd2   r6,r0           # combine
+/*
+ *     Step 5: if appropriate, negate the floating value
+ */
+       jbc     $msign,r3,cm2   # Jump if mantissa not signed
+       mnegd   r0,r0           # If negative, make it so
+/*
+ *     Step 6: call ldexp to complete the job
+ */
+cm2:   pushl   r2              # Put exponent in parameter list
+       movd    r0,-(sp)        #    and also mantissa
+       calls   $3,_ldexp       # go combine them
+
+
+exit:
+       movl    (sp)+,r7
+       movl    (sp)+,r6
+       ret
diff --git a/usr/src/lib/libc/vax/gen/nargs.s b/usr/src/lib/libc/vax/gen/nargs.s
new file mode 100644 (file)
index 0000000..c681bcd
--- /dev/null
@@ -0,0 +1,8 @@
+/*     nargs.s 4.1     83/06/27        */
+/* C library -- nargs */
+
+#include "DEFS.h"
+
+ENTRY(nargs)
+       movzbl  *8(fp),r0       /* 8(fp) is old ap */
+       ret