cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

_divulong.c (6187B)


      1/*-------------------------------------------------------------------------
      2   _divulong.c - routine for division of 32 bit unsigned long
      3
      4             Ecrit par -  Jean-Louis Vern . jlvern@writeme.com (1999)
      5
      6   This library is free software; you can redistribute it and/or modify it
      7   under the terms of the GNU Library 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 Library General Public License for more details.
     15
     16   You should have received a copy of the GNU Library General Public License
     17   along with this program; if not, write to the Free Software
     18   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     19
     20   In other words, you are welcome to use, share and improve this program.
     21   You are forbidden to forbid anyone else to use, share and improve
     22   what you give them.   Help stamp out software-hoarding!
     23-------------------------------------------------------------------------*/
     24
     25/*   Assembler-functions are provided for:
     26     mcs51 small
     27     mcs51 small stack-auto
     28*/
     29
     30#if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS)
     31#  if defined(SDCC_mcs51)
     32#    if defined(SDCC_MODEL_SMALL)
     33#      if defined(SDCC_STACK_AUTO)
     34#        define _DIVULONG_ASM_SMALL_AUTO
     35#      else
     36#        define _DIVULONG_ASM_SMALL
     37#      endif
     38#    endif
     39#  endif
     40#endif
     41
     42#if defined _DIVULONG_ASM_SMALL
     43
     44static void
     45_divlong_dummy (void) _naked
     46{
     47	_asm
     48
     49		.globl __divulong
     50
     51	__divulong:
     52
     53		#define count   r2
     54
     55		#define a0	dpl
     56		#define a1	dph
     57		#define a2	b
     58		#define a3	r3
     59
     60		#define reste0	r4
     61		#define reste1	r5
     62		#define reste2	r6
     63		#define reste3	r7
     64
     65#if defined(SDCC_NOOVERLAY)
     66		.area DSEG    (DATA)
     67#else
     68		.area OSEG    (OVR,DATA)
     69#endif
     70
     71		.globl __divulong_PARM_2
     72		.globl __divslong_PARM_2
     73
     74	__divulong_PARM_2:
     75	__divslong_PARM_2:
     76		.ds	4
     77
     78		.area CSEG    (CODE)
     79
     80		#define b0      (__divulong_PARM_2)
     81		#define b1      (__divulong_PARM_2 + 1)
     82		#define b2      (__divulong_PARM_2 + 2)
     83		#define b3      (__divulong_PARM_2 + 3)
     84
     85					; parameter a comes in a, b, dph, dpl
     86		mov	a3,a		; save parameter a3
     87
     88		mov	count,#32
     89		clr	a
     90		mov	reste0,a
     91		mov	reste1,a
     92		mov	reste2,a
     93		mov	reste3,a
     94
     95	; optimization  loop in lp0 until the first bit is shifted into rest
     96
     97	lp0:	mov	a,a0		; a <<= 1
     98		add	a,a0
     99		mov	a0,a
    100		mov	a,a1
    101		rlc	a
    102		mov	a1,a
    103		mov	a,a2
    104		rlc	a
    105		mov	a2,a
    106		mov	a,a3
    107		rlc	a
    108		mov	a3,a
    109
    110		jc	in_lp
    111		djnz	count,lp0
    112
    113		sjmp	exit
    114
    115	loop:	mov	a,a0		; a <<= 1
    116		add	a,a0
    117		mov	a0,a
    118		mov	a,a1
    119		rlc	a
    120		mov	a1,a
    121		mov	a,a2
    122		rlc	a
    123		mov	a2,a
    124		mov	a,a3
    125		rlc	a
    126		mov	a3,a
    127
    128	in_lp:	mov	a,reste0	; reste <<= 1
    129		rlc	a		;   feed in carry
    130		mov	reste0,a
    131		mov	a,reste1
    132		rlc	a
    133		mov	reste1,a
    134		mov	a,reste2
    135		rlc	a
    136		mov	reste2,a
    137		mov	a,reste3
    138		rlc	a
    139		mov	reste3,a
    140
    141		mov	a,reste0	; reste - b
    142		subb	a,b0		; carry is always clear here, because
    143					; reste <<= 1 never overflows
    144		mov	a,reste1
    145		subb	a,b1
    146		mov	a,reste2
    147		subb	a,b2
    148		mov	a,reste3
    149		subb	a,b3
    150
    151		jc	minus		; reste >= b?
    152
    153					; -> yes;  reste -= b;
    154		mov	a,reste0
    155		subb	a,b0		; carry is always clear here (jc)
    156		mov	reste0,a
    157		mov	a,reste1
    158		subb	a,b1
    159		mov	reste1,a
    160		mov	a,reste2
    161		subb	a,b2
    162		mov	reste2,a
    163		mov	a,reste3
    164		subb	a,b3
    165		mov	reste3,a
    166
    167		orl	a0,#1
    168
    169	minus:	djnz	count,loop	; -> no
    170
    171	exit:	mov	a,a3		; prepare the return value
    172		ret
    173
    174	_endasm ;
    175}
    176
    177#elif defined _DIVULONG_ASM_SMALL_AUTO
    178
    179static void
    180_divlong_dummy (void) _naked
    181{
    182	_asm
    183
    184		.globl __divulong
    185
    186	__divulong:
    187
    188		#define count   r2
    189
    190		#define a0	dpl
    191		#define a1	dph
    192		#define a2	b
    193		#define a3	r3
    194
    195		#define reste0	r4
    196		#define reste1	r5
    197		#define reste2	r6
    198		#define reste3	r7
    199
    200		.globl __divlong	; entry point for __divslong
    201
    202		#define b0	r1
    203
    204		ar0 = 0			; BUG register set is not considered
    205		ar1 = 1
    206
    207					; parameter a comes in a, b, dph, dpl
    208		mov	a3,a		; save parameter a3
    209
    210		mov	a,sp
    211		add	a,#-2-3		; 2 bytes return address, 3 bytes param b
    212		mov	r0,a		; r0 points to b0
    213
    214	__divlong:			; entry point for __divslong
    215
    216		mov	ar1,@r0		; load b0
    217		inc	r0		; r0 points to b1
    218
    219		mov	count,#32
    220		clr	a
    221		mov	reste0,a
    222		mov	reste1,a
    223		mov	reste2,a
    224		mov	reste3,a
    225
    226	; optimization  loop in lp0 until the first bit is shifted into rest
    227
    228	lp0:	mov	a,a0		; a <<= 1
    229		add	a,a0
    230		mov	a0,a
    231		mov	a,a1
    232		rlc	a
    233		mov	a1,a
    234		mov	a,a2
    235		rlc	a
    236		mov	a2,a
    237		mov	a,a3
    238		rlc	a
    239		mov	a3,a
    240
    241		jc	in_lp
    242		djnz	count,lp0
    243
    244		sjmp	exit
    245
    246	loop:	mov	a,a0		; a <<= 1
    247		add	a,a0
    248		mov	a0,a
    249		mov	a,a1
    250		rlc	a
    251		mov	a1,a
    252		mov	a,a2
    253		rlc	a
    254		mov	a2,a
    255		mov	a,a3
    256		rlc	a
    257		mov	a3,a
    258
    259	in_lp:	mov	a,reste0	; reste <<= 1
    260		rlc	a		;   feed in carry
    261		mov	reste0,a
    262		mov	a,reste1
    263		rlc	a
    264		mov	reste1,a
    265		mov	a,reste2
    266		rlc	a
    267		mov	reste2,a
    268		mov	a,reste3
    269		rlc	a
    270		mov	reste3,a
    271
    272		mov	a,reste0	; reste - b
    273		subb	a,b0		; carry is always clear here, because
    274					; reste <<= 1 never overflows
    275		mov	a,reste1
    276		subb	a,@r0		; b1
    277		mov	a,reste2
    278		inc	r0
    279		subb	a,@r0		; b2
    280		mov	a,reste3
    281		inc	r0
    282		subb	a,@r0		; b3
    283		dec	r0
    284		dec	r0
    285
    286		jc	minus		; reste >= b?
    287
    288					; -> yes;  reste -= b;
    289		mov	a,reste0
    290		subb	a,b0		; carry is always clear here (jc)
    291		mov	reste0,a
    292		mov	a,reste1
    293		subb	a,@r0		; b1
    294		mov	reste1,a
    295		mov	a,reste2
    296		inc	r0
    297		subb	a,@r0		; b2
    298		mov	reste2,a
    299		mov	a,reste3
    300		inc	r0
    301		subb	a,@r0		; b3
    302		mov	reste3,a
    303		dec	r0
    304		dec	r0
    305
    306		orl	a0,#1
    307
    308	minus:	djnz	count,loop	; -> no
    309
    310	exit:	mov	a,a3		; prepare the return value
    311		ret
    312
    313	_endasm ;
    314}
    315
    316#else // _DIVULONG_ASM
    317
    318#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1)
    319
    320unsigned long
    321_divulong (unsigned long a, unsigned long b)
    322{
    323  unsigned long reste = 0L;
    324  unsigned char count = 32;
    325  #if defined(__SDCC_STACK_AUTO) || defined(__SDCC_z80) || defined(__SDCC_sm83)
    326    char c;
    327  #else
    328    bit c;
    329  #endif
    330
    331  do
    332  {
    333    // reste: a <- 0;
    334    c = MSB_SET(a);
    335    a <<= 1;
    336    reste <<= 1;
    337    if (c)
    338      reste |= 1L;
    339
    340    if (reste >= b)
    341    {
    342      reste -= b;
    343      // a <- (result = 1)
    344      a |= 1L;
    345    }
    346  }
    347  while (--count);
    348  return a;
    349}
    350
    351#endif // _DIVULONG_ASM