summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorkx <kx@radix-linux.su>2026-10-09 18:00:15 +0300
committerkx <kx@radix-linux.su>2026-10-09 18:00:15 +0300
commit065da3509019b15dd0e678072e6be629e5330bef (patch)
tree69c934c9e786ac048b4fbe8f4c4c5571661521f4 /cpu
parentd130fe27fa753be02ed76fd9b277aa3c3d928eb9 (diff)
downloadlibmcpu-0.4.0.tar.xz
Version 0.4.00.4.0
Diffstat (limited to 'cpu')
-rw-r--r--cpu/Makefile.am162
-rw-r--r--cpu/cpu-byteorder.c116
-rw-r--r--cpu/cpu-context.c589
-rw-r--r--cpu/cpu-context.h120
-rw-r--r--cpu/cpu-errno.h160
-rw-r--r--cpu/cpu-instruction.c1649
-rw-r--r--cpu/cpu-instruction.h32
-rw-r--r--cpu/cpu-registers.c74
-rw-r--r--cpu/cpu-registers.h33
-rw-r--r--cpu/cpu-syscalls.c2174
-rw-r--r--cpu/cpu-syscalls.h59
-rw-r--r--cpu/cpu-sysdeps.h288
-rw-r--r--cpu/sysdeps/README19
-rw-r--r--cpu/sysdeps/generic/README2
-rwxr-xr-xcpu/sysdeps/i386/configure-fragment8
-rw-r--r--cpu/sysdeps/i386/i586/README2
-rw-r--r--cpu/sysdeps/i386/i686/README2
-rw-r--r--cpu/sysdeps/i386/i786/Implies2
-rw-r--r--cpu/sysdeps/i386/preconfigure12
-rw-r--r--cpu/sysdeps/i386/preconfigure.ac11
-rwxr-xr-xcpu/sysdeps/powerpc/configure-fragment8
-rw-r--r--cpu/sysdeps/powerpc/powerpc32/README2
-rw-r--r--cpu/sysdeps/powerpc/powerpc64/README2
-rw-r--r--cpu/sysdeps/powerpc/powerpc64le/README2
-rw-r--r--cpu/sysdeps/powerpc/preconfigure22
-rw-r--r--cpu/sysdeps/powerpc/preconfigure.ac21
-rwxr-xr-xcpu/sysdeps/sparc/configure-fragment8
-rw-r--r--cpu/sysdeps/sparc/preconfigure57
-rw-r--r--cpu/sysdeps/sparc/preconfigure.ac56
-rw-r--r--cpu/sysdeps/unix/sys-errno.c442
-rw-r--r--cpu/sysdeps/unix/sysv/linux/i386/i686/README2
-rw-r--r--cpu/sysdeps/unix/sysv/linux/i386/i786/Implies2
-rw-r--r--cpu/sysdeps/unix/sysv/linux/powerpc/powerpc32/README2
-rw-r--r--cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64/README2
-rw-r--r--cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64le/README2
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/README8
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-chown-linux.h66
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-mode-linux.h53
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-stat-linux.h124
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-time-linux.h64
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-access.c42
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chdir.c53
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chmod.c41
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chown.c45
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_getres.c48
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_gettime.c47
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_nanosleep.c93
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-close.c16
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-creat.c30
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-dup.c36
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchdir.c35
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchmod.c39
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchown.c42
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fcntl.c115
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fstat.c43
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fsync.c32
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-ftruncate.c39
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-getdents.c227
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-link.c34
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lseek.c35
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lstat.c43
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-mkdir.c69
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-open.c114
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-pipe2.c44
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-read.c21
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-readlink.c40
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rename.c34
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rmdir.c35
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-select.c109
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-stat.c42
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-symlink.c34
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-truncate.c58
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-unlink.c34
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-write.c21
-rw-r--r--cpu/sysdeps/unix/sysv/linux/x86_64/x32/README2
-rw-r--r--cpu/sysdeps/x86_64/64/README2
-rwxr-xr-xcpu/sysdeps/x86_64/configure-fragment8
-rw-r--r--cpu/sysdeps/x86_64/preconfigure79
-rw-r--r--cpu/sysdeps/x86_64/preconfigure.ac39
-rw-r--r--cpu/sysdeps/x86_64/x32/README2
80 files changed, 8381 insertions, 0 deletions
diff --git a/cpu/Makefile.am b/cpu/Makefile.am
new file mode 100644
index 0000000..c3a3eab
--- /dev/null
+++ b/cpu/Makefile.am
@@ -0,0 +1,162 @@
+
+sysnames = @sysnames@
+
+vpath %.c $(addprefix $(top_srcdir)/, $(sysnames))
+
+lib_LTLIBRARIES = libmcpu.la
+
+libmcpu_la_SOURCES = cpu-context.c cpu-context.h cpu-registers.c cpu-registers.h cpu-byteorder.c cpu-instruction.c cpu-instruction.h cpu-syscalls.c cpu-syscalls.h cpu-sysdeps.h cpu-errno.h
+
+nodist_libmcpu_la_SOURCES = sys-errno.c sys-open.c sys-creat.c sys-close.c sys-dup.c sys-read.c sys-write.c sys-lseek.c \
+ sys-link.c sys-unlink.c sys-chdir.c sys-mkdir.c sys-chmod.c sys-chown.c sys-access.c sys-rename.c sys-rmdir.c \
+ sys-symlink.c sys-readlink.c sys-stat.c sys-fstat.c sys-lstat.c sys-fcntl.c sys-pipe2.c sys-getdents.c sys-select.c sys-fsync.c sys-truncate.c sys-ftruncate.c sys-fchmod.c sys-fchown.c sys-fchdir.c sys-clock_gettime.c sys-clock_getres.c sys-clock_nanosleep.c
+
+libmcpu_la_CPPFLAGS = -I$(top_srcdir)/include $(LIBMPU_CPPFLAGS)
+libmcpu_la_CFLAGS = $(LIBMPU_CFLAGS)
+libmcpu_la_LIBADD = $(LIBMPU_LIBS)
+libmcpu_la_LDFLAGS = -version-info @LIBMCPU_LT_VERSION_INFO@ $(LIBMPU_LDFLAGS)
+
+# Automake's generated libtool compile rules rebuild a source pathname from
+# $(srcdir) and therefore lose the pathname selected by GNU make vpath.
+# These explicit rules compile the prerequisite path resolved by vpath ($<).
+
+libmcpu_la-sys-errno.lo: sys-errno.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-errno.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-errno.Tpo $(DEPDIR)/libmcpu_la-sys-errno.Plo
+
+libmcpu_la-sys-open.lo: sys-open.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-open.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-open.Tpo $(DEPDIR)/libmcpu_la-sys-open.Plo
+
+libmcpu_la-sys-creat.lo: sys-creat.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-creat.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-creat.Tpo $(DEPDIR)/libmcpu_la-sys-creat.Plo
+
+libmcpu_la-sys-close.lo: sys-close.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-close.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-close.Tpo $(DEPDIR)/libmcpu_la-sys-close.Plo
+
+libmcpu_la-sys-dup.lo: sys-dup.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-dup.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-dup.Tpo $(DEPDIR)/libmcpu_la-sys-dup.Plo
+
+libmcpu_la-sys-read.lo: sys-read.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-read.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-read.Tpo $(DEPDIR)/libmcpu_la-sys-read.Plo
+
+libmcpu_la-sys-write.lo: sys-write.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-write.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-write.Tpo $(DEPDIR)/libmcpu_la-sys-write.Plo
+
+libmcpu_la-sys-lseek.lo: sys-lseek.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-lseek.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-lseek.Tpo $(DEPDIR)/libmcpu_la-sys-lseek.Plo
+
+libmcpu_la-sys-link.lo: sys-link.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-link.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-link.Tpo $(DEPDIR)/libmcpu_la-sys-link.Plo
+
+libmcpu_la-sys-unlink.lo: sys-unlink.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-unlink.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-unlink.Tpo $(DEPDIR)/libmcpu_la-sys-unlink.Plo
+
+libmcpu_la-sys-chdir.lo: sys-chdir.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-chdir.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-chdir.Tpo $(DEPDIR)/libmcpu_la-sys-chdir.Plo
+
+libmcpu_la-sys-mkdir.lo: sys-mkdir.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-mkdir.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-mkdir.Tpo $(DEPDIR)/libmcpu_la-sys-mkdir.Plo
+
+libmcpu_la-sys-access.lo: sys-access.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-access.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-access.Tpo $(DEPDIR)/libmcpu_la-sys-access.Plo
+
+libmcpu_la-sys-rename.lo: sys-rename.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-rename.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-rename.Tpo $(DEPDIR)/libmcpu_la-sys-rename.Plo
+
+libmcpu_la-sys-rmdir.lo: sys-rmdir.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-rmdir.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-rmdir.Tpo $(DEPDIR)/libmcpu_la-sys-rmdir.Plo
+
+libmcpu_la-sys-symlink.lo: sys-symlink.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-symlink.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-symlink.Tpo $(DEPDIR)/libmcpu_la-sys-symlink.Plo
+
+libmcpu_la-sys-readlink.lo: sys-readlink.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-readlink.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-readlink.Tpo $(DEPDIR)/libmcpu_la-sys-readlink.Plo
+
+libmcpu_la-sys-stat.lo: sys-stat.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-stat.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-stat.Tpo $(DEPDIR)/libmcpu_la-sys-stat.Plo
+
+libmcpu_la-sys-fstat.lo: sys-fstat.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-fstat.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-fstat.Tpo $(DEPDIR)/libmcpu_la-sys-fstat.Plo
+
+libmcpu_la-sys-lstat.lo: sys-lstat.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-lstat.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-lstat.Tpo $(DEPDIR)/libmcpu_la-sys-lstat.Plo
+
+libmcpu_la-sys-chmod.lo: sys-chmod.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-chmod.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-chmod.Tpo $(DEPDIR)/libmcpu_la-sys-chmod.Plo
+
+libmcpu_la-sys-chown.lo: sys-chown.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-chown.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-chown.Tpo $(DEPDIR)/libmcpu_la-sys-chown.Plo
+
+libmcpu_la-sys-fcntl.lo: sys-fcntl.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-fcntl.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-fcntl.Tpo $(DEPDIR)/libmcpu_la-sys-fcntl.Plo
+
+libmcpu_la-sys-pipe2.lo: sys-pipe2.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-pipe2.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-pipe2.Tpo $(DEPDIR)/libmcpu_la-sys-pipe2.Plo
+
+libmcpu_la-sys-getdents.lo: sys-getdents.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-getdents.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-getdents.Tpo $(DEPDIR)/libmcpu_la-sys-getdents.Plo
+
+
+libmcpu_la-sys-select.lo: sys-select.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-select.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-select.Tpo $(DEPDIR)/libmcpu_la-sys-select.Plo
+
+libmcpu_la-sys-fsync.lo: sys-fsync.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-fsync.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-fsync.Tpo $(DEPDIR)/libmcpu_la-sys-fsync.Plo
+
+libmcpu_la-sys-truncate.lo: sys-truncate.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-truncate.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-truncate.Tpo $(DEPDIR)/libmcpu_la-sys-truncate.Plo
+
+libmcpu_la-sys-ftruncate.lo: sys-ftruncate.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-ftruncate.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-ftruncate.Tpo $(DEPDIR)/libmcpu_la-sys-ftruncate.Plo
+
+libmcpu_la-sys-fchmod.lo: sys-fchmod.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-fchmod.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-fchmod.Tpo $(DEPDIR)/libmcpu_la-sys-fchmod.Plo
+
+libmcpu_la-sys-fchown.lo: sys-fchown.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-fchown.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-fchown.Tpo $(DEPDIR)/libmcpu_la-sys-fchown.Plo
+
+libmcpu_la-sys-fchdir.lo: sys-fchdir.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-fchdir.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-fchdir.Tpo $(DEPDIR)/libmcpu_la-sys-fchdir.Plo
+
+libmcpu_la-sys-clock_gettime.lo: sys-clock_gettime.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-clock_gettime.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-clock_gettime.Tpo $(DEPDIR)/libmcpu_la-sys-clock_gettime.Plo
+
+libmcpu_la-sys-clock_getres.lo: sys-clock_getres.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-clock_getres.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-clock_getres.Tpo $(DEPDIR)/libmcpu_la-sys-clock_getres.Plo
+
+libmcpu_la-sys-clock_nanosleep.lo: sys-clock_nanosleep.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmcpu_la_CPPFLAGS) $(CPPFLAGS) $(libmcpu_la_CFLAGS) $(CFLAGS) -MT $@ -MD -MP -MF $(DEPDIR)/libmcpu_la-sys-clock_nanosleep.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libmcpu_la-sys-clock_nanosleep.Tpo $(DEPDIR)/libmcpu_la-sys-clock_nanosleep.Plo
diff --git a/cpu/cpu-byteorder.c b/cpu/cpu-byteorder.c
new file mode 100644
index 0000000..ebc612a
--- /dev/null
+++ b/cpu/cpu-byteorder.c
@@ -0,0 +1,116 @@
+/***************************************************************
+ __CPU_BYTEORDER.C
+
+ Byte-order accessors for canonical PROGRAM fields and
+ architectural data-object representation.
+
+ PART OF : CPU - library .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#include <string.h>
+#include <libmcpu.h>
+
+__mpu_uint16_t
+__cpu_data_get_u16( const __mpu_UNIT_t *p )
+{
+ __mpu_uint16_t v = 0;
+ if( p ) memcpy( &v, p, sizeof(v) );
+ return( v );
+}
+
+__mpu_uint32_t
+__cpu_data_get_u32( const __mpu_UNIT_t *p )
+{
+ __mpu_uint32_t v = 0;
+ if( p ) memcpy( &v, p, sizeof(v) );
+ return( v );
+}
+
+__mpu_uint64_t
+__cpu_data_get_u64( const __mpu_UNIT_t *p )
+{
+ __mpu_uint64_t v = 0;
+ if( p ) memcpy( &v, p, sizeof(v) );
+ return( v );
+}
+
+void
+__cpu_data_put_u16( __mpu_UNIT_t *p, __mpu_uint16_t v )
+{
+ if( p ) memcpy( p, &v, sizeof(v) );
+}
+
+void
+__cpu_data_put_u32( __mpu_UNIT_t *p, __mpu_uint32_t v )
+{
+ if( p ) memcpy( p, &v, sizeof(v) );
+}
+
+void
+__cpu_data_put_u64( __mpu_UNIT_t *p, __mpu_uint64_t v )
+{
+ if( p ) memcpy( p, &v, sizeof(v) );
+}
+
+__mpu_uint16_t
+__cpu_code_get_u16( const __mpu_UNIT_t *p )
+{
+ if( !p ) return( 0 );
+ return (__mpu_uint16_t)(((__mpu_uint16_t)p[0] << 8) |
+ (__mpu_uint16_t)p[1]);
+}
+
+__mpu_uint32_t
+__cpu_code_get_u32( const __mpu_UNIT_t *p )
+{
+ __mpu_uint32_t v;
+ if( !p ) return( 0 );
+ v = ((__mpu_uint32_t)p[0] << 24);
+ v |= ((__mpu_uint32_t)p[1] << 16);
+ v |= ((__mpu_uint32_t)p[2] << 8);
+ v |= (__mpu_uint32_t)p[3];
+ return( v );
+}
+
+__mpu_uint64_t
+__cpu_code_get_u64( const __mpu_UNIT_t *p )
+{
+ __mpu_uint64_t v = 0;
+ int k;
+ if( !p ) return( 0 );
+ for( k = 0; k < 8; ++k ) v = ( v << 8 ) | p[k];
+ return( v );
+}
+
+void
+__cpu_code_put_u16( __mpu_UNIT_t *p, __mpu_uint16_t v )
+{
+ if( !p ) return;
+ p[0] = (__mpu_UNIT_t)(v >> 8);
+ p[1] = (__mpu_UNIT_t)v;
+}
+
+void
+__cpu_code_put_u32( __mpu_UNIT_t *p, __mpu_uint32_t v )
+{
+ if( !p ) return;
+ p[0] = (__mpu_UNIT_t)(v >> 24);
+ p[1] = (__mpu_UNIT_t)(v >> 16);
+ p[2] = (__mpu_UNIT_t)(v >> 8);
+ p[3] = (__mpu_UNIT_t)v;
+}
+
+void
+__cpu_code_put_u64( __mpu_UNIT_t *p, __mpu_uint64_t v )
+{
+ int k;
+ if( !p ) return;
+ for( k = 7; k >= 0; --k )
+ {
+ p[k] = (__mpu_UNIT_t)( v & __mpu_UINT64_C( 0xff ) );
+ v >>= 8;
+ }
+}
diff --git a/cpu/cpu-context.c b/cpu/cpu-context.c
new file mode 100644
index 0000000..e77d93a
--- /dev/null
+++ b/cpu/cpu-context.c
@@ -0,0 +1,589 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <libmcpu.h>
+#include <cpu-context.h>
+#include <cpu-syscalls.h>
+
+__thread struct __cpu_context cctx;
+__thread struct __cpu_context *pcctx;
+
+static __mpu_uint32_t
+__cpu_get_mpu_psw( void )
+{
+ __mpu_uint32_t psw = 0;
+ if( __mpu_gta() ) psw |= PSW_AF_MASK;
+ if( __mpu_gtc() ) psw |= PSW_CF_MASK;
+ if( __mpu_gto() ) psw |= PSW_OF_MASK;
+ if( __mpu_gts() ) psw |= PSW_SF_MASK;
+ if( __mpu_gtp() ) psw |= PSW_PF_MASK;
+ if( __mpu_gtz() ) psw |= PSW_ZF_MASK;
+ if( __mpu_gtr() ) psw |= PSW_RF_MASK;
+ if( __mpu_gtv() ) psw |= PSW_VF_MASK;
+ if( __mpu_gtdom() ) psw |= PSW_DOMF_MASK;
+ if( __mpu_gtsng() ) psw |= PSW_SNGF_MASK;
+ if( __mpu_gtovf() ) psw |= PSW_OVFF_MASK;
+ if( __mpu_gtudf() ) psw |= PSW_UDFF_MASK;
+ if( __mpu_gttls() ) psw |= PSW_TLSF_MASK;
+ if( __mpu_gtpls() ) psw |= PSW_PLSF_MASK;
+ if( __mpu_gtind() ) psw |= PSW_INDF_MASK;
+ if( __mpu_gtinx() ) psw |= PSW_INXF_MASK;
+ return( psw );
+}
+
+static void
+__cpu_set_mpu_psw( __mpu_uint32_t p )
+{
+#define SF(mask,st,cl) do{if(p&(mask)) st(); else cl();}while(0)
+ SF( PSW_AF_MASK, __mpu_sta, __mpu_cla );
+ SF( PSW_CF_MASK, __mpu_stc, __mpu_clc );
+ SF( PSW_OF_MASK, __mpu_sto, __mpu_clo );
+ SF( PSW_SF_MASK, __mpu_sts, __mpu_cls );
+ SF( PSW_PF_MASK, __mpu_stp, __mpu_clp );
+ SF( PSW_ZF_MASK, __mpu_stz, __mpu_clz );
+ SF( PSW_RF_MASK, __mpu_str, __mpu_clr );
+ SF( PSW_VF_MASK, __mpu_stv, __mpu_clv );
+ SF( PSW_DOMF_MASK, __mpu_stdom, __mpu_cldom );
+ SF( PSW_SNGF_MASK, __mpu_stsng, __mpu_clsng );
+ SF( PSW_OVFF_MASK, __mpu_stovf, __mpu_clovf );
+ SF( PSW_UDFF_MASK, __mpu_studf, __mpu_cludf );
+ SF( PSW_TLSF_MASK, __mpu_sttls, __mpu_cltls );
+ SF( PSW_PLSF_MASK, __mpu_stpls, __mpu_clpls );
+ SF( PSW_INDF_MASK, __mpu_stind, __mpu_clind );
+ SF( PSW_INXF_MASK, __mpu_stinx, __mpu_clinx );
+#undef SF
+}
+
+/*
+ * Host backing store. Architectural size and host mapping capacity are kept
+ * separate deliberately: the latter is rounded to the host page size only so
+ * mmap()/mprotect()/munmap() can operate on complete pages. CPU bounds checks
+ * must always use the architectural size fields.
+ */
+static size_t
+host_page_size( void )
+{
+ static size_t page;
+ long n;
+ if( page ) return( page );
+ n = sysconf( _SC_PAGESIZE );
+ if( n <= 0 ) return( 0 );
+ page = (size_t)n;
+ return( page );
+}
+
+static void
+mem_unmap( __mpu_UNIT_t **p, __mpu_uint64_t *sz, __mpu_uint64_t *cap )
+{
+ if( *p && *cap && (__mpu_uint64_t)(size_t)*cap == *cap )
+ (void)munmap( (void *)*p, (size_t)*cap );
+ *p = 0;
+ *sz = 0;
+ *cap = 0;
+}
+
+static int mem_alloc( __mpu_UNIT_t **p, __mpu_uint64_t *sz, __mpu_uint64_t *cap,
+ __mpu_uint64_t n)
+{
+ size_t page, need, mapped, max = (size_t)-1;
+ void *q;
+
+ mem_unmap( p, sz, cap );
+ if( !n ) return( 0 );
+ if( (__mpu_uint64_t)(size_t)n != n ) return( -1 );
+
+ page = host_page_size();
+ if( !page ) return( -1 );
+ need = (size_t)n;
+ if( need > max - ( page - 1U ) ) return( -1 );
+ mapped = ( ( need + page - 1U ) / page ) * page;
+ if( !mapped ) return( -1 );
+
+ q = mmap( (void *)0, mapped, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if( q == MAP_FAILED ) return( -1 );
+
+ /* Anonymous mappings are zero-filled by the host kernel. */
+ *p = (__mpu_UNIT_t *)q;
+ *sz = n;
+ *cap = (__mpu_uint64_t)mapped;
+ return( 0 );
+}
+
+void
+__cpu_init( void )
+{
+ pcctx = &cctx;
+ __cpu_cwd_context_free();
+ __cpu_fd_context_free();
+ mem_unmap( &cctx._program, &cctx._program_size, &cctx._program_capacity );
+ mem_unmap( &cctx._data, &cctx._data_size, &cctx._data_capacity );
+ mem_unmap( &cctx._stack, &cctx._stack_size, &cctx._stack_capacity );
+ mem_unmap( &cctx._control, &cctx._control_size, &cctx._control_capacity );
+ mem_unmap( &cctx._input, &cctx._input_size, &cctx._input_capacity );
+ mem_unmap( &cctx._output, &cctx._output_size, &cctx._output_capacity );
+ mem_unmap( &cctx._trace, &cctx._trace_size, &cctx._trace_capacity );
+ mem_unmap( &cctx._heap, &cctx._heap_size, &cctx._heap_capacity );
+ memset( &cctx, 0, sizeof( cctx ) );
+ pcctx = &cctx;
+ __cpu_fd_context_init();
+ __cpu_cwd_context_init();
+ __mpu_init();
+}
+
+void
+__cpu_free_context( void )
+{
+ if( !pcctx ) pcctx = &cctx;
+ __cpu_cwd_context_free();
+ __cpu_fd_context_free();
+ mem_unmap( &pcctx->_program, &pcctx->_program_size, &pcctx->_program_capacity );
+ mem_unmap( &pcctx->_data, &pcctx->_data_size, &pcctx->_data_capacity );
+ mem_unmap( &pcctx->_stack, &pcctx->_stack_size, &pcctx->_stack_capacity );
+ mem_unmap( &pcctx->_control, &pcctx->_control_size, &pcctx->_control_capacity );
+ mem_unmap( &pcctx->_input, &pcctx->_input_size, &pcctx->_input_capacity );
+ mem_unmap( &pcctx->_output, &pcctx->_output_size, &pcctx->_output_capacity );
+ mem_unmap( &pcctx->_trace, &pcctx->_trace_size, &pcctx->_trace_capacity );
+ mem_unmap( &pcctx->_heap, &pcctx->_heap_size, &pcctx->_heap_capacity );
+ pcctx->_heap_brk = 0;
+ pcctx->_heap_limit = 0;
+ pcctx->_pc = 0;
+ pcctx->_sp = 0;
+ pcctx->_fp = 0;
+ pcctx->_psw = 0;
+ pcctx->_stop_reason = CPU_STOP_NONE;
+ pcctx->_exit_status = 0;
+ __mpu_free_context();
+}
+
+__mpu_uint64_t *
+__ptr_cpu_pc( void )
+{
+ return( &cctx._pc );
+}
+
+__mpu_uint64_t *
+__ptr_cpu_sp( void )
+{
+ return( &cctx._sp );
+}
+
+__mpu_uint64_t *
+__ptr_cpu_fp( void )
+{
+ return( &cctx._fp );
+}
+
+__mpu_UNIT_t *
+__ptr_cpu_registers( void )
+{
+ return( &cctx._regs[0] );
+}
+
+int
+__cpu_program_alloc( __mpu_uint64_t n )
+{
+ return( mem_alloc( &cctx._program, &cctx._program_size, &cctx._program_capacity, n ) );
+}
+
+void
+__cpu_program_free( void )
+{
+ mem_unmap( &cctx._program, &cctx._program_size, &cctx._program_capacity );
+ cctx._pc = 0;
+}
+
+int
+__cpu_program_protect( void )
+{
+ if( !cctx._program ) return( cctx._program_size == 0 ? 0 : -1 );
+ if( !cctx._program_capacity ||
+ (__mpu_uint64_t)(size_t)cctx._program_capacity != cctx._program_capacity)
+ return( -1 );
+ return( mprotect( (void *)cctx._program, (size_t)cctx._program_capacity, PROT_READ ) == 0 ? 0 : -1 );
+}
+
+__mpu_UNIT_t *
+__cpu_program_ptr( void )
+{
+ return( cctx._program );
+}
+
+__mpu_uint64_t
+__cpu_program_size( void )
+{
+ return( cctx._program_size );
+}
+
+int
+__cpu_program_set( const __mpu_UNIT_t *d, __mpu_uint64_t n )
+{
+ if( __cpu_program_alloc( n ) ) return( -1 );
+ if( n && d ) memcpy( cctx._program, d, (size_t)n );
+ if( __cpu_program_protect() )
+ {
+ __cpu_program_free();
+ return( -1 );
+ }
+ return( 0 );
+}
+
+int
+__cpu_data_alloc( __mpu_uint64_t n )
+{
+ return( mem_alloc( &cctx._data, &cctx._data_size, &cctx._data_capacity, n ) );
+}
+
+void
+__cpu_data_free( void )
+{
+ mem_unmap( &cctx._data, &cctx._data_size, &cctx._data_capacity );
+}
+
+__mpu_UNIT_t *
+__cpu_data_ptr( void )
+{
+ return( cctx._data );
+}
+
+__mpu_uint64_t
+__cpu_data_size( void )
+{
+ return( cctx._data_size );
+}
+
+int
+__cpu_data_set( const __mpu_UNIT_t *d, __mpu_uint64_t n )
+{
+ if( __cpu_data_alloc( n ) ) return( -1 );
+ if( n && d ) memcpy( cctx._data, d, (size_t)n );
+ return( 0 );
+}
+
+int
+__cpu_stack_alloc( __mpu_uint64_t n )
+{
+ int rc = mem_alloc( &cctx._stack, &cctx._stack_size, &cctx._stack_capacity, n );
+ cctx._sp = ( rc == 0 ) ? n : 0;
+ cctx._fp = ( rc == 0 ) ? n : 0;
+ return( rc );
+}
+
+void
+__cpu_stack_free( void )
+{
+ mem_unmap( &cctx._stack, &cctx._stack_size, &cctx._stack_capacity );
+ cctx._sp = 0;
+ cctx._fp = 0;
+}
+
+__mpu_UNIT_t *
+__cpu_stack_ptr( void )
+{
+ return( cctx._stack );
+}
+
+__mpu_uint64_t
+__cpu_stack_size( void )
+{
+ return( cctx._stack_size );
+}
+
+#define DEFINE_SEGMENT_API(name,field) \
+int __cpu_##name##_alloc(__mpu_uint64_t n){return mem_alloc(&cctx._##field,&cctx._##field##_size,&cctx._##field##_capacity,n);} \
+void __cpu_##name##_free(void){mem_unmap(&cctx._##field,&cctx._##field##_size,&cctx._##field##_capacity);} \
+__mpu_UNIT_t *__cpu_##name##_ptr(void){return cctx._##field;} \
+__mpu_uint64_t __cpu_##name##_size(void){return cctx._##field##_size;} \
+int __cpu_##name##_set(const __mpu_UNIT_t *d,__mpu_uint64_t n){if(__cpu_##name##_alloc(n))return -1;if(n&&d)memcpy(cctx._##field,d,(size_t)n);return 0;}
+
+DEFINE_SEGMENT_API( control, control )
+DEFINE_SEGMENT_API( input, input )
+DEFINE_SEGMENT_API( output, output )
+DEFINE_SEGMENT_API( trace, trace )
+#undef DEFINE_SEGMENT_API
+
+static int
+__cpu_heap_grow( __mpu_uint64_t new_size )
+{
+ size_t page, need, mapped, max = (size_t)-1;
+ __mpu_UNIT_t *p;
+
+ if( new_size <= cctx._heap_capacity ) return( 0 );
+ if( (__mpu_uint64_t)(size_t)new_size != new_size ) return( -1 );
+
+ page = host_page_size();
+ if( !page ) return( -1 );
+
+ need = (size_t)new_size;
+ if( need > max - (page - 1U) ) return( -1 );
+
+ mapped = ((need + page - 1U) / page) * page;
+ if( !mapped ) return( -1 );
+
+ p = (__mpu_UNIT_t *)mmap( (void *)0, mapped, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
+ if( p == (__mpu_UNIT_t *)MAP_FAILED ) return( -1 );
+
+ if( cctx._heap && cctx._heap_size )
+ memcpy( p, cctx._heap, (size_t)cctx._heap_size );
+
+ if( cctx._heap && cctx._heap_capacity )
+ (void)munmap( (void *)cctx._heap, (size_t)cctx._heap_capacity );
+
+ cctx._heap = p;
+ cctx._heap_capacity = (__mpu_uint64_t)mapped;
+
+ return( 0 );
+
+} /* End of __cpu_heap_grow() */
+
+
+int
+__cpu_heap_alloc( __mpu_uint64_t initial_size, __mpu_uint64_t maximum_size )
+{
+ int rc;
+
+ if( maximum_size < initial_size ||
+ maximum_size < CPU_HEAP_BEGIN || initial_size < CPU_HEAP_BEGIN )
+ return( -1 );
+
+ rc = mem_alloc( &cctx._heap, &cctx._heap_size,
+ &cctx._heap_capacity, initial_size );
+ if( rc )
+ {
+ cctx._heap_brk = 0;
+ cctx._heap_limit = 0;
+ return( rc );
+ }
+
+ cctx._heap_brk = CPU_HEAP_BEGIN;
+ cctx._heap_limit = maximum_size;
+
+ return( 0 );
+
+} /* End of __cpu_heap_alloc() */
+
+
+void
+__cpu_heap_free( void )
+{
+ mem_unmap( &cctx._heap, &cctx._heap_size, &cctx._heap_capacity );
+ cctx._heap_brk = 0;
+ cctx._heap_limit = 0;
+
+} /* End of __cpu_heap_free() */
+
+
+__mpu_uint64_t
+__cpu_heap_brk( __mpu_uint64_t new_brk )
+{
+ __mpu_uint64_t old_brk = cctx._heap_brk;
+
+ if( !cctx._heap || cctx._heap_limit < CPU_HEAP_BEGIN )
+ return( old_brk );
+
+ if( new_brk < CPU_HEAP_BEGIN || new_brk > cctx._heap_limit )
+ return( old_brk );
+
+ if( new_brk == old_brk ) return( old_brk );
+
+ if( new_brk < old_brk )
+ {
+ memset( cctx._heap + (size_t)new_brk, 0,
+ (size_t)(old_brk - new_brk) );
+ cctx._heap_brk = new_brk;
+ return( new_brk );
+ }
+
+ if( new_brk <= cctx._heap_size )
+ {
+ cctx._heap_brk = new_brk;
+ return( new_brk );
+ }
+
+ if( new_brk <= cctx._heap_capacity )
+ {
+ memset( cctx._heap + (size_t)cctx._heap_size, 0,
+ (size_t)(new_brk - cctx._heap_size) );
+ cctx._heap_size = new_brk;
+ cctx._heap_brk = new_brk;
+ return( new_brk );
+ }
+
+ if( __cpu_heap_grow( new_brk ) != 0 ) return( old_brk );
+
+ cctx._heap_size = new_brk;
+ cctx._heap_brk = new_brk;
+
+ return( new_brk );
+
+} /* End of __cpu_heap_brk() */
+
+
+__mpu_UNIT_t *
+__cpu_heap_ptr( void )
+{
+ return( cctx._heap );
+}
+
+__mpu_uint64_t
+__cpu_heap_size( void )
+{
+ return( cctx._heap_size );
+}
+
+__mpu_uint64_t
+__cpu_heap_limit( void )
+{
+ return( cctx._heap_limit );
+}
+
+cpu_stop_reason
+__cpu_get_stop_reason( void )
+{
+ return( cctx._stop_reason );
+}
+
+__mpu_int32_t
+__cpu_get_exit_status( void )
+{
+ return( cctx._exit_status );
+}
+
+void
+__cpu_clear_stop_reason( void )
+{
+ cctx._stop_reason = CPU_STOP_NONE;
+ cctx._exit_status = 0;
+}
+
+__mpu_uint32_t
+__cpu_get_psw( void )
+{
+ return( ( __cpu_get_mpu_psw() & PSW_MPU_MASK ) | ( cctx._psw & PSW_CPU_MASK ) );
+}
+
+void
+__cpu_set_psw( __mpu_uint32_t p )
+{
+ __cpu_set_mpu_psw( p & PSW_MPU_MASK );
+ cctx._psw = p & PSW_CPU_MASK;
+}
+
+void
+__cpu_clear_psw( void )
+{
+ __mpu_clear_mflags();
+ cctx._psw = 0;
+}
+
+int
+__cpu_gth( void )
+{
+ return( (int)__CFLAG( PSW_HF_MASK, PSW_HF_SHIFT ) );
+}
+
+int
+__cpu_gtt( void )
+{
+ return( (int)__CFLAG( PSW_TF_MASK, PSW_TF_SHIFT ) );
+}
+
+int
+__cpu_gti( void )
+{
+ return( (int)__CFLAG( PSW_IF_MASK, PSW_IF_SHIFT ) );
+}
+
+void
+__cpu_sth( void )
+{
+ __SET_CFLAG( PSW_HF_MASK );
+}
+
+void
+__cpu_stt( void )
+{
+ __SET_CFLAG( PSW_TF_MASK );
+}
+
+void
+__cpu_sti( void )
+{
+ __SET_CFLAG( PSW_IF_MASK );
+}
+
+void
+__cpu_clh( void )
+{
+ __CLEAR_CFLAG( PSW_HF_MASK );
+}
+
+void
+__cpu_clt( void )
+{
+ __CLEAR_CFLAG( PSW_TF_MASK );
+}
+
+void
+__cpu_cli( void )
+{
+ __CLEAR_CFLAG( PSW_IF_MASK );
+}
+
+void
+__cpu_cmh( void )
+{
+ __INVERT_CFLAG( PSW_HF_MASK );
+}
+
+void
+__cpu_cmt( void )
+{
+ __INVERT_CFLAG( PSW_TF_MASK );
+}
+
+void
+__cpu_cmi( void )
+{
+ __INVERT_CFLAG( PSW_IF_MASK );
+}
+
+int
+__cpu_gtmode( void )
+{
+ return( (int)( ( cctx._psw & PSW_MODE_MASK ) >> PSW_MODE_SHIFT ) );
+}
+
+int
+__cpu_stmode( unsigned int m )
+{
+ if( m > 3 ) return( -1 );
+ cctx._psw &= ~PSW_MODE_MASK;
+ cctx._psw |= ( (__mpu_uint32_t)m << PSW_MODE_SHIFT ) & PSW_MODE_MASK;
+ return( 0 );
+}
+
+int
+__cpu_ptr_make( __mpu_uint64_t *ptr, unsigned int segment, __mpu_uint64_t offset )
+{
+ if( !ptr || segment > CPU_PTR_SEG_MAX || offset > CPU_PTR_OFFSET_MASK ) return( -1 );
+ *ptr = ( (__mpu_uint64_t)segment << CPU_PTR_SEG_SHIFT ) | offset;
+ return( 0 );
+}
+
+unsigned int
+__cpu_ptr_segment( __mpu_uint64_t ptr )
+{
+ return( (unsigned int)( ( ptr & CPU_PTR_SEG_MASK ) >> CPU_PTR_SEG_SHIFT ) );
+}
+
+__mpu_uint64_t
+__cpu_ptr_offset( __mpu_uint64_t ptr )
+{
+ return( ptr & CPU_PTR_OFFSET_MASK );
+}
diff --git a/cpu/cpu-context.h b/cpu/cpu-context.h
new file mode 100644
index 0000000..1957df9
--- /dev/null
+++ b/cpu/cpu-context.h
@@ -0,0 +1,120 @@
+/***************************************************************
+ __CPU_CONTEXT.H
+
+ This file contains CPU CONTEXT operation functions & data
+ declarations.
+
+ PART OF : CPU - library .
+ USAGE : Internal only .
+ NOTE : Include "libcpu.h" before this FILE .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+#ifndef __CPU_CONTEXT_H
+#define __CPU_CONTEXT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CPU_GUEST_FD_MAX 256
+
+typedef struct __cpu_fd_entry
+{
+ int host_fd;
+ unsigned int owned;
+ unsigned int flags;
+} __cpu_fd_entry;
+
+typedef struct __cpu_context cpu_context;
+struct __cpu_context
+{
+ __mpu_uint64_t _pc;
+ __mpu_uint64_t _sp;
+ __mpu_uint64_t _fp;
+ __mpu_uint32_t _psw;
+ cpu_stop_reason _stop_reason;
+ __mpu_int32_t _exit_status;
+
+ __mpu_UNIT_t *_program;
+ __mpu_uint64_t _program_size;
+ __mpu_uint64_t _program_capacity;
+ __mpu_UNIT_t *_data;
+ __mpu_uint64_t _data_size;
+ __mpu_uint64_t _data_capacity;
+ __mpu_UNIT_t *_stack;
+ __mpu_uint64_t _stack_size;
+ __mpu_uint64_t _stack_capacity;
+ __mpu_UNIT_t *_control;
+ __mpu_uint64_t _control_size;
+ __mpu_uint64_t _control_capacity;
+ __mpu_UNIT_t *_input;
+ __mpu_uint64_t _input_size;
+ __mpu_uint64_t _input_capacity;
+ __mpu_UNIT_t *_output;
+ __mpu_uint64_t _output_size;
+ __mpu_uint64_t _output_capacity;
+ __mpu_UNIT_t *_trace;
+ __mpu_uint64_t _trace_size;
+ __mpu_uint64_t _trace_capacity;
+ __mpu_UNIT_t *_heap;
+ __mpu_uint64_t _heap_brk;
+ __mpu_uint64_t _heap_size;
+ __mpu_uint64_t _heap_capacity;
+ __mpu_uint64_t _heap_limit;
+
+ int _fd_initialized;
+ __cpu_fd_entry _fd[CPU_GUEST_FD_MAX];
+
+ int _cwd_initialized;
+ int _cwd_fd;
+
+ __mpu_UNIT_t _regs[CPU_REGISTERS_MEM_SIZE_IN_UNITS];
+};
+
+extern __thread struct __cpu_context *pcctx;
+
+#define __PC (pcctx->_pc)
+#define __SP (pcctx->_sp)
+#define __FP (pcctx->_fp)
+#define __REGS ((__mpu_UNIT_t *)&pcctx->_regs[0])
+#define __PROGRAM (pcctx->_program)
+#define __PSIZE (pcctx->_program_size)
+#define __PCAP (pcctx->_program_capacity)
+#define __DATA (pcctx->_data)
+#define __DSIZE (pcctx->_data_size)
+#define __DCAP (pcctx->_data_capacity)
+#define __STACK (pcctx->_stack)
+#define __SSIZE (pcctx->_stack_size)
+#define __SCAP (pcctx->_stack_capacity)
+#define __CONTROL (pcctx->_control)
+#define __CSIZE (pcctx->_control_size)
+#define __CCAP (pcctx->_control_capacity)
+#define __INPUT (pcctx->_input)
+#define __ISIZE (pcctx->_input_size)
+#define __ICAP (pcctx->_input_capacity)
+#define __OUTPUT (pcctx->_output)
+#define __OSIZE (pcctx->_output_size)
+#define __OCAP (pcctx->_output_capacity)
+#define __TRACE (pcctx->_trace)
+#define __TSIZE (pcctx->_trace_size)
+#define __TCAP (pcctx->_trace_capacity)
+#define __HEAP (pcctx->_heap)
+#define __HBRK (pcctx->_heap_brk)
+#define __HSIZE (pcctx->_heap_size)
+#define __HCAP (pcctx->_heap_capacity)
+#define __HLIMIT (pcctx->_heap_limit)
+#define __STOP_REASON (pcctx->_stop_reason)
+#define __EXIT_STATUS (pcctx->_exit_status)
+#define __CPU_PSW (pcctx->_psw)
+#define __SET_CFLAG(mask) (pcctx->_psw |= (mask))
+#define __CLEAR_CFLAG(mask) (pcctx->_psw &= ~(mask))
+#define __INVERT_CFLAG(mask) (pcctx->_psw ^= (mask))
+#define __CFLAG(mask,shift) ((pcctx->_psw & (mask)) >> (shift))
+
+extern __mpu_uint64_t __cpu_heap_brk( __mpu_uint64_t new_brk );
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/cpu/cpu-errno.h b/cpu/cpu-errno.h
new file mode 100644
index 0000000..20fb4c9
--- /dev/null
+++ b/cpu/cpu-errno.h
@@ -0,0 +1,160 @@
+/***************************************************************
+ __CPU_ERRNO.H
+
+ This file contains stable MCPU system-call error numbers.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_ERRNO_H
+#define __CPU_ERRNO_H
+
+#define __MCPU_EPERM 1 /* Operation not permitted */
+#define __MCPU_ENOENT 2 /* No such file or directory */
+#define __MCPU_ESRCH 3 /* No such process */
+#define __MCPU_EINTR 4 /* Interrupted system call */
+#define __MCPU_EIO 5 /* I/O error */
+#define __MCPU_ENXIO 6 /* No such device or address */
+#define __MCPU_E2BIG 7 /* Argument list too long */
+#define __MCPU_ENOEXEC 8 /* Exec format error */
+#define __MCPU_EBADF 9 /* Bad file number */
+#define __MCPU_ECHILD 10 /* No child processes */
+#define __MCPU_EAGAIN 11 /* Try again */
+#define __MCPU_ENOMEM 12 /* Out of memory */
+#define __MCPU_EACCES 13 /* Permission denied */
+#define __MCPU_EFAULT 14 /* Bad address */
+#define __MCPU_ENOTBLK 15 /* Block device required */
+#define __MCPU_EBUSY 16 /* Device or resource busy */
+#define __MCPU_EEXIST 17 /* File exists */
+#define __MCPU_EXDEV 18 /* Cross-device link */
+#define __MCPU_ENODEV 19 /* No such device */
+#define __MCPU_ENOTDIR 20 /* Not a directory */
+#define __MCPU_EISDIR 21 /* Is a directory */
+#define __MCPU_EINVAL 22 /* Invalid argument */
+#define __MCPU_ENFILE 23 /* File table overflow */
+#define __MCPU_EMFILE 24 /* Too many open files */
+#define __MCPU_ENOTTY 25 /* Not a typewriter */
+#define __MCPU_ETXTBSY 26 /* Text file busy */
+#define __MCPU_EFBIG 27 /* File too large */
+#define __MCPU_ENOSPC 28 /* No space left on device */
+#define __MCPU_ESPIPE 29 /* Illegal seek */
+#define __MCPU_EROFS 30 /* Read-only file system */
+#define __MCPU_EMLINK 31 /* Too many links */
+#define __MCPU_EPIPE 32 /* Broken pipe */
+#define __MCPU_EDOM 33 /* Math argument out of domain */
+#define __MCPU_ERANGE 34 /* Math result not representable */
+#define __MCPU_EDEADLK 35 /* Resource deadlock would occur */
+#define __MCPU_ENAMETOOLONG 36 /* File name too long */
+#define __MCPU_ENOLCK 37 /* No record locks available */
+#define __MCPU_ENOSYS 38 /* Invalid system call number */
+#define __MCPU_ENOTEMPTY 39 /* Directory not empty */
+#define __MCPU_ELOOP 40 /* Too many symbolic links encountered */
+
+#define __MCPU_EWOULDBLOCK __MCPU_EAGAIN
+
+#define __MCPU_ENOMSG 42 /* No message of desired type */
+#define __MCPU_EIDRM 43 /* Identifier removed */
+#define __MCPU_ECHRNG 44 /* Channel number out of range */
+#define __MCPU_EL2NSYNC 45 /* Level 2 not synchronized */
+#define __MCPU_EL3HLT 46 /* Level 3 halted */
+#define __MCPU_EL3RST 47 /* Level 3 reset */
+#define __MCPU_ELNRNG 48 /* Link number out of range */
+#define __MCPU_EUNATCH 49 /* Protocol driver not attached */
+#define __MCPU_ENOCSI 50 /* No CSI structure available */
+#define __MCPU_EL2HLT 51 /* Level 2 halted */
+#define __MCPU_EBADE 52 /* Invalid exchange */
+#define __MCPU_EBADR 53 /* Invalid request descriptor */
+#define __MCPU_EXFULL 54 /* Exchange full */
+#define __MCPU_ENOANO 55 /* No anode */
+#define __MCPU_EBADRQC 56 /* Invalid request code */
+#define __MCPU_EBADSLT 57 /* Invalid slot */
+
+#define __MCPU_EDEADLOCK __MCPU_EDEADLK
+
+#define __MCPU_EBFONT 59 /* Bad font file format */
+#define __MCPU_ENOSTR 60 /* Device not a stream */
+#define __MCPU_ENODATA 61 /* No data available */
+#define __MCPU_ETIME 62 /* Timer expired */
+#define __MCPU_ENOSR 63 /* Out of streams resources */
+#define __MCPU_ENONET 64 /* Machine is not on the network */
+#define __MCPU_ENOPKG 65 /* Package not installed */
+#define __MCPU_EREMOTE 66 /* Object is remote */
+#define __MCPU_ENOLINK 67 /* Link has been severed */
+#define __MCPU_EADV 68 /* Advertise error */
+#define __MCPU_ESRMNT 69 /* Srmount error */
+#define __MCPU_ECOMM 70 /* Communication error on send */
+#define __MCPU_EPROTO 71 /* Protocol error */
+#define __MCPU_EMULTIHOP 72 /* Multihop attempted */
+#define __MCPU_EDOTDOT 73 /* RFS specific error */
+#define __MCPU_EBADMSG 74 /* Not a data message */
+#define __MCPU_EOVERFLOW 75 /* Value too large for defined data type */
+#define __MCPU_ENOTUNIQ 76 /* Name not unique on network */
+#define __MCPU_EBADFD 77 /* File descriptor in bad state */
+#define __MCPU_EREMCHG 78 /* Remote address changed */
+#define __MCPU_ELIBACC 79 /* Cannot access a needed shared library */
+#define __MCPU_ELIBBAD 80 /* Accessing a corrupted shared library */
+#define __MCPU_ELIBSCN 81 /* .lib section in a.out corrupted */
+#define __MCPU_ELIBMAX 82 /* Too many shared libraries */
+#define __MCPU_ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define __MCPU_EILSEQ 84 /* Illegal byte sequence */
+#define __MCPU_ERESTART 85 /* Interrupted syscall should be restarted */
+#define __MCPU_ESTRPIPE 86 /* Streams pipe error */
+#define __MCPU_EUSERS 87 /* Too many users */
+#define __MCPU_ENOTSOCK 88 /* Socket operation on non-socket */
+#define __MCPU_EDESTADDRREQ 89 /* Destination address required */
+#define __MCPU_EMSGSIZE 90 /* Message too long */
+#define __MCPU_EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define __MCPU_ENOPROTOOPT 92 /* Protocol not available */
+#define __MCPU_EPROTONOSUPPORT 93 /* Protocol not supported */
+#define __MCPU_ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define __MCPU_EOPNOTSUPP 95 /* Operation not supported */
+#define __MCPU_EPFNOSUPPORT 96 /* Protocol family not supported */
+#define __MCPU_EAFNOSUPPORT 97 /* Address family not supported */
+#define __MCPU_EADDRINUSE 98 /* Address already in use */
+#define __MCPU_EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define __MCPU_ENETDOWN 100 /* Network is down */
+#define __MCPU_ENETUNREACH 101 /* Network is unreachable */
+#define __MCPU_ENETRESET 102 /* Network dropped connection because of reset */
+#define __MCPU_ECONNABORTED 103 /* Software caused connection abort */
+#define __MCPU_ECONNRESET 104 /* Connection reset by peer */
+#define __MCPU_ENOBUFS 105 /* No buffer space available */
+#define __MCPU_EISCONN 106 /* Transport endpoint is already connected */
+#define __MCPU_ENOTCONN 107 /* Transport endpoint is not connected */
+#define __MCPU_ESHUTDOWN 108 /* Cannot send after endpoint shutdown */
+#define __MCPU_ETOOMANYREFS 109 /* Too many references */
+#define __MCPU_ETIMEDOUT 110 /* Connection timed out */
+#define __MCPU_ECONNREFUSED 111 /* Connection refused */
+#define __MCPU_EHOSTDOWN 112 /* Host is down */
+#define __MCPU_EHOSTUNREACH 113 /* No route to host */
+#define __MCPU_EALREADY 114 /* Operation already in progress */
+#define __MCPU_EINPROGRESS 115 /* Operation now in progress */
+#define __MCPU_ESTALE 116 /* Stale file handle */
+#define __MCPU_EUCLEAN 117 /* Structure needs cleaning */
+#define __MCPU_ENOTNAM 118 /* Not a XENIX named type file */
+#define __MCPU_ENAVAIL 119 /* No XENIX semaphores available */
+#define __MCPU_EISNAM 120 /* Is a named type file */
+#define __MCPU_EREMOTEIO 121 /* Remote I/O error */
+#define __MCPU_EDQUOT 122 /* Quota exceeded */
+#define __MCPU_ENOMEDIUM 123 /* No medium found */
+#define __MCPU_EMEDIUMTYPE 124 /* Wrong medium type */
+#define __MCPU_ECANCELED 125 /* Operation canceled */
+#define __MCPU_ENOKEY 126 /* Required key not available */
+#define __MCPU_EKEYEXPIRED 127 /* Key has expired */
+#define __MCPU_EKEYREVOKED 128 /* Key has been revoked */
+#define __MCPU_EKEYREJECTED 129 /* Key was rejected by service */
+#define __MCPU_EOWNERDEAD 130 /* Owner died */
+#define __MCPU_ENOTRECOVERABLE 131 /* State not recoverable */
+#define __MCPU_ERFKILL 132 /* Operation not possible due to RF-kill */
+#define __MCPU_EHWPOISON 133 /* Memory page has hardware error */
+#define __MCPU_EFTYPE 134 /* Wrong file type for intended operation */
+
+#define __MCPU_ENOTSUP __MCPU_EOPNOTSUPP
+
+#define __MCPU_EUNKNOWN 4095 /* Unknown or unmapped HOST error */
+
+#endif /* __CPU_ERRNO_H */
diff --git a/cpu/cpu-instruction.c b/cpu/cpu-instruction.c
new file mode 100644
index 0000000..4a6b59e
--- /dev/null
+++ b/cpu/cpu-instruction.c
@@ -0,0 +1,1649 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include <libmcpu.h>
+#include <cpu-context.h>
+#include <cpu-registers.h>
+#include <cpu-instruction.h>
+#include <cpu-syscalls.h>
+
+static int
+getreg( const cpu_operand *o, __mpu_UNIT_t **p, __mpu_size_t *n )
+{
+ if( !o || o->type != CPU_OPERAND_REGISTER ) return( CPU_EXEC_OPERAND_FAULT );
+ *n = __cpu_reg_size( o->value.reg.bits );
+ if( !*n ) return( CPU_EXEC_REGISTER_FAULT );
+ *p = __cpu_reg_ptr( o->value.reg.bits, o->value.reg.address );
+ return( *p ? 0 : CPU_EXEC_REGISTER_FAULT );
+}
+
+static int
+reg2( const cpu_instruction *i, __mpu_UNIT_t **d, __mpu_UNIT_t **a, __mpu_size_t *n )
+{
+ __mpu_size_t nd, na;
+ int rc = getreg( &i->operand[0], d, &nd );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], a, &na );
+ if( rc ) return( rc );
+ if( nd != na ) return( CPU_EXEC_WIDTH_FAULT );
+ *n = nd;
+ return( 0 );
+}
+
+static int
+reg3( const cpu_instruction *i, __mpu_UNIT_t **d, __mpu_UNIT_t **a, __mpu_UNIT_t **b, __mpu_size_t *n )
+{
+ __mpu_size_t nd, na, nb;
+ int rc = getreg( &i->operand[0], d, &nd );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], a, &na );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], b, &nb );
+ if( rc ) return( rc );
+ if( nd != na || nd != nb ) return( CPU_EXEC_WIDTH_FAULT );
+ *n = nd;
+ return( 0 );
+}
+
+static int
+valid_real( __mpu_size_t n )
+{
+ return( n >= NB_R32 && n <= NB_R_MAX && ( n & ( n - 1 ) ) == 0 );
+}
+
+static int
+valid_complex( __mpu_size_t n )
+{
+ return( n >= 8 && n <= NB_C_MAX && ( n & ( n - 1 ) ) == 0 && valid_real( n / 2 ) );
+}
+
+/*
+ * LibMPU conversion helpers such as icvt()/r_cvt() may modify the LibMPU
+ * flag register as an implementation side effect. LibCPU conversion-class
+ * instructions are architecturally PSW-neutral, so preserve PSW[15:0].
+ *
+ * Do this through the public LibCPU/LibMPU flag facade instead of depending
+ * on LibMPU's private __MPU_FLAGS/context implementation detail.
+ */
+static __mpu_uint32_t
+cpu_status_flags_save( void )
+{
+ return( __cpu_get_psw() & PSW_MPU_MASK );
+}
+
+static void
+cpu_status_flags_restore( __mpu_uint32_t flags )
+{
+ __mpu_uint32_t psw = __cpu_get_psw();
+ __cpu_set_psw( ( psw & PSW_CPU_MASK ) | ( flags & PSW_MPU_MASK ) );
+}
+
+static int
+stack_offset( __mpu_int64_t off, __mpu_uint64_t width, __mpu_uint64_t *pos )
+{
+ __mpu_uint64_t p;
+ if( !__STACK || !__SSIZE || __SP > __SSIZE ) return( CPU_EXEC_STACK_FAULT );
+ if( off < 0 )
+ {
+ __mpu_uint64_t mag = (__mpu_uint64_t)( - ( off + 1 ) ) + 1U;
+ if( mag > __SP ) return( CPU_EXEC_STACK_FAULT );
+ p = __SP - mag;
+ }
+ else
+ {
+ __mpu_uint64_t add = (__mpu_uint64_t)off;
+ if( add > __SSIZE - __SP ) return( CPU_EXEC_STACK_FAULT );
+ p = __SP + add;
+ }
+ if( p > __SSIZE || width > __SSIZE - p ) return( CPU_EXEC_STACK_FAULT );
+ *pos = p;
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+frame_offset( __mpu_int64_t off, __mpu_uint64_t width, __mpu_uint64_t *pos )
+{
+ __mpu_uint64_t p;
+ if( !__STACK || !__SSIZE || __FP > __SSIZE ) return( CPU_EXEC_STACK_FAULT );
+ if( off < 0 )
+ {
+ __mpu_uint64_t mag = (__mpu_uint64_t)( - ( off + 1 ) ) + 1U;
+ if( mag > __FP ) return( CPU_EXEC_STACK_FAULT );
+ p = __FP - mag;
+ }
+ else
+ {
+ __mpu_uint64_t add = (__mpu_uint64_t)off;
+ if( add > __SSIZE - __FP ) return( CPU_EXEC_STACK_FAULT );
+ p = __FP + add;
+ }
+ if( p > __SSIZE || width > __SSIZE - p ) return( CPU_EXEC_STACK_FAULT );
+ *pos = p;
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+pointer_register( const cpu_operand *o, __mpu_UNIT_t **p )
+{
+ __mpu_size_t n;
+ int rc = getreg( o, p, &n );
+ if( rc ) return( rc );
+ return( n == CPU_PTR64_SIZE ? CPU_EXEC_SUCCESS : CPU_EXEC_WIDTH_FAULT );
+}
+
+static int pointer_resolve( __mpu_uint64_t ptr, __mpu_uint64_t width, int write,
+ __mpu_UNIT_t **base, __mpu_uint64_t *offset)
+{
+ unsigned int seg;
+
+ /* ABI NULL is the all-zero PTR64. It is never dereferenceable even
+ though its bit fields would otherwise decode as DATA offset zero. */
+ if( ptr == CPU_NULL_PTR ) return( CPU_EXEC_POINTER_FAULT );
+ seg = __cpu_ptr_segment( ptr );
+ __mpu_uint64_t off = __cpu_ptr_offset( ptr ), size = 0;
+ __mpu_UNIT_t *mem = 0;
+
+ switch( seg )
+ {
+ case CPU_PTR_SEG_DATA:
+ mem = __DATA;
+ size = __DSIZE;
+ break;
+ case CPU_PTR_SEG_STACK:
+ mem = __STACK;
+ size = __SSIZE;
+ break;
+ case CPU_PTR_SEG_PROGRAM:
+ if( write ) return( CPU_EXEC_MEMORY_FAULT );
+ mem = __PROGRAM;
+ size = __PSIZE;
+ break;
+ case CPU_PTR_SEG_CONTROL:
+ if( write ) return( CPU_EXEC_MEMORY_FAULT );
+ mem = __CONTROL;
+ size = __CSIZE;
+ break;
+ case CPU_PTR_SEG_INPUT:
+ if( write ) return( CPU_EXEC_MEMORY_FAULT );
+ mem = __INPUT;
+ size = __ISIZE;
+ break;
+ case CPU_PTR_SEG_OUTPUT:
+ mem = __OUTPUT;
+ size = __OSIZE;
+ break;
+ case CPU_PTR_SEG_TRACE:
+ mem = __TRACE;
+ size = __TSIZE;
+ break;
+ case CPU_PTR_SEG_HEAP:
+ mem = __HEAP;
+ size = __HBRK;
+ if( off < CPU_HEAP_BEGIN ) return( CPU_EXEC_MEMORY_FAULT );
+ break;
+ default:
+ return( CPU_EXEC_POINTER_FAULT );
+ }
+
+ if( !mem || off > size || width > size - off ) return( CPU_EXEC_MEMORY_FAULT );
+ *base = mem;
+ *offset = off;
+ return( CPU_EXEC_SUCCESS );
+}
+
+/*
+ * Apply a signed byte displacement to a PTR64 offset while preserving the
+ * four-bit segment selector. The arithmetic is deliberately performed on
+ * the 60-bit offset field only; carry/borrow is never allowed to enter SEG.
+ * `subtract' selects PTR - delta instead of PTR + delta.
+ */
+static int pointer_arith( __mpu_uint64_t ptr, __mpu_int64_t delta, int subtract,
+ __mpu_uint64_t *result)
+{
+ __mpu_uint64_t off = __cpu_ptr_offset( ptr );
+ __mpu_uint64_t mag;
+ unsigned int seg = __cpu_ptr_segment( ptr );
+ int positive = ( delta >= 0 );
+
+ if( !result ) return( CPU_EXEC_POINTER_FAULT );
+
+ if( positive )
+ mag = (__mpu_uint64_t)delta;
+ else
+ mag = (__mpu_uint64_t)( - ( delta + 1 ) ) + __mpu_UINT64_C( 1 );
+
+ /* PTR - negative_delta is addition; PTR + negative_delta is subtraction. */
+ if( ( !subtract && positive ) || ( subtract && !positive ) )
+ {
+ if( mag > CPU_PTR_OFFSET_MASK - off ) return( CPU_EXEC_POINTER_FAULT );
+ off+=mag;
+ }
+ else
+ {
+ if( mag > off ) return( CPU_EXEC_POINTER_FAULT );
+ off -= mag;
+ }
+
+ if( __cpu_ptr_make( result, seg, off ) ) return( CPU_EXEC_POINTER_FAULT );
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+reg_i64( const cpu_operand *o, __mpu_int64_t *v )
+{
+ __mpu_UNIT_t *p;
+ __mpu_uint64_t bits;
+ int rc = pointer_register( o, &p );
+ if( rc ) return( rc );
+ bits = __cpu_data_get_u64( p );
+ memcpy( v, &bits, sizeof( *v ) );
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+reg_ptr64( const cpu_operand *o, __mpu_uint64_t *v )
+{
+ __mpu_UNIT_t *p;
+ int rc = pointer_register( o, &p );
+ if( rc ) return( rc );
+ *v = __cpu_data_get_u64( p );
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+reg_u64( const cpu_operand *o, __mpu_uint64_t *v )
+{
+ __mpu_UNIT_t *p;
+ int rc = pointer_register( o, &p );
+ if( rc ) return( rc );
+ *v = __cpu_data_get_u64( p );
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+put_i64_result( const cpu_operand *o, __mpu_int64_t v )
+{
+ __mpu_UNIT_t *p;
+ __mpu_uint64_t bits;
+ int rc = pointer_register( o, &p );
+ if( rc ) return( rc );
+ memcpy( &bits, &v, sizeof( bits ) );
+ __cpu_data_put_u64( p, bits );
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+put_u64_result( const cpu_operand *o, __mpu_uint64_t v )
+{
+ __mpu_UNIT_t *p;
+ int rc = pointer_register( o, &p );
+ if( rc ) return( rc );
+ __cpu_data_put_u64( p, v );
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+reg_count32( const cpu_operand *o, unsigned int *count )
+{
+ __mpu_uint64_t v;
+ int rc = reg_u64( o, &v );
+ if( rc ) return( rc );
+ if( v > __mpu_UINT64_C( 0xffffffff ) ) return( CPU_EXEC_OPERAND_FAULT );
+ *count = (unsigned int)(__mpu_uint32_t)v;
+ return( CPU_EXEC_SUCCESS );
+}
+
+/* Resolve an indirect control-flow operand. The register must be a physical
+ r64/PTR64 value selecting PROGRAM, and the byte offset must address the
+ current architectural PROGRAM size. No host pointer is ever accepted. */
+static int
+code_pointer_target( const cpu_operand *o, __mpu_uint64_t *target )
+{
+ __mpu_uint64_t ptr, off;
+ int rc;
+
+ if( !target ) return( CPU_EXEC_POINTER_FAULT );
+ rc = reg_ptr64( o, &ptr );
+ if( rc ) return( rc );
+ if( ptr == CPU_NULL_PTR || __cpu_ptr_segment( ptr ) != CPU_PTR_SEG_PROGRAM )
+ return( CPU_EXEC_POINTER_FAULT );
+ off = __cpu_ptr_offset( ptr );
+ if( !__PROGRAM || off >= __PSIZE ) return( CPU_EXEC_POINTER_FAULT );
+ *target = off;
+ return( CPU_EXEC_SUCCESS );
+}
+
+static int
+rconst( mpu_real *d, int nb, __mpu_uint8_t k )
+{
+ switch( k )
+ {
+#define K(x,f) case x: f(d,nb); return 0
+ K( CPU_RCONST_ZERO, _m_zero );
+ K( CPU_RCONST_HALF, _m_half );
+ K( CPU_RCONST_ONE, _m_one );
+ K( CPU_RCONST_TWO, _m_two );
+ K( CPU_RCONST_TEN, _m_ten );
+ K( CPU_RCONST_MTEN, _m_mten );
+ K( CPU_RCONST_32, _m_32 );
+ K( CPU_RCONST_PI, _m_PI );
+ K( CPU_RCONST_E, _m_E );
+ K( CPU_RCONST_1_LN2, _m_1_ln2 );
+ K( CPU_RCONST_LN2, _m_ln2 );
+ K( CPU_RCONST_1_LN10, _m_1_ln10 );
+ K( CPU_RCONST_LN10, _m_ln10 );
+ K( CPU_RCONST_1_LG2, _m_1_lg2 );
+ K( CPU_RCONST_LG2, _m_lg2 );
+ K( CPU_RCONST_PI_2, _m_PI_2 );
+ K( CPU_RCONST_PI_3, _m_PI_3 );
+ K( CPU_RCONST_PI_4, _m_PI_4 );
+ K( CPU_RCONST_PI_5, _m_PI_5 );
+ K( CPU_RCONST_PI_6, _m_PI_6 );
+ K( CPU_RCONST_1_PI, _m_1_PI );
+ K( CPU_RCONST_2_PI, _m_2_PI );
+ K( CPU_RCONST_3_PI, _m_3_PI );
+ K( CPU_RCONST_4_PI, _m_4_PI );
+ K( CPU_RCONST_5_PI, _m_5_PI );
+ K( CPU_RCONST_2PI, _m_2PI );
+ K( CPU_RCONST_3PI, _m_3PI );
+ K( CPU_RCONST_1_2PI, _m_1_2PI );
+ K( CPU_RCONST_1_3PI, _m_1_3PI );
+ K( CPU_RCONST_1_4PI, _m_1_4PI );
+ K( CPU_RCONST_1_5PI, _m_1_5PI );
+ K( CPU_RCONST_1_6PI, _m_1_6PI );
+ K( CPU_RCONST_3PI_4, _m_3PI_4 );
+ K( CPU_RCONST_SQRTPI, _m_SQRTPI );
+ K( CPU_RCONST_1_SQRTPI, _m_1_SQRTPI );
+ K( CPU_RCONST_2_SQRTPI, _m_2_SQRTPI );
+ K( CPU_RCONST_SQRT2, _m_SQRT2 );
+ K( CPU_RCONST_1_SQRT2, _m_1_SQRT2 );
+ K( CPU_RCONST_SQRT3, _m_SQRT3 );
+ K( CPU_RCONST_1_SQRT3, _m_1_SQRT3 );
+ K( CPU_RCONST_DEGREE, _m_DEGREE );
+ K( CPU_RCONST_1_DEGREE, _m_1_DEGREE );
+ K( CPU_RCONST_GOLDENRATIO, _m_GOLDENRATIO );
+ K( CPU_RCONST_EULERGAMMA, _m_EULERGAMMA );
+ K( CPU_RCONST_CATALAN, _m_CATALAN );
+ K( CPU_RCONST_EPSILON, _real_epsilon );
+ K( CPU_RCONST_IND, _ind );
+ case CPU_RCONST_PNAN: _nan( d, 0, nb );
+ return( 0 );
+ case CPU_RCONST_NNAN: _nan( d, 1, nb );
+ return( 0 );
+ case CPU_RCONST_PNANMAX: _nan_max( d, 0, nb );
+ return( 0 );
+ case CPU_RCONST_NNANMAX: _nan_max( d, 1, nb );
+ return( 0 );
+ case CPU_RCONST_PNANMIN: _nan_min( d, 0, nb );
+ return( 0 );
+ case CPU_RCONST_NNANMIN: _nan_min( d, 1, nb );
+ return( 0 );
+ case CPU_RCONST_PINF: _inf( d, 0, nb );
+ return( 0 );
+ case CPU_RCONST_NINF: _inf( d, 1, nb );
+ return( 0 );
+ case CPU_RCONST_PREALMIN: _real_min( d, 0, nb );
+ return( 0 );
+ case CPU_RCONST_NREALMIN: _real_min( d, 1, nb );
+ return( 0 );
+ case CPU_RCONST_PREALMAX: _real_max( d, 0, nb );
+ return( 0 );
+ case CPU_RCONST_NREALMAX: _real_max( d, 1, nb );
+ return( 0 );
+ case CPU_RCONST_PZERO: _signull( d, 0, nb );
+ return( 0 );
+ case CPU_RCONST_NZERO: _signull( d, 1, nb );
+ return( 0 );
+#undef K
+ default: return( CPU_EXEC_OPERAND_FAULT );
+ }
+}
+
+int
+__cpu_exec( const cpu_instruction *i )
+{
+ __mpu_UNIT_t *d, *a, *b;
+ __mpu_size_t n;
+ int rc;
+ if( !i ) return( CPU_EXEC_INSTRUCTION_FAULT );
+ switch( i->opcode )
+ {
+ case CPU_OP_NOP: return( 0 );
+ case CPU_OP_HALT: __cpu_sth();
+ return( 0 );
+ case CPU_OP_END: return( CPU_EXEC_END );
+ case CPU_OP_SETF:
+ case CPU_OP_CLRF:
+ {
+ __mpu_uint32_t psw, mask;
+ if( i->operand[0].type != CPU_OPERAND_PSWBIT8 )
+ return( CPU_EXEC_OPERAND_FAULT );
+ if( i->operand[0].value.pswbit8 > CPU_PSWBIT_WRITE_MAX )
+ return( CPU_EXEC_OPERAND_FAULT );
+ psw = __cpu_get_psw();
+ mask = (__mpu_uint32_t)1U << i->operand[0].value.pswbit8;
+ if( i->opcode == CPU_OP_SETF ) psw |= mask;
+ else psw &= ~mask;
+ __cpu_set_psw( psw );
+ return( CPU_EXEC_SUCCESS );
+ }
+ case CPU_OP_CLRCPUF:
+ __cpu_set_psw( __cpu_get_psw() & ~PSW_CPUF_MASK );
+ return( CPU_EXEC_SUCCESS );
+ case CPU_OP_CLRMPUF:
+ __cpu_set_psw( __cpu_get_psw() & ~PSW_MPUF_MASK );
+ return( CPU_EXEC_SUCCESS );
+ case CPU_OP_SYSCALL:
+ __cpu_data_put_u64( __cpu_reg_ptr( 64, CPU_SYSCALL_RET_ADDR ),
+ __cpu_syscall_dispatch() );
+ return( CPU_EXEC_SUCCESS );
+ case CPU_OP_EXIT:
+ {
+ __mpu_UNIT_t *p;
+ __mpu_size_t z;
+ __mpu_uint32_t u;
+ __mpu_int32_t status;
+ rc = getreg( &i->operand[0], &p, &z );
+ if( rc ) return( rc );
+ if( z != 4U ) return( CPU_EXEC_WIDTH_FAULT );
+ u = __cpu_data_get_u32( p );
+ memcpy( &status, &u, sizeof( status ) );
+ __EXIT_STATUS = status;
+ return( CPU_EXEC_EXIT );
+ }
+ case CPU_OP_CLR: rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ memset( d, 0, n );
+ return( 0 );
+ case CPU_OP_MOV: rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ memmove( d, a, n );
+ return( 0 );
+ case CPU_OP_SWAP: rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ {
+ __mpu_size_t k;
+ for( k = 0; k < n; k++ )
+ {
+ __mpu_UNIT_t t = d[k];
+ d[k] = a[k];
+ a[k] = t;
+ }
+ }
+ return( 0 );
+ case CPU_OP_BSWAP:
+ rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ {
+ __mpu_size_t k;
+ /* Equal-width naturally aligned register views are either identical or
+ disjoint. These two paths are therefore exactly equivalent to the
+ architectural source-snapshot semantics without an 8 KiB temp. */
+ if( d == a )
+ {
+ for( k = 0; k < n / 2U; k++ )
+ {
+ __mpu_UNIT_t t = d[k];
+ d[k] = d[n - 1U - k];
+ d[n - 1U - k] = t;
+ }
+ }
+ else
+ {
+ for( k = 0; k < n; k++ ) d[k] = a[n - 1U - k];
+ }
+ }
+ return( 0 );
+ case CPU_OP_LDI:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( i->operand[1].type != CPU_OPERAND_IMM64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ mpu_int64_t s;
+ __mpu_int64_t v = (__mpu_int64_t)i->operand[1].value.imm64;
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ memcpy( s, &v, 8 );
+ icvt( ( mpu_int * ) d, ( mpu_int * ) s, (int)n, NB_I64 );
+ cpu_status_flags_restore( flags );
+ }
+ return( 0 );
+ case CPU_OP_LDR:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( !valid_real( n ) ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->operand[1].type != CPU_OPERAND_IMM64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ mpu_real64_t s;
+ __mpu_uint64_t u = i->operand[1].value.imm64;
+ __mpu_real64_t v;
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ memcpy( &v, &u, 8 );
+ memcpy( s, &v, 8 );
+ r_cvt( ( mpu_real * ) d, ( mpu_real * ) s, (int)n, NB_R64 );
+ cpu_status_flags_restore( flags );
+ }
+ return( 0 );
+ case CPU_OP_LDC:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( !valid_complex( n ) ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->operand[1].type != CPU_OPERAND_IMM64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ mpu_real32_t sr, si;
+ mpu_wide_real_t rr, ri;
+ __mpu_uint32_t ur = (__mpu_uint32_t)( i->operand[1].value.imm64 >> 32 ), ui = (__mpu_uint32_t)i->operand[1].value.imm64;
+ __mpu_real32_t fr, fi;
+ int cn = (int)( n / 2 );
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ memcpy( &fr, &ur, 4 );
+ memcpy( &fi, &ui, 4 );
+ memcpy( sr, &fr, 4 );
+ memcpy( si, &fi, 4 );
+ r_cvt( ( mpu_real * ) rr, ( mpu_real * ) sr, cn, NB_R32 );
+ r_cvt( ( mpu_real * ) ri, ( mpu_real * ) si, cn, NB_R32 );
+ c_gen_complex( ( mpu_complex * ) d, ( mpu_real * ) rr, ( mpu_real * ) ri, cn );
+ cpu_status_flags_restore( flags );
+ }
+ return( 0 );
+ case CPU_OP_LOAD:
+ case CPU_OP_STORE:
+ {
+ const cpu_operand *ro = ( i->opcode == CPU_OP_LOAD ) ? &i->operand[0] : &i->operand[1];
+ const cpu_operand *ao = ( i->opcode == CPU_OP_LOAD ) ? &i->operand[1] : &i->operand[0];
+ rc = getreg( ro, &d, &n );
+ if( rc ) return( rc );
+ if( ao->type != CPU_OPERAND_ADDR64 ) return( CPU_EXEC_OPERAND_FAULT );
+ if( ao->value.addr64 > __DSIZE || (__mpu_uint64_t)n > __DSIZE - ao->value.addr64 ) return( CPU_EXEC_MEMORY_FAULT );
+ if( i->opcode == CPU_OP_LOAD ) memmove( d, __DATA + ao->value.addr64, n );
+ else memmove( __DATA + ao->value.addr64, d, n );
+ return( 0 );
+ }
+
+ case CPU_OP_LEA:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( n != CPU_PTR64_SIZE ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->operand[1].type != CPU_OPERAND_PTR64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ __mpu_uint64_t ptr = i->operand[1].value.ptr64, off = __cpu_ptr_offset( ptr ), size = 0;
+ unsigned int seg = __cpu_ptr_segment( ptr );
+ switch( seg )
+ {
+ case CPU_PTR_SEG_DATA: size = __DSIZE;
+ break;
+ case CPU_PTR_SEG_STACK: size = __SSIZE;
+ break;
+ case CPU_PTR_SEG_PROGRAM: size = __PSIZE;
+ break;
+ case CPU_PTR_SEG_CONTROL: size = __CSIZE;
+ break;
+ case CPU_PTR_SEG_INPUT: size = __ISIZE;
+ break;
+ case CPU_PTR_SEG_OUTPUT: size = __OSIZE;
+ break;
+ case CPU_PTR_SEG_TRACE: size = __TSIZE;
+ break;
+ case CPU_PTR_SEG_HEAP: size = __HBRK;
+ if( off < CPU_HEAP_BEGIN ) return( CPU_EXEC_MEMORY_FAULT );
+ break;
+ default: return( CPU_EXEC_POINTER_FAULT );
+ }
+ if( off > size ) return( CPU_EXEC_MEMORY_FAULT );
+ __cpu_data_put_u64( d, ptr );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_LEASP:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( n != CPU_PTR64_SIZE ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->operand[1].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ __mpu_uint64_t pos, ptr;
+ rc = stack_offset( i->operand[1].value.off64, 0, &pos );
+ if( rc ) return( rc );
+ if( pos > CPU_PTR_OFFSET_MASK ) return( CPU_EXEC_POINTER_FAULT );
+ if( __cpu_ptr_make( &ptr, CPU_PTR_SEG_STACK, pos ) ) return( CPU_EXEC_POINTER_FAULT );
+ __cpu_data_put_u64( d, ptr );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_LOADP:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ rc = pointer_register( &i->operand[1], &a );
+ if( rc ) return( rc );
+ {
+ __mpu_uint64_t ptr, off;
+ __mpu_UNIT_t *base;
+ ptr = __cpu_data_get_u64( a );
+ rc = pointer_resolve( ptr, (__mpu_uint64_t)n, 0, &base, &off );
+ if( rc ) return( rc );
+ memmove( d, base + off, n );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_STOREP:
+ rc = pointer_register( &i->operand[0], &a );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &d, &n );
+ if( rc ) return( rc );
+ {
+ __mpu_uint64_t ptr, off;
+ __mpu_UNIT_t *base;
+ ptr = __cpu_data_get_u64( a );
+ rc = pointer_resolve( ptr, (__mpu_uint64_t)n, 1, &base, &off );
+ if( rc ) return( rc );
+ memmove( base + off, d, n );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_BMOV:
+ case CPU_OP_BMOVI:
+ {
+ __mpu_uint64_t dstptr, srcptr, count, dstoff, srcoff;
+ __mpu_UNIT_t *dstbase, *srcbase;
+ rc = reg_ptr64( &i->operand[0], &dstptr );
+ if( rc ) return( rc );
+ rc = reg_ptr64( &i->operand[1], &srcptr );
+ if( rc ) return( rc );
+ if( i->opcode == CPU_OP_BMOV )
+ {
+ rc = reg_u64( &i->operand[2], &count );
+ if( rc ) return( rc );
+ }
+ else
+ {
+ if( i->operand[2].type != CPU_OPERAND_IMM64 ) return( CPU_EXEC_OPERAND_FAULT );
+ count = i->operand[2].value.imm64;
+ }
+ /* Resolve and validate both complete ranges before modifying memory. */
+ rc = pointer_resolve( srcptr, count, 0, &srcbase, &srcoff );
+ if( rc ) return( rc );
+ rc = pointer_resolve( dstptr, count, 1, &dstbase, &dstoff );
+ if( rc ) return( rc );
+ if( (__mpu_uint64_t)(size_t)count != count ) return( CPU_EXEC_MEMORY_FAULT );
+ memmove( dstbase + dstoff, srcbase + srcoff, (size_t)count );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_PADD:
+ case CPU_OP_PSUB:
+ {
+ __mpu_uint64_t ptr, out;
+ __mpu_int64_t delta;
+ rc = pointer_register( &i->operand[0], &d );
+ if( rc ) return( rc );
+ rc = reg_ptr64( &i->operand[1], &ptr );
+ if( rc ) return( rc );
+ rc = reg_i64( &i->operand[2], &delta );
+ if( rc ) return( rc );
+ rc = pointer_arith( ptr, delta, i->opcode == CPU_OP_PSUB, &out );
+ if( rc ) return( rc );
+ __cpu_data_put_u64( d, out );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_PADDI:
+ case CPU_OP_PSUBI:
+ {
+ __mpu_uint64_t ptr, out;
+ __mpu_int64_t delta;
+ rc = pointer_register( &i->operand[0], &d );
+ if( rc ) return( rc );
+ rc = reg_ptr64( &i->operand[1], &ptr );
+ if( rc ) return( rc );
+ if( i->operand[2].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ delta = i->operand[2].value.off64;
+ rc = pointer_arith( ptr, delta, i->opcode == CPU_OP_PSUBI, &out );
+ if( rc ) return( rc );
+ __cpu_data_put_u64( d, out );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_PDIFF:
+ {
+ __mpu_uint64_t left, right;
+ __mpu_int64_t diff;
+ rc = pointer_register( &i->operand[0], &d );
+ if( rc ) return( rc );
+ rc = reg_ptr64( &i->operand[1], &left );
+ if( rc ) return( rc );
+ rc = reg_ptr64( &i->operand[2], &right );
+ if( rc ) return( rc );
+ if( __cpu_ptr_segment( left ) != __cpu_ptr_segment( right ) )
+ return( CPU_EXEC_POINTER_FAULT );
+ diff = (__mpu_int64_t)__cpu_ptr_offset( left ) -
+ (__mpu_int64_t)__cpu_ptr_offset( right );
+ {
+ __mpu_uint64_t bits;
+ memcpy( &bits, &diff, sizeof( bits ) );
+ __cpu_data_put_u64( d, bits );
+ }
+ }
+ return( CPU_EXEC_SUCCESS );
+
+#define I3(op,fn) case op: rc=reg3(i,&d,&a,&b,&n);if(rc)return rc;fn((mpu_int*)d,(mpu_int*)a,(mpu_int*)b,(int)n);return 0
+ I3( CPU_OP_IADD, iadd );
+ I3( CPU_OP_IADC, iadc );
+ I3( CPU_OP_ISUB, isub );
+ I3( CPU_OP_ISBB, isbb );
+ I3( CPU_OP_IAND, iand );
+ I3( CPU_OP_IOR, ior );
+ I3( CPU_OP_IXOR, ixor );
+#undef I3
+#define I2(op,fn) case op: rc=reg2(i,&d,&a,&n);if(rc)return rc;fn((mpu_int*)d,(mpu_int*)a,(int)n);return 0
+ I2( CPU_OP_INOT, inot );
+ I2( CPU_OP_INEG, ineg );
+ I2( CPU_OP_ISHL, ishl );
+ I2( CPU_OP_ISHR, ishr );
+ I2( CPU_OP_ISAL, isal );
+ I2( CPU_OP_ISAR, isar );
+ I2( CPU_OP_IROL, irol );
+ I2( CPU_OP_IROR, iror );
+ I2( CPU_OP_IRCL, ircl );
+ I2( CPU_OP_IRCR, ircr );
+ I2( CPU_OP_IINC, iinc );
+ I2( CPU_OP_IDEC, idec );
+#undef I2
+ case CPU_OP_IXCHG:
+ rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ ixchg( ( mpu_int * ) d, ( mpu_int * ) a, (int)n );
+ return( 0 );
+ case CPU_OP_ICPY:
+ case CPU_OP_ICVT:
+ {
+ __mpu_size_t nd, na;
+ rc = getreg( &i->operand[0], &d, &nd );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &na );
+ if( rc ) return( rc );
+ if( i->opcode == CPU_OP_ICPY ) icpy( ( mpu_int * ) d, ( mpu_int * ) a, (int)nd, (int)na );
+ else
+ {
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ icvt( ( mpu_int * ) d, ( mpu_int * ) a, (int)nd, (int)na );
+ cpu_status_flags_restore( flags );
+ }
+ }
+ return( 0 );
+ case CPU_OP_ISHLN: case CPU_OP_ISHRN: case CPU_OP_ISALN: case CPU_OP_ISARN:
+ case CPU_OP_IROLN: case CPU_OP_IRORN: case CPU_OP_IRCLN: case CPU_OP_IRCRN:
+ {
+ __mpu_size_t nd, na;
+ unsigned int count;
+ rc = getreg( &i->operand[0], &d, &nd );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &na );
+ if( rc ) return( rc );
+ if( nd != na ) return( CPU_EXEC_WIDTH_FAULT );
+ rc = reg_count32( &i->operand[2], &count );
+ if( rc ) return( rc );
+ switch( i->opcode )
+ {
+ case CPU_OP_ISHLN: ishln( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ case CPU_OP_ISHRN: ishrn( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ case CPU_OP_ISALN: isaln( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ case CPU_OP_ISARN: isarn( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ case CPU_OP_IROLN: iroln( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ case CPU_OP_IRORN: irorn( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ case CPU_OP_IRCLN: ircln( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ default: ircrn( ( mpu_int * ) d, ( mpu_int * ) a, count, (int)nd );
+ break;
+ }
+ }
+ return( 0 );
+ case CPU_OP_IMUL:
+ case CPU_OP_ISMUL:
+ {
+ __mpu_size_t np, na, nb;
+ rc = getreg( &i->operand[0], &d, &np );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &na );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &b, &nb );
+ if( rc ) return( rc );
+ if( na != nb || np < 2U * na ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->opcode == CPU_OP_IMUL ) imul( ( mpu_int * ) d, ( mpu_int * ) a, ( mpu_int * ) b, (int)np, (int)na );
+ else ismul( ( mpu_int * ) d, ( mpu_int * ) a, ( mpu_int * ) b, (int)np, (int)na );
+ }
+ return( 0 );
+ case CPU_OP_IDIV:
+ case CPU_OP_ISDIV:
+ {
+ __mpu_UNIT_t *q, *r, *num, *den;
+ __mpu_size_t nq, nr, nn, nd;
+ rc = getreg( &i->operand[0], &q, &nq );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &r, &nr );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &num, &nn );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[3], &den, &nd );
+ if( rc ) return( rc );
+ if( nq != nr || nq != nn || nq != nd ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->opcode == CPU_OP_IDIV ) idiv( ( mpu_int * ) q, ( mpu_int * ) r, ( mpu_int * ) num, ( mpu_int * ) den, (int)nq );
+ else isdiv( ( mpu_int * ) q, ( mpu_int * ) r, ( mpu_int * ) num, ( mpu_int * ) den, (int)nq );
+ }
+ return( 0 );
+ case CPU_OP_IBITSLEN:
+ {
+ __mpu_size_t na;
+ int v;
+ rc = getreg( &i->operand[1], &a, &na );
+ if( rc ) return( rc );
+ v = ibits_len( ( mpu_int * ) a, (int)na );
+ return( put_i64_result( &i->operand[0], (__mpu_int64_t)v ) );
+ }
+ case CPU_OP_ICMP: case CPU_OP_ITEST:
+ rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ if( i->opcode == CPU_OP_ICMP ) icmp( ( mpu_int * ) d, ( mpu_int * ) a, (int)n );
+ else itest( ( mpu_int * ) d, ( mpu_int * ) a, (int)n );
+ return( 0 );
+
+#define R3(op,fn,limit) case op: rc=reg3(i,&d,&a,&b,&n);if(rc)return rc;if(!valid_real(n)||n>(limit))return CPU_EXEC_WIDTH_FAULT;fn((mpu_real*)d,(mpu_real*)a,(mpu_real*)b,(int)n);return 0
+ R3( CPU_OP_RADD, r_add, NB_R_MAX );
+ R3( CPU_OP_RSUB, r_sub, NB_R_MAX );
+ R3( CPU_OP_RMUL, r_mul, NB_R_MAX );
+ R3( CPU_OP_RDIV, r_div, NB_R_MAX );
+ R3( CPU_OP_RPOW, r_pow, NB_R16384 );
+ R3( CPU_OP_RHYPOT, r_hypot, NB_R16384 );
+ R3( CPU_OP_RATAN2, r_atan2, NB_R16384 );
+ R3( CPU_OP_RREMAIN, r_remain, NB_R_MAX );
+#undef R3
+#define R2(op,fn,limit) case op: rc=reg2(i,&d,&a,&n);if(rc)return rc;if(!valid_real(n)||n>(limit))return CPU_EXEC_WIDTH_FAULT;fn((mpu_real*)d,(mpu_real*)a,(int)n);return 0
+ R2( CPU_OP_RSQRT, r_sqrt, NB_R16384 );
+ R2( CPU_OP_RSIN, r_sin, NB_R16384 );
+ R2( CPU_OP_RCOS, r_cos, NB_R16384 );
+ R2( CPU_OP_RTAN, r_tan, NB_R16384 );
+ R2( CPU_OP_RASIN, r_asin, NB_R16384 );
+ R2( CPU_OP_RACOS, r_acos, NB_R16384 );
+ R2( CPU_OP_RATAN, r_atan, NB_R16384 );
+ R2( CPU_OP_RLOG, r_log, NB_R16384 );
+ R2( CPU_OP_RLOG10, r_log10, NB_R16384 );
+ R2( CPU_OP_RLOG2, r_log2, NB_R16384 );
+ R2( CPU_OP_REXP, r_exp, NB_R16384 );
+ R2( CPU_OP_RSINH, r_sinh, NB_R16384 );
+ R2( CPU_OP_RCOSH, r_cosh, NB_R16384 );
+ R2( CPU_OP_RTANH, r_tanh, NB_R16384 );
+ R2( CPU_OP_RFLOOR, r_floor, NB_R_MAX );
+ R2( CPU_OP_RCEIL, r_ceil, NB_R_MAX );
+ R2( CPU_OP_RROUND, r_round, NB_R_MAX );
+ R2( CPU_OP_RLOG1P, r_log1p, NB_R16384 );
+ R2( CPU_OP_REXPM1, r_expm1, NB_R16384 );
+ R2( CPU_OP_RASINH, r_asinh, NB_R16384 );
+ R2( CPU_OP_RACOSH, r_acosh, NB_R16384 );
+ R2( CPU_OP_RATANH, r_atanh, NB_R16384 );
+#undef R2
+ case CPU_OP_RNEG:
+ case CPU_OP_RABS:
+ rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ if( !valid_real( n ) ) return( CPU_EXEC_WIDTH_FAULT );
+ if( d != a ) r_cpy( ( mpu_real * ) d, ( mpu_real * ) a, (int)n );
+ if( i->opcode == CPU_OP_RNEG ) r_neg( ( mpu_real * ) d, (int)n );
+ else r_abs( ( mpu_real * ) d, (int)n );
+ return( 0 );
+ case CPU_OP_RCPY:
+ rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ if( !valid_real( n ) ) return( CPU_EXEC_WIDTH_FAULT );
+ r_cpy( ( mpu_real * ) d, ( mpu_real * ) a, (int)n );
+ return( 0 );
+ case CPU_OP_RCVT:
+ {
+ __mpu_size_t nd, na;
+ rc = getreg( &i->operand[0], &d, &nd );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &na );
+ if( rc ) return( rc );
+ if( !valid_real( nd ) || !valid_real( na ) ) return( CPU_EXEC_WIDTH_FAULT );
+ {
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ r_cvt( ( mpu_real * ) d, ( mpu_real * ) a, (int)nd, (int)na );
+ cpu_status_flags_restore( flags );
+ }
+ }
+ return( 0 );
+ case CPU_OP_RCMP:
+ {
+ __mpu_size_t na, nb;
+ int v;
+ rc = getreg( &i->operand[1], &a, &na );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &b, &nb );
+ if( rc ) return( rc );
+ if( na != nb || !valid_real( na ) ) return( CPU_EXEC_WIDTH_FAULT );
+ v = r_cmp( ( mpu_real * ) a, ( mpu_real * ) b, (int)na );
+ return( put_i64_result( &i->operand[0], (__mpu_int64_t)v ) );
+ }
+ case CPU_OP_RFREXP:
+ {
+ __mpu_UNIT_t *sig, *exp, *src;
+ __mpu_size_t nsig, nexp, nsrc;
+ rc = getreg( &i->operand[0], &sig, &nsig );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &exp, &nexp );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &src, &nsrc );
+ if( rc ) return( rc );
+ if( nsig != nsrc || !valid_real( nsig ) ) return( CPU_EXEC_WIDTH_FAULT );
+ r_frexp( ( mpu_real * ) sig, ( mpu_int * ) exp, ( mpu_real * ) src, (int)nexp, (int)nsrc );
+ }
+ return( 0 );
+ case CPU_OP_RLDEXP:
+ {
+ __mpu_UNIT_t *dst, *src, *exp;
+ __mpu_size_t ndst, nsrc, nexp;
+ rc = getreg( &i->operand[0], &dst, &ndst );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &src, &nsrc );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &exp, &nexp );
+ if( rc ) return( rc );
+ if( ndst != nsrc || !valid_real( ndst ) ) return( CPU_EXEC_WIDTH_FAULT );
+ r_ldexp( ( mpu_real * ) dst, ( mpu_real * ) src, ( mpu_int * ) exp, (int)ndst, (int)nexp );
+ }
+ return( 0 );
+ case CPU_OP_RLOGB:
+ {
+ __mpu_UNIT_t *dst, *src;
+ __mpu_size_t ndst, nsrc;
+ rc = getreg( &i->operand[0], &dst, &ndst );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &src, &nsrc );
+ if( rc ) return( rc );
+ if( !valid_real( nsrc ) ) return( CPU_EXEC_WIDTH_FAULT );
+ r_logb( ( mpu_int * ) dst, ( mpu_real * ) src, (int)ndst, (int)nsrc );
+ }
+ return( 0 );
+ case CPU_OP_RMODF:
+ {
+ __mpu_UNIT_t *frac, *integ, *src;
+ __mpu_size_t nf, ni, ns;
+ rc = getreg( &i->operand[0], &frac, &nf );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &integ, &ni );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &src, &ns );
+ if( rc ) return( rc );
+ if( nf != ni || nf != ns || !valid_real( nf ) ) return( CPU_EXEC_WIDTH_FAULT );
+ r_modf( ( mpu_real * ) frac, ( mpu_real * ) integ, ( mpu_real * ) src, (int)nf );
+ }
+ return( 0 );
+ case CPU_OP_ITOR:
+ case CPU_OP_UITOR:
+ {
+ __mpu_UNIT_t *rdst, *isrc;
+ __mpu_size_t nr, ni;
+ rc = getreg( &i->operand[0], &rdst, &nr );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &isrc, &ni );
+ if( rc ) return( rc );
+ if( !valid_real( nr ) ) return( CPU_EXEC_WIDTH_FAULT );
+ {
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ if( i->opcode == CPU_OP_ITOR ) ltor( ( mpu_real * ) rdst, ( mpu_int * ) isrc, (int)nr, (int)ni );
+ else ultor( ( mpu_real * ) rdst, ( mpu_int * ) isrc, (int)nr, (int)ni );
+ cpu_status_flags_restore( flags );
+ }
+ }
+ return( 0 );
+ case CPU_OP_RTOI:
+ case CPU_OP_RTOUI:
+ {
+ __mpu_UNIT_t *idst, *frac, *src;
+ __mpu_size_t ni, nf, ns;
+ rc = getreg( &i->operand[0], &idst, &ni );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &frac, &nf );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &src, &ns );
+ if( rc ) return( rc );
+ if( nf != ns || !valid_real( nf ) ) return( CPU_EXEC_WIDTH_FAULT );
+ {
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ if( i->opcode == CPU_OP_RTOI ) rtol_frac( ( mpu_int * ) idst, ( mpu_real * ) frac, ( mpu_real * ) src, (int)ni, (int)ns );
+ else rtoul_frac( ( mpu_int * ) idst, ( mpu_real * ) frac, ( mpu_real * ) src, (int)ni, (int)ns );
+ cpu_status_flags_restore( flags );
+ }
+ }
+ return( 0 );
+ case CPU_OP_RISNEG:
+ case CPU_OP_RSIGN:
+ case CPU_OP_RISIND:
+ case CPU_OP_RISNAN:
+ case CPU_OP_RISNANMAX:
+ case CPU_OP_RISNANMIN:
+ case CPU_OP_RISINF:
+ case CPU_OP_RISSIGNULL:
+ {
+ __mpu_size_t ns;
+ int v;
+ rc = getreg( &i->operand[1], &a, &ns );
+ if( rc ) return( rc );
+ if( !valid_real( ns ) ) return( CPU_EXEC_WIDTH_FAULT );
+ switch( i->opcode )
+ {
+ case CPU_OP_RISNEG: v = r_is_neg( ( mpu_real * ) a, (int)ns );
+ break;
+ case CPU_OP_RSIGN: v = r_sign( ( mpu_real * ) a, (int)ns );
+ break;
+ case CPU_OP_RISIND: v = _is_ind( ( mpu_real * ) a, (int)ns );
+ break;
+ case CPU_OP_RISNAN: v = _is_nans( ( mpu_real * ) a, (int)ns );
+ break;
+ case CPU_OP_RISNANMAX: v = _is_nan_max( ( mpu_real * ) a, (int)ns );
+ break;
+ case CPU_OP_RISNANMIN: v = _is_nan_min( ( mpu_real * ) a, (int)ns );
+ break;
+ case CPU_OP_RISINF: v = _is_inf( ( mpu_real * ) a, (int)ns );
+ break;
+ default: v = _is_signull( ( mpu_real * ) a, (int)ns );
+ break;
+ }
+ return( put_i64_result( &i->operand[0], (__mpu_int64_t)v ) );
+ }
+ case CPU_OP_RCONST:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( !valid_real( n ) ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->operand[1].type != CPU_OPERAND_CONST8 ) return( CPU_EXEC_OPERAND_FAULT );
+ return( rconst( ( mpu_real * ) d, (int)n, i->operand[1].value.const8 ) );
+
+#define C3(op,fn,limit) case op: rc=reg3(i,&d,&a,&b,&n);if(rc)return rc;if(!valid_complex(n)||n>(limit))return CPU_EXEC_WIDTH_FAULT;fn((mpu_complex*)d,(mpu_complex*)a,(mpu_complex*)b,(int)(n/2));return 0
+ C3( CPU_OP_CADD, c_add, NB_C_MAX );
+ C3( CPU_OP_CSUB, c_sub, NB_C_MAX );
+ C3( CPU_OP_CMUL, c_mul, NB_C_MAX );
+ C3( CPU_OP_CDIV, c_div, NB_C_MAX );
+ C3( CPU_OP_CPOW, c_pow, NB_C32768 );
+#undef C3
+#define C2(op,fn) case op: rc=reg2(i,&d,&a,&n);if(rc)return rc;if(!valid_complex(n)||n>NB_C32768)return CPU_EXEC_WIDTH_FAULT;fn((mpu_complex*)d,(mpu_complex*)a,(int)(n/2));return 0
+ C2( CPU_OP_CEXP, c_exp );
+ C2( CPU_OP_CSIN, c_sin );
+ C2( CPU_OP_CCOS, c_cos );
+ C2( CPU_OP_CSINH, c_sinh );
+ C2( CPU_OP_CCOSH, c_cosh );
+ C2( CPU_OP_CLOG, c_log );
+ C2( CPU_OP_CSQRT, c_sqrt );
+#undef C2
+ case CPU_OP_CCONJ:
+ case CPU_OP_CCPY:
+ rc = reg2( i, &d, &a, &n );
+ if( rc ) return( rc );
+ if( !valid_complex( n ) ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->opcode == CPU_OP_CCONJ ) c_conj( ( mpu_complex * ) d, ( mpu_complex * ) a, (int)( n / 2 ) );
+ else c_cpy( ( mpu_complex * ) d, ( mpu_complex * ) a, (int)( n / 2 ) );
+ return( 0 );
+ case CPU_OP_CCVT:
+ {
+ __mpu_size_t nd, ns;
+ rc = getreg( &i->operand[0], &d, &nd );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &ns );
+ if( rc ) return( rc );
+ if( !valid_complex( nd ) || !valid_complex( ns ) ) return( CPU_EXEC_WIDTH_FAULT );
+ {
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ c_cvt( ( mpu_complex * ) d, ( mpu_complex * ) a, (int)( nd / 2 ), (int)( ns / 2 ) );
+ cpu_status_flags_restore( flags );
+ }
+ }
+ return( 0 );
+ case CPU_OP_CREAL:
+ case CPU_OP_CIMAG:
+ case CPU_OP_CABS:
+ case CPU_OP_CNORM:
+ case CPU_OP_CARG:
+ {
+ __mpu_size_t nr, nc;
+ rc = getreg( &i->operand[0], &d, &nr );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &nc );
+ if( rc ) return( rc );
+ if( !valid_real( nr ) || !valid_complex( nc ) || nc != 2U * nr ) return( CPU_EXEC_WIDTH_FAULT );
+ if( ( i->opcode == CPU_OP_CABS || i->opcode == CPU_OP_CARG ) && nr > NB_R16384 )
+ return( CPU_EXEC_WIDTH_FAULT );
+ switch( i->opcode )
+ {
+ case CPU_OP_CREAL: c_real_part( ( mpu_real * ) d, ( mpu_complex * ) a, (int)nr );
+ break;
+ case CPU_OP_CIMAG: c_imaginary( ( mpu_real * ) d, ( mpu_complex * ) a, (int)nr );
+ break;
+ case CPU_OP_CABS: c_abs( ( mpu_real * ) d, ( mpu_complex * ) a, (int)nr );
+ break;
+ case CPU_OP_CNORM: c_norm( ( mpu_real * ) d, ( mpu_complex * ) a, (int)nr );
+ break;
+ default: c_arg( ( mpu_real * ) d, ( mpu_complex * ) a, (int)nr );
+ break;
+ }
+ }
+ return( 0 );
+ case CPU_OP_CRTOC:
+ {
+ __mpu_size_t nc, nr;
+ rc = getreg( &i->operand[0], &d, &nc );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &nr );
+ if( rc ) return( rc );
+ if( !valid_complex( nc ) || !valid_real( nr ) || nc != 2U * nr ) return( CPU_EXEC_WIDTH_FAULT );
+ {
+ __mpu_uint32_t flags = cpu_status_flags_save();
+ c_real_to_complex( ( mpu_complex * ) d, ( mpu_real * ) a, (int)nr );
+ cpu_status_flags_restore( flags );
+ }
+ }
+ return( 0 );
+ case CPU_OP_CGEN:
+ case CPU_OP_CPOLAR:
+ {
+ __mpu_size_t nc, nr, ni;
+ rc = getreg( &i->operand[0], &d, &nc );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[1], &a, &nr );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &b, &ni );
+ if( rc ) return( rc );
+ if( nr != ni || !valid_real( nr ) || !valid_complex( nc ) || nc != 2U * nr ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->opcode == CPU_OP_CPOLAR && nr > NB_R16384 ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->opcode == CPU_OP_CGEN ) c_gen_complex( ( mpu_complex * ) d, ( mpu_real * ) a, ( mpu_real * ) b, (int)nr );
+ else c_polar( ( mpu_complex * ) d, ( mpu_real * ) a, ( mpu_real * ) b, (int)nr );
+ }
+ return( 0 );
+ case CPU_OP_CISEQ:
+ case CPU_OP_CISNE:
+ {
+ __mpu_size_t na, nb;
+ int v;
+ rc = getreg( &i->operand[1], &a, &na );
+ if( rc ) return( rc );
+ rc = getreg( &i->operand[2], &b, &nb );
+ if( rc ) return( rc );
+ if( na != nb || !valid_complex( na ) ) return( CPU_EXEC_WIDTH_FAULT );
+ v = ( i->opcode == CPU_OP_CISEQ ) ?
+ c_is_equal( ( mpu_complex * ) a, ( mpu_complex * ) b, (int)( na / 2 ) ):
+ c_is_nequal( ( mpu_complex * ) a, ( mpu_complex * ) b, (int)( na / 2 ) );
+ return( put_i64_result( &i->operand[0], (__mpu_int64_t)v ) );
+ }
+
+ case CPU_OP_JMP:
+ if( i->operand[0].type != CPU_OPERAND_CODE64 ) return( CPU_EXEC_OPERAND_FAULT );
+ if( i->operand[0].value.code64 >= __PSIZE ) return( CPU_EXEC_MEMORY_FAULT );
+ __PC = i->operand[0].value.code64;
+ return( CPU_EXEC_BRANCH );
+
+ case CPU_OP_JMPP:
+ {
+ __mpu_uint64_t target;
+ rc = code_pointer_target( &i->operand[0], &target );
+ if( rc ) return( rc );
+ __PC = target;
+ }
+ return( CPU_EXEC_BRANCH );
+
+ case CPU_OP_JSET:
+ case CPU_OP_JCLR:
+ if( i->operand[0].type != CPU_OPERAND_PSWBIT8 ||
+ i->operand[1].type != CPU_OPERAND_CODE64)
+ return( CPU_EXEC_OPERAND_FAULT );
+ if( i->operand[0].value.pswbit8 > CPU_PSWBIT_MAX )
+ return( CPU_EXEC_OPERAND_FAULT );
+ {
+ __mpu_uint32_t mask = (__mpu_uint32_t)1U << i->operand[0].value.pswbit8;
+ int set = ( ( __cpu_get_psw() & mask ) != 0 );
+ int take = ( i->opcode == CPU_OP_JSET ) ? set : !set;
+ if( take )
+ {
+ if( i->operand[1].value.code64 >= __PSIZE ) return( CPU_EXEC_MEMORY_FAULT );
+ __PC = i->operand[1].value.code64;
+ return( CPU_EXEC_BRANCH );
+ }
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_CALL:
+ if( i->operand[0].type != CPU_OPERAND_CODE64 ) return( CPU_EXEC_OPERAND_FAULT );
+ if( i->operand[0].value.code64 >= __PSIZE ) return( CPU_EXEC_MEMORY_FAULT );
+ if( __PC > __PSIZE || ( CPU_OPCODE_SIZE + CPU_CODE64_SIZE ) > __PSIZE - __PC ) return( CPU_EXEC_MEMORY_FAULT );
+ {
+ __mpu_uint64_t ret = __PC + CPU_OPCODE_SIZE + CPU_CODE64_SIZE;
+ __mpu_uint64_t p;
+ if( ret >= __PSIZE ) return( CPU_EXEC_MEMORY_FAULT );
+ if( !__STACK || !__SSIZE || __SP > __SSIZE || CPU_CODE64_SIZE > __SP ) return( CPU_EXEC_STACK_FAULT );
+ p = __SP - CPU_CODE64_SIZE;
+ __cpu_data_put_u64( __STACK + p, ret );
+ __SP = p;
+ __PC = i->operand[0].value.code64;
+ }
+ return( CPU_EXEC_BRANCH );
+
+ case CPU_OP_CALLP:
+ {
+ const __mpu_uint64_t ilen = CPU_OPCODE_SIZE + CPU_REG24_SIZE;
+ __mpu_uint64_t target, ret, p;
+
+ /* Validate every source of failure before touching STACK, SP or PC. */
+ rc = code_pointer_target( &i->operand[0], &target );
+ if( rc ) return( rc );
+ if( __PC > __PSIZE || ilen > __PSIZE - __PC ) return( CPU_EXEC_MEMORY_FAULT );
+ ret = __PC + ilen;
+ if( ret >= __PSIZE ) return( CPU_EXEC_MEMORY_FAULT );
+ if( !__STACK || !__SSIZE || __SP > __SSIZE || CPU_CODE64_SIZE > __SP )
+ return( CPU_EXEC_STACK_FAULT );
+
+ p = __SP - CPU_CODE64_SIZE;
+ __cpu_data_put_u64( __STACK + p, ret );
+ __SP = p;
+ __PC = target;
+ }
+ return( CPU_EXEC_BRANCH );
+
+ case CPU_OP_RET:
+ {
+ __mpu_uint64_t target;
+ if( !__STACK || !__SSIZE || __SP > __SSIZE || CPU_CODE64_SIZE > __SSIZE - __SP ) return( CPU_EXEC_STACK_FAULT );
+ target = __cpu_data_get_u64( __STACK + __SP );
+ if( target >= __PSIZE ) return( CPU_EXEC_MEMORY_FAULT );
+ __SP+=CPU_CODE64_SIZE;
+ __PC = target;
+ }
+ return( CPU_EXEC_BRANCH );
+
+ case CPU_OP_PUSH:
+ rc = getreg( &i->operand[0], &a, &n );
+ if( rc ) return( rc );
+ if( !__STACK || !__SSIZE || __SP > __SSIZE || (__mpu_uint64_t)n > __SP ) return( CPU_EXEC_STACK_FAULT );
+ {
+ __mpu_uint64_t p = __SP - (__mpu_uint64_t)n;
+ memmove( __STACK + p, a, n );
+ __SP = p;
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_POP:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( !__STACK || !__SSIZE || __SP > __SSIZE || (__mpu_uint64_t)n > __SSIZE - __SP ) return( CPU_EXEC_STACK_FAULT );
+ memmove( d, __STACK + __SP, n );
+ __SP += (__mpu_uint64_t)n;
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_LDSP:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( i->operand[1].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ __mpu_uint64_t p;
+ rc = stack_offset( i->operand[1].value.off64, (__mpu_uint64_t)n, &p );
+ if( rc ) return( rc );
+ memmove( d, __STACK + p, n );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_STSP:
+ if( i->operand[0].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ rc = getreg( &i->operand[1], &a, &n );
+ if( rc ) return( rc );
+ {
+ __mpu_uint64_t p;
+ rc = stack_offset( i->operand[0].value.off64, (__mpu_uint64_t)n, &p );
+ if( rc ) return( rc );
+ memmove( __STACK + p, a, n );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_ADJSP:
+ if( i->operand[0].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ __mpu_uint64_t p;
+ rc = stack_offset( i->operand[0].value.off64, 0, &p );
+ if( rc ) return( rc );
+ __SP = p;
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_PUSHFP:
+ if( !__STACK || !__SSIZE || __SP > __SSIZE || __FP > __SSIZE || CPU_PTR64_SIZE > __SP )
+ return( CPU_EXEC_STACK_FAULT );
+ {
+ __mpu_uint64_t p = __SP - CPU_PTR64_SIZE;
+ __cpu_data_put_u64( __STACK + p, __FP );
+ __SP = p;
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_SETFP:
+ if( !__STACK || !__SSIZE || __SP > __SSIZE ) return( CPU_EXEC_STACK_FAULT );
+ __FP = __SP;
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_RESTSP:
+ if( !__STACK || !__SSIZE || __FP > __SSIZE ) return( CPU_EXEC_STACK_FAULT );
+ __SP = __FP;
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_POPFP:
+ {
+ __mpu_uint64_t oldfp;
+ if( !__STACK || !__SSIZE || __SP > __SSIZE || CPU_PTR64_SIZE > __SSIZE - __SP )
+ return( CPU_EXEC_STACK_FAULT );
+ oldfp = __cpu_data_get_u64( __STACK + __SP );
+ if( oldfp > __SSIZE ) return( CPU_EXEC_STACK_FAULT );
+ __FP = oldfp;
+ __SP+=CPU_PTR64_SIZE;
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_LDFP:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( i->operand[1].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ __mpu_uint64_t p;
+ rc = frame_offset( i->operand[1].value.off64, (__mpu_uint64_t)n, &p );
+ if( rc ) return( rc );
+ memmove( d, __STACK + p, n );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_STFP:
+ if( i->operand[0].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ rc = getreg( &i->operand[1], &a, &n );
+ if( rc ) return( rc );
+ {
+ __mpu_uint64_t p;
+ rc = frame_offset( i->operand[0].value.off64, (__mpu_uint64_t)n, &p );
+ if( rc ) return( rc );
+ memmove( __STACK + p, a, n );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_LEAFP:
+ rc = getreg( &i->operand[0], &d, &n );
+ if( rc ) return( rc );
+ if( n != CPU_PTR64_SIZE ) return( CPU_EXEC_WIDTH_FAULT );
+ if( i->operand[1].type != CPU_OPERAND_OFF64 ) return( CPU_EXEC_OPERAND_FAULT );
+ {
+ __mpu_uint64_t pos, ptr;
+ rc = frame_offset( i->operand[1].value.off64, 0, &pos );
+ if( rc ) return( rc );
+ if( pos > CPU_PTR_OFFSET_MASK ) return( CPU_EXEC_POINTER_FAULT );
+ if( __cpu_ptr_make( &ptr, CPU_PTR_SEG_STACK, pos ) ) return( CPU_EXEC_POINTER_FAULT );
+ __cpu_data_put_u64( d, ptr );
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ case CPU_OP_SETSP:
+ rc = pointer_register( &i->operand[0], &a );
+ if( rc ) return( rc );
+ {
+ __mpu_uint64_t ptr, off;
+ unsigned int seg;
+ ptr = __cpu_data_get_u64( a );
+ seg = __cpu_ptr_segment( ptr );
+ off = __cpu_ptr_offset( ptr );
+ if( seg != CPU_PTR_SEG_STACK ) return( CPU_EXEC_POINTER_FAULT );
+ if( !__STACK || !__SSIZE || off > __SSIZE ) return( CPU_EXEC_STACK_FAULT );
+ __SP = off;
+ }
+ return( CPU_EXEC_SUCCESS );
+
+ default: return( CPU_EXEC_OPCODE_FAULT );
+ }
+}
+
+static int
+decode_need( __mpu_uint64_t program_size, __mpu_uint64_t pos,
+ __mpu_uint64_t n )
+{
+ return( pos <= program_size && n <= program_size - pos );
+}
+
+static int
+decode_reg( const __mpu_UNIT_t *program, __mpu_uint64_t program_size,
+ cpu_operand *o, __mpu_uint64_t *p )
+{
+ if( !decode_need( program_size, *p, 3 ) || __cpu_decode_reg24( &o->value.reg, program + *p ) ) return( -1 );
+ o->type = CPU_OPERAND_REGISTER;
+ *p += 3;
+ return( 0 );
+}
+
+static int
+decode_u64( const __mpu_UNIT_t *program, __mpu_uint64_t program_size,
+ cpu_operand *o, __mpu_uint64_t *p, cpu_operand_type t )
+{
+ __mpu_uint64_t v;
+ if( !decode_need( program_size, *p, 8 ) ) return( -1 );
+ v = __cpu_code_get_u64( program + *p );
+ *p += 8;
+ o->type = t;
+ if( t == CPU_OPERAND_IMM64 ) o->value.imm64 = v;
+ else if( t == CPU_OPERAND_ADDR64 ) o->value.addr64 = v;
+ else if( t == CPU_OPERAND_CODE64 ) o->value.code64 = v;
+ else if( t == CPU_OPERAND_OFF64 ) memcpy( &o->value.off64, &v, sizeof( v ) );
+ else if( t == CPU_OPERAND_PTR64 ) o->value.ptr64 = v;
+ else return( -1 );
+ return( 0 );
+}
+
+static int
+decode_u8( const __mpu_UNIT_t *program, __mpu_uint64_t program_size,
+ cpu_operand *o, __mpu_uint64_t *p, cpu_operand_type t )
+{
+ __mpu_uint8_t v;
+ if( !decode_need( program_size, *p, 1 ) ) return( -1 );
+ v = program[ ( *p )++];
+ o->type = t;
+ if( t == CPU_OPERAND_CONST8 ) o->value.const8 = v;
+ else if( t == CPU_OPERAND_PSWBIT8 ) o->value.pswbit8 = v;
+ else return( -1 );
+ return( 0 );
+}
+
+int
+__cpu_decode_at( const __mpu_UNIT_t *program, __mpu_uint64_t program_size,
+ __mpu_uint64_t pc, cpu_instruction *i )
+{
+ __mpu_uint64_t p = pc, start = p;
+ __mpu_uint16_t op;
+ int k;
+ if( !i || !program || !decode_need( program_size, p, 2 ) ) return( CPU_EXEC_DECODE_FAULT );
+ memset( i, 0, sizeof( *i ) );
+ op = __cpu_code_get_u16( program + p );
+ p += 2;
+ i->opcode = (cpu_opcode)op;
+#define DR(n) do{for(k=0;k<(n);k++)if(decode_reg(program,program_size,&i->operand[k],&p))return CPU_EXEC_DECODE_FAULT;}while(0)
+ switch( op )
+ {
+ case CPU_OP_NOP:case CPU_OP_HALT:case CPU_OP_END:case CPU_OP_SYSCALL:case CPU_OP_RET:
+ case CPU_OP_CLRCPUF:case CPU_OP_CLRMPUF:
+ case CPU_OP_PUSHFP:case CPU_OP_SETFP:case CPU_OP_RESTSP:case CPU_OP_POPFP:break;
+ case CPU_OP_SETF:case CPU_OP_CLRF:
+ if( decode_u8( program, program_size, &i->operand[0], &p, CPU_OPERAND_PSWBIT8 ) ) return( CPU_EXEC_DECODE_FAULT );
+ if( i->operand[0].value.pswbit8 > CPU_PSWBIT_WRITE_MAX ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_CLR: case CPU_OP_EXIT: DR( 1 );
+ break;
+ case CPU_OP_MOV:case CPU_OP_SWAP:case CPU_OP_BSWAP:
+ case CPU_OP_INOT:case CPU_OP_INEG:case CPU_OP_ICMP:case CPU_OP_ITEST:
+ case CPU_OP_ISHL:case CPU_OP_ISHR:case CPU_OP_ISAL:case CPU_OP_ISAR:
+ case CPU_OP_IROL:case CPU_OP_IROR:case CPU_OP_IRCL:case CPU_OP_IRCR:
+ case CPU_OP_IINC:case CPU_OP_IDEC:case CPU_OP_IXCHG:case CPU_OP_ICPY:
+ case CPU_OP_ICVT:case CPU_OP_IBITSLEN:
+ case CPU_OP_RSQRT:case CPU_OP_RSIN:case CPU_OP_RCOS:case CPU_OP_RTAN:
+ case CPU_OP_RASIN:case CPU_OP_RACOS:case CPU_OP_RATAN:
+ case CPU_OP_RLOG:case CPU_OP_RLOG10:case CPU_OP_RLOG2:case CPU_OP_REXP:
+ case CPU_OP_RSINH:case CPU_OP_RCOSH:case CPU_OP_RTANH:
+ case CPU_OP_RNEG:case CPU_OP_RABS:case CPU_OP_RCPY:case CPU_OP_RCVT:
+ case CPU_OP_RFLOOR:case CPU_OP_RCEIL:case CPU_OP_RROUND:case CPU_OP_RLOGB:
+ case CPU_OP_RLOG1P:case CPU_OP_REXPM1:case CPU_OP_RASINH:case CPU_OP_RACOSH:case CPU_OP_RATANH:
+ case CPU_OP_ITOR:case CPU_OP_UITOR:
+ case CPU_OP_RISNEG:case CPU_OP_RSIGN:case CPU_OP_RISIND:case CPU_OP_RISNAN:
+ case CPU_OP_RISNANMAX:case CPU_OP_RISNANMIN:case CPU_OP_RISINF:case CPU_OP_RISSIGNULL:
+ case CPU_OP_CEXP:case CPU_OP_CSIN:case CPU_OP_CCOS:case CPU_OP_CSINH:
+ case CPU_OP_CCOSH:case CPU_OP_CLOG:case CPU_OP_CSQRT:
+ case CPU_OP_CREAL:case CPU_OP_CIMAG:case CPU_OP_CRTOC:case CPU_OP_CCONJ:
+ case CPU_OP_CABS:case CPU_OP_CNORM:case CPU_OP_CARG:case CPU_OP_CCPY:case CPU_OP_CCVT:
+ DR( 2 );
+ break;
+ case CPU_OP_IADD:case CPU_OP_IADC:case CPU_OP_ISUB:case CPU_OP_ISBB:
+ case CPU_OP_IAND:case CPU_OP_IOR:case CPU_OP_IXOR:
+ case CPU_OP_ISHLN:case CPU_OP_ISHRN:case CPU_OP_ISALN:case CPU_OP_ISARN:
+ case CPU_OP_IROLN:case CPU_OP_IRORN:case CPU_OP_IRCLN:case CPU_OP_IRCRN:
+ case CPU_OP_IMUL:case CPU_OP_ISMUL:
+ case CPU_OP_RADD:case CPU_OP_RSUB:case CPU_OP_RMUL:case CPU_OP_RDIV:
+ case CPU_OP_RPOW:case CPU_OP_RHYPOT:case CPU_OP_RATAN2:case CPU_OP_RCMP:
+ case CPU_OP_RFREXP:case CPU_OP_RLDEXP:case CPU_OP_RMODF:case CPU_OP_RREMAIN:
+ case CPU_OP_RTOI:case CPU_OP_RTOUI:
+ case CPU_OP_CADD:case CPU_OP_CSUB:case CPU_OP_CMUL:case CPU_OP_CDIV:case CPU_OP_CPOW:
+ case CPU_OP_CGEN:case CPU_OP_CPOLAR:case CPU_OP_CISEQ:case CPU_OP_CISNE:
+ DR( 3 );
+ break;
+ case CPU_OP_IDIV: case CPU_OP_ISDIV: DR( 4 );
+ break;
+ case CPU_OP_LDI: case CPU_OP_LDR: case CPU_OP_LDC: DR( 1 );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_IMM64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_LOAD: DR( 1 );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_ADDR64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_STORE: if( decode_u64( program, program_size, &i->operand[0], &p, CPU_OPERAND_ADDR64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ if( decode_reg( program, program_size, &i->operand[1], &p ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_LEA: DR( 1 );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_PTR64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_LEASP: DR( 1 );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_LOADP: case CPU_OP_STOREP: DR( 2 );
+ break;
+ case CPU_OP_PADD: case CPU_OP_PSUB: case CPU_OP_PDIFF: case CPU_OP_BMOV: DR( 3 );
+ break;
+ case CPU_OP_BMOVI:
+ DR( 2 );
+ if( decode_u64( program, program_size, &i->operand[2], &p, CPU_OPERAND_IMM64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_PADDI:case CPU_OP_PSUBI:
+ DR( 2 );
+ if( decode_u64( program, program_size, &i->operand[2], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_RCONST: DR( 1 );
+ if( decode_u8( program, program_size, &i->operand[1], &p, CPU_OPERAND_CONST8 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_JMP: case CPU_OP_CALL: if( decode_u64( program, program_size, &i->operand[0], &p, CPU_OPERAND_CODE64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_JMPP: case CPU_OP_CALLP: DR( 1 );
+ break;
+ case CPU_OP_JSET:case CPU_OP_JCLR:
+ if( decode_u8( program, program_size, &i->operand[0], &p, CPU_OPERAND_PSWBIT8 ) ) return( CPU_EXEC_DECODE_FAULT );
+ if( i->operand[0].value.pswbit8 > CPU_PSWBIT_MAX ) return( CPU_EXEC_DECODE_FAULT );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_CODE64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_PUSH: case CPU_OP_POP: DR( 1 );
+ break;
+ case CPU_OP_LDSP: DR( 1 );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_STSP: if( decode_u64( program, program_size, &i->operand[0], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ if( decode_reg( program, program_size, &i->operand[1], &p ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_ADJSP: if( decode_u64( program, program_size, &i->operand[0], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_LDFP: DR( 1 );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_STFP: if( decode_u64( program, program_size, &i->operand[0], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ if( decode_reg( program, program_size, &i->operand[1], &p ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_LEAFP: DR( 1 );
+ if( decode_u64( program, program_size, &i->operand[1], &p, CPU_OPERAND_OFF64 ) ) return( CPU_EXEC_DECODE_FAULT );
+ break;
+ case CPU_OP_SETSP: DR( 1 );
+ break;
+ default: return( CPU_EXEC_OPCODE_FAULT );
+ }
+#undef DR
+ i->length = p - start;
+ return( 0 );
+}
+
+
+int
+__cpu_decode( cpu_instruction *i )
+{
+ return( __cpu_decode_at( __PROGRAM, __PSIZE, __PC, i ) );
+
+} /* End of __cpu_decode() */
+
+int
+__cpu_step( void )
+{
+ cpu_instruction i;
+ int rc = __cpu_decode( &i );
+ if( rc )
+ {
+ __STOP_REASON = CPU_STOP_FAULT;
+ return( rc );
+ }
+ rc = __cpu_exec( &i );
+ if( rc == CPU_EXEC_BRANCH )
+ {
+ if( __cpu_gth() )
+ {
+ __STOP_REASON = CPU_STOP_HALT;
+ return( CPU_EXEC_HALT );
+ }
+ return( CPU_EXEC_SUCCESS );
+ }
+ if( rc == CPU_EXEC_END )
+ {
+ __PC += i.length;
+ __STOP_REASON = CPU_STOP_END;
+ return( rc );
+ }
+ if( rc == CPU_EXEC_EXIT )
+ {
+ __PC += i.length;
+ __STOP_REASON = CPU_STOP_EXIT;
+ return( rc );
+ }
+ if( rc < 0 )
+ {
+ __STOP_REASON = CPU_STOP_FAULT;
+ return( rc );
+ }
+ if( rc ) return( rc );
+ __PC+=i.length;
+ if( __cpu_gth() )
+ {
+ __STOP_REASON = CPU_STOP_HALT;
+ return( CPU_EXEC_HALT );
+ }
+ return( CPU_EXEC_SUCCESS );
+}
+
+int
+__cpu_run( void )
+{
+ int rc;
+ __cpu_clh();
+ __cpu_clear_stop_reason();
+ for( ; ; )
+ {
+ rc = __cpu_step();
+ if( rc == CPU_EXEC_HALT ) return( CPU_EXEC_SUCCESS );
+ if( rc != CPU_EXEC_SUCCESS ) return( rc );
+ }
+}
diff --git a/cpu/cpu-instruction.h b/cpu/cpu-instruction.h
new file mode 100644
index 0000000..d787b43
--- /dev/null
+++ b/cpu/cpu-instruction.h
@@ -0,0 +1,32 @@
+/***************************************************************
+ __CPU_INSTRUCTION.H
+
+ This file contains CPU INSTRUCTION operation functions &
+ data declarations.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ NOTE : Include "libcpu.h" before this FILE .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_INSTRUCTION_H
+#define __CPU_INSTRUCTION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define __CPU_MAX_OPERANDS 4
+
+
+#ifdef __cplusplus
+} /* ... extern "C" */
+#endif
+
+#endif /* __CPU_INSTRUCTION_H */
diff --git a/cpu/cpu-registers.c b/cpu/cpu-registers.c
new file mode 100644
index 0000000..7cd7dee
--- /dev/null
+++ b/cpu/cpu-registers.c
@@ -0,0 +1,74 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <libmcpu.h>
+#include <cpu-context.h>
+#include <cpu-registers.h>
+
+__mpu_size_t
+__cpu_reg_size( unsigned int bits )
+{
+ if( bits < 8 || bits > 65536 || ( bits & ( bits - 1 ) ) ) return( 0 );
+ return( (__mpu_size_t)( bits >> 3 ) );
+}
+
+int
+__cpu_reg_valid( unsigned int bits, __mpu_uint32_t a )
+{
+ __mpu_size_t n = __cpu_reg_size( bits );
+ if( !n ) return( 0 );
+ if( ( a & ( n - 1 ) ) != 0 ) return( 0 );
+ if( a > CPU_REGISTER_ADDRESS_MAX ) return( 0 );
+ if( (__mpu_uint64_t)a + n > CPU_REGISTERS_MEM_SIZE_IN_UNITS ) return( 0 );
+ return( 1 );
+}
+
+__mpu_UNIT_t *
+__cpu_reg_ptr( unsigned int bits, __mpu_uint32_t a )
+{
+ return( __cpu_reg_valid( bits, a ) ? &__REGS[a] : (__mpu_UNIT_t *)0 );
+}
+
+int
+__cpu_encode_reg24( __mpu_UNIT_t out[3], const cpu_register *r )
+{
+ unsigned int code = 0, b;
+ if( !out || !r || !__cpu_reg_valid( r->bits, r->address ) ) return( -1 );
+ b = r->bits;
+ while( b > 8 )
+ {
+ b >>= 1;
+ ++code;
+ }
+ if( code > 13 ) return( -1 );
+ out[0] = (__mpu_UNIT_t)( ( code << 4 ) | ( ( r->address >> 16 ) & 0x0f ) );
+ out[1] = (__mpu_UNIT_t)( ( r->address >> 8 ) & 0xff );
+ out[2] = (__mpu_UNIT_t)( r->address & 0xff );
+ return( 0 );
+}
+
+int
+__cpu_decode_reg24( cpu_register *r, const __mpu_UNIT_t in[3] )
+{
+ unsigned int code;
+ __mpu_uint32_t a;
+ if( !r || !in ) return( -1 );
+ code = ( in[0] >> 4 ) & 0x0f;
+ if( code > 13 ) return( -1 );
+ a = ( (__mpu_uint32_t)( in[0] & 0x0f ) << 16 ) | ( (__mpu_uint32_t)in[1] << 8 ) | in[2];
+ r->bits = 8U << code;
+ r->address = a;
+ return( __cpu_reg_valid( r->bits, a ) ? 0 : -1 );
+}
+
+int
+__cpu_return_reg( cpu_register *r, unsigned int bits )
+{
+ __mpu_size_t n;
+ if( !r ) return( -1 );
+ n = __cpu_reg_size( bits );
+ if( !n || (__mpu_uint64_t)n > CPU_RETURN_AREA_SIZE ) return( -1 );
+ r->bits = bits;
+ r->address = (__mpu_uint32_t)( CPU_RETURN_AREA_END - (__mpu_uint32_t)n );
+ return( __cpu_reg_valid( r->bits, r->address ) ? 0 : -1 );
+}
diff --git a/cpu/cpu-registers.h b/cpu/cpu-registers.h
new file mode 100644
index 0000000..f9bf9cb
--- /dev/null
+++ b/cpu/cpu-registers.h
@@ -0,0 +1,33 @@
+/***************************************************************
+ __CPU_REGISTERS.H
+
+ This file contains CPU REGISTER operation functions & data
+ declarations.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ NOTE : Include "libcpu.h" before this FILE .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_REGISTERS_H
+#define __CPU_REGISTERS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define __CPU_REGISTER_MIN_BITS 8
+#define __CPU_REGISTER_MAX_BITS 65536
+
+
+#ifdef __cplusplus
+} /* ... extern "C" */
+#endif
+
+#endif /* __CPU_REGISTERS_H */
diff --git a/cpu/cpu-syscalls.c b/cpu/cpu-syscalls.c
new file mode 100644
index 0000000..f12e729
--- /dev/null
+++ b/cpu/cpu-syscalls.c
@@ -0,0 +1,2174 @@
+/***************************************************************
+ __CPU_SYSCALLS.C
+
+ This file contains source code of MCPU system calls.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ NOTE : NONE .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libmcpu.h>
+#include <cpu-context.h>
+#include <cpu-syscalls.h>
+#include <cpu-sysdeps.h>
+
+
+#define __NR_brk 10
+#define __NR_gettimeofday 0x01c
+#define __NR_clock_getres 0x021
+#define __NR_clock_gettime 0x022
+#define __NR_nanosleep 0x030
+#define __NR_clock_nanosleep 0x031
+
+#define __NR_read 0x100
+#define __NR_write 0x101
+#define __NR_lseek 0x102
+#define __NR_open 0x103
+#define __NR_creat 0x104
+#define __NR_close 0x105
+#define __NR_link 0x106
+#define __NR_unlink 0x107
+#define __NR_chdir 0x108
+#define __NR_mkdir 0x109
+#define __NR_chmod 0x10b
+#define __NR_chown 0x10c
+#define __NR_access 0x10f
+#define __NR_rename 0x111
+#define __NR_rmdir 0x112
+#define __NR_symlink 0x113
+#define __NR_readlink 0x114
+#define __NR_stat 0x115
+#define __NR_fstat 0x116
+#define __NR_lstat 0x117
+#define __NR_fcntl 0x119
+#define __NR_pipe2 0x11a
+#define __NR_getdents 0x11d
+#define __NR_select 0x11e
+#define __NR_fsync 0x120
+#define __NR_truncate 0x121
+#define __NR_ftruncate 0x122
+#define __NR_fchmod 0x123
+#define __NR_fchown 0x124
+#define __NR_fchdir 0x125
+#define __NR_dup 0x126
+#define __NR_dup2 0x127
+
+#define CPU_PATH_MAX 4096U
+
+
+static __mpu_uint64_t
+__cpu_syscall_error( int error )
+{
+ __mpu_int64_t ret = -(__mpu_int64_t)error;
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_syscall_error() */
+
+
+static __mpu_uint32_t
+__cpu_syscall_nargs( void )
+{
+ return( __cpu_data_get_u32( __cpu_reg_ptr( 32, CPU_SYSCALL_NARGS_ADDR ) ) );
+
+} /* End of __cpu_syscall_nargs() */
+
+
+static __mpu_uint64_t
+__cpu_syscall_arg( unsigned int n )
+{
+ static const __mpu_uint32_t address[CPU_SYSCALL_MAX_ARGS] =
+ {
+ CPU_SYSCALL_ARG0_ADDR,
+ CPU_SYSCALL_ARG1_ADDR,
+ CPU_SYSCALL_ARG2_ADDR,
+ CPU_SYSCALL_ARG3_ADDR,
+ CPU_SYSCALL_ARG4_ADDR,
+ CPU_SYSCALL_ARG5_ADDR
+ };
+
+ if( n >= CPU_SYSCALL_MAX_ARGS ) return( 0 );
+
+ return( __cpu_data_get_u64( __cpu_reg_ptr( 64, address[n] ) ) );
+
+} /* End of __cpu_syscall_arg() */
+
+
+static int
+__cpu_memory_resolve( __mpu_uint64_t ptr, __mpu_uint64_t size, int write,
+ __mpu_UNIT_t **memory )
+{
+ __mpu_UNIT_t *base = (__mpu_UNIT_t *)0;
+ __mpu_uint64_t limit = 0;
+ __mpu_uint64_t offset;
+ unsigned int segment;
+
+ if( !memory ) return( __MCPU_EFAULT );
+ *memory = (__mpu_UNIT_t *)0;
+
+ if( ptr == CPU_NULL_PTR ) return( __MCPU_EFAULT );
+
+ segment = __cpu_ptr_segment( ptr );
+ offset = __cpu_ptr_offset( ptr );
+
+ switch( segment )
+ {
+ case CPU_PTR_SEG_DATA:
+ base = __DATA;
+ limit = __DSIZE;
+ break;
+ case CPU_PTR_SEG_STACK:
+ base = __STACK;
+ limit = __SSIZE;
+ break;
+ case CPU_PTR_SEG_PROGRAM:
+ if( write ) return( __MCPU_EFAULT );
+ base = __PROGRAM;
+ limit = __PSIZE;
+ break;
+ case CPU_PTR_SEG_CONTROL:
+ if( write ) return( __MCPU_EFAULT );
+ base = __CONTROL;
+ limit = __CSIZE;
+ break;
+ case CPU_PTR_SEG_INPUT:
+ if( write ) return( __MCPU_EFAULT );
+ base = __INPUT;
+ limit = __ISIZE;
+ break;
+ case CPU_PTR_SEG_OUTPUT:
+ base = __OUTPUT;
+ limit = __OSIZE;
+ break;
+ case CPU_PTR_SEG_TRACE:
+ base = __TRACE;
+ limit = __TSIZE;
+ break;
+ case CPU_PTR_SEG_HEAP:
+ base = __HEAP;
+ limit = __HBRK;
+ if( offset < CPU_HEAP_BEGIN ) return( __MCPU_EFAULT );
+ break;
+ default:
+ return( __MCPU_EFAULT );
+ }
+
+ if( !base || offset > limit || size > limit - offset ) return( __MCPU_EFAULT );
+
+ *memory = base + offset;
+ return( 0 );
+
+} /* End of __cpu_memory_resolve() */
+
+
+static int
+__cpu_copyin( void *dst, __mpu_uint64_t src, __mpu_uint64_t size )
+{
+ __mpu_UNIT_t *memory;
+ int error;
+
+ if( !size ) return( 0 );
+ if( !dst ) return( __MCPU_EFAULT );
+
+ error = __cpu_memory_resolve( src, size, 0, &memory );
+ if( error ) return( error );
+
+ memcpy( dst, memory, (size_t)size );
+ return( 0 );
+
+} /* End of __cpu_copyin() */
+
+
+static int
+__cpu_copyout( __mpu_uint64_t dst, const void *src, __mpu_uint64_t size )
+{
+ __mpu_UNIT_t *memory;
+ int error;
+
+ if( !size ) return( 0 );
+ if( !src ) return( __MCPU_EFAULT );
+
+ error = __cpu_memory_resolve( dst, size, 1, &memory );
+ if( error ) return( error );
+
+ memcpy( memory, src, (size_t)size );
+ return( 0 );
+
+} /* End of __cpu_copyout() */
+
+
+static int
+__cpu_utf8_valid( const unsigned char *s, size_t n )
+{
+ size_t i = 0;
+
+ while( i < n )
+ {
+ unsigned int c = s[i++];
+
+ if( c < 0x80U ) continue;
+
+ if( c >= 0xc2U && c <= 0xdfU )
+ {
+ if( i >= n || ( s[i] & 0xc0U ) != 0x80U ) return( 0 );
+ ++i;
+ continue;
+ }
+
+ if( c == 0xe0U )
+ {
+ if( i + 1 >= n || s[i] < 0xa0U || s[i] > 0xbfU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2;
+ continue;
+ }
+
+ if( c >= 0xe1U && c <= 0xecU )
+ {
+ if( i + 1 >= n || ( s[i] & 0xc0U ) != 0x80U ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2;
+ continue;
+ }
+
+ if( c == 0xedU )
+ {
+ if( i + 1 >= n || s[i] < 0x80U || s[i] > 0x9fU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2;
+ continue;
+ }
+
+ if( c >= 0xeeU && c <= 0xefU )
+ {
+ if( i + 1 >= n || ( s[i] & 0xc0U ) != 0x80U ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2;
+ continue;
+ }
+
+ if( c == 0xf0U )
+ {
+ if( i + 2 >= n || s[i] < 0x90U || s[i] > 0xbfU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ||
+ ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 3;
+ continue;
+ }
+
+ if( c >= 0xf1U && c <= 0xf3U )
+ {
+ if( i + 2 >= n || ( s[i] & 0xc0U ) != 0x80U ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ||
+ ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 3;
+ continue;
+ }
+
+ if( c == 0xf4U )
+ {
+ if( i + 2 >= n || s[i] < 0x80U || s[i] > 0x8fU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ||
+ ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 3;
+ continue;
+ }
+
+ return( 0 );
+ }
+
+ return( 1 );
+
+} /* End of __cpu_utf8_valid() */
+
+
+static int
+__cpu_copyinstr( char **dst, __mpu_uint64_t src )
+{
+ __mpu_UNIT_t *memory;
+ __mpu_uint64_t offset;
+ __mpu_uint64_t limit;
+ __mpu_uint64_t n;
+ unsigned int segment;
+ char *s;
+
+ if( !dst ) return( __MCPU_EFAULT );
+ *dst = (char *)0;
+
+ if( src == CPU_NULL_PTR ) return( __MCPU_EFAULT );
+
+ segment = __cpu_ptr_segment( src );
+ offset = __cpu_ptr_offset( src );
+
+ if( __cpu_memory_resolve( src, 1, 0, &memory ) != 0 ) return( __MCPU_EFAULT );
+
+ switch( segment )
+ {
+ case CPU_PTR_SEG_DATA: limit = __DSIZE; break;
+ case CPU_PTR_SEG_STACK: limit = __SSIZE; break;
+ case CPU_PTR_SEG_PROGRAM: limit = __PSIZE; break;
+ case CPU_PTR_SEG_CONTROL: limit = __CSIZE; break;
+ case CPU_PTR_SEG_INPUT: limit = __ISIZE; break;
+ case CPU_PTR_SEG_OUTPUT: limit = __OSIZE; break;
+ case CPU_PTR_SEG_TRACE: limit = __TSIZE; break;
+ case CPU_PTR_SEG_HEAP: limit = __HBRK; break;
+ default: return( __MCPU_EFAULT );
+ }
+
+ n = 0;
+ while( offset + n < limit && n < CPU_PATH_MAX )
+ {
+ if( memory[n] == 0 ) break;
+ ++n;
+ }
+
+ if( offset + n >= limit || n >= CPU_PATH_MAX ) return( __MCPU_ENAMETOOLONG );
+ if( !__cpu_utf8_valid( memory, (size_t)n ) ) return( __MCPU_EILSEQ );
+
+ s = (char *)malloc( (size_t)n + 1U );
+ if( !s ) return( __MCPU_ENOMEM );
+ memcpy( s, memory, (size_t)n );
+ s[n] = '\0';
+ *dst = s;
+
+ return( 0 );
+
+} /* End of __cpu_copyinstr() */
+
+
+void
+__cpu_fd_context_init( void )
+{
+ unsigned int i;
+
+ if( !pcctx ) return;
+
+ for( i = 0; i < CPU_GUEST_FD_MAX; ++i )
+ {
+ pcctx->_fd[i].host_fd = -1;
+ pcctx->_fd[i].owned = 0;
+ pcctx->_fd[i].flags = 0;
+ }
+
+ pcctx->_fd[0].host_fd = 0;
+ pcctx->_fd[1].host_fd = 1;
+ pcctx->_fd[2].host_fd = 2;
+ pcctx->_fd[0].flags = 0;
+ pcctx->_fd[1].flags = 0;
+ pcctx->_fd[2].flags = 0;
+ pcctx->_fd_initialized = 1;
+
+} /* End of __cpu_fd_context_init() */
+
+
+void
+__cpu_fd_context_free( void )
+{
+ unsigned int i;
+
+ if( !pcctx || !pcctx->_fd_initialized ) return;
+
+ for( i = 0; i < CPU_GUEST_FD_MAX; ++i )
+ {
+ if( pcctx->_fd[i].host_fd >= 0 && pcctx->_fd[i].owned )
+ (void)__cpu_sys_close( pcctx->_fd[i].host_fd );
+
+ pcctx->_fd[i].host_fd = -1;
+ pcctx->_fd[i].owned = 0;
+ pcctx->_fd[i].flags = 0;
+ }
+
+ pcctx->_fd_initialized = 0;
+
+} /* End of __cpu_fd_context_free() */
+
+
+void
+__cpu_cwd_context_init( void )
+{
+ __mpu_int64_t ret;
+
+ if( !pcctx ) return;
+
+ pcctx->_cwd_fd = -1;
+ pcctx->_cwd_initialized = 0;
+
+ ret = __cpu_sys_cwd_init();
+ if( ret < 0 ) return;
+
+ pcctx->_cwd_fd = (int)ret;
+ pcctx->_cwd_initialized = 1;
+
+} /* End of __cpu_cwd_context_init() */
+
+
+void
+__cpu_cwd_context_free( void )
+{
+ if( !pcctx || !pcctx->_cwd_initialized ) return;
+
+ if( pcctx->_cwd_fd >= 0 )
+ (void)__cpu_sys_close( pcctx->_cwd_fd );
+
+ pcctx->_cwd_fd = -1;
+ pcctx->_cwd_initialized = 0;
+
+} /* End of __cpu_cwd_context_free() */
+
+
+static int
+__cpu_fd_get( __mpu_uint64_t fd, int *host_fd )
+{
+ if( !pcctx || !pcctx->_fd_initialized || fd >= CPU_GUEST_FD_MAX ||
+ pcctx->_fd[fd].host_fd < 0 ) return( __MCPU_EBADF );
+
+ if( host_fd ) *host_fd = pcctx->_fd[fd].host_fd;
+ return( 0 );
+
+} /* End of __cpu_fd_get() */
+
+
+static int
+__cpu_fd_find_from( __mpu_uint64_t minimum )
+{
+ unsigned int fd;
+
+ if( !pcctx || !pcctx->_fd_initialized || minimum >= CPU_GUEST_FD_MAX )
+ return( -1 );
+
+ for( fd = (unsigned int)minimum; fd < CPU_GUEST_FD_MAX; ++fd )
+ if( pcctx->_fd[fd].host_fd < 0 ) return( (int)fd );
+
+ return( -1 );
+
+} /* End of __cpu_fd_find_from() */
+
+
+static int
+__cpu_fd_install_from( int host_fd, __mpu_uint64_t minimum, unsigned int flags )
+{
+ int fd;
+
+ if( host_fd < 0 ) return( -1 );
+
+ fd = __cpu_fd_find_from( minimum );
+ if( fd < 0 ) return( -1 );
+
+ pcctx->_fd[fd].host_fd = host_fd;
+ pcctx->_fd[fd].owned = 1;
+ pcctx->_fd[fd].flags = flags;
+
+ return( fd );
+
+} /* End of __cpu_fd_install_from() */
+
+
+static int
+__cpu_fd_install( int host_fd )
+{
+ return( __cpu_fd_install_from( host_fd, 3, 0 ) );
+
+} /* End of __cpu_fd_install() */
+
+
+
+
+static __mpu_uint64_t
+__cpu_stat_i64_bits( __mpu_int64_t value )
+{
+ __mpu_uint64_t bits;
+
+ memcpy( &bits, &value, sizeof( bits ) );
+ return( bits );
+
+} /* End of __cpu_stat_i64_bits() */
+
+
+static int
+__cpu_stat_copyout( __mpu_uint64_t ptr, const struct __cpu_stat *st )
+{
+ __mpu_UNIT_t data[__CPU_STAT_SIZE];
+
+ if( !st ) return( __MCPU_EFAULT );
+
+ memset( data, 0, sizeof( data ) );
+
+ __cpu_data_put_u64( data + __CPU_STAT_ST_DEV, st->st_dev );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_INO, st->st_ino );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_MODE, st->st_mode );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_NLINK, st->st_nlink );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_UID, st->st_uid );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_GID, st->st_gid );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_RDEV, st->st_rdev );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_SIZE, __cpu_stat_i64_bits( st->st_size ) );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_BLKSIZE, __cpu_stat_i64_bits( st->st_blksize ) );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_BLOCKS, __cpu_stat_i64_bits( st->st_blocks ) );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_ATIME_SEC, __cpu_stat_i64_bits( st->st_atime_sec ) );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_ATIME_NSEC, st->st_atime_nsec );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_MTIME_SEC, __cpu_stat_i64_bits( st->st_mtime_sec ) );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_MTIME_NSEC, st->st_mtime_nsec );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_CTIME_SEC, __cpu_stat_i64_bits( st->st_ctime_sec ) );
+ __cpu_data_put_u64( data + __CPU_STAT_ST_CTIME_NSEC, st->st_ctime_nsec );
+
+ return( __cpu_copyout( ptr, data, sizeof( data ) ) );
+
+} /* End of __cpu_stat_copyout() */
+
+
+static __mpu_uint64_t
+__cpu_dirent_i64_bits( __mpu_int64_t value )
+{
+ __mpu_uint64_t bits;
+
+ memcpy( &bits, &value, sizeof( bits ) );
+ return( bits );
+
+} /* End of __cpu_dirent_i64_bits() */
+
+
+static int
+__cpu_dirent_copyout( __mpu_uint64_t ptr, const struct __cpu_dirent *de,
+ __mpu_uint64_t count )
+{
+ __mpu_UNIT_t *data;
+ __mpu_uint64_t nrecords;
+ __mpu_uint64_t i;
+ int error;
+
+ if( !de && count ) return( __MCPU_EFAULT );
+ if( count % __CPU_DIRENT_SIZE != 0 ) return( __MCPU_EINVAL );
+ if( count > (__mpu_uint64_t)(size_t)-1 ) return( __MCPU_EINVAL );
+
+ if( !count ) return( 0 );
+ data = (__mpu_UNIT_t *)calloc( 1, (size_t)count );
+ if( !data ) return( __MCPU_ENOMEM );
+
+ nrecords = count / __CPU_DIRENT_SIZE;
+ for( i = 0; i < nrecords; ++i )
+ {
+ __mpu_UNIT_t *record = data + i * __CPU_DIRENT_SIZE;
+
+ __cpu_data_put_u64( record + __CPU_DIRENT_D_INO, de[i].d_ino );
+ __cpu_data_put_u64( record + __CPU_DIRENT_D_OFF,
+ __cpu_dirent_i64_bits( de[i].d_off ) );
+ __cpu_data_put_u64( record + __CPU_DIRENT_D_RECLEN, de[i].d_reclen );
+ __cpu_data_put_u64( record + __CPU_DIRENT_D_TYPE, de[i].d_type );
+ memcpy( record + __CPU_DIRENT_D_NAME, de[i].d_name,
+ __CPU_DIRENT_NAME_SIZE );
+ }
+
+ error = __cpu_copyout( ptr, data, count );
+ free( data );
+ return( error );
+
+} /* End of __cpu_dirent_copyout() */
+
+
+static __mpu_int64_t
+__cpu_select_i64_from_bits( __mpu_uint64_t bits )
+{
+ __mpu_int64_t value;
+
+ memcpy( &value, &bits, sizeof( value ) );
+ return( value );
+
+} /* End of __cpu_select_i64_from_bits() */
+
+
+static int
+__cpu_fdset_load( __mpu_uint64_t ptr, __mpu_uint64_t words[__CPU_FD_SET_WORDS] )
+{
+ __mpu_UNIT_t data[__CPU_FD_SET_SIZE];
+ __mpu_UNIT_t *memory;
+ unsigned int i;
+ int error;
+
+ error = __cpu_memory_resolve( ptr, __CPU_FD_SET_SIZE, 1, &memory );
+ if( error ) return( error );
+ (void)memory;
+
+ error = __cpu_copyin( data, ptr, sizeof( data ) );
+ if( error ) return( error );
+
+ for( i = 0; i < __CPU_FD_SET_WORDS; ++i )
+ words[i] = __cpu_data_get_u64( data + i * 8U );
+
+ return( 0 );
+
+} /* End of __cpu_fdset_load() */
+
+
+static int
+__cpu_fdset_store( __mpu_uint64_t ptr,
+ const __mpu_uint64_t words[__CPU_FD_SET_WORDS] )
+{
+ __mpu_UNIT_t data[__CPU_FD_SET_SIZE];
+ unsigned int i;
+
+ memset( data, 0, sizeof( data ) );
+ for( i = 0; i < __CPU_FD_SET_WORDS; ++i )
+ __cpu_data_put_u64( data + i * 8U, words[i] );
+
+ return( __cpu_copyout( ptr, data, sizeof( data ) ) );
+
+} /* End of __cpu_fdset_store() */
+
+
+static int
+__cpu_fdset_isset( const __mpu_uint64_t words[__CPU_FD_SET_WORDS],
+ unsigned int fd )
+{
+ unsigned int word = fd / 64U;
+ unsigned int bit = fd % 64U;
+
+ return( ( words[word] & ( (__mpu_uint64_t)1U << bit ) ) != 0 );
+
+} /* End of __cpu_fdset_isset() */
+
+
+static void
+__cpu_fdset_set( __mpu_uint64_t words[__CPU_FD_SET_WORDS], unsigned int fd )
+{
+ unsigned int word = fd / 64U;
+ unsigned int bit = fd % 64U;
+
+ words[word] |= ( (__mpu_uint64_t)1U << bit );
+
+} /* End of __cpu_fdset_set() */
+
+
+static int
+__cpu_timeval_load( __mpu_uint64_t ptr, struct __cpu_timeval *timeout )
+{
+ __mpu_UNIT_t data[__CPU_TIMEVAL_SIZE];
+ int error;
+
+ if( !timeout ) return( __MCPU_EFAULT );
+
+ error = __cpu_copyin( data, ptr, sizeof( data ) );
+ if( error ) return( error );
+
+ timeout->tv_sec = __cpu_select_i64_from_bits(
+ __cpu_data_get_u64( data + __CPU_TIMEVAL_TV_SEC ) );
+ timeout->tv_usec = __cpu_select_i64_from_bits(
+ __cpu_data_get_u64( data + __CPU_TIMEVAL_TV_USEC ) );
+
+ if( timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999 )
+ return( __MCPU_EINVAL );
+
+ return( 0 );
+
+} /* End of __cpu_timeval_load() */
+
+
+static int
+__cpu_timespec_load( __mpu_uint64_t ptr, struct __cpu_timespec *ts )
+{
+ __mpu_UNIT_t data[__CPU_TIMESPEC_SIZE];
+ int error;
+
+ if( !ts ) return( __MCPU_EFAULT );
+
+ error = __cpu_copyin( data, ptr, sizeof( data ) );
+ if( error ) return( error );
+
+ ts->tv_sec = __cpu_select_i64_from_bits(
+ __cpu_data_get_u64( data + __CPU_TIMESPEC_TV_SEC ) );
+ ts->tv_nsec = __cpu_select_i64_from_bits(
+ __cpu_data_get_u64( data + __CPU_TIMESPEC_TV_NSEC ) );
+
+ if( ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec > 999999999 )
+ return( __MCPU_EINVAL );
+
+ return( 0 );
+
+} /* End of __cpu_timespec_load() */
+
+
+static __mpu_uint64_t
+__cpu_time_i64_bits( __mpu_int64_t value )
+{
+ __mpu_uint64_t bits;
+
+ memcpy( &bits, &value, sizeof( bits ) );
+ return( bits );
+
+} /* End of __cpu_time_i64_bits() */
+
+
+static int
+__cpu_timeval_copyout( __mpu_uint64_t ptr, const struct __cpu_timeval *tv )
+{
+ __mpu_UNIT_t data[__CPU_TIMEVAL_SIZE];
+
+ if( !tv ) return( __MCPU_EFAULT );
+
+ memset( data, 0, sizeof( data ) );
+ __cpu_data_put_u64( data + __CPU_TIMEVAL_TV_SEC,
+ __cpu_time_i64_bits( tv->tv_sec ) );
+ __cpu_data_put_u64( data + __CPU_TIMEVAL_TV_USEC,
+ __cpu_time_i64_bits( tv->tv_usec ) );
+
+ return( __cpu_copyout( ptr, data, sizeof( data ) ) );
+
+} /* End of __cpu_timeval_copyout() */
+
+
+static int
+__cpu_timespec_copyout( __mpu_uint64_t ptr, const struct __cpu_timespec *ts )
+{
+ __mpu_UNIT_t data[__CPU_TIMESPEC_SIZE];
+
+ if( !ts ) return( __MCPU_EFAULT );
+
+ memset( data, 0, sizeof( data ) );
+ __cpu_data_put_u64( data + __CPU_TIMESPEC_TV_SEC,
+ __cpu_time_i64_bits( ts->tv_sec ) );
+ __cpu_data_put_u64( data + __CPU_TIMESPEC_TV_NSEC,
+ __cpu_time_i64_bits( ts->tv_nsec ) );
+
+ return( __cpu_copyout( ptr, data, sizeof( data ) ) );
+
+} /* End of __cpu_timespec_copyout() */
+
+
+static __mpu_uint64_t
+__cpu_current_brk( void )
+{
+ __mpu_uint64_t ptr = CPU_NULL_PTR;
+
+ if( !__HEAP || __HLIMIT < CPU_HEAP_BEGIN || __HBRK < CPU_HEAP_BEGIN )
+ return( CPU_NULL_PTR );
+
+ if( __cpu_ptr_make( &ptr, CPU_PTR_SEG_HEAP, __HBRK ) != 0 )
+ return( CPU_NULL_PTR );
+
+ return( ptr );
+
+} /* End of __cpu_current_brk() */
+
+
+__mpu_uint64_t
+__cpu_SYS_brk( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t arg;
+ __mpu_uint64_t brk;
+ __mpu_uint64_t ptr = CPU_NULL_PTR;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_current_brk() );
+
+ arg = __cpu_syscall_arg( 0 );
+
+ if( arg == CPU_NULL_PTR ) return( __cpu_current_brk() );
+
+ if( __cpu_ptr_segment( arg ) != CPU_PTR_SEG_HEAP )
+ return( __cpu_current_brk() );
+
+ brk = __cpu_heap_brk( __cpu_ptr_offset( arg ) );
+
+ if( brk < CPU_HEAP_BEGIN || __cpu_ptr_make( &ptr, CPU_PTR_SEG_HEAP, brk ) != 0 )
+ return( CPU_NULL_PTR );
+
+ return( ptr );
+
+} /* End of __cpu_SYS_brk() */
+
+
+__mpu_uint64_t
+__cpu_SYS_close( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ if( pcctx->_fd[fd].owned )
+ {
+ ret = __cpu_sys_close( host_fd );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+ }
+
+ pcctx->_fd[fd].host_fd = -1;
+ pcctx->_fd[fd].owned = 0;
+ pcctx->_fd[fd].flags = 0;
+
+ return( 0 );
+
+} /* End of __cpu_SYS_close() */
+
+
+__mpu_uint64_t
+__cpu_SYS_dup( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int new_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ new_fd = __cpu_fd_find_from( 0 );
+ if( new_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) );
+
+ ret = __cpu_sys_dup( host_fd );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ pcctx->_fd[new_fd].host_fd = (int)ret;
+ pcctx->_fd[new_fd].owned = 1;
+ pcctx->_fd[new_fd].flags = 0;
+
+ return( (__mpu_uint64_t)new_fd );
+
+} /* End of __cpu_SYS_dup() */
+
+
+__mpu_uint64_t
+__cpu_SYS_dup2( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t old_fd;
+ __mpu_uint64_t new_fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ old_fd = __cpu_syscall_arg( 0 );
+ new_fd = __cpu_syscall_arg( 1 );
+
+ error = __cpu_fd_get( old_fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+ if( new_fd >= CPU_GUEST_FD_MAX ) return( __cpu_syscall_error( __MCPU_EBADF ) );
+
+ if( old_fd == new_fd ) return( new_fd );
+
+ ret = __cpu_sys_dup( host_fd );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ if( pcctx->_fd[new_fd].host_fd >= 0 && pcctx->_fd[new_fd].owned )
+ (void)__cpu_sys_close( pcctx->_fd[new_fd].host_fd );
+
+ pcctx->_fd[new_fd].host_fd = (int)ret;
+ pcctx->_fd[new_fd].owned = 1;
+ pcctx->_fd[new_fd].flags = 0;
+
+ return( new_fd );
+
+} /* End of __cpu_SYS_dup2() */
+
+
+__mpu_uint64_t
+__cpu_SYS_write( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_uint64_t ptr;
+ __mpu_uint64_t count;
+ __mpu_int64_t ret;
+ unsigned char *buf = (unsigned char *)0;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ ptr = __cpu_syscall_arg( 1 );
+ count = __cpu_syscall_arg( 2 );
+
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ if( count )
+ {
+ if( count > (__mpu_uint64_t)(size_t)-1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ buf = (unsigned char *)malloc( (size_t)count );
+ if( !buf ) return( __cpu_syscall_error( __MCPU_ENOMEM ) );
+ error = __cpu_copyin( buf, ptr, count );
+ if( error )
+ {
+ free( buf );
+ return( __cpu_syscall_error( error ) );
+ }
+ }
+
+ ret = __cpu_sys_write( host_fd, buf, count );
+ free( buf );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_write() */
+
+
+__mpu_uint64_t
+__cpu_SYS_read( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_uint64_t ptr;
+ __mpu_uint64_t count;
+ __mpu_int64_t ret;
+ unsigned char *buf = (unsigned char *)0;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ ptr = __cpu_syscall_arg( 1 );
+ count = __cpu_syscall_arg( 2 );
+
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ if( count )
+ {
+ __mpu_UNIT_t *memory;
+
+ if( count > (__mpu_uint64_t)(size_t)-1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ error = __cpu_memory_resolve( ptr, count, 1, &memory );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ buf = (unsigned char *)malloc( (size_t)count );
+ if( !buf ) return( __cpu_syscall_error( __MCPU_ENOMEM ) );
+ }
+
+ ret = __cpu_sys_read( host_fd, buf, count );
+ if( ret > 0 )
+ {
+ error = __cpu_copyout( ptr, buf, (__mpu_uint64_t)ret );
+ if( error ) ret = -(__mpu_int64_t)error;
+ }
+
+ free( buf );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_read() */
+
+
+__mpu_uint64_t
+__cpu_SYS_lseek( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_uint64_t bits;
+ __mpu_int64_t offset;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ bits = __cpu_syscall_arg( 1 );
+ memcpy( &offset, &bits, sizeof( offset ) );
+
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_lseek( host_fd, offset, __cpu_syscall_arg( 2 ) );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_lseek() */
+
+
+__mpu_uint64_t
+__cpu_SYS_open( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_open( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ),
+ __cpu_syscall_arg( 2 ) );
+ free( path );
+
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ fd = __cpu_fd_install( (int)ret );
+ if( fd < 0 )
+ {
+ (void)__cpu_sys_close( (int)ret );
+ return( __cpu_syscall_error( __MCPU_EMFILE ) );
+ }
+
+ return( (__mpu_uint64_t)fd );
+
+} /* End of __cpu_SYS_open() */
+
+
+__mpu_uint64_t
+__cpu_SYS_creat( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_creat( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) );
+ free( path );
+
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ fd = __cpu_fd_install( (int)ret );
+ if( fd < 0 )
+ {
+ (void)__cpu_sys_close( (int)ret );
+ return( __cpu_syscall_error( __MCPU_EMFILE ) );
+ }
+
+ return( (__mpu_uint64_t)fd );
+
+} /* End of __cpu_SYS_creat() */
+
+
+__mpu_uint64_t
+__cpu_SYS_link( __mpu_uint32_t sysno )
+{
+ char *oldpath = (char *)0;
+ char *newpath = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &oldpath, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ error = __cpu_copyinstr( &newpath, __cpu_syscall_arg( 1 ) );
+ if( error )
+ {
+ free( oldpath );
+ return( __cpu_syscall_error( error ) );
+ }
+
+ ret = __cpu_sys_link( pcctx->_cwd_fd, oldpath, newpath );
+ free( newpath );
+ free( oldpath );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_link() */
+
+
+__mpu_uint64_t
+__cpu_SYS_unlink( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_unlink( pcctx->_cwd_fd, path );
+ free( path );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_unlink() */
+
+
+__mpu_uint64_t
+__cpu_SYS_chdir( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int old_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_chdir( pcctx->_cwd_fd, path );
+ free( path );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ old_fd = pcctx->_cwd_fd;
+ pcctx->_cwd_fd = (int)ret;
+ pcctx->_cwd_initialized = 1;
+ if( old_fd >= 0 ) (void)__cpu_sys_close( old_fd );
+
+ return( 0 );
+
+} /* End of __cpu_SYS_chdir() */
+
+
+__mpu_uint64_t
+__cpu_SYS_fchdir( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int old_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_fchdir( host_fd );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ old_fd = pcctx->_cwd_fd;
+ pcctx->_cwd_fd = (int)ret;
+ pcctx->_cwd_initialized = 1;
+ if( old_fd >= 0 ) (void)__cpu_sys_close( old_fd );
+
+ return( 0 );
+
+} /* End of __cpu_SYS_fchdir() */
+
+
+__mpu_uint64_t
+__cpu_SYS_rename( __mpu_uint32_t sysno )
+{
+ char *oldpath = (char *)0;
+ char *newpath = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &oldpath, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ error = __cpu_copyinstr( &newpath, __cpu_syscall_arg( 1 ) );
+ if( error )
+ {
+ free( oldpath );
+ return( __cpu_syscall_error( error ) );
+ }
+
+ ret = __cpu_sys_rename( pcctx->_cwd_fd, oldpath, newpath );
+ free( newpath );
+ free( oldpath );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_rename() */
+
+
+__mpu_uint64_t
+__cpu_SYS_mkdir( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_mkdir( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) );
+ free( path );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_mkdir() */
+
+
+__mpu_uint64_t
+__cpu_SYS_chmod( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_chmod( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) );
+ free( path );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_chmod() */
+
+
+__mpu_uint64_t
+__cpu_SYS_chown( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_chown( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ),
+ __cpu_syscall_arg( 2 ) );
+ free( path );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_chown() */
+
+
+__mpu_uint64_t
+__cpu_SYS_access( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_access( pcctx->_cwd_fd, path, __cpu_syscall_arg( 1 ) );
+ free( path );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_access() */
+
+
+__mpu_uint64_t
+__cpu_SYS_rmdir( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_rmdir( pcctx->_cwd_fd, path );
+ free( path );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_rmdir() */
+
+
+__mpu_uint64_t
+__cpu_SYS_symlink( __mpu_uint32_t sysno )
+{
+ char *target = (char *)0;
+ char *linkpath = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &target, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ error = __cpu_copyinstr( &linkpath, __cpu_syscall_arg( 1 ) );
+ if( error )
+ {
+ free( target );
+ return( __cpu_syscall_error( error ) );
+ }
+
+ ret = __cpu_sys_symlink( pcctx->_cwd_fd, target, linkpath );
+ free( linkpath );
+ free( target );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_symlink() */
+
+
+__mpu_uint64_t
+__cpu_SYS_readlink( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_uint64_t ptr;
+ __mpu_uint64_t count;
+ __mpu_int64_t ret;
+ unsigned char *buf = (unsigned char *)0;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ptr = __cpu_syscall_arg( 1 );
+ count = __cpu_syscall_arg( 2 );
+
+ if( count )
+ {
+ __mpu_UNIT_t *memory;
+
+ if( count > (__mpu_uint64_t)(size_t)-1 )
+ {
+ free( path );
+ return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ }
+
+ error = __cpu_memory_resolve( ptr, count, 1, &memory );
+ if( error )
+ {
+ free( path );
+ return( __cpu_syscall_error( error ) );
+ }
+
+ buf = (unsigned char *)malloc( (size_t)count );
+ if( !buf )
+ {
+ free( path );
+ return( __cpu_syscall_error( __MCPU_ENOMEM ) );
+ }
+ }
+
+ ret = __cpu_sys_readlink( pcctx->_cwd_fd, path, buf, count );
+ free( path );
+
+ if( ret > 0 )
+ {
+ error = __cpu_copyout( ptr, buf, (__mpu_uint64_t)ret );
+ if( error ) ret = -(__mpu_int64_t)error;
+ }
+
+ free( buf );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_readlink() */
+
+
+__mpu_uint64_t
+__cpu_SYS_stat( __mpu_uint32_t sysno )
+{
+ struct __cpu_stat st;
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_stat( pcctx->_cwd_fd, path, &st );
+ free( path );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ error = __cpu_stat_copyout( __cpu_syscall_arg( 1 ), &st );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ return( 0 );
+
+} /* End of __cpu_SYS_stat() */
+
+
+__mpu_uint64_t
+__cpu_SYS_fstat( __mpu_uint32_t sysno )
+{
+ struct __cpu_stat st;
+ __mpu_uint64_t fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_fstat( host_fd, &st );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ error = __cpu_stat_copyout( __cpu_syscall_arg( 1 ), &st );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ return( 0 );
+
+} /* End of __cpu_SYS_fstat() */
+
+
+__mpu_uint64_t
+__cpu_SYS_lstat( __mpu_uint32_t sysno )
+{
+ struct __cpu_stat st;
+ char *path = (char *)0;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_lstat( pcctx->_cwd_fd, path, &st );
+ free( path );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ error = __cpu_stat_copyout( __cpu_syscall_arg( 1 ), &st );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ return( 0 );
+
+} /* End of __cpu_SYS_lstat() */
+
+
+__mpu_uint64_t
+__cpu_SYS_getdents( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_uint64_t ptr;
+ __mpu_uint64_t count;
+ __mpu_uint64_t usable;
+ __mpu_int64_t ret;
+ struct __cpu_dirent *buf = (struct __cpu_dirent *)0;
+ __mpu_UNIT_t *memory;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ ptr = __cpu_syscall_arg( 1 );
+ count = __cpu_syscall_arg( 2 );
+
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ if( count < __CPU_DIRENT_SIZE ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ if( count > (__mpu_uint64_t)(size_t)-1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_memory_resolve( ptr, count, 1, &memory );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ usable = ( count / __CPU_DIRENT_SIZE ) * __CPU_DIRENT_SIZE;
+ buf = (struct __cpu_dirent *)calloc( (size_t)( usable / __CPU_DIRENT_SIZE ),
+ sizeof( *buf ) );
+ if( !buf ) return( __cpu_syscall_error( __MCPU_ENOMEM ) );
+
+ ret = __cpu_sys_getdents( host_fd, buf, usable );
+ if( ret > 0 )
+ {
+ error = __cpu_dirent_copyout( ptr, buf, (__mpu_uint64_t)ret );
+ if( error ) ret = -(__mpu_int64_t)error;
+ }
+
+ free( buf );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_getdents() */
+
+
+__mpu_uint64_t
+__cpu_SYS_fcntl( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_uint64_t cmd;
+ __mpu_uint64_t arg;
+ __mpu_int64_t ret;
+ int host_fd;
+ int new_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ cmd = __cpu_syscall_arg( 1 );
+ arg = __cpu_syscall_arg( 2 );
+
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ switch( cmd )
+ {
+ case __CPU_F_DUPFD:
+ if( arg >= CPU_GUEST_FD_MAX ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ new_fd = __cpu_fd_find_from( arg );
+ if( new_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) );
+
+ ret = __cpu_sys_fcntl( host_fd, cmd, 0 );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ pcctx->_fd[new_fd].host_fd = (int)ret;
+ pcctx->_fd[new_fd].owned = 1;
+ pcctx->_fd[new_fd].flags = 0;
+ return( (__mpu_uint64_t)new_fd );
+
+ case __CPU_F_GETFD:
+ if( arg != 0 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ return( (__mpu_uint64_t)( pcctx->_fd[fd].flags & __CPU_FD_SUPPORTED ) );
+
+ case __CPU_F_SETFD:
+ if( arg & ~(__mpu_uint64_t)__CPU_FD_SUPPORTED )
+ return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ pcctx->_fd[fd].flags = (unsigned int)arg;
+ return( 0 );
+
+ case __CPU_F_GETFL:
+ if( arg != 0 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ ret = __cpu_sys_fcntl( host_fd, cmd, 0 );
+ return( (__mpu_uint64_t)ret );
+
+ case __CPU_F_SETFL:
+ ret = __cpu_sys_fcntl( host_fd, cmd, arg );
+ return( (__mpu_uint64_t)ret );
+
+ default:
+ return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ }
+
+} /* End of __cpu_SYS_fcntl() */
+
+
+__mpu_uint64_t
+__cpu_SYS_pipe2( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t ptr;
+ __mpu_uint64_t flags;
+ __mpu_UNIT_t data[__CPU_PIPEFD_SIZE];
+ __mpu_UNIT_t *memory;
+ __mpu_int64_t ret;
+ unsigned int fd_flags;
+ int host_pipe[2] = { -1, -1 };
+ int read_fd;
+ int write_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ ptr = __cpu_syscall_arg( 0 );
+ flags = __cpu_syscall_arg( 1 );
+
+ if( flags & ~(__mpu_uint64_t)__CPU_PIPE2_SUPPORTED )
+ return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_memory_resolve( ptr, __CPU_PIPEFD_SIZE, 1, &memory );
+ if( error ) return( __cpu_syscall_error( error ) );
+ (void)memory;
+
+ read_fd = __cpu_fd_find_from( 3 );
+ if( read_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) );
+
+ write_fd = __cpu_fd_find_from( (__mpu_uint64_t)read_fd + 1U );
+ if( write_fd < 0 ) return( __cpu_syscall_error( __MCPU_EMFILE ) );
+
+ ret = __cpu_sys_pipe2( host_pipe, flags & __CPU_O_NONBLOCK );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ memset( data, 0, sizeof( data ) );
+ __cpu_data_put_u64( data + __CPU_PIPEFD_READ, (__mpu_uint64_t)read_fd );
+ __cpu_data_put_u64( data + __CPU_PIPEFD_WRITE, (__mpu_uint64_t)write_fd );
+
+ error = __cpu_copyout( ptr, data, sizeof( data ) );
+ if( error )
+ {
+ (void)__cpu_sys_close( host_pipe[0] );
+ (void)__cpu_sys_close( host_pipe[1] );
+ return( __cpu_syscall_error( error ) );
+ }
+
+ fd_flags = ( flags & __CPU_O_CLOEXEC ) ? __CPU_FD_CLOEXEC : 0U;
+
+ pcctx->_fd[read_fd].host_fd = host_pipe[0];
+ pcctx->_fd[read_fd].owned = 1;
+ pcctx->_fd[read_fd].flags = fd_flags;
+
+ pcctx->_fd[write_fd].host_fd = host_pipe[1];
+ pcctx->_fd[write_fd].owned = 1;
+ pcctx->_fd[write_fd].flags = fd_flags;
+
+ return( 0 );
+
+} /* End of __cpu_SYS_pipe2() */
+
+
+
+__mpu_uint64_t
+__cpu_SYS_select( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t nfds;
+ __mpu_uint64_t read_ptr;
+ __mpu_uint64_t write_ptr;
+ __mpu_uint64_t except_ptr;
+ __mpu_uint64_t timeout_ptr;
+ __mpu_uint64_t read_in[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 };
+ __mpu_uint64_t write_in[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 };
+ __mpu_uint64_t except_in[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 };
+ __mpu_uint64_t read_out[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 };
+ __mpu_uint64_t write_out[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 };
+ __mpu_uint64_t except_out[__CPU_FD_SET_WORDS] = { 0, 0, 0, 0 };
+ struct __cpu_select_entry entries[CPU_GUEST_FD_MAX];
+ struct __cpu_timeval timeout;
+ const struct __cpu_timeval *ptimeout = (const struct __cpu_timeval *)0;
+ __mpu_int64_t ret;
+ __mpu_uint64_t nentries = 0;
+ __mpu_uint64_t ready = 0;
+ unsigned int fd;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 5 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ nfds = __cpu_syscall_arg( 0 );
+ read_ptr = __cpu_syscall_arg( 1 );
+ write_ptr = __cpu_syscall_arg( 2 );
+ except_ptr = __cpu_syscall_arg( 3 );
+ timeout_ptr = __cpu_syscall_arg( 4 );
+
+ if( nfds > CPU_GUEST_FD_MAX ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ if( read_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_fdset_load( read_ptr, read_in );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+ if( write_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_fdset_load( write_ptr, write_in );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+ if( except_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_fdset_load( except_ptr, except_in );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+ if( timeout_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_timeval_load( timeout_ptr, &timeout );
+ if( error ) return( __cpu_syscall_error( error ) );
+ ptimeout = &timeout;
+ }
+
+ memset( entries, 0, sizeof( entries ) );
+
+ for( fd = 0; fd < (unsigned int)nfds; ++fd )
+ {
+ unsigned int events = 0;
+
+ if( read_ptr != CPU_NULL_PTR && __cpu_fdset_isset( read_in, fd ) )
+ events |= __CPU_SELECT_READ;
+ if( write_ptr != CPU_NULL_PTR && __cpu_fdset_isset( write_in, fd ) )
+ events |= __CPU_SELECT_WRITE;
+ if( except_ptr != CPU_NULL_PTR && __cpu_fdset_isset( except_in, fd ) )
+ events |= __CPU_SELECT_EXCEPT;
+
+ if( !events ) continue;
+
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ entries[nentries].guest_fd = fd;
+ entries[nentries].host_fd = host_fd;
+ entries[nentries].events = events;
+ entries[nentries].revents = 0;
+ ++nentries;
+ }
+
+ ret = __cpu_sys_select( entries, nentries, ptimeout );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ for( nfds = 0; nfds < nentries; ++nfds )
+ {
+ fd = entries[nfds].guest_fd;
+
+ if( ( entries[nfds].revents & __CPU_SELECT_READ ) && read_ptr != CPU_NULL_PTR )
+ {
+ __cpu_fdset_set( read_out, fd );
+ ++ready;
+ }
+ if( ( entries[nfds].revents & __CPU_SELECT_WRITE ) && write_ptr != CPU_NULL_PTR )
+ {
+ __cpu_fdset_set( write_out, fd );
+ ++ready;
+ }
+ if( ( entries[nfds].revents & __CPU_SELECT_EXCEPT ) && except_ptr != CPU_NULL_PTR )
+ {
+ __cpu_fdset_set( except_out, fd );
+ ++ready;
+ }
+ }
+
+ if( read_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_fdset_store( read_ptr, read_out );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+ if( write_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_fdset_store( write_ptr, write_out );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+ if( except_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_fdset_store( except_ptr, except_out );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+
+ return( ready );
+
+} /* End of __cpu_SYS_select() */
+
+__mpu_uint64_t
+__cpu_SYS_gettimeofday( __mpu_uint32_t sysno )
+{
+ struct __cpu_timespec ts;
+ struct __cpu_timeval tv;
+ __mpu_uint64_t tv_ptr;
+ __mpu_uint64_t tz_ptr;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ tv_ptr = __cpu_syscall_arg( 0 );
+ tz_ptr = __cpu_syscall_arg( 1 );
+
+ if( tv_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) );
+ if( tz_ptr != CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ ret = __cpu_sys_clock_gettime( __CPU_CLOCK_REALTIME, &ts );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000;
+
+ error = __cpu_timeval_copyout( tv_ptr, &tv );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ return( 0 );
+
+} /* End of __cpu_SYS_gettimeofday() */
+
+
+__mpu_uint64_t
+__cpu_SYS_clock_getres( __mpu_uint32_t sysno )
+{
+ struct __cpu_timespec res;
+ __mpu_uint64_t clockid;
+ __mpu_uint64_t res_ptr;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ clockid = __cpu_syscall_arg( 0 );
+ res_ptr = __cpu_syscall_arg( 1 );
+
+ ret = __cpu_sys_clock_getres( clockid,
+ res_ptr == CPU_NULL_PTR ? (struct __cpu_timespec *)0 : &res );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ if( res_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_timespec_copyout( res_ptr, &res );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+
+ return( 0 );
+
+} /* End of __cpu_SYS_clock_getres() */
+
+
+__mpu_uint64_t
+__cpu_SYS_clock_gettime( __mpu_uint32_t sysno )
+{
+ struct __cpu_timespec ts;
+ __mpu_uint64_t clockid;
+ __mpu_uint64_t tp_ptr;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ clockid = __cpu_syscall_arg( 0 );
+ tp_ptr = __cpu_syscall_arg( 1 );
+
+ if( tp_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) );
+
+ ret = __cpu_sys_clock_gettime( clockid, &ts );
+ if( ret < 0 ) return( (__mpu_uint64_t)ret );
+
+ error = __cpu_timespec_copyout( tp_ptr, &ts );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ return( 0 );
+
+} /* End of __cpu_SYS_clock_gettime() */
+
+
+__mpu_uint64_t
+__cpu_SYS_nanosleep( __mpu_uint32_t sysno )
+{
+ struct __cpu_timespec req;
+ struct __cpu_timespec rem;
+ __mpu_uint64_t req_ptr;
+ __mpu_uint64_t rem_ptr;
+ __mpu_UNIT_t *memory;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ req_ptr = __cpu_syscall_arg( 0 );
+ rem_ptr = __cpu_syscall_arg( 1 );
+
+ if( req_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) );
+
+ error = __cpu_timespec_load( req_ptr, &req );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ if( rem_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_memory_resolve( rem_ptr, __CPU_TIMESPEC_SIZE, 1, &memory );
+ if( error ) return( __cpu_syscall_error( error ) );
+ (void)memory;
+ }
+
+ ret = __cpu_sys_clock_nanosleep( __CPU_CLOCK_MONOTONIC, 0, &req,
+ rem_ptr == CPU_NULL_PTR ? (struct __cpu_timespec *)0 : &rem );
+
+ if( ret == -(__mpu_int64_t)__MCPU_EINTR && rem_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_timespec_copyout( rem_ptr, &rem );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_nanosleep() */
+
+
+__mpu_uint64_t
+__cpu_SYS_clock_nanosleep( __mpu_uint32_t sysno )
+{
+ struct __cpu_timespec req;
+ struct __cpu_timespec rem;
+ __mpu_uint64_t clockid;
+ __mpu_uint64_t flags;
+ __mpu_uint64_t req_ptr;
+ __mpu_uint64_t rem_ptr;
+ __mpu_UNIT_t *memory;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 4 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ clockid = __cpu_syscall_arg( 0 );
+ flags = __cpu_syscall_arg( 1 );
+ req_ptr = __cpu_syscall_arg( 2 );
+ rem_ptr = __cpu_syscall_arg( 3 );
+
+ if( flags & ~(__mpu_uint64_t)__CPU_TIMER_ABSTIME )
+ return( __cpu_syscall_error( __MCPU_EINVAL ) );
+ if( req_ptr == CPU_NULL_PTR ) return( __cpu_syscall_error( __MCPU_EFAULT ) );
+
+ error = __cpu_timespec_load( req_ptr, &req );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ if( !( flags & __CPU_TIMER_ABSTIME ) && rem_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_memory_resolve( rem_ptr, __CPU_TIMESPEC_SIZE, 1, &memory );
+ if( error ) return( __cpu_syscall_error( error ) );
+ (void)memory;
+ }
+
+ ret = __cpu_sys_clock_nanosleep( clockid, flags, &req,
+ ( flags & __CPU_TIMER_ABSTIME ) || rem_ptr == CPU_NULL_PTR ?
+ (struct __cpu_timespec *)0 : &rem );
+
+ if( ret == -(__mpu_int64_t)__MCPU_EINTR && !( flags & __CPU_TIMER_ABSTIME ) &&
+ rem_ptr != CPU_NULL_PTR )
+ {
+ error = __cpu_timespec_copyout( rem_ptr, &rem );
+ if( error ) return( __cpu_syscall_error( error ) );
+ }
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_clock_nanosleep() */
+
+
+__mpu_uint64_t
+__cpu_SYS_fsync( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 1 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_fsync( host_fd );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_fsync() */
+
+
+__mpu_uint64_t
+__cpu_SYS_truncate( __mpu_uint32_t sysno )
+{
+ char *path = (char *)0;
+ __mpu_uint64_t bits;
+ __mpu_int64_t length;
+ __mpu_int64_t ret;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ error = __cpu_copyinstr( &path, __cpu_syscall_arg( 0 ) );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ bits = __cpu_syscall_arg( 1 );
+ memcpy( &length, &bits, sizeof( length ) );
+
+ ret = __cpu_sys_truncate( pcctx->_cwd_fd, path, length );
+ free( path );
+
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_truncate() */
+
+
+__mpu_uint64_t
+__cpu_SYS_ftruncate( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_uint64_t bits;
+ __mpu_int64_t length;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ bits = __cpu_syscall_arg( 1 );
+ memcpy( &length, &bits, sizeof( length ) );
+
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_ftruncate( host_fd, length );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_ftruncate() */
+
+
+__mpu_uint64_t
+__cpu_SYS_fchmod( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 2 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_fchmod( host_fd, __cpu_syscall_arg( 1 ) );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_fchmod() */
+
+
+__mpu_uint64_t
+__cpu_SYS_fchown( __mpu_uint32_t sysno )
+{
+ __mpu_uint64_t fd;
+ __mpu_int64_t ret;
+ int host_fd;
+ int error;
+
+ (void)sysno;
+
+ if( __cpu_syscall_nargs() != 3 ) return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ fd = __cpu_syscall_arg( 0 );
+ error = __cpu_fd_get( fd, &host_fd );
+ if( error ) return( __cpu_syscall_error( error ) );
+
+ ret = __cpu_sys_fchown( host_fd, __cpu_syscall_arg( 1 ),
+ __cpu_syscall_arg( 2 ) );
+ return( (__mpu_uint64_t)ret );
+
+} /* End of __cpu_SYS_fchown() */
+
+
+static const __cpu_syscall_handler_t __syscalls[] =
+{
+ [__NR_brk] = __cpu_SYS_brk,
+ [__NR_gettimeofday] = __cpu_SYS_gettimeofday,
+ [__NR_clock_getres] = __cpu_SYS_clock_getres,
+ [__NR_clock_gettime] = __cpu_SYS_clock_gettime,
+ [__NR_nanosleep] = __cpu_SYS_nanosleep,
+ [__NR_clock_nanosleep] = __cpu_SYS_clock_nanosleep,
+ [__NR_read] = __cpu_SYS_read,
+ [__NR_write] = __cpu_SYS_write,
+ [__NR_lseek] = __cpu_SYS_lseek,
+ [__NR_open] = __cpu_SYS_open,
+ [__NR_creat] = __cpu_SYS_creat,
+ [__NR_close] = __cpu_SYS_close,
+ [__NR_link] = __cpu_SYS_link,
+ [__NR_unlink] = __cpu_SYS_unlink,
+ [__NR_chdir] = __cpu_SYS_chdir,
+ [__NR_mkdir] = __cpu_SYS_mkdir,
+ [__NR_chmod] = __cpu_SYS_chmod,
+ [__NR_chown] = __cpu_SYS_chown,
+ [__NR_access] = __cpu_SYS_access,
+ [__NR_rename] = __cpu_SYS_rename,
+ [__NR_rmdir] = __cpu_SYS_rmdir,
+ [__NR_symlink] = __cpu_SYS_symlink,
+ [__NR_readlink] = __cpu_SYS_readlink,
+ [__NR_stat] = __cpu_SYS_stat,
+ [__NR_fstat] = __cpu_SYS_fstat,
+ [__NR_lstat] = __cpu_SYS_lstat,
+ [__NR_fcntl] = __cpu_SYS_fcntl,
+ [__NR_pipe2] = __cpu_SYS_pipe2,
+ [__NR_getdents] = __cpu_SYS_getdents,
+ [__NR_select] = __cpu_SYS_select,
+ [__NR_fsync] = __cpu_SYS_fsync,
+ [__NR_truncate] = __cpu_SYS_truncate,
+ [__NR_ftruncate] = __cpu_SYS_ftruncate,
+ [__NR_fchmod] = __cpu_SYS_fchmod,
+ [__NR_fchown] = __cpu_SYS_fchown,
+ [__NR_fchdir] = __cpu_SYS_fchdir,
+ [__NR_dup] = __cpu_SYS_dup,
+ [__NR_dup2] = __cpu_SYS_dup2,
+};
+
+
+__mpu_uint64_t
+__cpu_syscall_dispatch( void )
+{
+ __mpu_uint32_t sysno;
+
+ sysno = __cpu_data_get_u32( __cpu_reg_ptr( 32, CPU_SYSCALL_SYSNO_ADDR ) );
+
+ if( __cpu_syscall_nargs() > CPU_SYSCALL_MAX_ARGS )
+ return( __cpu_syscall_error( __MCPU_EINVAL ) );
+
+ if( sysno >= sizeof( __syscalls ) / sizeof( __syscalls[0] ) ||
+ __syscalls[sysno] == (__cpu_syscall_handler_t)0 )
+ return( __cpu_syscall_error( __MCPU_ENOSYS ) );
+
+ return( __syscalls[sysno]( sysno ) );
+
+} /* End of __cpu_syscall_dispatch() */
diff --git a/cpu/cpu-syscalls.h b/cpu/cpu-syscalls.h
new file mode 100644
index 0000000..636c0e7
--- /dev/null
+++ b/cpu/cpu-syscalls.h
@@ -0,0 +1,59 @@
+/***************************************************************
+ __CPU_SYSCALLS.H
+
+ This file contains CPU SYSCALL operation functions & data
+ declarations.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ NOTE : Include "libmcpu.h" before this FILE .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_SYSCALLS_H
+#define __CPU_SYSCALLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef __mpu_uint64_t (*__cpu_syscall_handler_t)( __mpu_uint32_t sysno );
+
+extern void __cpu_fd_context_init( void );
+extern void __cpu_fd_context_free( void );
+extern void __cpu_cwd_context_init( void );
+extern void __cpu_cwd_context_free( void );
+
+extern __mpu_uint64_t __cpu_SYS_brk( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_gettimeofday( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_clock_getres( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_clock_gettime( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_nanosleep( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_clock_nanosleep( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_open ( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_close( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_dup ( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_dup2 ( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_read ( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_write( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_lseek( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_chdir( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_fchdir( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_stat ( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_fstat( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_lstat( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_fcntl( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_SYS_pipe2( __mpu_uint32_t sysno );
+extern __mpu_uint64_t __cpu_syscall_dispatch( void );
+
+
+#ifdef __cplusplus
+} /* ... extern "C" */
+#endif
+
+#endif /* __CPU_SYSCALLS_H */
diff --git a/cpu/cpu-sysdeps.h b/cpu/cpu-sysdeps.h
new file mode 100644
index 0000000..81bb926
--- /dev/null
+++ b/cpu/cpu-sysdeps.h
@@ -0,0 +1,288 @@
+/***************************************************************
+ __CPU_SYSDEPS.H
+
+ This file contains HOST-dependent system call wrapper
+ declarations and internal MCPU syscall ABI constants.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ NOTE : Include "libmcpu.h" before this FILE .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_SYSDEPS_H
+#define __CPU_SYSDEPS_H
+
+#include <cpu-errno.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* MCPU open(2) ABI. These values are HOST-independent. */
+#define __CPU_O_ACCMODE 00000003U
+#define __CPU_O_RDONLY 00000000U
+#define __CPU_O_WRONLY 00000001U
+#define __CPU_O_RDWR 00000002U
+#define __CPU_O_CREAT 00000100U
+#define __CPU_O_EXCL 00000200U
+#define __CPU_O_NOCTTY 00000400U
+#define __CPU_O_TRUNC 00001000U
+#define __CPU_O_APPEND 00002000U
+#define __CPU_O_NONBLOCK 00004000U
+
+#define __CPU_O_SUPPORTED ( __CPU_O_ACCMODE | __CPU_O_CREAT | __CPU_O_EXCL | \
+ __CPU_O_NOCTTY | __CPU_O_TRUNC | __CPU_O_APPEND | \
+ __CPU_O_NONBLOCK )
+
+/* MCPU fcntl(2) ABI. Commands and descriptor flags are guest values. */
+#define __CPU_F_DUPFD 0U
+#define __CPU_F_GETFD 1U
+#define __CPU_F_SETFD 2U
+#define __CPU_F_GETFL 3U
+#define __CPU_F_SETFL 4U
+
+#define __CPU_FD_CLOEXEC 1U
+#define __CPU_FD_SUPPORTED __CPU_FD_CLOEXEC
+
+/* F_SETFL accepts access-mode bits for the conventional GETFL/SETFL cycle,
+ but only APPEND and NONBLOCK are mutable file-status flags. */
+#define __CPU_F_SETFL_SUPPORTED \
+ ( __CPU_O_ACCMODE | __CPU_O_APPEND | __CPU_O_NONBLOCK )
+
+/* MCPU pipe2(2) ABI. O_CLOEXEC is guest descriptor state; only
+ O_NONBLOCK is translated to a HOST file-status flag. */
+#define __CPU_O_CLOEXEC 02000000U
+#define __CPU_PIPE2_SUPPORTED ( __CPU_O_NONBLOCK | __CPU_O_CLOEXEC )
+#define __CPU_PIPEFD_SIZE 16U
+#define __CPU_PIPEFD_READ 0U
+#define __CPU_PIPEFD_WRITE 8U
+
+/* MCPU mode bits used by open(2) when O_CREAT is present. */
+#define __CPU_S_ISUID 00004000U
+#define __CPU_S_ISGID 00002000U
+#define __CPU_S_ISVTX 00001000U
+#define __CPU_S_IRUSR 00000400U
+#define __CPU_S_IWUSR 00000200U
+#define __CPU_S_IXUSR 00000100U
+#define __CPU_S_IRGRP 00000040U
+#define __CPU_S_IWGRP 00000020U
+#define __CPU_S_IXGRP 00000010U
+#define __CPU_S_IROTH 00000004U
+#define __CPU_S_IWOTH 00000002U
+#define __CPU_S_IXOTH 00000001U
+#define __CPU_S_SUPPORTED 00007777U
+
+/* MCPU chown(2) ABI. UINT64_MAX means "leave this ID unchanged". */
+#define __CPU_ID_NO_CHANGE ((__mpu_uint64_t)-1)
+
+#define __CPU_SEEK_SET 0U
+#define __CPU_SEEK_CUR 1U
+#define __CPU_SEEK_END 2U
+
+/* MCPU access(2) ABI. These values are HOST-independent. */
+#define __CPU_F_OK 0U
+#define __CPU_X_OK 1U
+#define __CPU_W_OK 2U
+#define __CPU_R_OK 4U
+#define __CPU_ACCESS_SUPPORTED (__CPU_X_OK | __CPU_W_OK | __CPU_R_OK)
+
+/* MCPU time ABI. All time values use signed 64-bit seconds and a separate
+ signed 64-bit fractional field. Clock IDs are HOST-independent. */
+#define __CPU_CLOCK_REALTIME 0U
+#define __CPU_CLOCK_MONOTONIC 1U
+#define __CPU_TIMER_ABSTIME 1U
+
+#define __CPU_TIMEVAL_SIZE 16U
+#define __CPU_TIMEVAL_TV_SEC 0U
+#define __CPU_TIMEVAL_TV_USEC 8U
+
+#define __CPU_TIMESPEC_SIZE 16U
+#define __CPU_TIMESPEC_TV_SEC 0U
+#define __CPU_TIMESPEC_TV_NSEC 8U
+
+struct __cpu_timeval
+{
+ __mpu_int64_t tv_sec;
+ __mpu_int64_t tv_usec;
+};
+
+struct __cpu_timespec
+{
+ __mpu_int64_t tv_sec;
+ __mpu_int64_t tv_nsec;
+};
+
+/* MCPU select(2) ABI. Descriptor sets contain four target-order u64
+ words, for a total of 256 guest descriptor bits. The timeout is input-only. */
+#define __CPU_FD_SETSIZE 256U
+#define __CPU_FD_SET_WORDS 4U
+#define __CPU_FD_SET_SIZE 32U
+
+#define __CPU_SELECT_READ 0x01U
+#define __CPU_SELECT_WRITE 0x02U
+#define __CPU_SELECT_EXCEPT 0x04U
+
+struct __cpu_select_entry
+{
+ unsigned int guest_fd;
+ int host_fd;
+ unsigned int events;
+ unsigned int revents;
+};
+
+/* MCPU stat(2) ABI. The structure is always exactly 128 bytes. */
+#define __CPU_STAT_SIZE 128U
+#define __CPU_STAT_ST_DEV 0U
+#define __CPU_STAT_ST_INO 8U
+#define __CPU_STAT_ST_MODE 16U
+#define __CPU_STAT_ST_NLINK 24U
+#define __CPU_STAT_ST_UID 32U
+#define __CPU_STAT_ST_GID 40U
+#define __CPU_STAT_ST_RDEV 48U
+#define __CPU_STAT_ST_SIZE 56U
+#define __CPU_STAT_ST_BLKSIZE 64U
+#define __CPU_STAT_ST_BLOCKS 72U
+#define __CPU_STAT_ST_ATIME_SEC 80U
+#define __CPU_STAT_ST_ATIME_NSEC 88U
+#define __CPU_STAT_ST_MTIME_SEC 96U
+#define __CPU_STAT_ST_MTIME_NSEC 104U
+#define __CPU_STAT_ST_CTIME_SEC 112U
+#define __CPU_STAT_ST_CTIME_NSEC 120U
+
+#define __CPU_S_IFMT 000170000U
+#define __CPU_S_IFIFO 000010000U
+#define __CPU_S_IFCHR 000020000U
+#define __CPU_S_IFDIR 000040000U
+#define __CPU_S_IFBLK 000060000U
+#define __CPU_S_IFREG 000100000U
+#define __CPU_S_IFLNK 000120000U
+#define __CPU_S_IFSOCK 000140000U
+
+/* MCPU getdents(2) ABI. Records are fixed at 288 bytes. */
+#define __CPU_DIRENT_SIZE 288U
+#define __CPU_DIRENT_D_INO 0U
+#define __CPU_DIRENT_D_OFF 8U
+#define __CPU_DIRENT_D_RECLEN 16U
+#define __CPU_DIRENT_D_TYPE 24U
+#define __CPU_DIRENT_D_NAME 32U
+#define __CPU_DIRENT_NAME_SIZE 256U
+
+#define __CPU_DT_UNKNOWN 0U
+#define __CPU_DT_FIFO 1U
+#define __CPU_DT_CHR 2U
+#define __CPU_DT_DIR 4U
+#define __CPU_DT_BLK 6U
+#define __CPU_DT_REG 8U
+#define __CPU_DT_LNK 10U
+#define __CPU_DT_SOCK 12U
+
+struct __cpu_dirent
+{
+ __mpu_uint64_t d_ino;
+ __mpu_int64_t d_off;
+ __mpu_uint64_t d_reclen;
+ __mpu_uint64_t d_type;
+ unsigned char d_name[__CPU_DIRENT_NAME_SIZE];
+};
+
+struct __cpu_stat
+{
+ __mpu_uint64_t st_dev;
+ __mpu_uint64_t st_ino;
+ __mpu_uint64_t st_mode;
+ __mpu_uint64_t st_nlink;
+ __mpu_uint64_t st_uid;
+ __mpu_uint64_t st_gid;
+ __mpu_uint64_t st_rdev;
+ __mpu_int64_t st_size;
+ __mpu_int64_t st_blksize;
+ __mpu_int64_t st_blocks;
+ __mpu_int64_t st_atime_sec;
+ __mpu_uint64_t st_atime_nsec;
+ __mpu_int64_t st_mtime_sec;
+ __mpu_uint64_t st_mtime_nsec;
+ __mpu_int64_t st_ctime_sec;
+ __mpu_uint64_t st_ctime_nsec;
+};
+
+
+
+/* Translate a positive HOST errno value into the stable positive MCPU errno
+ namespace. Zero maps to zero; unknown values map to __MCPU_EUNKNOWN. */
+extern int __cpu_errno_from_host( int errnum );
+
+extern __mpu_int64_t __cpu_sys_cwd_init( void );
+extern __mpu_int64_t __cpu_sys_chdir( int dirfd, const char *path );
+extern __mpu_int64_t __cpu_sys_fchdir( int fd );
+
+extern __mpu_int64_t __cpu_sys_open ( int dirfd, const char *path,
+ __mpu_uint64_t flags,
+ __mpu_uint64_t mode );
+extern __mpu_int64_t __cpu_sys_creat( int dirfd, const char *path,
+ __mpu_uint64_t mode );
+extern __mpu_int64_t __cpu_sys_close( int fd );
+extern __mpu_int64_t __cpu_sys_dup ( int fd );
+extern __mpu_int64_t __cpu_sys_read ( int fd, void *buf, __mpu_uint64_t count );
+extern __mpu_int64_t __cpu_sys_write( int fd, const void *buf, __mpu_uint64_t count );
+extern __mpu_int64_t __cpu_sys_lseek( int fd, __mpu_int64_t offset,
+ __mpu_uint64_t whence );
+extern __mpu_int64_t __cpu_sys_link ( int dirfd, const char *oldpath,
+ const char *newpath );
+extern __mpu_int64_t __cpu_sys_unlink( int dirfd, const char *path );
+extern __mpu_int64_t __cpu_sys_rename( int dirfd, const char *oldpath,
+ const char *newpath );
+extern __mpu_int64_t __cpu_sys_symlink( int dirfd, const char *target,
+ const char *linkpath );
+extern __mpu_int64_t __cpu_sys_readlink( int dirfd, const char *path,
+ void *buf, __mpu_uint64_t count );
+extern __mpu_int64_t __cpu_sys_mkdir ( int dirfd, const char *path,
+ __mpu_uint64_t mode );
+extern __mpu_int64_t __cpu_sys_chmod ( int dirfd, const char *path,
+ __mpu_uint64_t mode );
+extern __mpu_int64_t __cpu_sys_chown ( int dirfd, const char *path,
+ __mpu_uint64_t uid,
+ __mpu_uint64_t gid );
+extern __mpu_int64_t __cpu_sys_rmdir ( int dirfd, const char *path );
+extern __mpu_int64_t __cpu_sys_access( int dirfd, const char *path,
+ __mpu_uint64_t mode );
+
+extern __mpu_int64_t __cpu_sys_stat ( int dirfd, const char *path,
+ struct __cpu_stat *st );
+extern __mpu_int64_t __cpu_sys_fstat( int fd, struct __cpu_stat *st );
+extern __mpu_int64_t __cpu_sys_lstat( int dirfd, const char *path,
+ struct __cpu_stat *st );
+extern __mpu_int64_t __cpu_sys_getdents( int fd, struct __cpu_dirent *dirp,
+ __mpu_uint64_t count );
+extern __mpu_int64_t __cpu_sys_fsync( int fd );
+extern __mpu_int64_t __cpu_sys_truncate( int dirfd, const char *path,
+ __mpu_int64_t length );
+extern __mpu_int64_t __cpu_sys_ftruncate( int fd, __mpu_int64_t length );
+extern __mpu_int64_t __cpu_sys_fchmod( int fd, __mpu_uint64_t mode );
+extern __mpu_int64_t __cpu_sys_fchown( int fd, __mpu_uint64_t uid,
+ __mpu_uint64_t gid );
+extern __mpu_int64_t __cpu_sys_fcntl( int fd, __mpu_uint64_t cmd,
+ __mpu_uint64_t arg );
+extern __mpu_int64_t __cpu_sys_pipe2( int pipefd[2], __mpu_uint64_t flags );
+extern __mpu_int64_t __cpu_sys_select( struct __cpu_select_entry *entries,
+ __mpu_uint64_t count,
+ const struct __cpu_timeval *timeout );
+extern __mpu_int64_t __cpu_sys_clock_gettime( __mpu_uint64_t clockid,
+ struct __cpu_timespec *tp );
+extern __mpu_int64_t __cpu_sys_clock_getres( __mpu_uint64_t clockid,
+ struct __cpu_timespec *res );
+extern __mpu_int64_t __cpu_sys_clock_nanosleep( __mpu_uint64_t clockid,
+ __mpu_uint64_t flags,
+ const struct __cpu_timespec *req,
+ struct __cpu_timespec *rem );
+
+#ifdef __cplusplus
+} /* ... extern "C" */
+#endif
+
+#endif /* __CPU_SYSDEPS_H */
diff --git a/cpu/sysdeps/README b/cpu/sysdeps/README
new file mode 100644
index 0000000..461226e
--- /dev/null
+++ b/cpu/sysdeps/README
@@ -0,0 +1,19 @@
+LibMCPU HOST sysdeps
+====================
+
+This tree is the HOST-dependent adaptation layer for MCPU system-call wrappers.
+configure builds the ordered `sysnames` search list from the canonical HOST,
+architecture preconfigure fragments, the ABI/data model and Implies inheritance.
+cpu/Makefile.am uses that ordered list as the GNU make `vpath %.c` search path,
+so the first matching basename is the selected source.
+
+The search order is intentionally from the most specific implementation to the
+most generic implementation. `cpu/sysdeps/generic` is always last. A generic
+directory does not by itself make an otherwise unknown HOST supported.
+
+Starting with LibMCPU 0.3.25 raw HOST errno values must not escape this layer.
+The inherited `sys-errno.c` implementation provides `__cpu_errno_from_host()`;
+HOST syscall wrappers translate a real HOST failure into the stable MCPU errno
+namespace before returning to common CPU code. Errors created by the MCPU ABI
+itself use `__MCPU_E*` constants directly and are not sent through the HOST
+translator.
diff --git a/cpu/sysdeps/generic/README b/cpu/sysdeps/generic/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/generic/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/i386/configure-fragment b/cpu/sysdeps/i386/configure-fragment
new file mode 100755
index 0000000..a64629c
--- /dev/null
+++ b/cpu/sysdeps/i386/configure-fragment
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Regenerate this directory's sourced preconfigure fragment from preconfigure.ac.
+# Run from the architecture sysdeps directory.
+autoconf -Wno-syntax -I ../../.. -o preconfigure preconfigure.ac || exit 1
+chmod a-x preconfigure
+rm -f preconfigure~
+rm -rf autom4te.cache
diff --git a/cpu/sysdeps/i386/i586/README b/cpu/sysdeps/i386/i586/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/i386/i586/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/i386/i686/README b/cpu/sysdeps/i386/i686/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/i386/i686/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/i386/i786/Implies b/cpu/sysdeps/i386/i786/Implies
new file mode 100644
index 0000000..1cd29f6
--- /dev/null
+++ b/cpu/sysdeps/i386/i786/Implies
@@ -0,0 +1,2 @@
+# The PPro and PII cores are mostly the same.
+i386/i686
diff --git a/cpu/sysdeps/i386/preconfigure b/cpu/sysdeps/i386/preconfigure
new file mode 100644
index 0000000..43a17f4
--- /dev/null
+++ b/cpu/sysdeps/i386/preconfigure
@@ -0,0 +1,12 @@
+# This file is generated from preconfigure.ac by Autoconf. DO NOT EDIT!
+
+# Local preconfigure fragment for cpu/sysdeps/i386.
+
+case "$machine" in
+i456786)
+ base_machine=i386
+ machine=i386/$machine
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+esac
+
diff --git a/cpu/sysdeps/i386/preconfigure.ac b/cpu/sysdeps/i386/preconfigure.ac
new file mode 100644
index 0000000..cd419ee
--- /dev/null
+++ b/cpu/sysdeps/i386/preconfigure.ac
@@ -0,0 +1,11 @@
+dnl See acsite.m4 in the top-level source directory.
+MCPU_PROVIDES
+# Local preconfigure fragment for cpu/sysdeps/i386.
+
+case "$machine" in
+i[4567]86)
+ base_machine=i386
+ machine=i386/$machine
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+esac
diff --git a/cpu/sysdeps/powerpc/configure-fragment b/cpu/sysdeps/powerpc/configure-fragment
new file mode 100755
index 0000000..a64629c
--- /dev/null
+++ b/cpu/sysdeps/powerpc/configure-fragment
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Regenerate this directory's sourced preconfigure fragment from preconfigure.ac.
+# Run from the architecture sysdeps directory.
+autoconf -Wno-syntax -I ../../.. -o preconfigure preconfigure.ac || exit 1
+chmod a-x preconfigure
+rm -f preconfigure~
+rm -rf autom4te.cache
diff --git a/cpu/sysdeps/powerpc/powerpc32/README b/cpu/sysdeps/powerpc/powerpc32/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/powerpc/powerpc32/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/powerpc/powerpc64/README b/cpu/sysdeps/powerpc/powerpc64/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/powerpc/powerpc64/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/powerpc/powerpc64le/README b/cpu/sysdeps/powerpc/powerpc64le/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/powerpc/powerpc64le/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/powerpc/preconfigure b/cpu/sysdeps/powerpc/preconfigure
new file mode 100644
index 0000000..ac680cc
--- /dev/null
+++ b/cpu/sysdeps/powerpc/preconfigure
@@ -0,0 +1,22 @@
+# This file is generated from preconfigure.ac by Autoconf. DO NOT EDIT!
+
+# Local preconfigure fragment for cpu/sysdeps/powerpc.
+
+case "$machine" in
+powerpc64le)
+ base_machine=powerpc
+ machine=powerpc/powerpc64le
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+powerpc64*)
+ base_machine=powerpc
+ machine=powerpc/powerpc64
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+powerpc*)
+ base_machine=powerpc
+ machine=powerpc/powerpc32
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+esac
+
diff --git a/cpu/sysdeps/powerpc/preconfigure.ac b/cpu/sysdeps/powerpc/preconfigure.ac
new file mode 100644
index 0000000..9fd020f
--- /dev/null
+++ b/cpu/sysdeps/powerpc/preconfigure.ac
@@ -0,0 +1,21 @@
+dnl See acsite.m4 in the top-level source directory.
+MCPU_PROVIDES
+# Local preconfigure fragment for cpu/sysdeps/powerpc.
+
+case "$machine" in
+powerpc64le)
+ base_machine=powerpc
+ machine=powerpc/powerpc64le
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+powerpc64*)
+ base_machine=powerpc
+ machine=powerpc/powerpc64
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+powerpc*)
+ base_machine=powerpc
+ machine=powerpc/powerpc32
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+esac
diff --git a/cpu/sysdeps/sparc/configure-fragment b/cpu/sysdeps/sparc/configure-fragment
new file mode 100755
index 0000000..a64629c
--- /dev/null
+++ b/cpu/sysdeps/sparc/configure-fragment
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Regenerate this directory's sourced preconfigure fragment from preconfigure.ac.
+# Run from the architecture sysdeps directory.
+autoconf -Wno-syntax -I ../../.. -o preconfigure preconfigure.ac || exit 1
+chmod a-x preconfigure
+rm -f preconfigure~
+rm -rf autom4te.cache
diff --git a/cpu/sysdeps/sparc/preconfigure b/cpu/sysdeps/sparc/preconfigure
new file mode 100644
index 0000000..ecf135c
--- /dev/null
+++ b/cpu/sysdeps/sparc/preconfigure
@@ -0,0 +1,57 @@
+# This file is generated from preconfigure.ac by Autoconf. DO NOT EDIT!
+
+# Local preconfigure fragment for cpu/sysdeps/sparc.
+
+case "$machine" in
+sparc | sparcv67)
+ base_machine=sparc
+ machine=sparc/sparc32
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv8 | supersparc | hypersparc)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv8
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv8plus | sparcv8plusa | sparcv9)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv8plusb | sparcv9b)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9/sparcv9b
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv9v)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9/sparcv9v
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv9v2)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9/sparcv9v2
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparc64)
+ base_machine=sparc
+ machine=sparc/sparc64
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+sparc64b)
+ base_machine=sparc
+ machine=sparc/sparc64/sparcv9b
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+sparc64v)
+ base_machine=sparc
+ machine=sparc/sparc64/sparcv9v
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+sparc64v2)
+ base_machine=sparc
+ machine=sparc/sparc64/sparcv9v2
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+esac
+
diff --git a/cpu/sysdeps/sparc/preconfigure.ac b/cpu/sysdeps/sparc/preconfigure.ac
new file mode 100644
index 0000000..3a3361b
--- /dev/null
+++ b/cpu/sysdeps/sparc/preconfigure.ac
@@ -0,0 +1,56 @@
+dnl See acsite.m4 in the top-level source directory.
+MCPU_PROVIDES
+# Local preconfigure fragment for cpu/sysdeps/sparc.
+
+case "$machine" in
+sparc | sparcv[67])
+ base_machine=sparc
+ machine=sparc/sparc32
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv8 | supersparc | hypersparc)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv8
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv8plus | sparcv8plusa | sparcv9)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv8plusb | sparcv9b)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9/sparcv9b
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv9v)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9/sparcv9v
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparcv9v2)
+ base_machine=sparc
+ machine=sparc/sparc32/sparcv9/sparcv9v2
+ MCPU_HOST_DATA_MODEL=ILP32
+ ;;
+sparc64)
+ base_machine=sparc
+ machine=sparc/sparc64
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+sparc64b)
+ base_machine=sparc
+ machine=sparc/sparc64/sparcv9b
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+sparc64v)
+ base_machine=sparc
+ machine=sparc/sparc64/sparcv9v
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+sparc64v2)
+ base_machine=sparc
+ machine=sparc/sparc64/sparcv9v2
+ MCPU_HOST_DATA_MODEL=LP64
+ ;;
+esac
diff --git a/cpu/sysdeps/unix/sys-errno.c b/cpu/sysdeps/unix/sys-errno.c
new file mode 100644
index 0000000..ffcbb1d
--- /dev/null
+++ b/cpu/sysdeps/unix/sys-errno.c
@@ -0,0 +1,442 @@
+/***************************************************************
+ SYS-ERRNO.C
+
+ This file contains Linux/x86_64/LP64 HOST errno to MCPU
+ errno translation.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+int
+__cpu_errno_from_host( int errnum )
+{
+ if( errnum == 0 ) return( 0 );
+ if( errnum < 0 ) return( __MCPU_EUNKNOWN );
+
+#ifdef EPERM
+ if( errnum == EPERM ) return( __MCPU_EPERM );
+#endif
+#ifdef ENOENT
+ if( errnum == ENOENT ) return( __MCPU_ENOENT );
+#endif
+#ifdef ESRCH
+ if( errnum == ESRCH ) return( __MCPU_ESRCH );
+#endif
+#ifdef EINTR
+ if( errnum == EINTR ) return( __MCPU_EINTR );
+#endif
+#ifdef EIO
+ if( errnum == EIO ) return( __MCPU_EIO );
+#endif
+#ifdef ENXIO
+ if( errnum == ENXIO ) return( __MCPU_ENXIO );
+#endif
+#ifdef E2BIG
+ if( errnum == E2BIG ) return( __MCPU_E2BIG );
+#endif
+#ifdef ENOEXEC
+ if( errnum == ENOEXEC ) return( __MCPU_ENOEXEC );
+#endif
+#ifdef EBADF
+ if( errnum == EBADF ) return( __MCPU_EBADF );
+#endif
+#ifdef ECHILD
+ if( errnum == ECHILD ) return( __MCPU_ECHILD );
+#endif
+#ifdef EAGAIN
+ if( errnum == EAGAIN ) return( __MCPU_EAGAIN );
+#endif
+#ifdef ENOMEM
+ if( errnum == ENOMEM ) return( __MCPU_ENOMEM );
+#endif
+#ifdef EACCES
+ if( errnum == EACCES ) return( __MCPU_EACCES );
+#endif
+#ifdef EFAULT
+ if( errnum == EFAULT ) return( __MCPU_EFAULT );
+#endif
+#ifdef ENOTBLK
+ if( errnum == ENOTBLK ) return( __MCPU_ENOTBLK );
+#endif
+#ifdef EBUSY
+ if( errnum == EBUSY ) return( __MCPU_EBUSY );
+#endif
+#ifdef EEXIST
+ if( errnum == EEXIST ) return( __MCPU_EEXIST );
+#endif
+#ifdef EXDEV
+ if( errnum == EXDEV ) return( __MCPU_EXDEV );
+#endif
+#ifdef ENODEV
+ if( errnum == ENODEV ) return( __MCPU_ENODEV );
+#endif
+#ifdef ENOTDIR
+ if( errnum == ENOTDIR ) return( __MCPU_ENOTDIR );
+#endif
+#ifdef EISDIR
+ if( errnum == EISDIR ) return( __MCPU_EISDIR );
+#endif
+#ifdef EINVAL
+ if( errnum == EINVAL ) return( __MCPU_EINVAL );
+#endif
+#ifdef ENFILE
+ if( errnum == ENFILE ) return( __MCPU_ENFILE );
+#endif
+#ifdef EMFILE
+ if( errnum == EMFILE ) return( __MCPU_EMFILE );
+#endif
+#ifdef ENOTTY
+ if( errnum == ENOTTY ) return( __MCPU_ENOTTY );
+#endif
+#ifdef ETXTBSY
+ if( errnum == ETXTBSY ) return( __MCPU_ETXTBSY );
+#endif
+#ifdef EFBIG
+ if( errnum == EFBIG ) return( __MCPU_EFBIG );
+#endif
+#ifdef ENOSPC
+ if( errnum == ENOSPC ) return( __MCPU_ENOSPC );
+#endif
+#ifdef ESPIPE
+ if( errnum == ESPIPE ) return( __MCPU_ESPIPE );
+#endif
+#ifdef EROFS
+ if( errnum == EROFS ) return( __MCPU_EROFS );
+#endif
+#ifdef EMLINK
+ if( errnum == EMLINK ) return( __MCPU_EMLINK );
+#endif
+#ifdef EPIPE
+ if( errnum == EPIPE ) return( __MCPU_EPIPE );
+#endif
+#ifdef EDOM
+ if( errnum == EDOM ) return( __MCPU_EDOM );
+#endif
+#ifdef ERANGE
+ if( errnum == ERANGE ) return( __MCPU_ERANGE );
+#endif
+#ifdef EDEADLK
+ if( errnum == EDEADLK ) return( __MCPU_EDEADLK );
+#endif
+#ifdef ENAMETOOLONG
+ if( errnum == ENAMETOOLONG ) return( __MCPU_ENAMETOOLONG );
+#endif
+#ifdef ENOLCK
+ if( errnum == ENOLCK ) return( __MCPU_ENOLCK );
+#endif
+#ifdef ENOSYS
+ if( errnum == ENOSYS ) return( __MCPU_ENOSYS );
+#endif
+#ifdef ENOTEMPTY
+ if( errnum == ENOTEMPTY ) return( __MCPU_ENOTEMPTY );
+#endif
+#ifdef ELOOP
+ if( errnum == ELOOP ) return( __MCPU_ELOOP );
+#endif
+#ifdef ENOMSG
+ if( errnum == ENOMSG ) return( __MCPU_ENOMSG );
+#endif
+#ifdef EIDRM
+ if( errnum == EIDRM ) return( __MCPU_EIDRM );
+#endif
+#ifdef ECHRNG
+ if( errnum == ECHRNG ) return( __MCPU_ECHRNG );
+#endif
+#ifdef EL2NSYNC
+ if( errnum == EL2NSYNC ) return( __MCPU_EL2NSYNC );
+#endif
+#ifdef EL3HLT
+ if( errnum == EL3HLT ) return( __MCPU_EL3HLT );
+#endif
+#ifdef EL3RST
+ if( errnum == EL3RST ) return( __MCPU_EL3RST );
+#endif
+#ifdef ELNRNG
+ if( errnum == ELNRNG ) return( __MCPU_ELNRNG );
+#endif
+#ifdef EUNATCH
+ if( errnum == EUNATCH ) return( __MCPU_EUNATCH );
+#endif
+#ifdef ENOCSI
+ if( errnum == ENOCSI ) return( __MCPU_ENOCSI );
+#endif
+#ifdef EL2HLT
+ if( errnum == EL2HLT ) return( __MCPU_EL2HLT );
+#endif
+#ifdef EBADE
+ if( errnum == EBADE ) return( __MCPU_EBADE );
+#endif
+#ifdef EBADR
+ if( errnum == EBADR ) return( __MCPU_EBADR );
+#endif
+#ifdef EXFULL
+ if( errnum == EXFULL ) return( __MCPU_EXFULL );
+#endif
+#ifdef ENOANO
+ if( errnum == ENOANO ) return( __MCPU_ENOANO );
+#endif
+#ifdef EBADRQC
+ if( errnum == EBADRQC ) return( __MCPU_EBADRQC );
+#endif
+#ifdef EBADSLT
+ if( errnum == EBADSLT ) return( __MCPU_EBADSLT );
+#endif
+#ifdef EBFONT
+ if( errnum == EBFONT ) return( __MCPU_EBFONT );
+#endif
+#ifdef ENOSTR
+ if( errnum == ENOSTR ) return( __MCPU_ENOSTR );
+#endif
+#ifdef ENODATA
+ if( errnum == ENODATA ) return( __MCPU_ENODATA );
+#endif
+#ifdef ETIME
+ if( errnum == ETIME ) return( __MCPU_ETIME );
+#endif
+#ifdef ENOSR
+ if( errnum == ENOSR ) return( __MCPU_ENOSR );
+#endif
+#ifdef ENONET
+ if( errnum == ENONET ) return( __MCPU_ENONET );
+#endif
+#ifdef ENOPKG
+ if( errnum == ENOPKG ) return( __MCPU_ENOPKG );
+#endif
+#ifdef EREMOTE
+ if( errnum == EREMOTE ) return( __MCPU_EREMOTE );
+#endif
+#ifdef ENOLINK
+ if( errnum == ENOLINK ) return( __MCPU_ENOLINK );
+#endif
+#ifdef EADV
+ if( errnum == EADV ) return( __MCPU_EADV );
+#endif
+#ifdef ESRMNT
+ if( errnum == ESRMNT ) return( __MCPU_ESRMNT );
+#endif
+#ifdef ECOMM
+ if( errnum == ECOMM ) return( __MCPU_ECOMM );
+#endif
+#ifdef EPROTO
+ if( errnum == EPROTO ) return( __MCPU_EPROTO );
+#endif
+#ifdef EMULTIHOP
+ if( errnum == EMULTIHOP ) return( __MCPU_EMULTIHOP );
+#endif
+#ifdef EDOTDOT
+ if( errnum == EDOTDOT ) return( __MCPU_EDOTDOT );
+#endif
+#ifdef EBADMSG
+ if( errnum == EBADMSG ) return( __MCPU_EBADMSG );
+#endif
+#ifdef EOVERFLOW
+ if( errnum == EOVERFLOW ) return( __MCPU_EOVERFLOW );
+#endif
+#ifdef ENOTUNIQ
+ if( errnum == ENOTUNIQ ) return( __MCPU_ENOTUNIQ );
+#endif
+#ifdef EBADFD
+ if( errnum == EBADFD ) return( __MCPU_EBADFD );
+#endif
+#ifdef EREMCHG
+ if( errnum == EREMCHG ) return( __MCPU_EREMCHG );
+#endif
+#ifdef ELIBACC
+ if( errnum == ELIBACC ) return( __MCPU_ELIBACC );
+#endif
+#ifdef ELIBBAD
+ if( errnum == ELIBBAD ) return( __MCPU_ELIBBAD );
+#endif
+#ifdef ELIBSCN
+ if( errnum == ELIBSCN ) return( __MCPU_ELIBSCN );
+#endif
+#ifdef ELIBMAX
+ if( errnum == ELIBMAX ) return( __MCPU_ELIBMAX );
+#endif
+#ifdef ELIBEXEC
+ if( errnum == ELIBEXEC ) return( __MCPU_ELIBEXEC );
+#endif
+#ifdef EILSEQ
+ if( errnum == EILSEQ ) return( __MCPU_EILSEQ );
+#endif
+#ifdef ERESTART
+ if( errnum == ERESTART ) return( __MCPU_ERESTART );
+#endif
+#ifdef ESTRPIPE
+ if( errnum == ESTRPIPE ) return( __MCPU_ESTRPIPE );
+#endif
+#ifdef EUSERS
+ if( errnum == EUSERS ) return( __MCPU_EUSERS );
+#endif
+#ifdef ENOTSOCK
+ if( errnum == ENOTSOCK ) return( __MCPU_ENOTSOCK );
+#endif
+#ifdef EDESTADDRREQ
+ if( errnum == EDESTADDRREQ ) return( __MCPU_EDESTADDRREQ );
+#endif
+#ifdef EMSGSIZE
+ if( errnum == EMSGSIZE ) return( __MCPU_EMSGSIZE );
+#endif
+#ifdef EPROTOTYPE
+ if( errnum == EPROTOTYPE ) return( __MCPU_EPROTOTYPE );
+#endif
+#ifdef ENOPROTOOPT
+ if( errnum == ENOPROTOOPT ) return( __MCPU_ENOPROTOOPT );
+#endif
+#ifdef EPROTONOSUPPORT
+ if( errnum == EPROTONOSUPPORT ) return( __MCPU_EPROTONOSUPPORT );
+#endif
+#ifdef ESOCKTNOSUPPORT
+ if( errnum == ESOCKTNOSUPPORT ) return( __MCPU_ESOCKTNOSUPPORT );
+#endif
+#ifdef EOPNOTSUPP
+ if( errnum == EOPNOTSUPP ) return( __MCPU_EOPNOTSUPP );
+#endif
+#ifdef EPFNOSUPPORT
+ if( errnum == EPFNOSUPPORT ) return( __MCPU_EPFNOSUPPORT );
+#endif
+#ifdef EAFNOSUPPORT
+ if( errnum == EAFNOSUPPORT ) return( __MCPU_EAFNOSUPPORT );
+#endif
+#ifdef EADDRINUSE
+ if( errnum == EADDRINUSE ) return( __MCPU_EADDRINUSE );
+#endif
+#ifdef EADDRNOTAVAIL
+ if( errnum == EADDRNOTAVAIL ) return( __MCPU_EADDRNOTAVAIL );
+#endif
+#ifdef ENETDOWN
+ if( errnum == ENETDOWN ) return( __MCPU_ENETDOWN );
+#endif
+#ifdef ENETUNREACH
+ if( errnum == ENETUNREACH ) return( __MCPU_ENETUNREACH );
+#endif
+#ifdef ENETRESET
+ if( errnum == ENETRESET ) return( __MCPU_ENETRESET );
+#endif
+#ifdef ECONNABORTED
+ if( errnum == ECONNABORTED ) return( __MCPU_ECONNABORTED );
+#endif
+#ifdef ECONNRESET
+ if( errnum == ECONNRESET ) return( __MCPU_ECONNRESET );
+#endif
+#ifdef ENOBUFS
+ if( errnum == ENOBUFS ) return( __MCPU_ENOBUFS );
+#endif
+#ifdef EISCONN
+ if( errnum == EISCONN ) return( __MCPU_EISCONN );
+#endif
+#ifdef ENOTCONN
+ if( errnum == ENOTCONN ) return( __MCPU_ENOTCONN );
+#endif
+#ifdef ESHUTDOWN
+ if( errnum == ESHUTDOWN ) return( __MCPU_ESHUTDOWN );
+#endif
+#ifdef ETOOMANYREFS
+ if( errnum == ETOOMANYREFS ) return( __MCPU_ETOOMANYREFS );
+#endif
+#ifdef ETIMEDOUT
+ if( errnum == ETIMEDOUT ) return( __MCPU_ETIMEDOUT );
+#endif
+#ifdef ECONNREFUSED
+ if( errnum == ECONNREFUSED ) return( __MCPU_ECONNREFUSED );
+#endif
+#ifdef EHOSTDOWN
+ if( errnum == EHOSTDOWN ) return( __MCPU_EHOSTDOWN );
+#endif
+#ifdef EHOSTUNREACH
+ if( errnum == EHOSTUNREACH ) return( __MCPU_EHOSTUNREACH );
+#endif
+#ifdef EALREADY
+ if( errnum == EALREADY ) return( __MCPU_EALREADY );
+#endif
+#ifdef EINPROGRESS
+ if( errnum == EINPROGRESS ) return( __MCPU_EINPROGRESS );
+#endif
+#ifdef ESTALE
+ if( errnum == ESTALE ) return( __MCPU_ESTALE );
+#endif
+#ifdef EUCLEAN
+ if( errnum == EUCLEAN ) return( __MCPU_EUCLEAN );
+#endif
+#ifdef ENOTNAM
+ if( errnum == ENOTNAM ) return( __MCPU_ENOTNAM );
+#endif
+#ifdef ENAVAIL
+ if( errnum == ENAVAIL ) return( __MCPU_ENAVAIL );
+#endif
+#ifdef EISNAM
+ if( errnum == EISNAM ) return( __MCPU_EISNAM );
+#endif
+#ifdef EREMOTEIO
+ if( errnum == EREMOTEIO ) return( __MCPU_EREMOTEIO );
+#endif
+#ifdef EDQUOT
+ if( errnum == EDQUOT ) return( __MCPU_EDQUOT );
+#endif
+#ifdef ENOMEDIUM
+ if( errnum == ENOMEDIUM ) return( __MCPU_ENOMEDIUM );
+#endif
+#ifdef EMEDIUMTYPE
+ if( errnum == EMEDIUMTYPE ) return( __MCPU_EMEDIUMTYPE );
+#endif
+#ifdef ECANCELED
+ if( errnum == ECANCELED ) return( __MCPU_ECANCELED );
+#endif
+#ifdef ENOKEY
+ if( errnum == ENOKEY ) return( __MCPU_ENOKEY );
+#endif
+#ifdef EKEYEXPIRED
+ if( errnum == EKEYEXPIRED ) return( __MCPU_EKEYEXPIRED );
+#endif
+#ifdef EKEYREVOKED
+ if( errnum == EKEYREVOKED ) return( __MCPU_EKEYREVOKED );
+#endif
+#ifdef EKEYREJECTED
+ if( errnum == EKEYREJECTED ) return( __MCPU_EKEYREJECTED );
+#endif
+#ifdef EOWNERDEAD
+ if( errnum == EOWNERDEAD ) return( __MCPU_EOWNERDEAD );
+#endif
+#ifdef ENOTRECOVERABLE
+ if( errnum == ENOTRECOVERABLE ) return( __MCPU_ENOTRECOVERABLE );
+#endif
+#ifdef ERFKILL
+ if( errnum == ERFKILL ) return( __MCPU_ERFKILL );
+#endif
+#ifdef EHWPOISON
+ if( errnum == EHWPOISON ) return( __MCPU_EHWPOISON );
+#endif
+#ifdef EFTYPE
+ if( errnum == EFTYPE ) return( __MCPU_EFTYPE );
+#endif
+#ifdef EWOULDBLOCK
+ if( errnum == EWOULDBLOCK ) return( __MCPU_EWOULDBLOCK );
+#endif
+#ifdef EDEADLOCK
+ if( errnum == EDEADLOCK ) return( __MCPU_EDEADLOCK );
+#endif
+#ifdef ENOTSUP
+ if( errnum == ENOTSUP ) return( __MCPU_ENOTSUP );
+#endif
+#ifdef EUNKNOWN
+ if( errnum == EUNKNOWN ) return( __MCPU_EUNKNOWN );
+#endif
+
+ return( __MCPU_EUNKNOWN );
+
+} /* End of __cpu_errno_from_host() */
diff --git a/cpu/sysdeps/unix/sysv/linux/i386/i686/README b/cpu/sysdeps/unix/sysv/linux/i386/i686/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/i386/i686/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/unix/sysv/linux/i386/i786/Implies b/cpu/sysdeps/unix/sysv/linux/i386/i786/Implies
new file mode 100644
index 0000000..7cb7d9a
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/i386/i786/Implies
@@ -0,0 +1,2 @@
+# The PPro and PII cores are mostly the same.
+unix/sysv/linux/i386/i686
diff --git a/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc32/README b/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc32/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc32/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64/README b/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64le/README b/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64le/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/powerpc/powerpc64le/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/README b/cpu/sysdeps/unix/sysv/linux/x86_64/64/README
new file mode 100644
index 0000000..c28377c
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/README
@@ -0,0 +1,8 @@
+Linux/x86_64/LP64 HOST sysdeps
+==============================
+
+This directory contains the selected low-level syscall adapters for the
+currently supported Linux/x86_64 LP64 HOST profile. The common UNIX errno
+translator is inherited from `cpu/sysdeps/unix/sys-errno.c`; all real HOST
+failures are translated to stable MCPU errno values before control returns to
+the common CPU layer.
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-chown-linux.h b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-chown-linux.h
new file mode 100644
index 0000000..7b39ae4
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-chown-linux.h
@@ -0,0 +1,66 @@
+/***************************************************************
+ CPU-CHOWN-LINUX.H
+
+ This file contains Linux/x86_64/LP64 conversion helpers
+ for MCPU uid/gid values -> HOST uid_t/gid_t.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_CHOWN_LINUX_H
+#define __CPU_CHOWN_LINUX_H
+
+#include <errno.h>
+#include <sys/types.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+static int
+__cpu_uid_to_host( __mpu_uint64_t uid, uid_t *host_uid )
+{
+ uid_t u;
+
+ if( !host_uid ) return( __MCPU_EINVAL );
+ if( uid == __CPU_ID_NO_CHANGE )
+ {
+ *host_uid = (uid_t)-1;
+ return( 0 );
+ }
+
+ u = (uid_t)uid;
+ if( (__mpu_uint64_t)u != uid ) return( __MCPU_EOVERFLOW );
+
+ *host_uid = u;
+ return( 0 );
+
+} /* End of __cpu_uid_to_host() */
+
+
+static int
+__cpu_gid_to_host( __mpu_uint64_t gid, gid_t *host_gid )
+{
+ gid_t g;
+
+ if( !host_gid ) return( __MCPU_EINVAL );
+ if( gid == __CPU_ID_NO_CHANGE )
+ {
+ *host_gid = (gid_t)-1;
+ return( 0 );
+ }
+
+ g = (gid_t)gid;
+ if( (__mpu_uint64_t)g != gid ) return( __MCPU_EOVERFLOW );
+
+ *host_gid = g;
+ return( 0 );
+
+} /* End of __cpu_gid_to_host() */
+
+#endif /* __CPU_CHOWN_LINUX_H */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-mode-linux.h b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-mode-linux.h
new file mode 100644
index 0000000..a68e50c
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-mode-linux.h
@@ -0,0 +1,53 @@
+/***************************************************************
+ CPU-MODE-LINUX.H
+
+ This file contains Linux/x86_64/LP64 conversion helper
+ for MCPU permission bits -> HOST mode_t.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_MODE_LINUX_H
+#define __CPU_MODE_LINUX_H
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+static int
+__cpu_mode_to_host( __mpu_uint64_t mode, mode_t *host_mode )
+{
+ mode_t m = 0;
+
+ if( !host_mode ) return( __MCPU_EINVAL );
+ if( mode & ~(__mpu_uint64_t)__CPU_S_SUPPORTED ) return( __MCPU_EINVAL );
+
+ if( mode & __CPU_S_ISUID ) m |= S_ISUID;
+ if( mode & __CPU_S_ISGID ) m |= S_ISGID;
+#ifdef S_ISVTX
+ if( mode & __CPU_S_ISVTX ) m |= S_ISVTX;
+#endif
+ if( mode & __CPU_S_IRUSR ) m |= S_IRUSR;
+ if( mode & __CPU_S_IWUSR ) m |= S_IWUSR;
+ if( mode & __CPU_S_IXUSR ) m |= S_IXUSR;
+ if( mode & __CPU_S_IRGRP ) m |= S_IRGRP;
+ if( mode & __CPU_S_IWGRP ) m |= S_IWGRP;
+ if( mode & __CPU_S_IXGRP ) m |= S_IXGRP;
+ if( mode & __CPU_S_IROTH ) m |= S_IROTH;
+ if( mode & __CPU_S_IWOTH ) m |= S_IWOTH;
+ if( mode & __CPU_S_IXOTH ) m |= S_IXOTH;
+
+ *host_mode = m;
+ return( 0 );
+
+} /* End of __cpu_mode_to_host() */
+
+#endif /* __CPU_MODE_LINUX_H */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-stat-linux.h b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-stat-linux.h
new file mode 100644
index 0000000..58ac956
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-stat-linux.h
@@ -0,0 +1,124 @@
+/***************************************************************
+ CPU-STAT-LINUX.H
+
+ This file contains Linux/x86_64/LP64 conversion helpers
+ for the HOST struct stat -> MCPU struct __cpu_stat ABI.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_STAT_LINUX_H
+#define __CPU_STAT_LINUX_H
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+static int
+__cpu_stat_mode( mode_t mode, __mpu_uint64_t *out )
+{
+ __mpu_uint64_t m = 0;
+
+ if( !out ) return( __MCPU_EFAULT );
+
+ switch( mode & S_IFMT )
+ {
+ case S_IFIFO: m |= __CPU_S_IFIFO; break;
+ case S_IFCHR: m |= __CPU_S_IFCHR; break;
+ case S_IFDIR: m |= __CPU_S_IFDIR; break;
+ case S_IFBLK: m |= __CPU_S_IFBLK; break;
+ case S_IFREG: m |= __CPU_S_IFREG; break;
+ case S_IFLNK: m |= __CPU_S_IFLNK; break;
+#ifdef S_IFSOCK
+ case S_IFSOCK: m |= __CPU_S_IFSOCK; break;
+#endif
+ default: return( __MCPU_EOVERFLOW );
+ }
+
+ if( mode & S_ISUID ) m |= __CPU_S_ISUID;
+ if( mode & S_ISGID ) m |= __CPU_S_ISGID;
+#ifdef S_ISVTX
+ if( mode & S_ISVTX ) m |= __CPU_S_ISVTX;
+#endif
+ if( mode & S_IRUSR ) m |= __CPU_S_IRUSR;
+ if( mode & S_IWUSR ) m |= __CPU_S_IWUSR;
+ if( mode & S_IXUSR ) m |= __CPU_S_IXUSR;
+ if( mode & S_IRGRP ) m |= __CPU_S_IRGRP;
+ if( mode & S_IWGRP ) m |= __CPU_S_IWGRP;
+ if( mode & S_IXGRP ) m |= __CPU_S_IXGRP;
+ if( mode & S_IROTH ) m |= __CPU_S_IROTH;
+ if( mode & S_IWOTH ) m |= __CPU_S_IWOTH;
+ if( mode & S_IXOTH ) m |= __CPU_S_IXOTH;
+
+ *out = m;
+ return( 0 );
+
+} /* End of __cpu_stat_mode() */
+
+
+static int
+__cpu_stat_from_host( struct __cpu_stat *dst, const struct stat *src )
+{
+ int error;
+
+ if( !dst || !src ) return( __MCPU_EFAULT );
+
+ dst->st_dev = (__mpu_uint64_t)src->st_dev;
+ if( (dev_t)dst->st_dev != src->st_dev ) return( __MCPU_EOVERFLOW );
+
+ dst->st_ino = (__mpu_uint64_t)src->st_ino;
+ if( (ino_t)dst->st_ino != src->st_ino ) return( __MCPU_EOVERFLOW );
+
+ error = __cpu_stat_mode( src->st_mode, &dst->st_mode );
+ if( error ) return( error );
+
+ dst->st_nlink = (__mpu_uint64_t)src->st_nlink;
+ if( (nlink_t)dst->st_nlink != src->st_nlink ) return( __MCPU_EOVERFLOW );
+
+ dst->st_uid = (__mpu_uint64_t)src->st_uid;
+ if( (uid_t)dst->st_uid != src->st_uid ) return( __MCPU_EOVERFLOW );
+
+ dst->st_gid = (__mpu_uint64_t)src->st_gid;
+ if( (gid_t)dst->st_gid != src->st_gid ) return( __MCPU_EOVERFLOW );
+
+ dst->st_rdev = (__mpu_uint64_t)src->st_rdev;
+ if( (dev_t)dst->st_rdev != src->st_rdev ) return( __MCPU_EOVERFLOW );
+
+ dst->st_size = (__mpu_int64_t)src->st_size;
+ if( (off_t)dst->st_size != src->st_size ) return( __MCPU_EOVERFLOW );
+
+ dst->st_blksize = (__mpu_int64_t)src->st_blksize;
+ if( (blksize_t)dst->st_blksize != src->st_blksize ) return( __MCPU_EOVERFLOW );
+
+ dst->st_blocks = (__mpu_int64_t)src->st_blocks;
+ if( (blkcnt_t)dst->st_blocks != src->st_blocks ) return( __MCPU_EOVERFLOW );
+
+ dst->st_atime_sec = (__mpu_int64_t)src->st_atim.tv_sec;
+ if( (time_t)dst->st_atime_sec != src->st_atim.tv_sec ) return( __MCPU_EOVERFLOW );
+ if( src->st_atim.tv_nsec < 0 ) return( __MCPU_EOVERFLOW );
+ dst->st_atime_nsec = (__mpu_uint64_t)src->st_atim.tv_nsec;
+
+ dst->st_mtime_sec = (__mpu_int64_t)src->st_mtim.tv_sec;
+ if( (time_t)dst->st_mtime_sec != src->st_mtim.tv_sec ) return( __MCPU_EOVERFLOW );
+ if( src->st_mtim.tv_nsec < 0 ) return( __MCPU_EOVERFLOW );
+ dst->st_mtime_nsec = (__mpu_uint64_t)src->st_mtim.tv_nsec;
+
+ dst->st_ctime_sec = (__mpu_int64_t)src->st_ctim.tv_sec;
+ if( (time_t)dst->st_ctime_sec != src->st_ctim.tv_sec ) return( __MCPU_EOVERFLOW );
+ if( src->st_ctim.tv_nsec < 0 ) return( __MCPU_EOVERFLOW );
+ dst->st_ctime_nsec = (__mpu_uint64_t)src->st_ctim.tv_nsec;
+
+ return( 0 );
+
+} /* End of __cpu_stat_from_host() */
+
+#endif /* __CPU_STAT_LINUX_H */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-time-linux.h b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-time-linux.h
new file mode 100644
index 0000000..8bdda84
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/cpu-time-linux.h
@@ -0,0 +1,64 @@
+/***************************************************************
+ CPU-TIME-LINUX.H
+
+ Linux/x86_64/LP64 conversion helpers for the MCPU time ABI.
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __CPU_TIME_LINUX_H
+#define __CPU_TIME_LINUX_H
+
+#include <errno.h>
+#include <time.h>
+
+
+static int
+__cpu_clockid_to_host( __mpu_uint64_t clockid, clockid_t *host_clockid )
+{
+ if( !host_clockid ) return( __MCPU_EFAULT );
+
+ switch( clockid )
+ {
+ case __CPU_CLOCK_REALTIME:
+ *host_clockid = CLOCK_REALTIME;
+ return( 0 );
+ case __CPU_CLOCK_MONOTONIC:
+ *host_clockid = CLOCK_MONOTONIC;
+ return( 0 );
+ default:
+ return( __MCPU_EINVAL );
+ }
+
+} /* End of __cpu_clockid_to_host() */
+
+
+static int
+__cpu_timespec_from_host( struct __cpu_timespec *dst,
+ const struct timespec *src )
+{
+ __mpu_int64_t sec;
+ __mpu_int64_t nsec;
+
+ if( !dst || !src ) return( __MCPU_EFAULT );
+
+ sec = (__mpu_int64_t)src->tv_sec;
+ if( (time_t)sec != src->tv_sec ) return( __MCPU_EOVERFLOW );
+
+ nsec = (__mpu_int64_t)src->tv_nsec;
+ if( (long)nsec != src->tv_nsec ) return( __MCPU_EOVERFLOW );
+ if( nsec < 0 || nsec > 999999999 ) return( __MCPU_EOVERFLOW );
+
+ dst->tv_sec = sec;
+ dst->tv_nsec = nsec;
+
+ return( 0 );
+
+} /* End of __cpu_timespec_from_host() */
+
+#endif /* __CPU_TIME_LINUX_H */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-access.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-access.c
new file mode 100644
index 0000000..5bb9a45
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-access.c
@@ -0,0 +1,42 @@
+/***************************************************************
+ SYS-ACCESS.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_access().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_access( int dirfd, const char *path, __mpu_uint64_t mode )
+{
+ int host_mode = 0;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+ if( mode & ~(__mpu_uint64_t)__CPU_ACCESS_SUPPORTED )
+ return( -(__mpu_int64_t)__MCPU_EINVAL );
+
+ if( mode & __CPU_R_OK ) host_mode |= R_OK;
+ if( mode & __CPU_W_OK ) host_mode |= W_OK;
+ if( mode & __CPU_X_OK ) host_mode |= X_OK;
+
+ if( faccessat( dirfd, path, host_mode, 0 ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_access() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chdir.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chdir.c
new file mode 100644
index 0000000..c6da354
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chdir.c
@@ -0,0 +1,53 @@
+/***************************************************************
+ SYS-CHDIR.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_cwd_init() and __cpu_sys_chdir().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+static __mpu_int64_t
+__cpu_open_directory( int dirfd, const char *path )
+{
+ int fd;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ fd = openat( dirfd, path, O_PATH | O_DIRECTORY | O_CLOEXEC );
+ if( fd < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( (__mpu_int64_t)fd );
+
+} /* End of __cpu_open_directory() */
+
+
+__mpu_int64_t
+__cpu_sys_cwd_init( void )
+{
+ return( __cpu_open_directory( AT_FDCWD, "." ) );
+
+} /* End of __cpu_sys_cwd_init() */
+
+
+__mpu_int64_t
+__cpu_sys_chdir( int dirfd, const char *path )
+{
+ return( __cpu_open_directory( dirfd, path ) );
+
+} /* End of __cpu_sys_chdir() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chmod.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chmod.c
new file mode 100644
index 0000000..6719bf7
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chmod.c
@@ -0,0 +1,41 @@
+/***************************************************************
+ SYS-CHMOD.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_chmod().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-mode-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_chmod( int dirfd, const char *path, __mpu_uint64_t mode )
+{
+ mode_t host_mode;
+ int error;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ error = __cpu_mode_to_host( mode, &host_mode );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( fchmodat( dirfd, path, host_mode, 0 ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_chmod() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chown.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chown.c
new file mode 100644
index 0000000..42e748e
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-chown.c
@@ -0,0 +1,45 @@
+/***************************************************************
+ SYS-CHOWN.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_chown().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-chown-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_chown( int dirfd, const char *path, __mpu_uint64_t uid,
+ __mpu_uint64_t gid )
+{
+ uid_t host_uid;
+ gid_t host_gid;
+ int error;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ error = __cpu_uid_to_host( uid, &host_uid );
+ if( error ) return( -(__mpu_int64_t)error );
+ error = __cpu_gid_to_host( gid, &host_gid );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( fchownat( dirfd, path, host_uid, host_gid, 0 ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_chown() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_getres.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_getres.c
new file mode 100644
index 0000000..d156d61
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_getres.c
@@ -0,0 +1,48 @@
+/***************************************************************
+ SYS-CLOCK_GETRES.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_clock_getres().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <time.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-time-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_clock_getres( __mpu_uint64_t clockid, struct __cpu_timespec *res )
+{
+ struct timespec ts;
+ clockid_t host_clockid;
+ int error;
+
+ error = __cpu_clockid_to_host( clockid, &host_clockid );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( clock_getres( host_clockid, res ? &ts : (struct timespec *)0 ) < 0 )
+ return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ if( res )
+ {
+ error = __cpu_timespec_from_host( res, &ts );
+ if( error ) return( -(__mpu_int64_t)error );
+ }
+
+ return( 0 );
+
+} /* End of __cpu_sys_clock_getres() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_gettime.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_gettime.c
new file mode 100644
index 0000000..6e017fc
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_gettime.c
@@ -0,0 +1,47 @@
+/***************************************************************
+ SYS-CLOCK_GETTIME.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_clock_gettime().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <time.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-time-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_clock_gettime( __mpu_uint64_t clockid, struct __cpu_timespec *tp )
+{
+ struct timespec ts;
+ clockid_t host_clockid;
+ int error;
+
+ if( !tp ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ error = __cpu_clockid_to_host( clockid, &host_clockid );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( clock_gettime( host_clockid, &ts ) < 0 )
+ return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ error = __cpu_timespec_from_host( tp, &ts );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ return( 0 );
+
+} /* End of __cpu_sys_clock_gettime() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_nanosleep.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_nanosleep.c
new file mode 100644
index 0000000..8659441
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-clock_nanosleep.c
@@ -0,0 +1,93 @@
+/***************************************************************
+ SYS-CLOCK_NANOSLEEP.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_clock_nanosleep().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <time.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-time-linux.h"
+
+
+static int
+__cpu_timespec_to_host( struct timespec *dst,
+ const struct __cpu_timespec *src )
+{
+ time_t sec;
+ long nsec;
+
+ if( !dst || !src ) return( __MCPU_EFAULT );
+ if( src->tv_sec < 0 || src->tv_nsec < 0 || src->tv_nsec > 999999999 )
+ return( __MCPU_EINVAL );
+
+ sec = (time_t)src->tv_sec;
+ if( (__mpu_int64_t)sec != src->tv_sec ) return( __MCPU_EOVERFLOW );
+
+ nsec = (long)src->tv_nsec;
+ if( (__mpu_int64_t)nsec != src->tv_nsec ) return( __MCPU_EOVERFLOW );
+
+ dst->tv_sec = sec;
+ dst->tv_nsec = nsec;
+
+ return( 0 );
+
+} /* End of __cpu_timespec_to_host() */
+
+
+__mpu_int64_t
+__cpu_sys_clock_nanosleep( __mpu_uint64_t clockid, __mpu_uint64_t flags,
+ const struct __cpu_timespec *req,
+ struct __cpu_timespec *rem )
+{
+ struct timespec host_req;
+ struct timespec host_rem;
+ struct timespec *host_prem = (struct timespec *)0;
+ clockid_t host_clockid;
+ int host_flags = 0;
+ int ret;
+ int error;
+
+ if( !req ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ error = __cpu_clockid_to_host( clockid, &host_clockid );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( flags == __CPU_TIMER_ABSTIME )
+ host_flags = TIMER_ABSTIME;
+ else if( flags != 0 )
+ return( -(__mpu_int64_t)__MCPU_EINVAL );
+
+ error = __cpu_timespec_to_host( &host_req, req );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( !host_flags && rem ) host_prem = &host_rem;
+
+ ret = clock_nanosleep( host_clockid, host_flags, &host_req, host_prem );
+ if( ret != 0 )
+ {
+ if( ret == EINTR && host_prem )
+ {
+ error = __cpu_timespec_from_host( rem, &host_rem );
+ if( error ) return( -(__mpu_int64_t)error );
+ }
+ return( -(__mpu_int64_t)__cpu_errno_from_host( ret ) );
+ }
+
+ return( 0 );
+
+} /* End of __cpu_sys_clock_nanosleep() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-close.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-close.c
new file mode 100644
index 0000000..48aceed
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-close.c
@@ -0,0 +1,16 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+__mpu_int64_t
+__cpu_sys_close( int fd )
+{
+ if( close( fd ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+}
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-creat.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-creat.c
new file mode 100644
index 0000000..9bbccce
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-creat.c
@@ -0,0 +1,30 @@
+/***************************************************************
+ SYS-CREAT.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_creat().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_creat( int dirfd, const char *path, __mpu_uint64_t mode )
+{
+ return( __cpu_sys_open( dirfd, path,
+ __CPU_O_WRONLY | __CPU_O_CREAT | __CPU_O_TRUNC,
+ mode ) );
+
+} /* End of __cpu_sys_creat() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-dup.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-dup.c
new file mode 100644
index 0000000..f140b69
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-dup.c
@@ -0,0 +1,36 @@
+/***************************************************************
+ SYS-DUP.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_dup().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_dup( int fd )
+{
+ int ret;
+
+ ret = dup( fd );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ return( (__mpu_int64_t)ret );
+
+} /* End of __cpu_sys_dup() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchdir.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchdir.c
new file mode 100644
index 0000000..3323975
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchdir.c
@@ -0,0 +1,35 @@
+/***************************************************************
+ SYS-FCHDIR.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_fchdir().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_fchdir( int fd )
+{
+ int cwd_fd;
+
+ cwd_fd = openat( fd, ".", O_PATH | O_DIRECTORY | O_CLOEXEC );
+ if( cwd_fd < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( (__mpu_int64_t)cwd_fd );
+
+} /* End of __cpu_sys_fchdir() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchmod.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchmod.c
new file mode 100644
index 0000000..a4f90be
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchmod.c
@@ -0,0 +1,39 @@
+/***************************************************************
+ SYS-FCHMOD.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_fchmod().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-mode-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_fchmod( int fd, __mpu_uint64_t mode )
+{
+ mode_t host_mode;
+ int error;
+
+ error = __cpu_mode_to_host( mode, &host_mode );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( fchmod( fd, host_mode ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_fchmod() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchown.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchown.c
new file mode 100644
index 0000000..a3e793b
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fchown.c
@@ -0,0 +1,42 @@
+/***************************************************************
+ SYS-FCHOWN.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_fchown().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-chown-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_fchown( int fd, __mpu_uint64_t uid, __mpu_uint64_t gid )
+{
+ uid_t host_uid;
+ gid_t host_gid;
+ int error;
+
+ error = __cpu_uid_to_host( uid, &host_uid );
+ if( error ) return( -(__mpu_int64_t)error );
+ error = __cpu_gid_to_host( gid, &host_gid );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( fchown( fd, host_uid, host_gid ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_fchown() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fcntl.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fcntl.c
new file mode 100644
index 0000000..d04074e
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fcntl.c
@@ -0,0 +1,115 @@
+/***************************************************************
+ SYS-FCNTL.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_fcntl().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+static int
+__cpu_fcntl_getfl( int host_flags, __mpu_uint64_t *guest_flags )
+{
+ __mpu_uint64_t flags = 0;
+
+ if( !guest_flags ) return( __MCPU_EINVAL );
+
+ switch( host_flags & O_ACCMODE )
+ {
+ case O_RDONLY: flags |= __CPU_O_RDONLY; break;
+ case O_WRONLY: flags |= __CPU_O_WRONLY; break;
+ case O_RDWR: flags |= __CPU_O_RDWR; break;
+ default: return( __MCPU_EINVAL );
+ }
+
+ if( host_flags & O_APPEND ) flags |= __CPU_O_APPEND;
+ if( host_flags & O_NONBLOCK ) flags |= __CPU_O_NONBLOCK;
+
+ *guest_flags = flags;
+ return( 0 );
+
+} /* End of __cpu_fcntl_getfl() */
+
+
+static int
+__cpu_fcntl_setfl( __mpu_uint64_t guest_flags, int *host_flags )
+{
+ int flags = 0;
+
+ if( !host_flags ) return( __MCPU_EINVAL );
+ if( guest_flags & ~(__mpu_uint64_t)__CPU_F_SETFL_SUPPORTED )
+ return( __MCPU_EINVAL );
+
+ switch( guest_flags & __CPU_O_ACCMODE )
+ {
+ case __CPU_O_RDONLY:
+ case __CPU_O_WRONLY:
+ case __CPU_O_RDWR:
+ break;
+ default:
+ return( __MCPU_EINVAL );
+ }
+
+ if( guest_flags & __CPU_O_APPEND ) flags |= O_APPEND;
+ if( guest_flags & __CPU_O_NONBLOCK ) flags |= O_NONBLOCK;
+
+ *host_flags = flags;
+ return( 0 );
+
+} /* End of __cpu_fcntl_setfl() */
+
+
+__mpu_int64_t
+__cpu_sys_fcntl( int fd, __mpu_uint64_t cmd, __mpu_uint64_t arg )
+{
+ __mpu_uint64_t guest_flags;
+ int host_flags;
+ int error;
+ int ret;
+
+ switch( cmd )
+ {
+ case __CPU_F_DUPFD:
+ if( arg != 0 ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+ ret = fcntl( fd, F_DUPFD, 0 );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( (__mpu_int64_t)ret );
+
+ case __CPU_F_GETFL:
+ if( arg != 0 ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+ ret = fcntl( fd, F_GETFL );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ error = __cpu_fcntl_getfl( ret, &guest_flags );
+ if( error ) return( -(__mpu_int64_t)error );
+ return( (__mpu_int64_t)guest_flags );
+
+ case __CPU_F_SETFL:
+ error = __cpu_fcntl_setfl( arg, &host_flags );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ ret = fcntl( fd, F_SETFL, host_flags );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+ default:
+ return( -(__mpu_int64_t)__MCPU_EINVAL );
+ }
+
+} /* End of __cpu_sys_fcntl() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fstat.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fstat.c
new file mode 100644
index 0000000..53b0309
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fstat.c
@@ -0,0 +1,43 @@
+/***************************************************************
+ SYS-FSTAT.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_fstat().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-stat-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_fstat( int fd, struct __cpu_stat *st )
+{
+ struct stat host_st;
+ int error;
+
+ if( fd < 0 ) return( -(__mpu_int64_t)__MCPU_EBADF );
+ if( !st ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( fstat( fd, &host_st ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ error = __cpu_stat_from_host( st, &host_st );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ return( 0 );
+
+} /* End of __cpu_sys_fstat() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fsync.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fsync.c
new file mode 100644
index 0000000..3ba7e11
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-fsync.c
@@ -0,0 +1,32 @@
+/***************************************************************
+ SYS-FSYNC.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_fsync().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_fsync( int fd )
+{
+ if( fsync( fd ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_fsync() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-ftruncate.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-ftruncate.c
new file mode 100644
index 0000000..f5e55ad
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-ftruncate.c
@@ -0,0 +1,39 @@
+/***************************************************************
+ SYS-FTRUNCATE.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_ftruncate().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_ftruncate( int fd, __mpu_int64_t length )
+{
+ off_t host_length;
+
+ host_length = (off_t)length;
+ if( (__mpu_int64_t)host_length != length )
+ return( -(__mpu_int64_t)__MCPU_EOVERFLOW );
+
+ if( ftruncate( fd, host_length ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_ftruncate() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-getdents.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-getdents.c
new file mode 100644
index 0000000..6b8928c
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-getdents.c
@@ -0,0 +1,227 @@
+/***************************************************************
+ SYS-GETDENTS.C
+
+ Linux/x86_64/LP64 implementation of __cpu_sys_getdents().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dirent.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+#define __CPU_HOST_DIRENT_BUFFER 4096U
+
+struct __cpu_linux_dirent64
+{
+ uint64_t d_ino;
+ int64_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[];
+};
+
+static int
+__cpu_dirent_utf8_valid( const unsigned char *s, size_t n )
+{
+ size_t i = 0;
+
+ while( i < n )
+ {
+ unsigned int c = s[i++];
+
+ if( c < 0x80U ) continue;
+ if( c >= 0xc2U && c <= 0xdfU )
+ {
+ if( i >= n || ( s[i] & 0xc0U ) != 0x80U ) return( 0 );
+ ++i; continue;
+ }
+ if( c == 0xe0U )
+ {
+ if( i + 1 >= n || s[i] < 0xa0U || s[i] > 0xbfU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2; continue;
+ }
+ if( c >= 0xe1U && c <= 0xecU )
+ {
+ if( i + 1 >= n || ( s[i] & 0xc0U ) != 0x80U ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2; continue;
+ }
+ if( c == 0xedU )
+ {
+ if( i + 1 >= n || s[i] < 0x80U || s[i] > 0x9fU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2; continue;
+ }
+ if( c >= 0xeeU && c <= 0xefU )
+ {
+ if( i + 1 >= n || ( s[i] & 0xc0U ) != 0x80U ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 2; continue;
+ }
+ if( c == 0xf0U )
+ {
+ if( i + 2 >= n || s[i] < 0x90U || s[i] > 0xbfU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ||
+ ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 3; continue;
+ }
+ if( c >= 0xf1U && c <= 0xf3U )
+ {
+ if( i + 2 >= n || ( s[i] & 0xc0U ) != 0x80U ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ||
+ ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 3; continue;
+ }
+ if( c == 0xf4U )
+ {
+ if( i + 2 >= n || s[i] < 0x80U || s[i] > 0x8fU ||
+ ( s[i + 1] & 0xc0U ) != 0x80U ||
+ ( s[i + 2] & 0xc0U ) != 0x80U ) return( 0 );
+ i += 3; continue;
+ }
+ return( 0 );
+ }
+ return( 1 );
+}
+
+static __mpu_uint64_t
+__cpu_dirent_type( unsigned char type )
+{
+ switch( type )
+ {
+#ifdef DT_FIFO
+ case DT_FIFO: return( __CPU_DT_FIFO );
+#endif
+#ifdef DT_CHR
+ case DT_CHR: return( __CPU_DT_CHR );
+#endif
+#ifdef DT_DIR
+ case DT_DIR: return( __CPU_DT_DIR );
+#endif
+#ifdef DT_BLK
+ case DT_BLK: return( __CPU_DT_BLK );
+#endif
+#ifdef DT_REG
+ case DT_REG: return( __CPU_DT_REG );
+#endif
+#ifdef DT_LNK
+ case DT_LNK: return( __CPU_DT_LNK );
+#endif
+#ifdef DT_SOCK
+ case DT_SOCK: return( __CPU_DT_SOCK );
+#endif
+ default: return( __CPU_DT_UNKNOWN );
+ }
+}
+
+__mpu_int64_t
+__cpu_sys_getdents( int fd, struct __cpu_dirent *dirp, __mpu_uint64_t count )
+{
+ unsigned char hostbuf[__CPU_HOST_DIRENT_BUFFER];
+ struct stat st;
+ off_t start;
+ off_t resume;
+ ssize_t nread;
+ size_t pos = 0;
+ size_t nrecords = 0;
+ size_t maxrecords;
+
+ if( !dirp ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+ if( count < __CPU_DIRENT_SIZE ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+
+ maxrecords = (size_t)( count / __CPU_DIRENT_SIZE );
+
+ if( fstat( fd, &st ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ if( !S_ISDIR( st.st_mode ) ) return( -(__mpu_int64_t)__MCPU_ENOTDIR );
+
+ start = lseek( fd, (off_t)0, SEEK_CUR );
+ if( start == (off_t)-1 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ resume = start;
+
+ nread = syscall( SYS_getdents64, fd, hostbuf, sizeof( hostbuf ) );
+ if( nread < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ if( nread == 0 ) return( 0 );
+
+ while( pos < (size_t)nread )
+ {
+ struct __cpu_linux_dirent64 *de;
+ const char *nul;
+ size_t namespace;
+ size_t namelen;
+
+ if( (size_t)nread - pos < offsetof( struct __cpu_linux_dirent64, d_name ) + 1U )
+ goto malformed;
+
+ de = (struct __cpu_linux_dirent64 *)( hostbuf + pos );
+ if( de->d_reclen < offsetof( struct __cpu_linux_dirent64, d_name ) + 1U ||
+ de->d_reclen > (size_t)nread - pos ) goto malformed;
+
+ if( nrecords >= maxrecords ) break;
+
+ namespace = de->d_reclen - offsetof( struct __cpu_linux_dirent64, d_name );
+ nul = (const char *)memchr( de->d_name, '\0', namespace );
+ if( !nul ) goto malformed;
+ namelen = (size_t)( nul - de->d_name );
+
+ if( namelen >= __CPU_DIRENT_NAME_SIZE )
+ {
+ if( lseek( fd, resume, SEEK_SET ) == (off_t)-1 )
+ return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( nrecords ? (__mpu_int64_t)( nrecords * __CPU_DIRENT_SIZE )
+ : -(__mpu_int64_t)__MCPU_ENAMETOOLONG );
+ }
+
+ if( !__cpu_dirent_utf8_valid( (const unsigned char *)de->d_name, namelen ) )
+ {
+ if( lseek( fd, resume, SEEK_SET ) == (off_t)-1 )
+ return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( nrecords ? (__mpu_int64_t)( nrecords * __CPU_DIRENT_SIZE )
+ : -(__mpu_int64_t)__MCPU_EILSEQ );
+ }
+
+ dirp[nrecords].d_ino = (__mpu_uint64_t)de->d_ino;
+ dirp[nrecords].d_off = (__mpu_int64_t)de->d_off;
+ dirp[nrecords].d_reclen = __CPU_DIRENT_SIZE;
+ dirp[nrecords].d_type = __cpu_dirent_type( de->d_type );
+ memset( dirp[nrecords].d_name, 0, __CPU_DIRENT_NAME_SIZE );
+ memcpy( dirp[nrecords].d_name, de->d_name, namelen );
+
+ resume = (off_t)de->d_off;
+ ++nrecords;
+ pos += de->d_reclen;
+ }
+
+ if( pos < (size_t)nread )
+ {
+ if( lseek( fd, resume, SEEK_SET ) == (off_t)-1 )
+ return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ }
+
+ return( (__mpu_int64_t)( nrecords * __CPU_DIRENT_SIZE ) );
+
+malformed:
+ if( lseek( fd, start, SEEK_SET ) == (off_t)-1 )
+ return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( -(__mpu_int64_t)__MCPU_EIO );
+
+} /* End of __cpu_sys_getdents() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-link.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-link.c
new file mode 100644
index 0000000..fd19f0d
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-link.c
@@ -0,0 +1,34 @@
+/***************************************************************
+ SYS-LINK.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_link().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_link( int dirfd, const char *oldpath, const char *newpath )
+{
+ if( !oldpath || !newpath ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( linkat( dirfd, oldpath, dirfd, newpath, 0 ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_link() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lseek.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lseek.c
new file mode 100644
index 0000000..0de650e
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lseek.c
@@ -0,0 +1,35 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+__mpu_int64_t
+__cpu_sys_lseek( int fd, __mpu_int64_t offset, __mpu_uint64_t whence )
+{
+ off_t host_offset;
+ off_t ret;
+ int host_whence;
+
+ switch( whence )
+ {
+ case __CPU_SEEK_SET: host_whence = SEEK_SET; break;
+ case __CPU_SEEK_CUR: host_whence = SEEK_CUR; break;
+ case __CPU_SEEK_END: host_whence = SEEK_END; break;
+ default: return( -(__mpu_int64_t)__MCPU_EINVAL );
+ }
+
+ host_offset = (off_t)offset;
+ if( (__mpu_int64_t)host_offset != offset ) return( -(__mpu_int64_t)__MCPU_EOVERFLOW );
+
+ ret = lseek( fd, host_offset, host_whence );
+ if( ret == (off_t)-1 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ if( (off_t)(__mpu_int64_t)ret != ret ) return( -(__mpu_int64_t)__MCPU_EOVERFLOW );
+ return( (__mpu_int64_t)ret );
+}
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lstat.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lstat.c
new file mode 100644
index 0000000..3ea9353
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-lstat.c
@@ -0,0 +1,43 @@
+/***************************************************************
+ SYS-LSTAT.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_lstat().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-stat-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_lstat( int dirfd, const char *path, struct __cpu_stat *st )
+{
+ struct stat host_st;
+ int error;
+
+ if( !path || !st ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( fstatat( dirfd, path, &host_st, AT_SYMLINK_NOFOLLOW ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ error = __cpu_stat_from_host( st, &host_st );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ return( 0 );
+
+} /* End of __cpu_sys_lstat() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-mkdir.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-mkdir.c
new file mode 100644
index 0000000..76ced3a
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-mkdir.c
@@ -0,0 +1,69 @@
+/***************************************************************
+ SYS-MKDIR.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_mkdir().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+static int
+__cpu_mkdir_mode( __mpu_uint64_t mode, mode_t *host_mode )
+{
+ mode_t m = 0;
+
+ if( !host_mode ) return( __MCPU_EINVAL );
+ if( mode & ~(__mpu_uint64_t)__CPU_S_SUPPORTED ) return( __MCPU_EINVAL );
+
+ if( mode & __CPU_S_ISUID ) m |= S_ISUID;
+ if( mode & __CPU_S_ISGID ) m |= S_ISGID;
+#ifdef S_ISVTX
+ if( mode & __CPU_S_ISVTX ) m |= S_ISVTX;
+#endif
+ if( mode & __CPU_S_IRUSR ) m |= S_IRUSR;
+ if( mode & __CPU_S_IWUSR ) m |= S_IWUSR;
+ if( mode & __CPU_S_IXUSR ) m |= S_IXUSR;
+ if( mode & __CPU_S_IRGRP ) m |= S_IRGRP;
+ if( mode & __CPU_S_IWGRP ) m |= S_IWGRP;
+ if( mode & __CPU_S_IXGRP ) m |= S_IXGRP;
+ if( mode & __CPU_S_IROTH ) m |= S_IROTH;
+ if( mode & __CPU_S_IWOTH ) m |= S_IWOTH;
+ if( mode & __CPU_S_IXOTH ) m |= S_IXOTH;
+
+ *host_mode = m;
+ return( 0 );
+
+} /* End of __cpu_mkdir_mode() */
+
+
+__mpu_int64_t
+__cpu_sys_mkdir( int dirfd, const char *path, __mpu_uint64_t mode )
+{
+ mode_t host_mode;
+ int error;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ error = __cpu_mkdir_mode( mode, &host_mode );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( mkdirat( dirfd, path, host_mode ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_mkdir() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-open.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-open.c
new file mode 100644
index 0000000..36a9994
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-open.c
@@ -0,0 +1,114 @@
+/***************************************************************
+ SYS-OPEN.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_open().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+static int
+__cpu_open_flags( __mpu_uint64_t flags, int *host_flags )
+{
+ int f = 0;
+
+ if( !host_flags ) return( __MCPU_EINVAL );
+ if( flags & ~(__mpu_uint64_t)__CPU_O_SUPPORTED ) return( __MCPU_EINVAL );
+
+ switch( flags & __CPU_O_ACCMODE )
+ {
+ case __CPU_O_RDONLY: f |= O_RDONLY; break;
+ case __CPU_O_WRONLY: f |= O_WRONLY; break;
+ case __CPU_O_RDWR: f |= O_RDWR; break;
+ default: return( __MCPU_EINVAL );
+ }
+
+ if( flags & __CPU_O_CREAT ) f |= O_CREAT;
+ if( flags & __CPU_O_EXCL ) f |= O_EXCL;
+ if( flags & __CPU_O_NOCTTY ) f |= O_NOCTTY;
+ if( flags & __CPU_O_TRUNC ) f |= O_TRUNC;
+ if( flags & __CPU_O_APPEND ) f |= O_APPEND;
+ if( flags & __CPU_O_NONBLOCK ) f |= O_NONBLOCK;
+
+ *host_flags = f;
+ return( 0 );
+
+} /* End of __cpu_open_flags() */
+
+
+static int
+__cpu_open_mode( __mpu_uint64_t mode, mode_t *host_mode )
+{
+ mode_t m = 0;
+
+ if( !host_mode ) return( __MCPU_EINVAL );
+ if( mode & ~(__mpu_uint64_t)__CPU_S_SUPPORTED ) return( __MCPU_EINVAL );
+
+ if( mode & __CPU_S_ISUID ) m |= S_ISUID;
+ if( mode & __CPU_S_ISGID ) m |= S_ISGID;
+#ifdef S_ISVTX
+ if( mode & __CPU_S_ISVTX ) m |= S_ISVTX;
+#endif
+ if( mode & __CPU_S_IRUSR ) m |= S_IRUSR;
+ if( mode & __CPU_S_IWUSR ) m |= S_IWUSR;
+ if( mode & __CPU_S_IXUSR ) m |= S_IXUSR;
+ if( mode & __CPU_S_IRGRP ) m |= S_IRGRP;
+ if( mode & __CPU_S_IWGRP ) m |= S_IWGRP;
+ if( mode & __CPU_S_IXGRP ) m |= S_IXGRP;
+ if( mode & __CPU_S_IROTH ) m |= S_IROTH;
+ if( mode & __CPU_S_IWOTH ) m |= S_IWOTH;
+ if( mode & __CPU_S_IXOTH ) m |= S_IXOTH;
+
+ *host_mode = m;
+ return( 0 );
+
+} /* End of __cpu_open_mode() */
+
+
+__mpu_int64_t
+__cpu_sys_open( int dirfd, const char *path, __mpu_uint64_t flags,
+ __mpu_uint64_t mode )
+{
+ mode_t host_mode = 0;
+ int host_flags;
+ int error;
+ int fd;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ error = __cpu_open_flags( flags, &host_flags );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ if( flags & __CPU_O_CREAT )
+ {
+ error = __cpu_open_mode( mode, &host_mode );
+ if( error ) return( -(__mpu_int64_t)error );
+ fd = openat( dirfd, path, host_flags, host_mode );
+ }
+ else
+ {
+ if( mode != 0 ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+ fd = openat( dirfd, path, host_flags );
+ }
+
+ if( fd < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( (__mpu_int64_t)fd );
+
+} /* End of __cpu_sys_open() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-pipe2.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-pipe2.c
new file mode 100644
index 0000000..bb211a2
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-pipe2.c
@@ -0,0 +1,44 @@
+/***************************************************************
+ SYS-PIPE2.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_pipe2().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_pipe2( int pipefd[2], __mpu_uint64_t flags )
+{
+ int host_flags = 0;
+ int ret;
+
+ if( !pipefd ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+ if( flags & ~(__mpu_uint64_t)__CPU_O_NONBLOCK )
+ return( -(__mpu_int64_t)__MCPU_EINVAL );
+
+ if( flags & __CPU_O_NONBLOCK ) host_flags |= O_NONBLOCK;
+
+ ret = pipe2( pipefd, host_flags );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ return( 0 );
+
+} /* End of __cpu_sys_pipe2() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-read.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-read.c
new file mode 100644
index 0000000..4816d37
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-read.c
@@ -0,0 +1,21 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+__mpu_int64_t
+__cpu_sys_read( int fd, void *buf, __mpu_uint64_t count )
+{
+ ssize_t ret;
+
+ if( count > (__mpu_uint64_t)SIZE_MAX ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+ ret = read( fd, buf, (size_t)count );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( (__mpu_int64_t)ret );
+}
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-readlink.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-readlink.c
new file mode 100644
index 0000000..bda2a47
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-readlink.c
@@ -0,0 +1,40 @@
+/***************************************************************
+ SYS-READLINK.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_readlink().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_readlink( int dirfd, const char *path, void *buf,
+ __mpu_uint64_t count )
+{
+ ssize_t ret;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+ if( count > (__mpu_uint64_t)SIZE_MAX ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+
+ ret = readlinkat( dirfd, path, (char *)buf, (size_t)count );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( (__mpu_int64_t)ret );
+
+} /* End of __cpu_sys_readlink() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rename.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rename.c
new file mode 100644
index 0000000..d79b3fb
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rename.c
@@ -0,0 +1,34 @@
+/***************************************************************
+ SYS-RENAME.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_rename().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_rename( int dirfd, const char *oldpath, const char *newpath )
+{
+ if( !oldpath || !newpath ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( renameat( dirfd, oldpath, dirfd, newpath ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_rename() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rmdir.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rmdir.c
new file mode 100644
index 0000000..41ee0c2
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-rmdir.c
@@ -0,0 +1,35 @@
+/***************************************************************
+ SYS-RMDIR.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_rmdir().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_rmdir( int dirfd, const char *path )
+{
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( unlinkat( dirfd, path, AT_REMOVEDIR ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_rmdir() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-select.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-select.c
new file mode 100644
index 0000000..a87d138
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-select.c
@@ -0,0 +1,109 @@
+/***************************************************************
+ SYS-SELECT.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_select().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_select( struct __cpu_select_entry *entries, __mpu_uint64_t count,
+ const struct __cpu_timeval *timeout )
+{
+ struct pollfd *pfds = (struct pollfd *)0;
+ struct timespec ts;
+ struct timespec *pts = (struct timespec *)0;
+ __mpu_uint64_t i;
+ time_t sec;
+ int ret;
+
+ if( count && !entries ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+ if( count > (__mpu_uint64_t)(size_t)-1 / sizeof( *pfds ) )
+ return( -(__mpu_int64_t)__MCPU_EINVAL );
+
+ if( timeout )
+ {
+ if( timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999 )
+ return( -(__mpu_int64_t)__MCPU_EINVAL );
+
+ sec = (time_t)timeout->tv_sec;
+ if( (__mpu_int64_t)sec != timeout->tv_sec )
+ return( -(__mpu_int64_t)__MCPU_EOVERFLOW );
+
+ ts.tv_sec = sec;
+ ts.tv_nsec = (long)( timeout->tv_usec * 1000 );
+ pts = &ts;
+ }
+
+ if( count )
+ {
+ pfds = (struct pollfd *)calloc( (size_t)count, sizeof( *pfds ) );
+ if( !pfds ) return( -(__mpu_int64_t)__MCPU_ENOMEM );
+ }
+
+ for( i = 0; i < count; ++i )
+ {
+ pfds[i].fd = entries[i].host_fd;
+ pfds[i].events = 0;
+ pfds[i].revents = 0;
+ entries[i].revents = 0;
+
+ if( entries[i].events & __CPU_SELECT_READ ) pfds[i].events |= POLLIN;
+ if( entries[i].events & __CPU_SELECT_WRITE ) pfds[i].events |= POLLOUT;
+ if( entries[i].events & __CPU_SELECT_EXCEPT ) pfds[i].events |= POLLPRI;
+ }
+
+ ret = ppoll( pfds, (nfds_t)count, pts, (const sigset_t *)0 );
+ if( ret < 0 )
+ {
+ ret = -(__mpu_int64_t)__cpu_errno_from_host( errno );
+ free( pfds );
+ return( (__mpu_int64_t)ret );
+ }
+
+ for( i = 0; i < count; ++i )
+ {
+ short revents = pfds[i].revents;
+
+ if( revents & POLLNVAL )
+ {
+ free( pfds );
+ return( -(__mpu_int64_t)__MCPU_EBADF );
+ }
+
+ if( ( entries[i].events & __CPU_SELECT_READ ) &&
+ ( revents & ( POLLIN | POLLHUP | POLLERR ) ) )
+ entries[i].revents |= __CPU_SELECT_READ;
+
+ if( ( entries[i].events & __CPU_SELECT_WRITE ) &&
+ ( revents & ( POLLOUT | POLLERR ) ) )
+ entries[i].revents |= __CPU_SELECT_WRITE;
+
+ if( ( entries[i].events & __CPU_SELECT_EXCEPT ) && ( revents & POLLPRI ) )
+ entries[i].revents |= __CPU_SELECT_EXCEPT;
+ }
+
+ free( pfds );
+ return( 0 );
+
+} /* End of __cpu_sys_select() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-stat.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-stat.c
new file mode 100644
index 0000000..bb3a154
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-stat.c
@@ -0,0 +1,42 @@
+/***************************************************************
+ SYS-STAT.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_stat().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+#include "cpu-stat-linux.h"
+
+
+__mpu_int64_t
+__cpu_sys_stat( int dirfd, const char *path, struct __cpu_stat *st )
+{
+ struct stat host_st;
+ int error;
+
+ if( !path || !st ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( fstatat( dirfd, path, &host_st, 0 ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ error = __cpu_stat_from_host( st, &host_st );
+ if( error ) return( -(__mpu_int64_t)error );
+
+ return( 0 );
+
+} /* End of __cpu_sys_stat() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-symlink.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-symlink.c
new file mode 100644
index 0000000..276a277
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-symlink.c
@@ -0,0 +1,34 @@
+/***************************************************************
+ SYS-SYMLINK.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_symlink().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_symlink( int dirfd, const char *target, const char *linkpath )
+{
+ if( !target || !linkpath ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( symlinkat( target, dirfd, linkpath ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_symlink() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-truncate.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-truncate.c
new file mode 100644
index 0000000..4a34b44
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-truncate.c
@@ -0,0 +1,58 @@
+/***************************************************************
+ SYS-TRUNCATE.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_truncate().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_truncate( int dirfd, const char *path, __mpu_int64_t length )
+{
+ off_t host_length;
+
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ host_length = (off_t)length;
+ if( (__mpu_int64_t)host_length != length )
+ return( -(__mpu_int64_t)__MCPU_EOVERFLOW );
+
+ {
+ int fd;
+ int error;
+
+ fd = openat( dirfd, path, O_WRONLY | O_CLOEXEC );
+ if( fd < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+
+ if( ftruncate( fd, host_length ) < 0 )
+ {
+ error = errno;
+ (void)close( fd );
+ return( -(__mpu_int64_t)__cpu_errno_from_host( error ) );
+ }
+
+ (void)close( fd );
+ }
+
+ return( 0 );
+
+} /* End of __cpu_sys_truncate() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-unlink.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-unlink.c
new file mode 100644
index 0000000..155dc79
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-unlink.c
@@ -0,0 +1,34 @@
+/***************************************************************
+ SYS-UNLINK.C
+
+ This file contains Linux/x86_64/LP64 implementation of
+ __cpu_sys_unlink().
+
+ PART OF : CPU - library .
+
+ USAGE : Internal only .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+
+__mpu_int64_t
+__cpu_sys_unlink( int dirfd, const char *path )
+{
+ if( !path ) return( -(__mpu_int64_t)__MCPU_EFAULT );
+
+ if( unlinkat( dirfd, path, 0 ) < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( 0 );
+
+} /* End of __cpu_sys_unlink() */
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-write.c b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-write.c
new file mode 100644
index 0000000..e5398c7
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/64/sys-write.c
@@ -0,0 +1,21 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <libmcpu.h>
+#include <cpu-sysdeps.h>
+
+__mpu_int64_t
+__cpu_sys_write( int fd, const void *buf, __mpu_uint64_t count )
+{
+ ssize_t ret;
+
+ if( count > (__mpu_uint64_t)SIZE_MAX ) return( -(__mpu_int64_t)__MCPU_EINVAL );
+ ret = write( fd, buf, (size_t)count );
+ if( ret < 0 ) return( -(__mpu_int64_t)__cpu_errno_from_host( errno ) );
+ return( (__mpu_int64_t)ret );
+}
diff --git a/cpu/sysdeps/unix/sysv/linux/x86_64/x32/README b/cpu/sysdeps/unix/sysv/linux/x86_64/x32/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/unix/sysv/linux/x86_64/x32/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/x86_64/64/README b/cpu/sysdeps/x86_64/64/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/x86_64/64/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.
diff --git a/cpu/sysdeps/x86_64/configure-fragment b/cpu/sysdeps/x86_64/configure-fragment
new file mode 100755
index 0000000..a64629c
--- /dev/null
+++ b/cpu/sysdeps/x86_64/configure-fragment
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Regenerate this directory's sourced preconfigure fragment from preconfigure.ac.
+# Run from the architecture sysdeps directory.
+autoconf -Wno-syntax -I ../../.. -o preconfigure preconfigure.ac || exit 1
+chmod a-x preconfigure
+rm -f preconfigure~
+rm -rf autom4te.cache
diff --git a/cpu/sysdeps/x86_64/preconfigure b/cpu/sysdeps/x86_64/preconfigure
new file mode 100644
index 0000000..9abbeec
--- /dev/null
+++ b/cpu/sysdeps/x86_64/preconfigure
@@ -0,0 +1,79 @@
+# This file is generated from preconfigure.ac by Autoconf. DO NOT EDIT!
+
+# Local preconfigure fragment for cpu/sysdeps/x86_64.
+
+test -n "$base_machine" || case "$machine" in
+x86_64)
+ base_machine=x86_64
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC uses the x86_64 x32 data model by default" >&5
+printf %s "checking whether $CC uses the x86_64 x32 data model by default... " >&6; }
+if test ${mcpu_cv_x86_64_x32+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifndef __ILP32__
+# error not x32
+#endif
+int main( void ) { return 0; }
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ mcpu_cv_x86_64_x32=yes
+else case e in #(
+ e) mcpu_cv_x86_64_x32=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $mcpu_cv_x86_64_x32" >&5
+printf "%s\n" "$mcpu_cv_x86_64_x32" >&6; }
+
+ if test "$mcpu_cv_x86_64_x32" = yes; then
+ machine=x86_64/x32
+ MCPU_HOST_DATA_MODEL=ILP32
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC uses the x86_64 LP64 data model" >&5
+printf %s "checking whether $CC uses the x86_64 LP64 data model... " >&6; }
+if test ${mcpu_cv_x86_64_lp64+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+typedef char mcpu_int_must_be_4[(sizeof(int) == 4) ? 1 : -1];
+typedef char mcpu_long_must_be_8[(sizeof(long) == 8) ? 1 : -1];
+typedef char mcpu_ptr_must_be_8[(sizeof(void *) == 8) ? 1 : -1];
+int main( void ) { return 0; }
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ mcpu_cv_x86_64_lp64=yes
+else case e in #(
+ e) mcpu_cv_x86_64_lp64=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $mcpu_cv_x86_64_lp64" >&5
+printf "%s\n" "$mcpu_cv_x86_64_lp64" >&6; }
+ if test "$mcpu_cv_x86_64_lp64" != yes; then
+ as_fn_error $? "Not supported HOST $host: unsupported x86_64 data model" "$LINENO" 5
+ fi
+ machine=x86_64/64
+ MCPU_HOST_DATA_MODEL=LP64
+ fi
+ ;;
+esac
+
diff --git a/cpu/sysdeps/x86_64/preconfigure.ac b/cpu/sysdeps/x86_64/preconfigure.ac
new file mode 100644
index 0000000..7679c59
--- /dev/null
+++ b/cpu/sysdeps/x86_64/preconfigure.ac
@@ -0,0 +1,39 @@
+dnl See acsite.m4 in the top-level source directory.
+MCPU_PROVIDES
+# Local preconfigure fragment for cpu/sysdeps/x86_64.
+
+test -n "$base_machine" || case "$machine" in
+x86_64)
+ base_machine=x86_64
+
+ AC_CACHE_CHECK([whether $CC uses the x86_64 x32 data model by default],
+ [mcpu_cv_x86_64_x32], [dnl
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#ifndef __ILP32__
+# error not x32
+#endif
+int main( void ) { return 0; }
+ ]])], [mcpu_cv_x86_64_x32=yes], [mcpu_cv_x86_64_x32=no])
+ ])
+
+ if test "$mcpu_cv_x86_64_x32" = yes; then
+ machine=x86_64/x32
+ MCPU_HOST_DATA_MODEL=ILP32
+ else
+ AC_CACHE_CHECK([whether $CC uses the x86_64 LP64 data model],
+ [mcpu_cv_x86_64_lp64], [dnl
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+typedef char mcpu_int_must_be_4[(sizeof(int) == 4) ? 1 : -1];
+typedef char mcpu_long_must_be_8[(sizeof(long) == 8) ? 1 : -1];
+typedef char mcpu_ptr_must_be_8[(sizeof(void *) == 8) ? 1 : -1];
+int main( void ) { return 0; }
+ ]])], [mcpu_cv_x86_64_lp64=yes], [mcpu_cv_x86_64_lp64=no])
+ ])
+ if test "$mcpu_cv_x86_64_lp64" != yes; then
+ AC_MSG_ERROR([Not supported HOST $host: unsupported x86_64 data model])
+ fi
+ machine=x86_64/64
+ MCPU_HOST_DATA_MODEL=LP64
+ fi
+ ;;
+esac
diff --git a/cpu/sysdeps/x86_64/x32/README b/cpu/sysdeps/x86_64/x32/README
new file mode 100644
index 0000000..f00b0cb
--- /dev/null
+++ b/cpu/sysdeps/x86_64/x32/README
@@ -0,0 +1,2 @@
+This directory is part of the LibMCPU HOST sysdeps inheritance tree.
+HOST-dependent syscall wrappers will be added here in later releases.