added functions _ltoa _uitoa
[fw/sdcc] / device / lib / _mulint.c
1 /*-------------------------------------------------------------------------
2   _mulint.c :- routine for (unsigned) int (16 bit) multiplication
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (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 /* Signed and unsigned multiplication are the same - as long as the output
26    has the same precision as the input.
27
28    To do: _muluint and _mulsint should be replaced by _mulint.
29
30    bernhard@bernhardheld.de
31
32    Assembler-functions are provided for:
33      ds390
34      mcs51 small
35      mcs51 small stack-auto
36      mcs51 large
37 */
38
39 #if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
40 #  if defined(SDCC_ds390)
41 #    if !defined(SDCC_STACK_AUTO)
42 #      define _MULINT_ASM_LARGE
43 #    endif
44 #  elif defined(SDCC_mcs51)
45 #    if defined(SDCC_MODEL_SMALL)
46 #      if defined(SDCC_STACK_AUTO) && !defined(SDCC_PARMS_IN_BANK1)
47 #        define _MULINT_ASM_SMALL_AUTO
48 #      else
49 #        define _MULINT_ASM_SMALL
50 #      endif
51 #    else // must be SDCC_MODEL_LARGE
52 #      if !defined(SDCC_STACK_AUTO)
53 #        define _MULINT_ASM_LARGE
54 #     endif
55 #   endif
56 #  endif
57 #endif
58
59 #ifdef _MULINT_ASM_LARGE
60
61 unsigned int
62 _muluint (unsigned int a, unsigned int b)       // in future: _mulint
63 {
64   a*b; // hush the compiler
65
66   /* mulint=
67       (int)(lsb_a*lsb_b) +
68       (char)(msb_a*lsb_b)<<8 +
69       (char)(lsb_a*msb_b)<<8
70   */
71
72   _asm
73     mov r2,dph ; msb_a
74     mov r3,dpl ; lsb_a
75
76     mov b,r3 ; lsb_a
77 #if defined(SDCC_PARMS_IN_BANK1)
78     mov a,b1_0
79 #else
80     mov dptr,#__muluint_PARM_2
81     movx a,@dptr ; lsb_b
82 #endif
83     mul ab ; lsb_a*lsb_b
84     mov r0,a
85     mov r1,b
86
87     mov b,r2 ; msb_a
88 #if defined(SDCC_PARMS_IN_BANK1)
89     mov a,b1_0
90 #else
91     movx a,@dptr ; lsb_b
92 #endif
93     mul ab ; msb_a*lsb_b
94     add a,r1
95     mov r1,a
96
97     mov b,r3 ; lsb_a
98 #if defined(SDCC_PARMS_IN_BANK1)
99     mov a,b1_1
100 #else
101     inc dptr
102     movx a,@dptr ; msb_b
103 #endif
104     mul ab ; lsb_a*msb_b
105     add a,r1
106
107     mov dph,a
108     mov dpl,r0
109     ret
110   _endasm;
111 }
112
113 int
114 _mulsint (int a, int b)         // obsolete
115 {
116   return _muluint (a, b);
117 }
118
119 #elif defined _MULINT_ASM_SMALL || defined _MULINT_ASM_SMALL_AUTO
120
121 void
122 _mulint_dummy (void) _naked
123 {
124         _asm
125
126         __mulint:
127         __muluint:                              ; obsolete
128         __mulsint:                              ; obsolete
129
130                 .globl __mulint
131                 .globl __muluint                ; obsolete
132                 .globl __mulsint                ; obsolete
133
134 #if !defined(SDCC_STACK_AUTO) || defined(SDCC_PARMS_IN_BANK1)
135
136 #if defined(SDCC_NOOVERLAY)
137                 .area DSEG    (DATA)
138 #else
139                 .area OSEG    (OVR,DATA)
140 #endif
141 #if defined(SDCC_PARMS_IN_BANK1)
142         #define bl      (b1_0)   
143         #define bh      (b1_1)   
144 #else
145         #define bl      (__mulint_PARM_2)        
146         #define bh      (__mulint_PARM_2 + 1)    
147         __mulint_PARM_2:
148         __muluint_PARM_2:                       ; obsolete
149         __mulsint_PARM_2:                       ; obsolete
150
151                 .globl __mulint_PARM_2
152                 .globl __muluint_PARM_2         ; obsolete
153                 .globl __mulsint_PARM_2         ; obsolete
154
155                 .ds     2
156 #endif                                               
157
158                 .area CSEG    (CODE)
159
160                 ; globbered registers none
161
162                 mov     a,dpl                   ;  1  al
163                 mov     b,bl                    ;  2  bl
164                 mul     ab                      ;  4  al * bl
165                 xch     a,dpl                   ;  1  store low-byte of return value, fetch al
166                 push    b                       ;  2
167
168                 mov     b,bh                    ;  2  bh
169                 mul     ab                      ;  4  al * bh
170                 pop     b                       ;  2
171                 add     a,b                     ;  1
172                 xch     a,dph                   ;  1  ah -> acc
173
174                 mov     b,bl                    ;  2  bl
175                 mul     ab                      ;  4  ah * bl
176                 add     a,dph                   ;  1
177                 mov     dph,a                   ;  1
178                 ret                             ;  2
179                                                 ; 30
180
181 #else // SDCC_STACK_AUTO
182
183                 ; globbered registers r0
184
185                 mov     a,#-2                   ;  1  return address 2 bytes
186                 add     a,sp                    ;  1
187                 mov     r0,a                    ;  1  r0 points to bh
188
189                 mov     a,@r0                   ;  1  bh
190                 mov     b,dpl                   ;  2  al
191                 mul     ab                      ;  4  al * bh
192                 push    acc                     ;  2
193
194                 mov     b,dpl                   ;  2  al
195                 dec     r0                      ;  1
196                 mov     a,@r0                   ;  1  bl
197                 mul     ab                      ;  4  al * bl
198
199                 mov     dpl,a                   ;  1  low-byte of return-value
200
201                 pop     acc                     ;  2
202                 add     a,b                     ;  1
203                 xch     a,dph                   ;  1  ah -> acc
204
205                 mov     b,@r0                   ;  2  bl
206                 mul     ab                      ;  4  ah * bl
207                 add     a,dph                   ;  1
208                 mov     dph,a                   ;  1
209
210                 ret
211
212 #endif // SDCC_STACK_AUTO
213
214         _endasm ;
215 }
216
217 #else
218
219 union uu {
220         struct { unsigned char lo,hi ;} s;
221         unsigned int t;
222 } ;
223
224 unsigned int
225 _muluint (unsigned int a, unsigned int b)       // in future: _mulint
226 {
227 #if defined(SDCC_MODEL_LARGE) || defined(SDCC_ds390)            // still needed for large + stack-auto
228         union uu xdata *x;
229         union uu xdata *y;
230         union uu t;
231         x = (union uu xdata *)&a;
232         y = (union uu xdata *)&b;
233 #else
234         register union uu *x;
235         register union uu *y;
236         union uu t;
237         x = (union uu *)&a;
238         y = (union uu *)&b;
239 #endif
240
241         t.t = x->s.lo * y->s.lo;
242         t.s.hi += (x->s.lo * y->s.hi) + (x->s.hi * y->s.lo);
243
244        return t.t;
245 }
246
247 int
248 _mulsint (int a, int b)         // obsolete
249 {
250   return _muluint (a, b);
251 }
252
253 #endif
254
255 #undef _MULINT_ASM