blob: 802fe8afacf60010c10fe0c34ccf19b066742cbe (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/***************************************************************************
* Copyright (c) 2026 10xEngineers
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/* Newlib system call stubs for RISC-V QEMU virt regression tests.
Provides _write (UART output for printf), _exit (QEMU test finisher),
and other minimal stubs needed by newlib. */
#include <sys/stat.h>
#include <errno.h>
#include <stdint.h>
#define UART0_THR (*(volatile unsigned char *)0x10000000L)
#define UART0_LSR (*(volatile unsigned char *)0x10000005L)
#define LSR_TX_IDLE (1 << 5)
/* QEMU virt sifive_test device for clean exit. */
#define VIRT_TEST (*(volatile uint32_t *)0x100000L)
#define VIRT_TEST_PASS 0x5555u
#define VIRT_TEST_FAIL 0x3333u
/* Called by testcontrol.c when EXTERNAL_EXIT is defined. */
__attribute__((noreturn)) void external_exit(unsigned int code)
{
if (code == 0)
VIRT_TEST = VIRT_TEST_PASS;
else
VIRT_TEST = (code << 16) | VIRT_TEST_FAIL;
/* Should not reach here, but halt if it does. */
while (1)
;
}
int _write(int fd, const char *buf, int count)
{
(void)fd;
for (int i = 0; i < count; i++)
{
while ((UART0_LSR & LSR_TX_IDLE) == 0)
;
UART0_THR = (unsigned char)buf[i];
}
return count;
}
extern char _end[];
static char *heap_ptr = 0;
void *_sbrk(int incr)
{
if (heap_ptr == 0)
heap_ptr = _end;
char *prev = heap_ptr;
heap_ptr += incr;
return prev;
}
int _close(int fd)
{
(void)fd;
errno = EBADF;
return -1;
}
int _fstat(int fd, struct stat *st)
{
(void)fd;
st->st_mode = S_IFCHR;
return 0;
}
int _isatty(int fd)
{
(void)fd;
return 1;
}
int _lseek(int fd, int offset, int whence)
{
(void)fd;
(void)offset;
(void)whence;
errno = ESPIPE;
return -1;
}
int _read(int fd, char *buf, int count)
{
(void)fd;
(void)buf;
(void)count;
return 0;
}
__attribute__((noreturn)) void _exit(int code)
{
external_exit((unsigned int)code);
}
/* Override newlib's exit() to avoid pulling in __call_exitprocs and
__stdio_exit_handler (compiled with mcmodel=medlow). */
__attribute__((noreturn)) void exit(int code)
{
external_exit((unsigned int)code);
}
/* Minimal rand/srand to avoid pulling newlib's version which uses
_impure_ptr (compiled with mcmodel=medlow, unreachable on RV64). */
static unsigned long rand_seed = 1;
int rand(void)
{
rand_seed = rand_seed * 1103515245UL + 12345UL;
return (int)((rand_seed >> 16) & 0x7fff);
}
void srand(unsigned int seed)
{
rand_seed = seed;
}
|