Skip to content

Commit

Permalink
Simplify and fix hello world example
Browse files Browse the repository at this point in the history
  • Loading branch information
franzflasch committed Feb 10, 2024
1 parent 29f667c commit 87684ce
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 254 deletions.
258 changes: 8 additions & 250 deletions firmware/main.c
Original file line number Diff line number Diff line change
@@ -1,266 +1,24 @@
#include <stdint.h>
#include <stddef.h>


void *memcpy(void *restrict dest, const void *restrict src, size_t n)
{
unsigned char *d = dest;
const unsigned char *s = src;

#ifdef __GNUC__

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LS >>
#define RS <<
#else
#define LS <<
#define RS >>
#endif

typedef uint32_t __attribute__((__may_alias__)) u32;
uint32_t w, x;

for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++;

if ((uintptr_t)d % 4 == 0) {
for (; n>=16; s+=16, d+=16, n-=16) {
*(u32 *)(d+0) = *(u32 *)(s+0);
*(u32 *)(d+4) = *(u32 *)(s+4);
*(u32 *)(d+8) = *(u32 *)(s+8);
*(u32 *)(d+12) = *(u32 *)(s+12);
}
if (n&8) {
*(u32 *)(d+0) = *(u32 *)(s+0);
*(u32 *)(d+4) = *(u32 *)(s+4);
d += 8; s += 8;
}
if (n&4) {
*(u32 *)(d+0) = *(u32 *)(s+0);
d += 4; s += 4;
}
if (n&2) {
*d++ = *s++; *d++ = *s++;
}
if (n&1) {
*d = *s;
}
return dest;
}

if (n >= 32) switch ((uintptr_t)d % 4) {
case 1:
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
n -= 3;
for (; n>=17; s+=16, d+=16, n-=16) {
x = *(u32 *)(s+1);
*(u32 *)(d+0) = (w LS 24) | (x RS 8);
w = *(u32 *)(s+5);
*(u32 *)(d+4) = (x LS 24) | (w RS 8);
x = *(u32 *)(s+9);
*(u32 *)(d+8) = (w LS 24) | (x RS 8);
w = *(u32 *)(s+13);
*(u32 *)(d+12) = (x LS 24) | (w RS 8);
}
break;
case 2:
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
n -= 2;
for (; n>=18; s+=16, d+=16, n-=16) {
x = *(u32 *)(s+2);
*(u32 *)(d+0) = (w LS 16) | (x RS 16);
w = *(u32 *)(s+6);
*(u32 *)(d+4) = (x LS 16) | (w RS 16);
x = *(u32 *)(s+10);
*(u32 *)(d+8) = (w LS 16) | (x RS 16);
w = *(u32 *)(s+14);
*(u32 *)(d+12) = (x LS 16) | (w RS 16);
}
break;
case 3:
w = *(u32 *)s;
*d++ = *s++;
n -= 1;
for (; n>=19; s+=16, d+=16, n-=16) {
x = *(u32 *)(s+3);
*(u32 *)(d+0) = (w LS 8) | (x RS 24);
w = *(u32 *)(s+7);
*(u32 *)(d+4) = (x LS 8) | (w RS 24);
x = *(u32 *)(s+11);
*(u32 *)(d+8) = (w LS 8) | (x RS 24);
w = *(u32 *)(s+15);
*(u32 *)(d+12) = (x LS 8) | (w RS 24);
}
break;
}
if (n&16) {
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
}
if (n&8) {
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
}
if (n&4) {
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
}
if (n&2) {
*d++ = *s++; *d++ = *s++;
}
if (n&1) {
*d = *s;
}
return dest;
#endif

for (; n; n--) *d++ = *s++;
return dest;
}

