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
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,
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:
35 mcs51 small stack-auto
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
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
51 # define _MULINT_ASM_SMALL
53 # else // must be __SDCC_MODEL_LARGE
54 # if !defined(__SDCC_STACK_AUTO)
55 # define _MULINT_ASM_LARGE
61 #if defined(_MULINT_ASM_LARGE)
66 _mulint (int a
, int b
) __SDCC_NONBANKED
68 a
*b
; // hush the compiler
72 (char)(msb_a*lsb_b)<<8 +
73 (char)(lsb_a*msb_b)<<8
81 #if defined(__SDCC_PARMS_IN_BANK1)
84 mov dptr
,#__mulint_PARM_2
92 #if defined(__SDCC_PARMS_IN_BANK1)
102 #if defined(__SDCC_PARMS_IN_BANK1)
118 #elif defined(_MULINT_ASM_SMALL) || defined(_MULINT_ASM_SMALL_AUTO)
121 #pragma less_pedantic
123 _mulint_dummy (void) __naked
131 #if !defined(__SDCC_STACK_AUTO) || defined(__SDCC_PARMS_IN_BANK1)
133 #if defined(__SDCC_NOOVERLAY)
136 .area
OSEG (OVR
,DATA
)
138 #if defined(__SDCC_PARMS_IN_BANK1)
142 #define bl (__mulint_PARM_2)
143 #define bh (__mulint_PARM_2 + 1)
146 .globl __mulint_PARM_2
153 ; globbered registers none
158 xch a
,dpl
; 1 store low
-byte of
return value
, fetch al
165 xch a
,dph
; 1 ah
-> acc
174 #else // __SDCC_STACK_AUTO
176 ; globbered registers r0
178 mov a
,#-2 ; 1 return address 2 bytes
180 mov r0
,a
; 1 r0 points to bh
192 mov dpl
,a
; 1 low
-byte of
return-value
196 xch a
,dph
; 1 ah
-> acc
205 #endif // __SDCC_STACK_AUTO
215 #if __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__
217 struct { unsigned char hi
, lo
;} s
;
222 struct { unsigned char lo
,hi
;} s
;
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
234 x
= (union uu __xdata
*)&a
;
235 y
= (union uu __xdata
*)&b
;
237 register union uu
*x
;
238 register union uu
*y
;
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
);