?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. /*-------------------------------------------------------------------------
  2.    _moduint.c - routine for unsigned int (16 bit) modulus
  3.  
  4.    Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
  5.    Bug fixes by Martijn van Balen, aed@iae.nl
  6.  
  7.    This library is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by the
  9.    Free Software Foundation; either version 2, or (at your option) any
  10.    later version.
  11.  
  12.    This library is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this library; see the file COPYING. If not, write to the
  19.    Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
  20.    MA 02110-1301, USA.
  21.  
  22.    As a special exception, if you link this library with other files,
  23.    some of which are compiled with SDCC, to produce an executable,
  24.    this library does not by itself cause the resulting executable to
  25.    be covered by the GNU General Public License. This exception does
  26.    not however invalidate any other reasons why the executable file
  27.    might be covered by the GNU General Public License.
  28. -------------------------------------------------------------------------*/
  29.  
  30. /*   Assembler-functions are provided for:
  31.      mcs51 small
  32.      mcs51 small stack-auto
  33. */
  34.  
  35. #if !defined(__SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
  36. #  if defined(__SDCC_mcs51)
  37. #    if defined(__SDCC_MODEL_SMALL)
  38. #      if defined(__SDCC_STACK_AUTO)
  39. #        define _MODUINT_ASM_SMALL_AUTO
  40. #      else
  41. #        define _MODUINT_ASM_SMALL
  42. #      endif
  43. #    endif
  44. #  endif
  45. #endif
  46.  
  47. #if defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
  48.  
  49. static void
  50. _moduint_dummy (void) __naked
  51. {
  52.         __asm
  53.  
  54.         .globl __moduint
  55.  
  56. __moduint:
  57.  
  58.         #define count   r2
  59.         #define al      dpl
  60.         #define ah      dph
  61.  
  62. #if defined(__SDCC_STACK_AUTO) && !defined(__SDCC_PARMS_IN_BANK1)
  63.  
  64.         ar0 = 0                 ; BUG register set is not considered
  65.         ar1 = 1
  66.  
  67.         .globl __modint
  68.  
  69.         mov     a,sp
  70.         add     a,#-2           ; 2 bytes return address
  71.         mov     r0,a            ; r0 points to bh
  72.         mov     ar1,@r0         ; load bh
  73.         dec     r0
  74.         mov     ar0,@r0         ; load bl
  75.  
  76.         #define bl      r0
  77.         #define bh      r1
  78.  
  79. __modint:                       ; entry point for __modsint
  80.  
  81.  
  82. #else // __SDCC_STACK_AUTO
  83.  
  84. #if !defined(__SDCC_PARMS_IN_BANK1)
  85. #if defined(__SDCC_NOOVERLAY)
  86.         .area DSEG    (DATA)
  87. #else
  88.         .area OSEG    (OVR,DATA)
  89. #endif
  90.  
  91.         .globl __moduint_PARM_2
  92.         .globl __modsint_PARM_2
  93.  
  94. __moduint_PARM_2:
  95. __modsint_PARM_2:
  96.         .ds     2
  97.  
  98.         .area CSEG    (CODE)
  99.  
  100.         #define bl      (__moduint_PARM_2)
  101.         #define bh      (__moduint_PARM_2 + 1)
  102. #else
  103.         #define bl      (b1_0)
  104.         #define bh      (b1_1)
  105. #endif
  106. #endif // __SDCC_STACK_AUTO
  107.  
  108.         mov     a,bl            ; avoid endless loop
  109.         orl     a,bh
  110.         jz      div_by_0
  111.  
  112.         mov     count,#1
  113.  
  114. loop1:  mov     a,bl            ; b <<= 1
  115.         add     a,acc
  116.         mov     bl,a
  117.         mov     a,bh
  118.         rlc     a
  119.         jc      msbset
  120.         mov     bh,a
  121.  
  122.         mov     a,al            ; a - b
  123.         subb    a,bl            ; here carry is always clear
  124.         mov     a,ah
  125.         subb    a,bh
  126.  
  127.         jc      start
  128.  
  129.         inc     count
  130.         sjmp    loop1
  131.  
  132. start:  clr     c
  133.         mov     a,bh            ; b >>= 1;
  134. msbset: rrc     a
  135.         mov     bh,a
  136.         mov     a,bl
  137.         rrc     a
  138.         mov     bl,a
  139.  
  140. loop2:  clr     c
  141.         mov     a,al            ; a - b
  142.         subb    a,bl
  143.  
  144.         mov     b,a
  145.         mov     a,ah
  146.         subb    a,bh
  147.  
  148.         jc      smaller         ; a >= b?
  149.  
  150.         mov     ah,a            ; -> yes;  a = a - b;
  151.         mov     al,b
  152. smaller:                        ; -> no
  153.         clr     c
  154.         mov     a,bh            ; b >>= 1;
  155.         rrc     a
  156.         mov     bh,a
  157.         mov     a,bl
  158.         rrc     a
  159.         mov     bl,a
  160.  
  161.         djnz    count,loop2
  162. div_by_0:
  163.         ret
  164.  
  165.         __endasm;
  166. }
  167.  
  168. #else  // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
  169.  
  170. #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
  171.  
  172. unsigned int
  173. _moduint (unsigned int a, unsigned int b)
  174. {
  175.   unsigned char count = 0;
  176.  
  177.   while (!MSB_SET(b))
  178.   {
  179.     b <<= 1;
  180.     if (b > a)
  181.     {
  182.       b >>=1;
  183.       break;
  184.     }
  185.     count++;
  186.   }
  187.   do
  188.   {
  189.     if (a >= b)
  190.       a -= b;
  191.     b >>= 1;
  192.   }
  193.   while (count--);
  194.   return a;
  195. }
  196.  
  197. #endif  // defined _MODUINT_ASM_SMALL || defined _MODUINT_ASM_SMALL_AUTO
  198.