Skip to content

Instantly share code, notes, and snippets.

@ZipCPU
Created March 8, 2017 02:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZipCPU/29f3898b970c15e64239afbcab449237 to your computer and use it in GitHub Desktop.
Save ZipCPU/29f3898b970c15e64239afbcab449237 to your computer and use it in GitHub Desktop.
////////////////////////////////////////////////////////////////////
//
// Filename: string.c
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: To provide *some* of the C-library's capabilities, without
// using perfectly optimal functions--but rather simple things that
// can be easily tested and debugged.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory. Run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include "string.h"
char *
strcpy(char *dst, const char *src) {
char v, *d = dst;
do {
*dst++ = (v = *src++);
} while(v);
return d;
}
char *
strcat(char *dst, const char *src) {
char v, *d = dst;
do {
v = *dst++;
} while(v);
dst--;
strcpy(dst, src);
return d;
}
#ifdef C_STRING_FNS
size_t
strlen(const char *str) {
size_t ln = 0;
while(*str++)
ln++;
return ln;
}
#else
asm("\t.section\t.text\n"
"\t.global\tstrlen\n"
"strlen:\n"
"\tMOV\tR1,R2\n"
"\tCLR\tR1\n"
".Lstrlen_loop:\n"
"\tLB\t(R2),R3\n"
"\tCMP\t0,R3\n"
"\tRTN.Z\n"
"\tADD\t1,R2\n"
"\tADD\t1,R1\n"
"\tBRA\t.Lstrlen_loop\n");
#endif
void *memcpy(void *dest, const void *src, size_t ln) {
char *d = dest; const char *s = src;
if (((((unsigned)d ^ (unsigned)s)&3)==0)&&(ln>4)) {
// Source and destination are aligned with each other
// Align them to a word boundary
int n = (3-(((unsigned)d)&3));
ln -= n;
while(n>0) {
*d++ = *s++; n--;
}
int *id = (int *)d;
const int *is = (const int *)s;
while(ln >= 4) {
*id++ = *is++; ln-=4;
} d = (char *)id; s = (const char *)is;
}
while(ln > 0) {
*d++ = *s++; ln--;
} return dest;
}
.file "string.c"
.section .text
.global strlen
strlen:
MOV R1,R2
CLR R1
.Lstrlen_loop:
LB (R2),R3
CMP 0,R3
RTN.Z
ADD 1,R2
ADD 1,R1
BRA .Lstrlen_loop
.text
.align 2
.global strcpy
.type strcpy, @function
strcpy:
MOV R1,R3
.L2:
ADD 1,R3 ; addsi3
ADD 1,R2 ; addsi3
LB -1(R2),R4 ; Zero-Extend:QI
SB R4,-1(R3)
CMP 0,R4
BNZ .L2
RETN
.size strcpy, .-strcpy
.align 2
.global strcat
.type strcat, @function
strcat:
MOV R1,R3
BRA .L5
.L7:
.L5:
ADD 1,R3 ; addsi3_raw
LB -1(R3),R4 ; Zero-Extend:QI
CMP 0,R4
BNZ .L7
.L6:
ADD 1,R2 ; addsi3
LB -1(R2),R4 ; Zero-Extend:QI
SB R4,-1(R3)
CMP 0,R4
RETN.Z
MOV 1(R3),R3
BRA .L6
.size strcat, .-strcat
.align 2
.global memcpy
.type memcpy, @function
memcpy:
SUB 24,SP ; subsi3
SW R5,(SP)
SW R6,4(SP)
SW R7,8(SP)
SW R8,12(SP)
SW R9,16(SP)
SW R10,20(SP)
MOV R2,R4
XOR R1,R4 ; xorsi3
TEST 3,R4
LDI 0,R4
LDI.Z 1,R4 ; cmov
CMP 5,R3
LDI 0,R5
LDI.NC 1,R5 ; cmov
TEST R5,R4
BNZ .L11
MOV R1,R4
.L16:
CMP 0,R3
BNZ .L12
BRA .L30
.L11:
MOV R1,R4
XOR -1,R4 ; xorsi3
AND 3,R4 ; andsi3
SUB R4,R3 ; subsi3_raw
CMP 0,R4
BZ .L25
LB (R2),R5 ; Zero-Extend:QI
SB R5,(R1)
MOV R4,R5
ADD -1,R5 ; addsi3_raw
BZ .L14
LB 1(R2),R8 ; Zero-Extend:QI
SB R8,1(R1)
CMP 2,R4
[NZ] LB 2(R2),R10 ; Zero-Extend:QI
[NZ] SB R10,2(R1)
.L14:
ADD R4,R2 ; addsi3
MOV R1,R5
ADD R4,R5 ; addsi3
MOV R5,R4
BRA .L13
.L25:
MOV R1,R4
.L13:
CMP 4,R3
BC .L26
MOV R2,R7
MOV R4,R6
MOV R3,R5
.L15:
ADD 4,R6 ; addsi3
LW (R7),R8
ADD 4,R7 ; addsi3_raw
SW R8,-4(R6)
ADD -4,R5 ; addsi3_raw
CMP 4,R5
BNC .L15
MOV R3,R5
ADD -4,R5 ; addsi3
AND -4,R5 ; andsi3
ADD 4,R5 ; addsi3
AND 3,R3 ; andsi3
ADD R5,R2 ; addsi3
ADD R5,R4 ; addsi3
BRA .L16
.L26:
.L12:
MOV R2,R5
ADD 4,R5 ; addsi3_raw
CMP R5,R4
LDI 0,R5
LDI.NC 1,R5 ; cmov
MOV R4,R6
ADD 4,R6 ; addsi3_raw
CMP R6,R2
OR.NC 1,R5 ; cior
MOV R5,R6
CMP 10,R3
LDI 0,R5
LDI.NC 1,R5 ; cmov
AND R6,R5 ; andsi3
MOV R5,R6
MOV R4,R5
OR R2,R5 ; iorsi3
TEST 3,R5
LDI 0,R5
LDI.Z 1,R5 ; cmov
TEST R6,R5
BZ .L17
MOV R3,R5
ADD -4,R5 ; addsi3
LSR 2,R5 ; lshrsi3
ADD 1,R5 ; addsi3
MOV R5,R9
LSL 2,R9 ; ashlsi3
MOV R2,R8
MOV R4,R7
LDI 0,R6
.L18:
LW (R8),R10
SW R10,(R7)
ADD 1,R6 ; addsi3
ADD 4,R8 ; addsi3
ADD 4,R7 ; addsi3_raw
CMP R5,R6
BC .L18
BRA .L40
.L21:
LB 2(R2),R2 ; Zero-Extend:QI
SB R2,2(R4)
BRA .L30
.L40:
MOV R3,R5
SUB R9,R5 ; subsi3
ADD R9,R4 ; addsi3
ADD R9,R2 ; addsi3_raw
CMP R3,R9
BZ .L30
LB (R2),R3 ; Zero-Extend:QI
SB R3,(R4)
MOV R5,R3
ADD -1,R3 ; addsi3_raw
BZ .L30
LB 1(R2),R8 ; Zero-Extend:QI
SB R8,1(R4)
CMP 2,R5
BNZ .L21
BRA .L30
.L17:
MOV R4,R10
ADD R3,R10 ; addsi3
MOV R10,R3
.L23:
ADD 1,R4 ; addsi3
ADD 1,R2 ; addsi3
LB -1(R2),R5 ; Zero-Extend:QI
SB R5,-1(R4)
CMP R3,R4
BNZ .L23
.L30:
LW (SP),R5
LW 4(SP),R6
LW 8(SP),R7
LW 12(SP),R8
LW 16(SP),R9
LW 20(SP),R10
ADD 24,SP ; addsi3
RETN
.size memcpy, .-memcpy
.ident "GCC: (zip-gcc-170306) 6.2.0"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment