struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / device / lib / _mulint.c
blob2a8ea6dcc0351275b96769b1f0bbdb8fa9d289fb
1 /*-------------------------------------------------------------------------
2 _mulint.c - routine for (unsigned) int (16 bit) multiplication
4 Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
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 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this library; see the file COPYING. If not, write to the
18 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19 MA 02110-1301, USA.
21 As a special exception, if you link this library with other files,
22 some of which are compiled with SDCC, to produce an executable,
23 this library does not by itself cause the resulting executable to
24 be covered by the GNU General Public License. This exception does
25 not however invalidate any other reasons why the executable file
26 might be covered by the GNU General Public License.
27 -------------------------------------------------------------------------*/
29 /* Signed and unsigned multiplication are the same - as long as the output
30 has the same precision as the input.
32 Assembler-functions are provided for:
33 ds390
34 mcs51 small
35 mcs51 small stack-auto
36 mcs51 large
39 #include <sdcc-lib.h>
41 #if !defined(__SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
42 # if defined(__SDCC_ds390)
43 # if !defined(__SDCC_STACK_AUTO)
44 # define _MULINT_ASM_LARGE
45 # endif
46 # elif defined(__SDCC_mcs51)
47 # if defined(__SDCC_MODEL_SMALL)
48 # if defined(__SDCC_STACK_AUTO) && !defined(__SDCC_PARMS_IN_BANK1)
49 # define _MULINT_ASM_SMALL_AUTO
50 # else
51 # define _MULINT_ASM_SMALL
52 # endif
53 # else // must be __SDCC_MODEL_LARGE
54 # if !defined(__SDCC_STACK_AUTO)
55 # define _MULINT_ASM_LARGE
56 # endif
57 # endif
58 # endif
59 #endif
61 #if defined(_MULINT_ASM_LARGE)
63 #pragma save
64 #pragma less_pedantic
65 int
66 _mulint (int a, int b) __SDCC_NONBANKED
68 a*b; // hush the compiler
70 /* mulint=
71 (int)(lsb_a*lsb_b) +
72 (char)(msb_a*lsb_b)<<8 +
73 (char)(lsb_a*msb_b)<<8
76 __asm
77 mov r2,dph ; msb_a
78 mov r3,dpl ; lsb_a
80 mov b,r3 ; lsb_a
81 #if defined(__SDCC_PARMS_IN_BANK1)
82 mov a,b1_0
83 #else
84 mov dptr,#__mulint_PARM_2
85 movx a,@dptr ; lsb_b
86 #endif
87 mul ab ; lsb_a*lsb_b
88 mov r0,a
89 mov r1,b
91 mov b,r2 ; msb_a
92 #if defined(__SDCC_PARMS_IN_BANK1)
93 mov a,b1_0
94 #else
95 movx a,@dptr ; lsb_b
96 #endif
97 mul ab ; msb_a*lsb_b
98 add a,r1
99 mov r1,a
101 mov b,r3 ; lsb_a
102 #if defined(__SDCC_PARMS_IN_BANK1)
103 mov a,b1_1
104 #else
105 inc dptr
106 movx a,@dptr ; msb_b
107 #endif
108 mul ab ; lsb_a*msb_b
109 add a,r1
111 mov dph,a
112 mov dpl,r0
114 __endasm;
116 #pragma restore
118 #elif defined(_MULINT_ASM_SMALL) || defined(_MULINT_ASM_SMALL_AUTO)
120 #pragma save
121 #pragma less_pedantic
123 _mulint_dummy (void) __naked
125 __asm
127 __mulint:
129 .globl __mulint
131 #if !defined(__SDCC_STACK_AUTO) || defined(__SDCC_PARMS_IN_BANK1)
133 #if defined(__SDCC_NOOVERLAY)
134 .area DSEG (DATA)
135 #else
136 .area OSEG (OVR,DATA)
137 #endif
138 #if defined(__SDCC_PARMS_IN_BANK1)
139 #define bl (b1_0)
140 #define bh (b1_1)
141 #else
142 #define bl (__mulint_PARM_2)
143 #define bh (__mulint_PARM_2 + 1)
144 __mulint_PARM_2:
146 .globl __mulint_PARM_2
148 .ds 2
149 #endif
151 .area CSEG (CODE)
153 ; globbered registers none
155 mov a,dpl ; 1 al
156 mov b,bl ; 2 bl
157 mul ab ; 4 al * bl
158 xch a,dpl ; 1 store low-byte of return value, fetch al
159 push b ; 2
161 mov b,bh ; 2 bh
162 mul ab ; 4 al * bh
163 pop b ; 2
164 add a,b ; 1
165 xch a,dph ; 1 ah -> acc
167 mov b,bl ; 2 bl
168 mul ab ; 4 ah * bl
169 add a,dph ; 1
170 mov dph,a ; 1
171 ret ; 2
172 ; 30
174 #else // __SDCC_STACK_AUTO
176 ; globbered registers r0
178 mov a,#-2 ; 1 return address 2 bytes
179 add a,sp ; 1
180 mov r0,a ; 1 r0 points to bh
182 mov a,@r0 ; 1 bh
183 mov b,dpl ; 2 al
184 mul ab ; 4 al * bh
185 push acc ; 2
187 mov b,dpl ; 2 al
188 dec r0 ; 1
189 mov a,@r0 ; 1 bl
190 mul ab ; 4 al * bl
192 mov dpl,a ; 1 low-byte of return-value
194 pop acc ; 2
195 add a,b ; 1
196 xch a,dph ; 1 ah -> acc
198 mov b,@r0 ; 2 bl
199 mul ab ; 4 ah * bl
200 add a,dph ; 1
201 mov dph,a ; 1
205 #endif // __SDCC_STACK_AUTO
207 __endasm;
209 #pragma restore
211 #else
213 #include <stdbit.h>
215 #if __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__
216 union uu {
217 struct { unsigned char hi, lo ;} s;
218 unsigned int t;
220 #else
221 union uu {
222 struct { unsigned char lo,hi ;} s;
223 unsigned int t;
225 #endif
228 _mulint (int a, int b) __SDCC_NONBANKED
230 #if !defined(__SDCC_STACK_AUTO) && (defined(__SDCC_MODEL_LARGE) || defined(__SDCC_ds390)) // still needed for large
231 union uu __xdata *x;
232 union uu __xdata *y;
233 union uu t;
234 x = (union uu __xdata *)&a;
235 y = (union uu __xdata *)&b;
236 #else
237 register union uu *x;
238 register union uu *y;
239 union uu t;
240 x = (union uu *)&a;
241 y = (union uu *)&b;
242 #endif
244 // sdcc is bad at handling union accesses. So we use (unsigned char)a instead of x->s.lo here.
245 t.t = (unsigned char)a * (unsigned char)b;
246 t.s.hi += ((unsigned char)a * y->s.hi) + (x->s.hi * (unsigned char)b);
248 return t.t;
251 #endif
253 #undef _MULINT_ASM