* device/lib/pic/Makefile.in, device/lib/pic/Makefile.subdir,
[fw/sdcc] / 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:   mov     a,xl            ; x <<= 1
113                 add     a,acc
114                 mov     xl,a
115                 mov     a,xh
116                 rlc     a
117                 mov     xh,a
118
119                 mov     a,reste_l       ; reste <<= 1
120                 rlc     a               ;   feed in carry
121                 mov     reste_l,a
122                 mov     a,reste_h
123                 rlc     a
124                 mov     reste_h,a
125
126                 mov     a,reste_l       ; reste - y
127                 subb    a,yl            ; here carry is always clear, because
128                                         ; reste <<= 1 never overflows
129                 mov     b,a
130                 mov     a,reste_h
131                 subb    a,yh
132
133                 jc      smaller         ; reste >= y?
134
135                 mov     reste_h,a       ; -> yes;  reste = reste - y;
136                 mov     reste_l,b
137                 orl     xl,#1
138         smaller:                        ; -> no
139                 djnz    count,loop
140                 ret
141
142         _endasm ;
143 }
144
145 #else  // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO
146
147 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
148
149 unsigned int
150 _divuint (unsigned int x, unsigned int y)
151 {
152   unsigned int reste = 0;
153   unsigned char count = 16;
154   BOOL c;
155
156   do
157   {
158     // reste: x <- 0;
159     c = MSB_SET(x);
160     x <<= 1;
161     reste <<= 1;
162     if (c)
163       reste |= 1;
164
165     if (reste >= y)
166     {
167       reste -= y;
168       // x <- (result = 1)
169       x |= 1;
170     }
171   }
172   while (--count);
173   return x;
174 }
175
176 #endif  // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO