; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.

;
; char *_itoa(char *buf, int num, int base, int unsi)
;
; Acts as itoa if unsi == 0, as utoa otherwise
;
_itoa:
    mov rax, ax0
    xor rdx, rdx

    ; make sure base is in [2, 32]

    cmp ax2, 2
    jmp.b .bad

    cmp ax2, 36
    jmp.a .bad

    ; deal with zero
    test ax1, ax1
    jmp.z .zero

    ; deal with base 10 signedness

    test ax3, ax3   ; unsigned mode
    jmp.nz .conv

    cmp ax2, 10     ; base 10
    jmp.nz .conv

    cmp ax1, -9223372036854775808   ; LONG_MIN
    jmp.z .min

    sgn rdx, ax1    ; extract ax1 sign

    cmp rdx, -1     ; negative?
    not.z ax1       ; -x = ~x+1
    inc.z ax1       ; need "neg" inst...

    ; main loop
.conv:
    test ax1, ax1
    jmp.z .fini

    mov rsx, ax1
    mod rsx, ax2    ; ax1 % base

    cmp rsx, 9      ; rsx > 9 ?
    jmp.a .nondec

    add rsx, 48   ; '0'
    jmp .next

.nondec:
    add rsx, 87     ; 'a' - 10

.next:
    mov b[ax0], rsx
    inc ax0

    div ax1, ax2
    jmp .conv

    ; add minus flag, null-terminate and reverse
.fini:
    cmp rdx, -1
    mov.z b[ax0], 45    ; '-'
    inc.z ax0

    mov b[ax0], 0

    mov ax0, rax
    call strrev2

    ret

;
; exceptional cases
;

.bad:
    mov q[errno], EINVAL
    mov b[rax], 0
    ret

.zero:
    mov b[ax0], 48   ; '0'
    mov b[ax0+1], 0
    ret

.min:
    mov ax1, .min10
    call strcpy
    ret

.min10 = "-9223372036854775808"

;
; wrappers
;

itoa:
    mov ax3, 0
    jmp _itoa

utoa:
    mov ax3, 1
    jmp _itoa