blob: d58fc266203fe3d451ca2721f89713f760c41a44 [file] [log] [blame]
/* Copyright (c) 2002, Reiner Patommel
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
/* $Id: ltoa.S 1944 2009-04-01 23:12:20Z arcanum $ */
/*
ltoa.S
Contributors:
Created by Reiner Patommel based on
itoa.s by Michael Rickmann <mrickma@gwdg.de>
Changes: Reiner Patommel <rpato@post4.tele.dk> bug# 4010
#include <stdlib.h>
char *ltoa(long int value, char *string, int radix);
----------------------------------------------------------------------
*/
#if !defined(__DOXYGEN__)
#include "macros.inc"
#include "ctoasm.inc"
ASSEMBLY_CLIB_SECTION
.global _U(ltoa)
.func _U(ltoa)
/* function arguments */
#define a_val_hhi r25
#define a_val_hlo r24
#define a_val_hi r23
#define a_val_lo r22
#define a_str_hi r21
#define a_str_lo r20
#define a_radix_hi r19
#define a_radix r18
/* local variables */
#define r_radix r28
_U(ltoa):
X_movw ZL, a_str_lo ; Z = &string
push r28 ; save r28
push ZH ; keep &string
push ZL
cpi a_radix, 2 ; no radix < 2
brlt 99f ; return with \0
cpi a_radix, 37 ; no radix > 36
brge 99f ; return with \0
mov r_radix, a_radix; save radix
clt ; make sure T flag is clear
cpi r_radix, 10 ; decimal number?
brne 1f
bst a_val_hhi, 7 ; remember sign of decimal number
brtc 1f ; number positive? -> convert
com a_val_hhi ; make decimal number positive
com a_val_hlo
com a_val_hi
neg a_val_lo
sbci a_val_hi, lo8(-1)
sbci a_val_hlo, lo8(-1)
sbci a_val_hhi, lo8(-1)
1:
mov r18, r_radix ; radix is divisor
clr r19 ; remainder of number is dividend
clr r20
clr r21
push ZH ; Z will be clobbered
push ZL ; dividend in r25:r22, divisor in r21:r18
XCALL _U(__udivmodsi4); quotient in r21:r18, remainder in r25:r22
pop ZL
pop ZH
subi r22, 0xd0 ; + '0'
cpi r22, 0x3a ; > '9' ?
brlt 10f
subi r22, 0xd9 ; + 'a' - 10 - '0'
10:
st Z+, r22 ; write character to string in reverse order!
X_movw a_val_lo, r18 ; quotient -> dividend
X_movw a_val_hlo, r20
subi a_val_lo, 0
sbci a_val_hi, 0
sbci a_val_hlo, 0
sbci a_val_hhi,0 ; value == 0 ?
brne 1b
brtc 99f ; decimal number positive -> finish
ldi r28, '-'
st Z+, r28 ; write minus sign to string
99:
st Z, __zero_reg__ ; terminate string
pop a_val_hlo ; restore &string as return value
pop a_val_hhi
pop r28 ; restore r28
XJMP _U(strrev) ; reverse string
.endfunc
#endif /* not __DOXYGEN__ */