* sdcc/device/lib/Makefile.in: added library sources for mcs51, small,
[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 al      dpl
59                 #define ah      dph
60
61 #if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1)
62
63                 ar0 = 0                 ; BUG register set is not considered
64                 ar1 = 1
65
66                 .globl __divint
67
68                 mov     a,sp
69                 add     a,#-2           ; 2 bytes return address
70                 mov     r0,a            ; r0 points to bh
71                 mov     ar1,@r0         ; load bh
72                 dec     r0
73                 mov     ar0,@r0         ; load bl
74
75                 #define bl      r0
76                 #define bh      r1
77
78         __divint:                       ; entry point for __divsint
79
80
81 #else // SDCC_STACK_AUTO
82
83 #if !defined(SDCC_PARMS_IN_BANK1)
84 #if defined(SDCC_NOOVERLAY)
85                 .area DSEG    (DATA)
86 #else
87                 .area OSEG    (OVR,DATA)
88 #endif
89
90                 .globl __divuint_PARM_2
91                 .globl __divsint_PARM_2
92
93         __divuint_PARM_2:
94         __divsint_PARM_2:
95                 .ds     2
96
97                 .area CSEG    (CODE)
98 #endif // !SDCC_PARMS_IN_BANK1
99 #if defined(SDCC_PARMS_IN_BANK1)
100                 #define bl      (b1_0)
101                 #define bh      (b1_1)
102 #else
103                 #define bl      (__divuint_PARM_2)
104                 #define bh      (__divuint_PARM_2 + 1)
105 #endif // SDCC_PARMS_IN_BANK1
106 #endif // SDCC_STACK_AUTO
107
108                 mov     count,#16
109                 clr     a
110                 mov     reste_l,a
111                 mov     reste_h,a
112
113         loop:   mov     a,al            ; a <<= 1
114                 add     a,acc
115                 mov     al,a
116                 mov     a,ah
117                 rlc     a
118                 mov     ah,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 - b
128                 subb    a,bl            ; here carry is always clear, because
129                                         ; reste <<= 1 never overflows
130                 mov     b,a
131                 mov     a,reste_h
132                 subb    a,bh
133
134                 jc      smaller         ; reste >= b?
135
136                 mov     reste_h,a       ; -> yes;  reste = reste - b;
137                 mov     reste_l,b
138                 orl     al,#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 a, unsigned int b)
152 {
153   unsigned int reste = 0;
154   unsigned char count = 16;
155   BOOL c;
156
157   do
158   {
159     // reste: a <- 0;
160     c = MSB_SET(a);
161     a <<= 1;
162     reste <<= 1;
163     if (c)
164       reste |= 1;
165
166     if (reste >= b)
167     {
168       reste -= b;
169       // a <- (result = 1)
170       a |= 1;
171     }
172   }
173   while (--count);
174   return a;
175 }
176
177 #endif  // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO