commit - 166c6b70ce597414f40e5a3e2ba33f1572c0b8a4
commit + d83e2c2bfa0da3e560fb2531756425b8fa7b00b1
blob - 2739ea77906d91f6c1a52c00b357948a4c7390ef
blob + d5a600d820bf688595bba5fe8d1422b4282f2199
--- .gitignore
+++ .gitignore
+tools/bin
+tools/build
+tools/include
+tools/lib
+tools/libexec
+tools/riscv64-unknown-linux-musl
+tools/share
+tools/src
*.swp
*.core
*.o
*.elf
+*.pdf
rootfs
syscalls.h
rvemu
blob - b88ff85a5f3c5a6be87cde2b332b0bfcdf00d464
blob + dda54ef21b86d17b849a365a3e017cd10a0b0e91
--- Makefile
+++ Makefile
SUDO = doas
PREFIX = /usr/local
-CROSS = riscv64-unknown-linux-musl
-CFLAGS = -std=c2x -fPIC -O3
-LDFLAGS = -s -pie -static -lpthread
+TARGET = riscv64-unknown-linux-musl
+CROSS = ./tools/bin/${TARGET}
+CFLAGS = -std=c2x -fPIC -O0 -g
+LDFLAGS = -pie -static -lpthread
OBJ = rvemu.o ecall.o cpu.o exec.o
PROGS = test.elf hello.elf
.S.o: syscalls.inc
${CROSS}-as -o $@ $<
+.c.elf: linker.ld
+ ${CROSS}-gcc -o $@ $<
+
.o.elf: linker.ld
${CROSS}-ld -s -T linker.ld -o $@ $<
blob - a8e4ca5cef165745638682cdc3cd92323f4b09ea
blob + 01a083c40878b0008d9c60680e2858af82eab131
--- cpu.c
+++ cpu.c
return x;
}
+#define log(fmt, ...) eprintf ("%08llx: " fmt "\n", pc - 4, __VA_ARGS__)
void cpu_exec (u32 instr)
{
const char *name;
const u8 rs1 = (instr >> 15) & 0x1f;
const u8 rs2 = (instr >> 20) & 0x1f;
const u8 funct7 = instr >> 25;
+ const u8 funct6 = instr >> 26;
const u64 imm_i = extend ((i32)instr >> 20);
const u64 imm_s = extend (((i32)instr >> 25 << 5) | ((instr >> 7) & 0x1f));
const u64 imm_b = extend (((i32)instr >> 31 << 12)
u64 a, b, c;
switch (instr & 0x7f) {
case 0b0110111: // lui rd, uimm
- eprintf ("lui x%u, %u\n", (uint)rd, imm_u);
+ log ("lui x%u, %llu", (uint)rd, imm_u);
cpu_set (rd, imm_u);
break;
case 0b0010111: // auipc rd, uimm
- eprintf ("auipc x%u, %u\n", (uint)rd, imm_u);
+ log ("auipc x%u, %llu", (uint)rd, imm_u);
cpu_set (rd, pc + imm_u - 4);
break;
case 0b1101111: // jal rd, jimm
- eprintf ("jal x%u, %d\n", (uint)rd, (int)imm_j);
+ log ("jal x%u, %lld", (uint)rd, imm_j);
cpu_set (rd, pc);
pc += imm_j - 4;
break;
case 0b1100111: // jalr rd, rs1, iimm
switch (funct3) {
case 0b000:
- eprintf ("jalr x%u, x%u, %d\n", (uint)rd, (uint)rs1, (int)imm_i);
+ // XXX: Fix broken musl
+ if (cpu_get (rs1) == 0) {
+ warnx ("%08llx: tried to jump to address 0!", pc - 4);
+ return;
+ }
+ log ("jalr x%u, x%u, %lld", (uint)rd, (uint)rs1, imm_i);
cpu_set (rd, pc);
pc = cpu_get (rs1);
break;
default:
goto ud;
}
- eprintf ("%s x%u, x%u, %d\n", name, (uint)rs1, (uint)rs2, (int)imm_b);
+ log ("%s x%u, x%u, %d", name, (uint)rs1, (uint)rs2, (int)imm_b);
if (c)
pc += imm_b - 4;
break;
default:
goto ud;
}
- eprintf ("%s x%u, %d(x%u)\n", name, (uint)rd, (int)imm_i, (uint)rs1);
+ log ("%s x%u, %d(x%u)", name, (uint)rd, (int)imm_i, (uint)rs1);
cpu_set (rd, b);
break;
case 0b0100011: // sx rs2, simm(rs1)
default:
goto ud;
}
- eprintf ("%s x%u, %d(x%u)\n", name, (uint)rs2, (int)imm_s, (uint)rs1);
+ log ("%s x%u, %d(x%u)", name, (uint)rs2, (int)imm_s, (uint)rs1);
break;
case 0b0010011: // alui rd, rs1, iimm
a = cpu_get (rs1);
c = a + b;
break;
case 0b001: // slli
- if (funct7 != 0)
+ if (funct6 != 0)
goto ud;
name = "slli";
c = a << shamt;
c = a ^ b;
break;
case 0b101: // srli/srai
- switch (funct7) {
- case 0b0000000:
+ switch (funct6) {
+ case 0b000000:
name = "srli";
c = a >> shamt;
break;
- case 0b0100000:
+ case 0b010000:
name = "srai";
c = (i64)a >> shamt;
break;
default:
goto ud;
}
- eprintf ("%s x%u, x%u, %lld\n", name, (uint)rd, (uint)rs1, (i64)imm_i);
+ log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i);
cpu_set (rd, c);
break;
case 0b0011011: // aluiw rd, rs1, iimm
}
c &= 0x00000000ffffffff;
c = extend (c);
- eprintf ("%s x%u, x%u, %lld\n", name, (uint)rd, (uint)rs1, (i64)imm_i);
+ log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i);
cpu_set (rd, c);
break;
case 0b0110011: // alu rd, rs1, rs2
a = cpu_get (rs1);
b = cpu_get (rs2);
- c = (instr >> 30) & 1;
- switch (funct3) {
- case 0b000: // add/sub
- if (c) {
- name = "sub";
- a -= b;
- } else {
- name = "add";
- a += b;
- }
+ switch (funct10) {
+ case 0b0000000'000:
+ name = "add";
+ c = a + b;
break;
- case 0b001: // sll
+ case 0b0000001'000:
+ name = "mul";
+ c = a * b;
+ break;
+ case 0b0100000'000:
+ name = "sub";
+ c = a - b;
+ break;
+ case 0b0000000'001:
name = "sll";
- a <<= b;
+ c = a << b;
break;
- case 0b010: // slt
+ case 0b0000000'010:
name = "slt";
- a = (i64)a < (i64)b;
+ c = (i64)a < (i64)b;
break;
- case 0b011: // sltu
+ case 0b0000000'011:
name = "sltu";
- a = a < b;
- break;
- case 0b100: // xor
+ c = a < b;
+ break;
+ case 0b0000000'100:
name = "xor";
- a ^= b;
+ c = a ^ b;
break;
- case 0b101: // srl/sra
- if (c) {
- name = "sra";
- a = (i64)a >> (b & 0x3f);
- } else {
- name = "srl";
- a >>= (b & 0x3f);
- }
+ case 0b0000001'100:
+ name = "div";
+ c = b != 0 ? (i64)a / (i64)b : -1;
break;
- case 0b110: // or
+ case 0b0000000'101:
+ name = "srl";
+ c = a >> (b & 0x3f);
+ break;
+ case 0b0000001'101:
+ name = "divu";
+ c = b != 0 ? a / b : -1;
+ break;
+ case 0b0100000'101:
+ name = "sra";
+ c = (i64)a >> (b & 0x3f);
+ break;
+ case 0b0000000'110:
name = "or";
- a |= b;
+ c = a | b;
break;
- case 0b111: // and
+ case 0b0000001'110:
+ name = "rem";
+ c = b != 0 ? (i64)a % (i64)b : -1;
+ break;
+ case 0b0000000'111:
name = "and";
- a &= b;
+ c = a & b;
break;
+ case 0b0000001'111:
+ name = "remu";
+ c = b != 0 ? a % b : -1;
+ break;
}
- eprintf ("%s x%u, x%u, x%u\n", name, (uint)rd, (uint)rs1, (uint)rs2);
- cpu_set (rd, a);
+ log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2);
+ cpu_set (rd, c);
break;
case 0b0111011: // aluw
a = cpu_get (rs1);
default:
goto ud;
}
- eprintf ("%s x%u, x%u, x%u\n", name, (uint)rd, (uint)rs1, (uint)rs2);
+ log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2);
cpu_set (rd, extend ((i32)a));
break;
case 0b0001111: // fence/fence.tso/pause
- eprintf ("fence\n");
+ eprintf ("%08llx: efence\n", pc - 4);
break;
case 0b1110011: // ecall/ebreak
- eprintf (
- "ecall a0=%u, a1=%u, a2=%u, a3=%u, a4=%u, a5=%u, a7=%u\n",
+ log (
+ "ecall a0=%llu, a1=%llu, a2=%llu, a3=%llu, a4=%llu, a5=%llu, a7=%llu",
cpu_get (10),
cpu_get (11),
cpu_get (12),
blob - f2631d600322b6a3bc1d74865ef5cd3f54fe743a
blob + d9d65bf68d10b5d9c1590f6519a0c84c3eceaed5
--- ecall.c
+++ ecall.c
ret = enosys ("waitid");
break;
case SYS_set_tid_address:
- ret = enosys ("set_tid_address");
+ warnx ("set_tid_address(): not implemented");
+ ret = getpid ();
break;
case SYS_unshare:
ret = enosys ("unshare");
ret = map (my_execve (str (a0), ptr (char *, a1), ptr (char *, a2)));
break;
case SYS_mmap:
+ //eprintf ("mmap (%p, %zu, %d, %d, %d, %lld);\n", ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
ptr = mmap (ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
if (ptr == NULL) {
ret = -map_errno (errno);
blob - f5eebd803603f22e5415e2c2dbd56c756d929182
blob + 016725c65ba8bd0ec68749e033a54b366ba424b9
--- rvemu.c
+++ rvemu.c
#include <errno.h>
#include "rvemu.h"
-u64 brkval;
+u64 brkval = 0;
+static void load_segment (int fd, Elf64_Phdr phdr)
+{
+ size_t end, len, ps;
+ int prot = 0;
+ void *addr, *ptr;
+
+
+ if (phdr.p_filesz > phdr.p_memsz)
+ errx (1, "invalid program header: p_filesz > p_memsz");
+
+ ps = getpagesize ();
+ addr = (void *)(phdr.p_vaddr & ~(ps - 1));
+ len = phdr.p_memsz + phdr.p_vaddr - (size_t)addr;
+
+ ptr = mmap (
+ addr,
+ len,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0
+ );
+ fprintf (stderr, "mmap (%p, %#zx) = %p;\n", addr, len, ptr);
+
+ if (ptr == NULL)
+ err (1, "mmap()");
+
+ if (phdr.p_filesz > 0) {
+ lseek (fd, phdr.p_offset, SEEK_SET);
+ read (fd, ptr, phdr.p_filesz);
+ }
+
+ if (phdr.p_flags & (PF_R | PF_X))
+ prot |= PROT_READ;
+ if (phdr.p_flags & PF_W)
+ prot |= PROT_WRITE;
+ if (mprotect (addr, len, prot) != 0)
+ err (1, "mprotect()");
+
+ end = phdr.p_vaddr + phdr.p_memsz;
+ if (end > brkval)
+ brkval = end;
+}
+
static void load_image (const char *filename)
{
Elf64_Ehdr ehdr;
for (unsigned i = 0; i < ehdr.e_phnum; ++i) {
Elf64_Phdr phdr;
- u32 flags = 0, end;
- void *ptr;
- if (phdr.p_flags & PF_R)
- flags |= PROT_READ;
- if (phdr.p_flags & PF_W)
- flags |= PROT_WRITE;
- if (phdr.p_flags & PF_X)
- flags |= PROT_EXEC;
-
lseek (fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET);
if (read (fd, &phdr, ehdr.e_phentsize) != ehdr.e_phentsize)
err (1, "failed to read program header %u", i);
case PT_NULL:
break;
case PT_LOAD:
- eprintf ("loading %016llx into %016llx flags %x memsz %u\n",
- phdr.p_offset, phdr.p_vaddr, phdr.p_flags, phdr.p_memsz);
- if (phdr.p_filesz == phdr.p_memsz) {
- ptr = mmap (
- (void *)phdr.p_vaddr,
- phdr.p_memsz,
- flags,
- MAP_PRIVATE | MAP_COPY,
- fd,
- phdr.p_offset
- );
- } else if (phdr.p_filesz == 0) {
- ptr = mmap (
- (void *)phdr.p_vaddr,
- phdr.p_memsz,
- flags,
- MAP_ANON | MAP_PRIVATE,
- -1,
- 0
- );
- } else {
- errx (1, "%u: p_filesz: %llu, p_memsz: %llu",
- i, phdr.p_filesz, phdr.p_memsz);
- }
-
- if ((u64)ptr != phdr.p_vaddr)
- err (1, "%u: failed to map program header", i);
-
- end = (((u64)ptr + phdr.p_memsz) + 4095) & ~0x3ff;
- if (end > brkval)
- brkval = end;
+ load_segment (fd, phdr);
break;
case PT_INTERP:
case PT_DYNAMIC:
if (ptr != stack_bottom)
err (1, "failed to map stack");
+ // auxv
cpu_push (0);
+ cpu_push (0);
+ cpu_push (getegid ());
+ cpu_push (14);
+ cpu_push (getgid ());
+ cpu_push (13);
+ cpu_push (geteuid ());
+ cpu_push (12);
+ cpu_push (getuid ());
+ cpu_push (11);
+ cpu_push (getpagesize ());
+ cpu_push (6);
+
+ cpu_push (0);
for (int i = envc - 1; i >= 0; --i)
cpu_push ((u64)envp[i]);
cpu_push (0);
- for (int i = argc; i >= 0; --i)
+ for (int i = argc - 1; i >= 0; --i)
cpu_push ((u64)argv[i]);
cpu_push (argc);
}
char *base;
void *ptr;
- eprintf ("&main = %p\n", &main);
-
base = basename (argv[0]);
if (strcmp (base, "rvemu") == 0) {
blob - 85a84552dd1982a85a006dc9c3b5193fa5b25c11 (mode 644)
blob + /dev/null
--- test.S
+++ /dev/null
-.include "syscalls.inc"
-
-.section .data
-parent: .string "Parent\n"
-child: .string "Child\n"
-arg0:
-path: .string "./hello.elf"
-argv:
- .dword arg0
- .dword 0
-
-envp:
- .dword 0
-
-.section .text
-.global _start
-.type _start, %function
-_start:
- addi sp, sp, -4
-
- li a0, 17
- li a1, 0
- li a7, SYS_clone
- ecall
-
- beq a0, zero, .Lchild
-
- li a0, 1
- la a1, parent
- li a2, 7
- li a7, SYS_write
- ecall
-
- la a0, path
- la a1, argv
- la a2, envp
- li a7, SYS_execve
- ecall
-
- jal printhex
-
- li a0, 0
- li a7, SYS_exit
- ecall
-
-.Lchild:
- li a0, 1
- la a1, child
- li a2, 6
- li a7, SYS_write
- ecall
-
- li a0, 0
- li a7, SYS_exit
- ecall
-
-# printhex(u64 a0)
-printhex:
- addi sp, sp, -12
- sw s0, 8(sp)
- sw s1, 4(sp)
- li s0, 52
- mv s1, a0
-
-.Loop:
- srl t0, s1, s0
- andi t0, t0, 0xf
-
- li t1, 10
- blt t0, t1, .Ldec
- addi t0, t0, 55
- j .Lprint
-
-.Ldec:
- addi t0, t0, 48
-
-.Lprint:
- sb t0, 0(sp)
- li a0, 1
- mv a1, sp
- li a2, 2
- li a7, 64
- ecall
-
- beq s0, zero, .Lret
- addi s0, s0, -4
- j .Loop
-
-.Lret:
- li t0, 10
- sw t0, 0(sp)
- li a0, 1
- mv a1, sp
- li a2, 1
- ecall
-
- lw s1, 4(sp)
- lw s0, 8(sp)
- addi sp, sp, 12
- ret
-
-
-
blob - /dev/null
blob + e61a4cd6fefd3e020aa5e35cc33c1a32f776730d (mode 644)
--- /dev/null
+++ test.c
+#include <unistd.h>
+#include <string.h>
+
+int main (void) {
+ const char str[] = "Hello, World\n";
+ write (1, str, sizeof (str) - 1);
+ return 0;
+}
blob - /dev/null
blob + 85a84552dd1982a85a006dc9c3b5193fa5b25c11 (mode 644)
--- /dev/null
+++ test2.S
+.include "syscalls.inc"
+
+.section .data
+parent: .string "Parent\n"
+child: .string "Child\n"
+arg0:
+path: .string "./hello.elf"
+argv:
+ .dword arg0
+ .dword 0
+
+envp:
+ .dword 0
+
+.section .text
+.global _start
+.type _start, %function
+_start:
+ addi sp, sp, -4
+
+ li a0, 17
+ li a1, 0
+ li a7, SYS_clone
+ ecall
+
+ beq a0, zero, .Lchild
+
+ li a0, 1
+ la a1, parent
+ li a2, 7
+ li a7, SYS_write
+ ecall
+
+ la a0, path
+ la a1, argv
+ la a2, envp
+ li a7, SYS_execve
+ ecall
+
+ jal printhex
+
+ li a0, 0
+ li a7, SYS_exit
+ ecall
+
+.Lchild:
+ li a0, 1
+ la a1, child
+ li a2, 6
+ li a7, SYS_write
+ ecall
+
+ li a0, 0
+ li a7, SYS_exit
+ ecall
+
+# printhex(u64 a0)
+printhex:
+ addi sp, sp, -12
+ sw s0, 8(sp)
+ sw s1, 4(sp)
+ li s0, 52
+ mv s1, a0
+
+.Loop:
+ srl t0, s1, s0
+ andi t0, t0, 0xf
+
+ li t1, 10
+ blt t0, t1, .Ldec
+ addi t0, t0, 55
+ j .Lprint
+
+.Ldec:
+ addi t0, t0, 48
+
+.Lprint:
+ sb t0, 0(sp)
+ li a0, 1
+ mv a1, sp
+ li a2, 2
+ li a7, 64
+ ecall
+
+ beq s0, zero, .Lret
+ addi s0, s0, -4
+ j .Loop
+
+.Lret:
+ li t0, 10
+ sw t0, 0(sp)
+ li a0, 1
+ mv a1, sp
+ li a2, 1
+ ecall
+
+ lw s1, 4(sp)
+ lw s0, 8(sp)
+ addi sp, sp, 12
+ ret
+
+
+
blob - /dev/null
blob + 7c00c653c85d2f7a68c6ddec2ec894995f887fc2 (mode 644)
--- /dev/null
+++ tools/Makefile
+.POSIX:
+
+TOP != pwd
+STAMPS = ${TOP}/build/.stamps
+PREFIX = ${TOP}
+TARGET = riscv64-unknown-linux-musl
+ARCH = rv64ima
+
+BINUTILS_VER = 2.42
+GCC_VER = 13.2.0
+MUSL_VER = 1.2.4
+LINUX_VER = 6.6.17
+LINUX_MAJOR != echo ${LINUX_VER} | cut -d. -f1
+GMP_VER = 6.3.0
+MPFR_VER = 4.2.1
+MPC_VER = 1.3.1
+
+GMAKE = gmake -j8
+#SUDO = doas
+
+all: build
+
+build: ${STAMPS}/libgcc-install
+
+clean:
+ rm -rf bin build include lib libexec ${TARGET} share
+
+test:
+ ${PREFIX}/bin/${TARGET}-gcc -o /dev/null test.c
+
+download: src/binutils.tgz src/gcc.tgz src/musl.tgz src/linux.tgz src/gmp.tgz src/mpfr.tgz src/mpc.tgz
+extract: ${STAMPS}/binutils-extract ${STAMPS}/gcc-extract ${STAMPS}/musl-extract ${STAMPS}/linux-extract ${STAMPS}/gmp ${STAMPS}/mpfr ${STAMPS}/mpc
+
+headers: ${STAMPS}/linux-headers
+install-headers: ${STAMPS}/linux-hdrinst
+binutils: ${STAMPS}/binutils-build
+install-binutils: ${STAMPS}/binutils-install
+
+# DOWNLOAD
+
+src/binutils.tgz:
+ mkdir -p src
+ ftp -o $@ https://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VER}.tar.gz
+
+src/gcc.tgz:
+ mkdir -p src
+ ftp -o $@ https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VER}/gcc-${GCC_VER}.tar.gz
+
+src/musl.tgz:
+ mkdir -p src
+ ftp -o $@ http://musl.libc.org/releases/musl-${MUSL_VER}.tar.gz
+
+src/linux.tgz:
+ mkdir -p src
+ ftp -o $@ https://mirrors.edge.kernel.org/pub/linux/kernel/v${LINUX_MAJOR}.x/linux-${LINUX_VER}.tar.gz
+
+src/gmp.tgz:
+ mkdir -p src
+ ftp -o $@ https://gmplib.org/download/gmp/gmp-${GMP_VER}.tar.gz
+
+src/mpfr.tgz:
+ mkdir -p src
+ ftp -o $@ https://www.mpfr.org/mpfr-current/mpfr-${MPFR_VER}.tar.gz
+
+src/mpc.tgz:
+ mkdir -p src
+ ftp -o $@ https://ftp.gnu.org/gnu/mpc/mpc-${MPC_VER}.tar.gz
+
+# EXTRACT
+
+${STAMPS}/binutils-extract: src/binutils.tgz
+ mkdir -p ${STAMPS}
+ rm -rf build/binutils
+ tar -C build -xzf src/binutils.tgz
+ mv build/binutils-* build/binutils
+ touch $@
+
+${STAMPS}/gcc-extract: src/gcc.tgz
+ mkdir -p ${STAMPS}
+ rm -rf build/gcc
+ tar -C build -xzf src/gcc.tgz
+ mv build/gcc-* build/gcc
+ cd build/gcc && ln -sf ../gmp ../mpfr ../mpc .
+ touch $@
+
+${STAMPS}/musl-extract: src/musl.tgz
+ mkdir -p ${STAMPS}
+ rm -rf build/musl
+ tar -C build -xzf src/musl.tgz
+ mv build/musl-* build/musl
+ touch $@
+
+${STAMPS}/linux-extract: src/linux.tgz
+ mkdir -p ${STAMPS}
+ rm -rf build/linux
+ tar -C build -xzf src/linux.tgz
+ mv build/linux-* build/linux
+ sed -i 's/sed/gsed/g' build/linux/scripts/headers_install.sh
+ touch $@
+
+${STAMPS}/gmp: src/gmp.tgz
+ mkdir -p ${STAMPS}
+ tar -C build -xzf src/gmp.tgz
+ mv build/gmp-* build/gmp
+ touch $@
+
+${STAMPS}/mpfr: src/mpfr.tgz
+ mkdir -p ${STAMPS}
+ tar -C build -xzf src/mpfr.tgz
+ mv build/mpfr-* build/mpfr
+ touch $@
+
+${STAMPS}/mpc: src/mpc.tgz
+ mkdir -p ${STAMPS}
+ tar -C build -xzf src/mpc.tgz
+ mv build/mpc-* build/mpc
+ touch $@
+
+
+# KERNEL HEADERS
+
+${STAMPS}/linux-headers: ${STAMPS}/linux-extract
+ cd ${TOP}/build/linux && ${GMAKE} ARCH=riscv HOSTCC=${CC} headers
+ rm -f ${TOP}/build/linux/usr/include/Makefile
+ rm -f ${TOP}/build/linux/usr/include/headers_check.pl
+ touch $@
+
+${STAMPS}/linux-hdrinst: ${STAMPS}/linux-headers
+ mkdir -p ${PREFIX}/${TARGET}
+ cd ${TOP}/build/linux && ${SUDO} cp -rf ${TOP}/build/linux/usr/include ${PREFIX}/${TARGET}/
+ touch $@
+
+# BINUTILS
+
+${STAMPS}/binutils-configure: ${STAMPS}/binutils-extract
+ mkdir -p ${TOP}/build/binutils/build
+ cd ${TOP}/build/binutils/build && ../configure \
+ --prefix=${PREFIX} \
+ --target=${TARGET} \
+ --with-system-zlib \
+ --with-arch=${ARCH} \
+ --disable-nls \
+ --disable-werror \
+ --disable-multilib
+ touch $@
+
+${STAMPS}/binutils-build: ${STAMPS}/binutils-configure
+ cd ${TOP}/build/binutils/build && ${GMAKE}
+ touch $@
+
+${STAMPS}/binutils-install: ${STAMPS}/binutils-build
+ cd ${TOP}/build/binutils/build && ${SUDO} ${GMAKE} install
+ touch $@
+
+# GCC
+
+${STAMPS}/gcc-configure: ${STAMPS}/gcc-extract ${STAMPS}/binutils-install ${STAMPS}/gmp ${STAMPS}/mpfr ${STAMPS}/mpc
+ mkdir -p ${TOP}/build/gcc/build
+ cd ${TOP}/build/gcc/build && ../configure \
+ --prefix=${PREFIX} \
+ --target=${TARGET} \
+ --with-system-zlib \
+ --with-arch=${ARCH} \
+ --with-newlib \
+ --without-headers \
+ --enable-languages=c \
+ --disable-nls \
+ --disable-multilib \
+ --disable-libssp \
+ --disable-libsanitizer \
+ --disable-libstdcxx \
+ --disable-libgomp \
+ --disable-libquadmath \
+ --disable-libvtv \
+ --disable-shared \
+ --enable-static \
+ --disable-threads
+ touch $@
+
+${STAMPS}/gcc-build: ${STAMPS}/gcc-configure
+ cd ${TOP}/build/gcc/build && ${GMAKE} all-gcc
+ touch $@
+
+${STAMPS}/gcc-install: ${STAMPS}/gcc-build
+ cd ${TOP}/build/gcc/build && ${SUDO} ${GMAKE} install-gcc
+ touch $@
+
+# MUSL
+
+${STAMPS}/musl-configure: ${STAMPS}/musl-extract ${STAMPS}/gcc-install
+ mkdir -p ${TOP}/build/musl/build
+ cd ${TOP}/build/musl/build && ../configure \
+ --prefix=${PREFIX}/${TARGET} \
+ --target=${TARGET} \
+ --disable-shared \
+ --disable-wrapper \
+ --enable-static
+ touch $@
+
+${STAMPS}/musl-build: ${STAMPS}/musl-configure ${STAMPS}/linux-hdrinst
+ cd ${TOP}/build/musl/build && ${GMAKE}
+ touch $@
+
+${STAMPS}/musl-install: ${STAMPS}/musl-build
+ cd ${TOP}/build/musl/build && ${SUDO} ${GMAKE} install
+ touch $@
+
+# LIBGCC
+
+${STAMPS}/libgcc-build: ${STAMPS}/gcc-install ${STAMPS}/musl-install
+ cd ${TOP}/build/gcc/build && ${GMAKE} all-target-libgcc
+ touch $@
+
+${STAMPS}/libgcc-install: ${STAMPS}/libgcc-build
+ cd ${TOP}/build/gcc/build && ${SUDO} ${GMAKE} install-target-libgcc
+ touch $@