1/* Copyright (c) 2002  Michael Stumpf  <mistumpf@de.pepperl-fuchs.com>
2   Copyright (c) 2006,2009  Dmitry Xmelkov
3   All rights reserved.
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are met:
7
8   * Redistributions of source code must retain the above copyright
9     notice, this list of conditions and the following disclaimer.
10   * Redistributions in binary form must reproduce the above copyright
11     notice, this list of conditions and the following disclaimer in
12     the documentation and/or other materials provided with the
13     distribution.
14   * Neither the name of the copyright holders nor the names of
15     contributors may be used to endorse or promote products derived
16     from this software without specific prior written permission.
17
18   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28   POSSIBILITY OF SUCH DAMAGE. */
29
30/* $Id: modf.S 2473 2015-04-09 08:10:22Z pitchumani $ */
31
32#if !defined(__AVR_TINY__)
33
34#include "fp32def.h"
35#include "asmdef.h"
36
37/*  double modf (double x, double *iptr);
38
39    The modf() function breaks the argument x into an integral part and a
40    fractional part, each of which has the same sign as x. The integral part
41    is stored in iptr.
42	This implementation skips writing by zero pointer.
43 */
44
45#define	iptr_lo	r20
46
47ENTRY modf
48ENTRY modff
49  ; save iptr
50	X_movw	ZL, iptr_lo
51  ; XH = exponent field
52	X_movw	XL, rA2
53	lsl	XL
54	rol	XH
55  ; B = A
56	X_movw	rB0, rA0
57	X_movw	rB2, rA2
58  ; Is there an integral part?
59	subi	XH, 127		; exp of 1.0
60	brsh	1f
61  ; fabs(x) < 1.0:	*iptr = copysign(0, x),  return x
62	clr	rB0
63	clr	rB1
64	clr	rB2
65	andi	rB3, 0x80
66	rjmp	.L_write
67  ; Is there a fraction part?
681:	subi	XH, 23
69	brsh	4f		; no fraction part
70  ; check fraction:  B >>= 23 - (exp-127)
71	mov	XL, XH		; Now XH is -23..-1
72	clr	r0		; to control, is the fraction zero?
732:	lsr	rB2
74	ror	rB1
75	ror	rB0
76	adc	r0, r1
77	inc	XL
78	brmi	2b
79	tst	r0
80	breq	.L_nfrc		; fraction == 0
81  ; restore and clear fraction:  B <<= 23 - (exp-127)
823:	lsl	rB0
83	rol	rB1
84	rol	rB2
85	inc	XH
86	brmi	3b
87  ; write B
88	rcall	.L_write
89  ; return nonzero fraction:  A - B
90	XJMP	_U(__subsf3)
91  ; exponent too big:  compare with smallest NaN (0x7f800001)
924:	cpi	rA0, 1
93	cpc	rA1, r1
94	ldi	XL, 0x80
95	cpc	rA2, XL
96	sbci	XH, 128 - 23
97	brsh	.L_write	; NaN: write and return as is
98  ; fraction == 0
99.L_nfrc:
100	X_movw	rB0, rA0
101	X_movw	rB2, rA2
102  ; A = 0.0 with sign
103	clr	rA0
104	clr	rA1
105	clr	rA2
106	andi	rA3, 0x80
107.L_write:
108	adiw	ZL, 0		; skip writing with NULL pointer
109	breq	1f
110	st	Z,   rB0
111	std	Z+1, rB1
112	std	Z+2, rB2
113	std	Z+3, rB3
1141:	ret
115ENDFUNC
116
117#endif /* !defined(__AVR_TINY__) */
118