void *memset(void *dest, int c, size_t n)
{
unsigned char *s = dest;
size_t k;

/* Fill head and tail with minimal branching. Each
* conditional ensures that all the subsequently used
* offsets are well-defined and in the dest region. */

if (!n) return dest;
s[0] = c;
s[n-1] = c;
if (n <= 2) return dest;
s[1] = c;
s[2] = c;
s[n-2] = c;
s[n-3] = c;
if (n <= 6) return dest;
s[3] = c;
s[n-4] = c;
if (n <= 8) return dest;

/* Advance pointer to align it at a 4-byte boundary,
* and truncate n to a multiple of 4. The previous code
* already took care of any head/tail that get cut off
* by the alignment. */

k = -(uintptr_t)s & 3;
s += k;
n -= k;
n &= -4;

#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) u32;
typedef uint64_t __attribute__((__may_alias__)) u64;

u32 c32 = ((u32)-1)/255 * (unsigned char)c;

/* In preparation to copy 32 bytes at a time, aligned on
* an 8-byte bounary, fill head/tail up to 28 bytes each.
* As in the initial byte-based head/tail fill, each
* conditional below ensures that the subsequent offsets
* are valid (e.g. !(n<=24) implies n>=28). */

*(u32 *)(s+0) = c32;
*(u32 *)(s+n-4) = c32;
if (n <= 8) return dest;
*(u32 *)(s+4) = c32;
*(u32 *)(s+8) = c32;
*(u32 *)(s+n-12) = c32;
*(u32 *)(s+n-8) = c32;
if (n <= 24) return dest;
*(u32 *)(s+12) = c32;
*(u32 *)(s+16) = c32;
*(u32 *)(s+20) = c32;
*(u32 *)(s+24) = c32;
*(u32 *)(s+n-28) = c32;
*(u32 *)(s+n-24) = c32;
*(u32 *)(s+n-20) = c32;
*(u32 *)(s+n-16) = c32;

/* Align to a multiple of 8 so we can fill 64 bits at a time,
* and avoid writing the same bytes twice as much as is
* practical without introducing additional branching. */

k = 24 + ((uintptr_t)s & 4);
s += k;
n -= k;

/* If this loop is reached, 28 tail bytes have already been
* filled, so any remainder when n drops below 32 can be
* safely ignored. */

u64 c64 = c32 | ((u64)c32 << 32);
for (; n >= 32; n-=32, s+=32) {
*(u64 *)(s+0) = c64;
*(u64 *)(s+8) = c64;
*(u64 *)(s+16) = c64;
*(u64 *)(s+24) = c64;
}
#else
/* Pure C fallback with no aliasing violations. */
for (; n; n--, s++) *s = c;
#endif

return dest;
}

#define reg_uart_data (*(volatile uint32_t*)0x300000)
#define reg_uart_data (*(volatile uint8_t*)0x3000000UL)

void putchar(char c)
{
if (c == '\n')
putchar('\r');
reg_uart_data = c;
if (c == '\n')
putchar('\r');
reg_uart_data = c;
}

void print(const char *p)
{
while (*p)
putchar(*(p++));
while (*p)
putchar(*(p++));
}

/* This is just for testing purposes and debugging
assembly code
*/
void test_func(void)
{
int i = 42;
uint32_t test_array[100] = { [0 ... 99] = 0xDEADBEEF };

while(1)
{
i++;
test_array[0]++;
if(i==84) break;
}
}


int main(void)
{
int i = 0;

test_func();

print("Hello World from a simple RV32I ISA emulator!\n");

while(1)
{
i++;
print("Hello World from a simple RV32I ISA emulator!\n");

if(i==10) break;
}

print("Bye!\n");

return 0;
return 0;
}


4 changes: 2 additions & 2 deletions firmware/sections.lds
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00100000, LENGTH = 0x004000 /* entire flash, 4 MiB */
RAM (xrw) : ORIGIN = 0x00000000, LENGTH = 0x004000 /* 1 KB */
FLASH (rx) : ORIGIN = 0x80000000, LENGTH = 0x001000 /* entire flash, 4 MiB */
RAM (xrw) : ORIGIN = 0x80001000, LENGTH = 0x003000 /* 1 KB */
}

SECTIONS {
Expand Down
4 changes: 2 additions & 2 deletions firmware/start.s
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ start:

# zero-initialize register file
addi x1, zero, 0
li sp, 0x00001000
li sp, 0x80004000
# x2 (sp) is initialized by reset
addi x3, zero, 0
addi x4, zero, 0
Expand Down Expand Up @@ -37,7 +37,7 @@ addi x30, zero, 0
addi x31, zero, 0

# zero initialize entire scratchpad memory
li a0, 0x00000000
li a0, 0x80001000
setmemloop:
sw a0, 0(a0)
addi a0, a0, 4
Expand Down

0 comments on commit 87684ce

Please sign in to comment.