* src/SDCCmain.c (preProcess): added define SDCC_NOOVERLAY
[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)
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     mov dptr,#__muluint_PARM_2
78     movx a,@dptr ; lsb_b
79     mul ab ; lsb_a*lsb_b
80     mov r0,a
81     mov r1,b
82
83     mov b,r2 ; msb_a
84     movx a,@dptr ; lsb_b
85     mul ab ; msb_a*lsb_b
86     add a,r1
87     mov r1,a
88
89     mov b,r3 ; lsb_a
90     inc dptr
91     movx a,@dptr ; msb_b
92     mul ab ; lsb_a*msb_b
93     add a,r1
94
95     mov dph,a
96     mov dpl,r0
97     ret
98   _endasm;
99 }
100
101 int
102 _mulsint (int a, int b)         // obsolete
103 {
104   return _muluint (a, b);
105 }
106
107 #elif defined _MULINT_ASM_SMALL || defined _MULINT_ASM_SMALL_AUTO
108
109 void
110 _mulint_dummy (void) _naked
111 {
112         _asm
113
114         __mulint:
115         __muluint:                              ; obsolete
116         __mulsint:                              ; obsolete
117
118                 .globl __mulint
119                 .globl __muluint                ; obsolete
120                 .globl __mulsint                ; obsolete
121
122 #if !defined(SDCC_STACK_AUTO)
123
124 #if defined(SDCC_NOOVERLAY)
125                 .area DSEG    (DATA)
126 #else
127                 .area OSEG    (OVR,DATA)
128 #endif
129
130         __mulint_PARM_2:
131         __muluint_PARM_2:                       ; obsolete
132         __mulsint_PARM_2:                       ; obsolete
133
134                 .globl __mulint_PARM_2
135                 .globl __muluint_PARM_2         ; obsolete
136                 .globl __mulsint_PARM_2         ; obsolete
137
138                 .ds     2
139
140                 .area CSEG    (CODE)
141
142                 ; globbered registers none
143
144                 mov     a,dpl                   ;  1  al
145                 mov     b,__mulint_PARM_2       ;  2  bl
146                 mul     ab                      ;  4  al * bl
147                 xch     a,dpl                   ;  1  store low-byte of return value, fetch al
148                 push    b                       ;  2
149
150                 mov     b,__mulint_PARM_2 + 1   ;  2  bh
151                 mul     ab                      ;  4  al * bh
152                 pop     b                       ;  2
153                 add     a,b                     ;  1
154                 xch     a,dph                   ;  1  ah -> acc
155
156                 mov     b,__mulint_PARM_2       ;  2  bl
157                 mul     ab                      ;  4  ah * bl
158                 add     a,dph                   ;  1
159                 mov     dph,a                   ;  1
160                 ret                             ;  2
161                                                 ; 30
162
163 #else // SDCC_STACK_AUTO
164
165                 ; globbered registers r0
166
167                 mov     a,#-2                   ;  1  return address 2 bytes
168                 add     a,sp                    ;  1
169                 mov     r0,a                    ;  1  r0 points to bh
170
171                 mov     a,@r0                   ;  1  bh
172                 mov     b,dpl                   ;  2  al
173                 mul     ab                      ;  4  al * bh
174                 push    acc                     ;  2
175
176                 mov     b,dpl                   ;  2  al
177                 dec     r0                      ;  1
178                 mov     a,@r0                   ;  1  bl
179                 mul     ab                      ;  4  al * bl
180
181                 mov     dpl,a                   ;  1  low-byte of return-value
182
183                 pop     acc                     ;  2
184                 add     a,b                     ;  1
185                 xch     a,dph                   ;  1  ah -> acc
186
187                 mov     b,@r0                   ;  2  bl
188                 mul     ab                      ;  4  ah * bl
189                 add     a,dph                   ;  1
190                 mov     dph,a                   ;  1
191
192                 ret
193
194 #endif // SDCC_STACK_AUTO
195
196         _endasm ;
197 }
198
199 #else
200
201 union uu {
202         struct { unsigned char lo,hi ;} s;
203         unsigned int t;
204 } ;
205
206 unsigned int
207 _muluint (unsigned int a, unsigned int b)       // in future: _mulint
208 {
209 #ifdef SDCC_MODEL_LARGE         // still needed for large + stack-auto
210         union uu xdata *x;
211         union uu xdata *y;
212         union uu t;
213         x = (union uu xdata *)&a;
214         y = (union uu xdata *)&b;
215 #else
216         register union uu *x;
217         register union uu *y;
218         union uu t;
219         x = (union uu *)&a;
220         y = (union uu *)&b;
221 #endif
222
223         t.t = x->s.lo * y->s.lo;
224         t.s.hi += (x->s.lo * y->s.hi) + (x->s.hi * y->s.lo);
225
226        return t.t;
227 }
228
229 int
230 _mulsint (int a, int b)         // obsolete
231 {
232   return _muluint (a, b);
233 }
234
235 #endif
236
237 #undef _MULINT_ASM