?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. /*-------------------------------------------------------------------------
  2.    _modulong.c - routine for modulus of 32 bit unsigned long
  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) && !defined (__SDCC_PARMS_IN_BANK1)
  39. #        define _MODULONG_ASM_SMALL_AUTO
  40. #      else
  41. #        define _MODULONG_ASM_SMALL
  42. #      endif
  43. #    endif
  44. #  endif
  45. #endif
  46.  
  47. #if defined _MODULONG_ASM_SMALL
  48.  
  49. static void
  50. _modlong_dummy (void) __naked
  51. {
  52.         __asm
  53.  
  54.         .globl __modulong
  55.  
  56.         #define a0      dpl
  57.         #define a1      dph
  58.         #define a2      b
  59.         #define a3      r1
  60.         #define count   r0
  61.  
  62. __modulong:
  63. #if defined(__SDCC_PARMS_IN_BANK1)
  64.         #define b0      (b1_0)
  65.         #define b1      (b1_1)
  66.         #define b2      (b1_2)
  67.         #define b3      (b1_3)
  68. #else
  69. #if defined(__SDCC_NOOVERLAY)
  70.         .area DSEG    (DATA)
  71. #else
  72.         .area OSEG    (OVR,DATA)
  73. #endif
  74.  
  75.         .globl __modulong_PARM_2
  76.         .globl __modslong_PARM_2
  77.  
  78. __modulong_PARM_2:
  79. __modslong_PARM_2:
  80.         .ds     4
  81.  
  82.         .area CSEG    (CODE)
  83.  
  84.         #define b0      (__modulong_PARM_2)
  85.         #define b1      (__modulong_PARM_2 + 1)
  86.         #define b2      (__modulong_PARM_2 + 2)
  87.         #define b3      (__modulong_PARM_2 + 3)
  88. #endif
  89.                                 ; parameter a comes in a, b, dph, dpl
  90.         mov     a3,a            ; save parameter a3
  91.  
  92.         mov     a,b0            ; b == 0? avoid endless loop
  93.         orl     a,b1
  94.         orl     a,b2
  95.         orl     a,b3
  96.         jz      div_by_0
  97.  
  98.         mov     count,#0
  99.         clr     c               ; when loop1 jumps immediately to loop2
  100.  
  101. loop1:  inc     count
  102.  
  103.         mov     a,b3            ; if (!MSB_SET(b))
  104.         jb      acc.7,loop2
  105.  
  106.         mov     a,b0            ; b <<= 1
  107.         add     a,acc
  108.         mov     b0,a
  109.         mov     a,b1
  110.         rlc     a
  111.         mov     b1,a
  112.         mov     a,b2
  113.         rlc     a
  114.         mov     b2,a
  115.         mov     a,b3
  116.         rlc     a
  117.         mov     b3,a
  118.  
  119.         mov     a,a0            ; a - b
  120.         subb    a,b0            ; here carry is always clear
  121.         mov     a,a1
  122.         subb    a,b1
  123.         mov     a,a2
  124.         subb    a,b2
  125.         mov     a,a3
  126.         subb    a,b3
  127.  
  128.         jnc     loop1
  129.  
  130.  
  131.         clr     c
  132.         mov     a,b3            ; b >>= 1;
  133.         rrc     a
  134.         mov     b3,a
  135.         mov     a,b2
  136.         rrc     a
  137.         mov     b2,a
  138.         mov     a,b1
  139.         rrc     a
  140.         mov     b1,a
  141.         mov     a,b0
  142.         rrc     a
  143.         mov     b0,a
  144.  
  145. loop2:  ; clr   c                 never set
  146.         mov     a,a0            ; a - b
  147.         subb    a,b0
  148.         mov     r4,a
  149.         mov     a,a1
  150.         subb    a,b1
  151.         mov     r5,a
  152.         mov     a,a2
  153.         subb    a,b2
  154.         mov     r6,a
  155.         mov     a,a3
  156.         subb    a,b3
  157.  
  158.         jc      smaller         ; a >= b?
  159.  
  160.         mov     a3,a            ; -> yes;  a = a - b;
  161.         mov     a2,r6
  162.         mov     a1,r5
  163.         mov     a0,r4
  164. smaller:                        ; -> no
  165.         clr     c
  166.         mov     a,b3            ; b >>= 1;
  167.         rrc     a
  168.         mov     b3,a
  169.         mov     a,b2
  170.         rrc     a
  171.         mov     b2,a
  172.         mov     a,b1
  173.         rrc     a
  174.         mov     b1,a
  175.         mov     a,b0
  176.         rrc     a
  177.         mov     b0,a
  178.  
  179.         djnz    count,loop2
  180.  
  181.         mov     a,a3            ; prepare the return value
  182. div_by_0:
  183.         ret
  184.  
  185.         __endasm;
  186. }
  187.  
  188. #elif defined _MODULONG_ASM_SMALL_AUTO
  189.  
  190. static void
  191. _modlong_dummy (void) __naked
  192. {
  193.         __asm
  194.  
  195.         .globl __modulong
  196.  
  197. __modulong:
  198.  
  199.         #define count   r0
  200.  
  201.         #define a0      dpl
  202.         #define a1      dph
  203.         #define a2      b
  204.         #define a3      r1
  205.  
  206.         #define b0      r2
  207.         #define b1      r3
  208.         #define b2      r4
  209.         #define b3      r5
  210.  
  211.         ar2 = 2                 ; BUG register set is not considered
  212.         ar3 = 3
  213.         ar4 = 4
  214.         ar5 = 5
  215.  
  216.         .globl __modlong        ; entry point for __modslong
  217.  
  218.                                 ; parameter a comes in a, b, dph, dpl
  219.         mov     a3,a            ; save parameter a3
  220.  
  221.         mov     a,sp
  222.         add     a,#-2-3         ; 2 bytes return address, 3 bytes param b
  223.         mov     r0,a            ; r1 points to b0
  224.  
  225.         mov     ar2,@r0         ; load b0
  226.         inc     r0              ; r0 points to b1
  227.         mov     ar3,@r0         ; b1
  228.         inc     r0
  229.         mov     ar4,@r0         ; b2
  230.         inc     r0
  231.         mov     ar5,@r0         ; b3
  232.  
  233. __modlong:                      ; entry point for __modslong
  234.                                 ; a in r1, b, dph, dpl
  235.                                 ; b in r5, r4, r3, r2
  236.  
  237.         mov     count,#0
  238.  
  239.         mov     a,b0            ; b == 0? avoid endless loop
  240.         orl     a,b1
  241.         orl     a,b2
  242.         orl     a,b3
  243.         jz      div_by_0
  244.  
  245.         mov     count,#0
  246.         clr     c               ; when loop1 jumps immediately to loop2
  247.  
  248. loop1:  inc     count
  249.  
  250.         mov     a,b3            ; if (!MSB_SET(b))
  251.         jb      acc.7,loop2
  252.  
  253.         mov     a,b0            ; b <<= 1
  254.         add     a,acc
  255.         mov     b0,a
  256.         mov     a,b1
  257.         rlc     a
  258.         mov     b1,a
  259.         mov     a,b2
  260.         rlc     a
  261.         mov     b2,a
  262.         mov     a,b3
  263.         rlc     a
  264.         mov     b3,a
  265.  
  266.         mov     a,a0            ; a - b
  267.         subb    a,b0            ; here carry is always clear
  268.         mov     a,a1
  269.         subb    a,b1
  270.         mov     a,a2
  271.         subb    a,b2
  272.         mov     a,a3
  273.         subb    a,b3
  274.  
  275.         jnc     loop1
  276.  
  277.         clr     c
  278.         mov     a,b3            ; b >>= 1;
  279.         rrc     a
  280.         mov     b3,a
  281.         mov     a,b2
  282.         rrc     a
  283.         mov     b2,a
  284.         mov     a,b1
  285.         rrc     a
  286.         mov     b1,a
  287.         mov     a,b0
  288.         rrc     a
  289.         mov     b0,a
  290.  
  291. loop2:  ; clr   c                 never set
  292.         mov     a,a0            ; a - b
  293.         subb    a,b0
  294.         mov     a,a1
  295.         subb    a,b1
  296.         mov     r6,a            ; d1
  297.         mov     a,a2
  298.         subb    a,b2
  299.         mov     r7,a            ; d2
  300.         mov     a,a3
  301.         subb    a,b3
  302.  
  303.         jc      smaller         ; a >= b?
  304.  
  305.         mov     a3,a            ; -> yes;  a = a - b;
  306.         mov     a2,r7
  307.         mov     a1,r6
  308.         mov     a,a0
  309.         subb    a,b0
  310.         mov     a0,a
  311. smaller:                        ; -> no
  312.         clr     c
  313.         mov     a,b3            ; b >>= 1;
  314.         rrc     a
  315.         mov     b3,a
  316.         mov     a,b2
  317.         rrc     a
  318.         mov     b2,a
  319.         mov     a,b1
  320.         rrc     a
  321.         mov     b1,a
  322.         mov     a,b0
  323.         rrc     a
  324.         mov     b0,a
  325.  
  326.         djnz    count,loop2
  327.  
  328.         mov     a,a3            ; prepare the return value
  329. div_by_0:
  330.         ret
  331.  
  332.         __endasm;
  333. }
  334.  
  335. #else // _MODULONG_ASM
  336.  
  337. #define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
  338.  
  339. unsigned long
  340. _modulong (unsigned long a, unsigned long b)
  341. {
  342.   unsigned char count = 0;
  343.  
  344.   while (!MSB_SET(b))
  345.   {
  346.      b <<= 1;
  347.      if (b > a)
  348.      {
  349.         b >>=1;
  350.         break;
  351.      }
  352.      count++;
  353.   }
  354.   do
  355.   {
  356.     if (a >= b)
  357.       a -= b;
  358.     b >>= 1;
  359.   }
  360.   while (count--);
  361.  
  362.   return a;
  363. }
  364.  
  365. #endif // _MODULONG_ASM
  366.