mirror of
https://github.com/TinyCC/tinycc.git
synced 2026-02-05 13:21:37 +00:00
tcc.h, arm-gen.c, arm64-gen.c, i386-gen.c, riscv64-gen.c, x86_64-gen.c: - remove old code tccrun.c: - update to use lib/run_nostdlib.c Makefile, lib/Makefile, lib/run_nostdlib.c: - new code tests/nostdlib_test.c: - testcode
95 lines
2.4 KiB
C
95 lines
2.4 KiB
C
/* ------------------------------------------------------------- */
|
|
/* support for run_nostdlib() */
|
|
|
|
// FIXME: implement arm64 assembler
|
|
#if defined(__aarch64__)
|
|
#define USE_ARM64_ASM
|
|
static void *alloca_arm64(unsigned long);
|
|
__asm__(
|
|
#ifdef __leading_underscore
|
|
"_alloca_arm64:\n\t"
|
|
#else
|
|
"alloca_arm64:\n\t"
|
|
#endif
|
|
".int 0x91003c00\n\t" // add x0, x0, #15
|
|
".int 0x927cec00\n\t" // and x0, x0, #-16
|
|
".int 0xcb2063ff\n\t" // sub sp, sp, x0
|
|
".int 0x910003e0\n\t" // mov x0, sp
|
|
".int 0xd65f03c0" // ret
|
|
);
|
|
static void goto_arm64(void *start);
|
|
__asm__(
|
|
#ifdef __leading_underscore
|
|
"_goto_arm64:\n\t"
|
|
#else
|
|
"goto_arm64:\n\t"
|
|
#endif
|
|
".int 0xd61f0000" // br x0
|
|
);
|
|
#endif
|
|
|
|
void _run_nostdlib(void *start, int argc, char **argv, char **envp)
|
|
{
|
|
#if !defined(_WIN32)
|
|
int i, n = 1;
|
|
unsigned long l;
|
|
char **sp, **e = envp;
|
|
|
|
if (envp)
|
|
while (*e++)
|
|
n++;
|
|
l = (((unsigned long) argc + n + 2 + 1) & -2) * sizeof(char *);
|
|
/* nostdlib so avoid alloca() */
|
|
/* also code below will be removed because compiler detects dead store */
|
|
#if defined(USE_ARM64_ASM)
|
|
sp = alloca_arm64(l);
|
|
#else
|
|
#if defined(__aarch64__)
|
|
__asm__("sub sp, sp, %1\n"
|
|
"\tmov %0, sp"
|
|
#elif defined(__arm__)
|
|
__asm__("sub sp, sp, %1\n"
|
|
"\tmov %0, sp"
|
|
#elif defined(__i386__)
|
|
__asm("sub %1, %%esp\n"
|
|
"\tmov %%esp, %0"
|
|
#elif defined(__riscv)
|
|
__asm__("sub sp, sp, %1\n"
|
|
"\tmv %0, sp"
|
|
#elif defined(__x86_64__)
|
|
__asm__("subq %1, %%rsp\n"
|
|
"\tmovq %%rsp, %0"
|
|
#endif
|
|
: "=r" (sp)
|
|
: "r" (l));
|
|
#endif
|
|
/* create sysv memory layout: argc, argv[], NULL, envp[], NULL */
|
|
sp[0] = (char *) (__SIZE_TYPE__) argc;
|
|
for (i = 0; i < argc; i++)
|
|
sp[i + 1] = argv[i];
|
|
sp[argc + 1] = (char *) 0;
|
|
if (envp)
|
|
for (i = 0; i < n; i++)
|
|
sp[i + argc + 2] = envp[i];
|
|
else
|
|
sp[argc + 2] = (char *) 0;
|
|
#endif
|
|
|
|
/* goto *start does not work for clang. Use assembly. */
|
|
#if defined(USE_ARM64_ASM)
|
|
goto_arm64(start);
|
|
#else
|
|
#if defined(__aarch64__)
|
|
__asm__("br %0" : : "r" (start));
|
|
#elif defined(__arm__)
|
|
__asm__("mov pc, %0" : : "r" (start));
|
|
#elif defined(__i386__)
|
|
__asm__("jmp *%0" : : "r" (start));
|
|
#elif defined(__riscv)
|
|
__asm__("jalr %0" : : "r" (start));
|
|
#elif defined(__x86_64__)
|
|
__asm__("jmp *%0" : : "r" (start));
|
|
#endif
|
|
#endif
|
|
}
|