        TTL                     'itoa'
        OPT                     D
*==============================================================================
*
*                       i t o a ,  l t o a
*
*==============================================================================
*  int  itoa (N, Str)   int  N; char *Str;
*  int  ltoa (N, Str)   long N; char *Str;
*
*       Convert the (signed) integer N to a null-terminated ASCII string
*       of decimal digits and place in the area pointed to by Str.  If N is
*       negative, the output string begins with a '-'.  No leading blanks or
*       zeros are produced.  The function returns the number of characters
*       placed in the output string, excluding the null terminator.
*
itoa    IDNT
        SECTION 9
        XDEF    .itoa
        XDEF    .ltoa
*
.itoa:
.ltoa:
        link    a6,#0                   ; create stack frame for saving A6
        movem.l d2,-(a7)                ; save D2
; stack now looks like:
;       STR                             ; A6+12  A7+16
;       N                               ; A6+8   A7+12
;       Return address                  ; A6+4   A7+8
; A6 -> A6                              ; A6+0   A7+4
; A7 -> D2                              ; A6-4   A7+0
;
        move.l  16(a7),a0               ; A0 -> Str
        move.l  12(a7),d0                ; N
        bpl.s   plus                    ; OK if N is positive
;
        neg.l   d0                      ; N is negative: make it positive
        move.b  #'-',(a0)+              ; Output a '-' sign
plus:
; copy number onto stack (backwards), to later copy to str
;
        move.b  #0,-(a7)                ; Null-terminator for output string
mainlp:                                 ; The main loop
        cmpi.l  #65535,d0               ; Is hi word of number equal 0 ?
        bhi.s   not0                    ; long value to convert
;
        moveq   #10,d1                  ; amount to divide by
div16:                                  ; do 16-bit div
        cmp.l   d1,d0                   ; Is number < 10 ?
        bcs.s   done                    ; yes, we're done
;
        divu    d1,d0                   ; no, Divide number by 10
        swap    d0                      ; Quotient in hi, remainder in lo
        addi.b  #'0',d0                 ; Convert from binary to ASCII
        move.b  d0,-(a7)                ; Save the remainder on stack
        andi.b  #0,d0                   ; Clear low order byte
        swap    d0                      ; Quotient back to low order word
        bra     div16                   ; keep processing until 0
;;
not0:                                   ; Hi word != 0, prepare 32-bit div
        moveq   #0,d1                   ; Initialize remainder to 0
        moveq   #31,d2                  ; divide by successive subtractions?
div32:                                  ; 32/16-bit division
        lsl.l   #1,d0
        roxl.l  #1,d1                   ; 64-bit left shift
        cmpi.b  #10,d1                  ; Remainder > divisor ?
        bcs.s   continue
;
        subi.b  #10,d1                  ; if so, subtract it
        addq.b  #1,d0                   ; add 1 to quotient
continue:
        dbf     d2,div32
;
        addi.b  #'0',d1                 ; Convert from binary to ASCII
        move.b  d1,-(a7)                ; Save the remainder on stack
        bra     mainlp                  ; drop to 16 bit divide when number
                                        ; small enough
;;
done:                                   ; Last digit not pushed on stack
        addi.b  #'0',d0                 ; Convert from binary to ASCII
        move.b  d0,(a0)+
rev:                                    ; Loop for reversing the digits
        move.b  (a7)+,(a0)+             ; Copy output from stack to Str
        bne     rev                     ; copy up to null at end
;                                       ; stack restored
        move.l  a0,d0                   ; Ptr to Str after the null char
        subq.l  #1,d0
        sub.l   12(a6),d0                ; end-start = number of chars in string
                                        ; including 0 at end of string.
;
        movem.l -4(a6),d2               ; restore d2
        unlk    a6                      ; reset stack frame to callers
        rts                             ; return to caller
;;
*
        END

 
