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/asm/mos6502/_memset.c

      1 /*-------------------------------------------------------------------------
      2    _memset.c - part of string library functions
      3 
      4    Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
      5    Copyright (C) 2020, Sergey Belyashov sergey.belyashov@gmail.com
      6    Copyright (C) 2022, Sebastian 'basxto' Riedel
      7    mcs51 assembler by Frieder Ferlemann (2007)
      8 
      9    This library is free software; you can redistribute it and/or modify it
     10    under the terms of the GNU General Public License as published by the
     11    Free Software Foundation; either version 2, or (at your option) any
     12    later version.
     13 
     14    This library is distributed in the hope that it will be useful,
     15    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17    GNU General Public License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with this library; see the file COPYING. If not, write to the
     21    Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
     22    MA 02110-1301, USA.
     23 
     24    As a special exception, if you link this library with other files,
     25    some of which are compiled with SDCC, to produce an executable,
     26    this library does not by itself cause the resulting executable to
     27    be covered by the GNU General Public License. This exception does
     28    not however invalidate any other reasons why the executable file
     29    might be covered by the GNU General Public License.
     30 -------------------------------------------------------------------------*/
     31 
     32 #include <stdlib.h>
     33 #include <string.h>
     34 
     35 #undef memset /* Avoid conflict with builtin memset() in Z80 and some related ports */
     36 
     37 #if defined (_SDCC_NO_ASM_LIB_FUNCS) || !defined (__SDCC_mcs51) || \
     38     (!defined (__SDCC_MODEL_SMALL) && !defined (__SDCC_MODEL_LARGE)) || \
     39      (defined (__SDCC_STACK_AUTO) || defined (__SDCC_PARMS_IN_BANK1) )
     40 
     41 #ifdef __SDCC_BROKEN_STRING_FUNCTIONS
     42 void *memset (void *s, unsigned char c, size_t n)
     43 #else
     44 void *memset (void *s, int c, size_t n)
     45 #endif
     46 
     47 #if !defined (_SDCC_NO_ASM_LIB_FUNCS) && (\
     48               defined (__SDCC_z80) ||\
     49               defined (__SDCC_z180) ||\
     50               defined (__SDCC_z80n))
     51 #ifdef __SDCC_BROKEN_STRING_FUNCTIONS      
     52 #error Unimplemented broken string function
     53 #endif    
     54 __naked
     55 {
     56   (void)s;
     57   (void)c;
     58   (void)n;
     59   __asm
     60     pop   iy
     61     pop   bc
     62     push  hl
     63     ld    a, c
     64     or    a, b
     65     jr    Z, end
     66     ld    (hl), e
     67     dec   bc
     68     ld    a, c
     69     or    a, b
     70     jr    Z, end
     71     ld    e, l
     72     ld    d, h
     73     inc   de
     74     ldir 
     75 end:
     76     pop   de
     77     jp	(iy)
     78   __endasm;
     79 }
     80 #elif !defined (_SDCC_NO_ASM_LIB_FUNCS) && (\
     81               defined (__SDCC_ez80_z80) ||\
     82               defined (__SDCC_r2k) ||\
     83               defined (__SDCC_z3ka))
     84 
     85 __naked
     86 {
     87   (void)s;
     88   (void)c;
     89   (void)n;
     90   __asm
     91     pop   af
     92     pop   hl
     93 #ifdef __SDCC_BROKEN_STRING_FUNCTIONS
     94     dec   sp
     95 #endif
     96     pop   de
     97     pop   bc
     98     push  bc
     99     push  de
    100 #ifdef __SDCC_BROKEN_STRING_FUNCTIONS
    101     inc   sp
    102 #endif
    103     push  hl
    104     push  af
    105     ld    a, c
    106     or    a, b
    107     ret   Z
    108 #ifdef __SDCC_BROKEN_STRING_FUNCTIONS
    109     ld    (hl), d
    110 #else
    111     ld    (hl), e
    112 #endif
    113     dec   bc
    114     ld    a, c
    115     or    a, b
    116     ret   Z
    117     push  hl
    118     ld    e, l
    119     ld    d, h
    120     inc   de
    121     ldir
    122     pop   hl
    123     ret
    124   __endasm;
    125 }
    126 #elif !defined (_SDCC_NO_ASM_LIB_FUNCS) && defined(__SDCC_sm83)
    127 __naked
    128 {
    129 	(void)s;//de
    130 	(void)c;//bc or for broken string function in a
    131 	(void)n;//stack+2, stack+3
    132 __asm
    133         ; Algorithm is Duff`s device
    134 	ldhl	sp,	#3
    135 __endasm;
    136 #ifdef __SDCC_BROKEN_STRING_FUNCTIONS
    137 __asm
    138 	ld	b, (hl)
    139 	dec	hl
    140 __endasm;
    141 #else
    142 __asm
    143 
    144 	ld	a, (hl-)
    145 	ld	b, a
    146 	ld	a, c
    147 __endasm;
    148 #endif  
    149 __asm
    150 	ld	c, (hl)
    151 	ld	l, e
    152 	ld	h, d
    153 	;shift LSB to carry
    154 	srl	b
    155 	rr	c
    156 	jr nc, skip_one
    157         ld	(hl+), a
    158 skip_one:
    159 	;n/2 in bc
    160 	;shift second LSB to carry
    161 	srl	b
    162 	rr	c
    163         ;n/4 in bc
    164 	inc	b
    165 	inc	c
    166 	jr nc, test
    167 	jr	copy_two
    168 copy_four:
    169         ld	(hl+), a
    170 	ld	(hl+), a
    171 copy_two:
    172         ld	(hl+), a
    173 	ld	(hl+), a
    174 test:
    175 	dec	c
    176 	jr	NZ, copy_four
    177 	dec	b
    178 	jr	NZ, copy_four
    179         ;restore dest
    180 	ld	c, e
    181 	ld	b, d
    182 	pop	hl
    183 	pop	af
    184 	jp	(hl)
    185 __endasm;
    186 }
    187 #else
    188 {
    189   register size_t sz = n;
    190   if (sz != 0)
    191     {
    192       register char *dst = s;
    193       register char data = (char)c;
    194       do {
    195         *dst++ = data;
    196       } while (--sz);
    197     }
    198   return s;
    199 }
    200 #endif
    201 #else
    202 
    203   /* assembler implementation for mcs51 */
    204   static void dummy(void) __naked
    205   {
    206     __asm
    207 
    208   /* assigning function parameters to registers.
    209      __SDCC_PARMS_IN_BANK1 or __SDCC_STACK_AUTO not yet implemented. */
    210   #if defined (__SDCC_MODEL_SMALL)
    211 
    212     #if defined(__SDCC_NOOVERLAY)
    213         .area DSEG    (DATA)
    214     #else
    215         .area OSEG    (OVR,DATA)
    216     #endif
    217         _memset_PARM_2::
    218               .ds 1
    219         _memset_PARM_3::
    220               .ds 2
    221 
    222         .area CSEG    (CODE)
    223 
    224         _memset::
    225 
    226         ;   Assign buf (b holds memspace, no need to touch)
    227                 mov     r4,dpl
    228                 mov     r5,dph
    229                 ;
    230         ;   Assign count
    231                 mov     r6,_memset_PARM_3
    232                 mov     r7,(_memset_PARM_3 + 1)
    233                 ;
    234         ;   if (!count) return buf;
    235         ;   check for count != 0 intermangled with gymnastic
    236         ;   preparing djnz instructions
    237                 cjne    r6,#0x00,COUNT_LSB_NOT_ZERO
    238                 mov     a,r7
    239                 jz      MEMSET_END
    240                 dec     r7
    241         COUNT_LSB_NOT_ZERO:
    242                 inc     r7
    243                 ;
    244                 ; This was 8 byte overhead for preparing
    245                 ; the count argument for an integer loop with two
    246                 ; djnz instructions - it might make sense to
    247                 ; let SDCC automatically generate this when
    248                 ; it encounters a loop like:
    249                 ; for(i=0;i<j;i++){...}
    250                 ; (at least for option --opt-code-speed)
    251                 ;
    252 
    253         ;   Assign ch
    254                 mov     a,_memset_PARM_2
    255 
    256   #else
    257 
    258         .area XSEG    (XDATA)
    259 
    260         _memset_PARM_2::
    261                 .ds 1
    262         _memset_PARM_3::
    263                 .ds 2
    264 
    265         .area CSEG    (CODE)
    266 
    267         _memset::
    268 
    269         ;   Assign buf (b holds memspace, no need to touch)
    270                 mov     r4,dpl
    271                 mov     r5,dph
    272                 ;
    273         ;   Assign count
    274                 mov     dptr,#_memset_PARM_3
    275                 movx    a,@dptr
    276                 mov     r6,a
    277                 inc     dptr
    278                 movx    a,@dptr
    279                 mov     r7,a
    280                 ;
    281         ;   if (!count) return buf;
    282         ;   check for count != 0 intermangled with gymnastic
    283         ;   preparing djnz instructions
    284                 cjne    r6,#0x00,COUNT_LSB_NOT_ZERO
    285         ;   acc holds r7
    286                 jz      MEMSET_END
    287                 dec     r7
    288         COUNT_LSB_NOT_ZERO:
    289                 inc     r7
    290                 ;
    291         ;   Assign ch
    292                 mov     dptr,#_memset_PARM_2
    293                 movx    a,@dptr
    294         ;   acc is precious now
    295                 ;
    296         ;   Restore dptr
    297                 mov     dpl,r4
    298                 mov     dph,r5
    299 
    300   #endif
    301 
    302         /* now independent of the parameter passing everything
    303            should be in registers by now and the loop may start */
    304         ;   _memset.c do {
    305 
    306         MEMSET_LOOP:
    307         ;   _memset.c *p = ch;
    308                 lcall   __gptrput
    309 
    310         ;   _memset.c p++;
    311                 inc     dptr
    312 
    313         ;   _memset.c } while(--count) ;
    314                 djnz    r6,MEMSET_LOOP
    315                 djnz    r7,MEMSET_LOOP
    316                 ;
    317 
    318         MEMSET_END:
    319         ;   _memset.c return buf ;
    320                 ; b was unchanged
    321                 mov     dpl,r4
    322                 mov     dph,r5
    323                 ;
    324                 ret
    325 
    326     __endasm;
    327   }
    328 
    329 #endif

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