Imported Upstream version 2.9.0
[debian/cc1111] / device / lib / hc08 / _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 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
31 #  if defined(SDCC_mcs51)
32 #    if defined(SDCC_MODEL_SMALL)
33 #      if defined(SDCC_STACK_AUTO)
34 #        define _DIVUINT_ASM_SMALL_AUTO
35 #      else
36 #        define _DIVUINT_ASM_SMALL
37 #      endif
38 #    endif
39 #  endif
40 #endif
41
42 #if defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO
43
44 static void
45 _divuint_dummy (void) _naked
46 {
47   __asm
48
49     .globl __divuint
50
51   __divuint:
52
53     #define count   r2
54     #define reste_l r3
55     #define reste_h r4
56     #define al      dpl
57     #define ah      dph
58
59 #if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1)
60
61     ar0 = 0     ; BUG register set is not considered
62     ar1 = 1
63
64     .globl __divint
65
66     mov a,sp
67     add a,#-2   ; 2 bytes return address
68     mov r0,a    ; r0 points to bh
69     mov ar1,@r0   ; load bh
70     dec r0
71     mov ar0,@r0   ; load bl
72
73     #define bl      r0
74     #define bh      r1
75
76   __divint:     ; entry point for __divsint
77
78
79 #else // SDCC_STACK_AUTO
80
81 #if !defined(SDCC_PARMS_IN_BANK1)
82 #if defined(SDCC_NOOVERLAY)
83     .area DSEG    (DATA)
84 #else
85     .area OSEG    (OVR,DATA)
86 #endif
87
88     .globl __divuint_PARM_2
89     .globl __divsint_PARM_2
90
91   __divuint_PARM_2:
92   __divsint_PARM_2:
93     .ds 2
94
95     .area CSEG    (CODE)
96 #endif // !SDCC_PARMS_IN_BANK1
97 #if defined(SDCC_PARMS_IN_BANK1)
98     #define bl      (b1_0)
99     #define bh      (b1_1)
100 #else
101     #define bl      (__divuint_PARM_2)
102     #define bh      (__divuint_PARM_2 + 1)
103 #endif // SDCC_PARMS_IN_BANK1
104 #endif // SDCC_STACK_AUTO
105
106     mov count,#16
107     clr a
108     mov reste_l,a
109     mov reste_h,a
110
111   loop: mov a,al    ; a <<= 1
112     add a,acc
113     mov al,a
114     mov a,ah
115     rlc a
116     mov ah,a
117
118     mov a,reste_l ; reste <<= 1
119     rlc a   ;   feed in carry
120     mov reste_l,a
121     mov a,reste_h
122     rlc a
123     mov reste_h,a
124
125     mov a,reste_l ; reste - b
126     subb  a,bl    ; here carry is always clear, because
127           ; reste <<= 1 never overflows
128     mov b,a
129     mov a,reste_h
130     subb  a,bh
131
132     jc  smaller   ; reste >= b?
133
134     mov reste_h,a ; -> yes;  reste = reste - b;
135     mov reste_l,b
136     orl al,#1
137   smaller:      ; -> no
138     djnz  count,loop
139     ret
140
141   __endasm ;
142 }
143
144 #else  // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO
145
146 #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
147
148 unsigned int
149 _divuint (unsigned int a, unsigned int b)
150 {
151   unsigned int reste = 0;
152   unsigned char count = 16;
153   char c;
154
155   do
156   {
157     // reste: a <- 0;
158     c = MSB_SET(a);
159     a <<= 1;
160     reste <<= 1;
161     if (c)
162       reste |= 1;
163
164     if (reste >= b)
165     {
166       reste -= b;
167       // a <- (result = 1)
168       a |= 1;
169     }
170   }
171   while (--count);
172   return a;
173 }
174
175 #endif  // defined _DIVUINT_ASM_SMALL || defined _DIVUINT_ASM_SMALL_AUTO