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