git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/libc/_divulong.c

      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 
     44 static 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 
    179 static 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 
    320 unsigned 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) || defined(__SDCC_mos6502)
    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

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.