?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*-------------------------------------------------------------------------
  2.    _mulint.c - routine for (unsigned) int (16 bit) multiplication
  3.  
  4.    Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
  5.  
  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.
  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 General Public License for more details.
  15.  
  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.
  20.  
  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. -------------------------------------------------------------------------*/
  28.  
  29. /* Signed and unsigned multiplication are the same - as long as the output
  30.    has the same precision as the input.
  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. #if defined(_MULINT_ASM_LARGE)
  60.  
  61. #pragma save
  62. #pragma less_pedantic
  63. int
  64. _mulint (int a, int b)
  65. {
  66.   a*b; // hush the compiler
  67.  
  68.   /* mulint=
  69.       (int)(lsb_a*lsb_b) +
  70.       (char)(msb_a*lsb_b)<<8 +
  71.       (char)(lsb_a*msb_b)<<8
  72.   */
  73.  
  74.   __asm
  75.     mov r2,dph ; msb_a
  76.     mov r3,dpl ; lsb_a
  77.  
  78.     mov b,r3 ; lsb_a
  79. #if defined(__SDCC_PARMS_IN_BANK1)
  80.     mov a,b1_0
  81. #else
  82.     mov dptr,#__mulint_PARM_2
  83.     movx a,@dptr ; lsb_b
  84. #endif
  85.     mul ab ; lsb_a*lsb_b
  86.     mov r0,a
  87.     mov r1,b
  88.  
  89.     mov b,r2 ; msb_a
  90. #if defined(__SDCC_PARMS_IN_BANK1)
  91.     mov a,b1_0
  92. #else
  93.     movx a,@dptr ; lsb_b
  94. #endif
  95.     mul ab ; msb_a*lsb_b
  96.     add a,r1
  97.     mov r1,a
  98.  
  99.     mov b,r3 ; lsb_a
  100. #if defined(__SDCC_PARMS_IN_BANK1)
  101.     mov a,b1_1
  102. #else
  103.     inc dptr
  104.     movx a,@dptr ; msb_b
  105. #endif
  106.     mul ab ; lsb_a*msb_b
  107.     add a,r1
  108.  
  109.     mov dph,a
  110.     mov dpl,r0
  111.     ret
  112.   __endasm;
  113. }
  114. #pragma restore
  115.  
  116. #elif defined(_MULINT_ASM_SMALL) || defined(_MULINT_ASM_SMALL_AUTO)
  117.  
  118. #pragma save
  119. #pragma less_pedantic
  120. int
  121. _mulint_dummy (void) __naked
  122. {
  123.         __asm
  124.  
  125. __mulint:
  126.  
  127.         .globl __mulint
  128.  
  129. #if !defined(__SDCC_STACK_AUTO) || defined(__SDCC_PARMS_IN_BANK1)
  130.  
  131. #if defined(__SDCC_NOOVERLAY)
  132.         .area DSEG    (DATA)
  133. #else
  134.         .area OSEG    (OVR,DATA)
  135. #endif
  136. #if defined(__SDCC_PARMS_IN_BANK1)
  137.         #define bl      (b1_0)
  138.         #define bh      (b1_1)
  139. #else
  140.         #define bl      (__mulint_PARM_2)
  141.         #define bh      (__mulint_PARM_2 + 1)
  142. __mulint_PARM_2:
  143.  
  144.         .globl __mulint_PARM_2
  145.  
  146.         .ds     2
  147. #endif
  148.  
  149.         .area CSEG    (CODE)
  150.  
  151.         ; globbered registers none
  152.  
  153.         mov     a,dpl                   ;  1  al
  154.         mov     b,bl                    ;  2  bl
  155.         mul     ab                      ;  4  al * bl
  156.         xch     a,dpl                   ;  1  store low-byte of return value, fetch al
  157.         push    b                       ;  2
  158.  
  159.         mov     b,bh                    ;  2  bh
  160.         mul     ab                      ;  4  al * bh
  161.         pop     b                       ;  2
  162.         add     a,b                     ;  1
  163.         xch     a,dph                   ;  1  ah -> acc
  164.  
  165.         mov     b,bl                    ;  2  bl
  166.         mul     ab                      ;  4  ah * bl
  167.         add     a,dph                   ;  1
  168.         mov     dph,a                   ;  1
  169.         ret                             ;  2
  170.                                         ; 30
  171.  
  172. #else // __SDCC_STACK_AUTO
  173.  
  174.         ; globbered registers r0
  175.  
  176.         mov     a,#-2                   ;  1  return address 2 bytes
  177.         add     a,sp                    ;  1
  178.         mov     r0,a                    ;  1  r0 points to bh
  179.  
  180.         mov     a,@r0                   ;  1  bh
  181.         mov     b,dpl                   ;  2  al
  182.         mul     ab                      ;  4  al * bh
  183.         push    acc                     ;  2
  184.  
  185.         mov     b,dpl                   ;  2  al
  186.         dec     r0                      ;  1
  187.         mov     a,@r0                   ;  1  bl
  188.         mul     ab                      ;  4  al * bl
  189.  
  190.         mov     dpl,a                   ;  1  low-byte of return-value
  191.  
  192.         pop     acc                     ;  2
  193.         add     a,b                     ;  1
  194.         xch     a,dph                   ;  1  ah -> acc
  195.  
  196.         mov     b,@r0                   ;  2  bl
  197.         mul     ab                      ;  4  ah * bl
  198.         add     a,dph                   ;  1
  199.         mov     dph,a                   ;  1
  200.  
  201.         ret
  202.  
  203. #endif // __SDCC_STACK_AUTO
  204.  
  205.         __endasm;
  206. }
  207. #pragma restore
  208.  
  209. #else
  210.  
  211. #if defined(__SDCC_hc08) || defined(__SDCC_s08) || defined(__SDCC_stm8)
  212. // Big-endian
  213. union uu {
  214.         struct { unsigned char hi, lo ;} s;
  215.         unsigned int t;
  216. };
  217. #else
  218. // Little-endian
  219. union uu {
  220.         struct { unsigned char lo,hi ;} s;
  221.         unsigned int t;
  222. };
  223. #endif
  224.  
  225. int
  226. _mulint (int a, int b)
  227. {
  228. #if !defined(__SDCC_STACK_AUTO) && (defined(__SDCC_MODEL_LARGE) || defined(__SDCC_ds390))       // still needed for large
  229.         union uu __xdata *x;
  230.         union uu __xdata *y;
  231.         union uu t;
  232.         x = (union uu __xdata *)&a;
  233.         y = (union uu __xdata *)&b;
  234. #else
  235.         register union uu *x;
  236.         register union uu *y;
  237.         union uu t;
  238.         x = (union uu *)&a;
  239.         y = (union uu *)&b;
  240. #endif
  241.  
  242.   // sdcc is bad at handling union accesses. So we use (unsigned char)a instead of x->s.lo here.
  243.   t.t = (unsigned char)a * (unsigned char)b;
  244.   t.s.hi += ((unsigned char)a * y->s.hi) + (x->s.hi * (unsigned char)b);
  245.  
  246.   return t.t;
  247. }
  248.  
  249. #endif
  250.  
  251. #undef _MULINT_ASM
  252.