Imported Upstream version 2.9.0
[debian/cc1111] / device / lib / _divuint.c
1 /*-------------------------------------------------------------------------
2   _divuint.c :- routine for unsigned int (16 bit) division
3
4              Ecrit par -  Jean-Louis Vern . jlvern@writeme.com (1999)
5
6    This library is free software; you can redistribute it and/or modify it
7    under the terms of the GNU Library General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 /*   Assembler-functions are provided for:
26      mcs51 small
27      mcs51 small stack-auto
28 */
29
30 #include <stdbool.h>
31
32 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
33 #  if defined(SDCC_mcs51)
34 #    if defined(SDCC_MODEL_SMALL)
35 #      if defined(SDCC_STACK_AUTO)
36 #        define _DIVUINT_ASM_SMALL_AUTO
37 #      else
38 #        define _DIVUINT_ASM_SMALL
39 #      endif
40 #    endif
41 #  endif
42 #endif
43
44 #if defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO
45
46 static void
47 _divuint_dummy (void) __naked
48 {
49         __asm
50
51         .globl __divuint
52
53 __divuint:
54
55         #define count   r2
56         #define reste_l r3
57         #define reste_h r4
58         #define xl      dpl
59         #define xh      dph
60
61 #if defined(SDCC_PARMS_IN_BANK1)
62         #define yl      (b1_0)
63         #define yh      (b1_1)
64 #else // SDCC_PARMS_IN_BANK1
65   #if defined(SDCC_STACK_AUTO)
66
67         .globl __divint
68
69         mov     a,sp
70         add     a,#-2           ; 2 bytes return address
71         mov     r0,a            ; r0 points to yh
72         mov     a,@r0           ; load yh
73         mov     r1,a
74         dec     r0
75         mov     a,@r0           ; load yl
76         mov     r0,a
77
78         #define yl      r0
79         #define yh      r1
80
81 __divint:                       ; entry point for __divsint
82
83
84   #else // SDCC_STACK_AUTO
85
86     #if defined(SDCC_NOOVERLAY)
87         .area DSEG    (DATA)
88     #else
89         .area OSEG    (OVR,DATA)
90     #endif
91
92         .globl __divuint_PARM_2
93         .globl __divsint_PARM_2
94
95 __divuint_PARM_2:
96 __divsint_PARM_2:
97         .ds     2
98
99         .area CSEG    (CODE)
100
101         #define yl      (__divuint_PARM_2)
102         #define yh      (__divuint_PARM_2 + 1)
103
104   #endif // SDCC_STACK_AUTO
105 #endif // SDCC_PARMS_IN_BANK1
106
107         mov     count,#16
108         clr     a
109         mov     reste_l,a
110         mov     reste_h,a
111
112 loop:
113         mov     a,xl            ; x <<= 1
114         add     a,acc
115         mov     xl,a
116         mov     a,xh
117         rlc     a
118         mov     xh,a
119
120         mov     a,reste_l       ; reste <<= 1
121         rlc     a               ;   feed in carry
122         mov     reste_l,a
123         mov     a,reste_h
124         rlc     a
125         mov     reste_h,a
126
127         mov     a,reste_l       ; reste - y
128         subb    a,yl            ; here carry is always clear, because
129                                         ; reste <<= 1 never overflows
130         mov     b,a
131         mov     a,reste_h
132         subb    a,yh
133
134         jc      smaller         ; reste >= y?
135
136         mov     reste_h,a       ; -> yes;  reste = reste - y;
137         mov     reste_l,b
138         orl     xl,#1
139 smaller:                        ; -> no
140         djnz    count,loop
141         ret
142
143         __endasm;
144 }
145
146 #else  // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO
147
148 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
149
150 unsigned int
151 _divuint (unsigned int x, unsigned int y)
152 {
153   unsigned int reste = 0;
154   unsigned char count = 16;
155   BOOL c;
156
157   do
158   {
159     // reste: x <- 0;
160     c = MSB_SET(x);
161     x <<= 1;
162     reste <<= 1;
163     if (c)
164       reste |= 1;
165
166     if (reste >= y)
167     {
168       reste -= y;
169       // x <- (result = 1)
170       x |= 1;
171     }
172   }
173   while (--count);
174   return x;
175 }
176
177 #endif  // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO