summaryrefslogtreecommitdiff
path: root/include/libmcpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/libmcpu.h')
-rw-r--r--include/libmcpu.h729
1 files changed, 729 insertions, 0 deletions
diff --git a/include/libmcpu.h b/include/libmcpu.h
new file mode 100644
index 0000000..178f872
--- /dev/null
+++ b/include/libmcpu.h
@@ -0,0 +1,729 @@
+
+/***************************************************************
+ LIBMCPU.H
+
+ This file contains public MCPU operation functions & data
+ declarations.
+
+ PART OF : MCPU - library .
+
+ Copyright (C) 2026 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifndef __LIB_MCPU_H
+#define __LIB_MCPU_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libmpu.h>
+
+#define CPU_REGISTERS_MEM_SIZE_IN_UNITS 524288
+#define CPU_REGISTER_ADDRESS_MAX 0x0007ffffU
+#define CPU_REGISTER_MIN_BITS 8U
+#define CPU_REGISTER_MAX_BITS 65536U
+
+/* LibCPU CALL ABI return-value area at the top of the register file. */
+#define CPU_RETURN_AREA_SIZE 0x00002000U
+#define CPU_RETURN_AREA_BEGIN 0x0007e000U
+#define CPU_RETURN_AREA_END 0x00080000U
+
+/* MCPU SYSCALL register ABI. */
+#define CPU_SYSCALL_NARGS_ADDR 0x0007fff8U
+#define CPU_SYSCALL_SYSNO_ADDR 0x0007fffcU
+#define CPU_SYSCALL_RET_ADDR 0x0007fff8U
+#define CPU_SYSCALL_ARG0_ADDR 0x0007fff0U
+#define CPU_SYSCALL_ARG1_ADDR 0x0007ffe8U
+#define CPU_SYSCALL_ARG2_ADDR 0x0007ffe0U
+#define CPU_SYSCALL_ARG3_ADDR 0x0007ffd8U
+#define CPU_SYSCALL_ARG4_ADDR 0x0007ffd0U
+#define CPU_SYSCALL_ARG5_ADDR 0x0007ffc8U
+#define CPU_SYSCALL_MAX_ARGS 6U
+
+
+/* Machine encoding sizes. */
+#define CPU_OPCODE_SIZE 2U
+#define CPU_REG24_SIZE 3U
+#define CPU_IMM64_SIZE 8U
+#define CPU_ADDR64_SIZE 8U
+#define CPU_CODE64_SIZE 8U
+#define CPU_OFF64_SIZE 8U
+#define CPU_CONST8_SIZE 1U
+#define CPU_PSWBIT8_SIZE 1U
+#define CPU_PTR64_SIZE 8U
+
+/*
+ * Byte-order domains.
+ *
+ * PROGRAM multi-byte machine fields are always canonical MSB-first.
+ * Architectural data objects (register file, DATA, STACK and future data
+ * segments) use the target data representation selected by LibMPU.
+ * CPU_DATA_* aliases make this ABI dependency explicit to LibCPU tools.
+ */
+#define CPU_CODE_BYTE_ORDER_MSB_FIRST 1
+#define CPU_DATA_BYTE_ORDER MPU_BYTE_ORDER
+#define CPU_DATA_BYTE_ORDER_BIG_ENDIAN MPU_BYTE_ORDER_BIG_ENDIAN
+#define CPU_DATA_BYTE_ORDER_LITTLE_ENDIAN MPU_BYTE_ORDER_LITTLE_ENDIAN
+#define CPU_DATA_WORD_ORDER MPU_WORD_ORDER
+#define CPU_DATA_WORD_ORDER_BIG_ENDIAN MPU_WORD_ORDER_BIG_ENDIAN
+#define CPU_DATA_WORD_ORDER_LITTLE_ENDIAN MPU_WORD_ORDER_LITTLE_ENDIAN
+
+extern __mpu_uint16_t __cpu_data_get_u16( const __mpu_UNIT_t *p );
+extern __mpu_uint32_t __cpu_data_get_u32( const __mpu_UNIT_t *p );
+extern __mpu_uint64_t __cpu_data_get_u64( const __mpu_UNIT_t *p );
+extern void __cpu_data_put_u16( __mpu_UNIT_t *p, __mpu_uint16_t v );
+extern void __cpu_data_put_u32( __mpu_UNIT_t *p, __mpu_uint32_t v );
+extern void __cpu_data_put_u64( __mpu_UNIT_t *p, __mpu_uint64_t v );
+
+extern __mpu_uint16_t __cpu_code_get_u16( const __mpu_UNIT_t *p );
+extern __mpu_uint32_t __cpu_code_get_u32( const __mpu_UNIT_t *p );
+extern __mpu_uint64_t __cpu_code_get_u64( const __mpu_UNIT_t *p );
+extern void __cpu_code_put_u16( __mpu_UNIT_t *p, __mpu_uint16_t v );
+extern void __cpu_code_put_u32( __mpu_UNIT_t *p, __mpu_uint32_t v );
+extern void __cpu_code_put_u64( __mpu_UNIT_t *p, __mpu_uint64_t v );
+
+/* Fixed CALL ABI bases. Individual argument offsets are computed inside
+ the aligned argument block and are therefore not generally fixed. */
+#define CPU_CALL_RETURN_PC_SIZE CPU_CODE64_SIZE
+#define CPU_ABI_CALLEE_ARGUMENT_BLOCK_OFFSET 8U
+#define CPU_ABI_FP_ARGUMENT_BLOCK_OFFSET 16U
+#define CPU_ABI_HIDDEN_RESULT_BLOCK_OFFSET 0U
+
+/* LibCPU C-like ABI/data-layout conventions used by assembler/linker code. */
+#define CPU_ABI_MAX_ALIGN 16U
+#define CPU_ABI_STACK_ALIGN 16U
+#define CPU_ABI_STACK_RED_ZONE_SIZE 0U
+#define CPU_ABI_ARGUMENT_BLOCK_ALIGN 16U
+#define CPU_DATA_NULL_GUARD_SIZE 16U
+#define CPU_HEAP_GUARD_SIZE 16U
+#define CPU_HEAP_BEGIN CPU_HEAP_GUARD_SIZE
+#define CPU_NULL_PTR __mpu_UINT64_C( 0x0000000000000000 )
+
+
+/***************************************************************
+ PTR64 - segmented virtual pointer.
+
+ bits 63..60 : 4-bit segment selector
+ bits 59..0 : byte offset inside the selected segment
+
+ A PTR64 is an architectural value, never a host pointer. The
+ 60-bit offset gives each segment a 2^60-byte (1 EiB) virtual
+ address span. Segment identifiers 0x3..0x7 are assigned to model/runtime data
+ address spaces. Selectors 0x8..0xf remain reserved.
+ ***************************************************************/
+#define CPU_PTR_SEG_SHIFT 60U
+#define CPU_PTR_SEG_MASK __mpu_UINT64_C( 0xf000000000000000 )
+#define CPU_PTR_OFFSET_MASK __mpu_UINT64_C( 0x0fffffffffffffff )
+
+typedef enum __cpu_ptr_segment
+{
+ CPU_PTR_SEG_DATA = 0x0,
+ CPU_PTR_SEG_STACK = 0x1,
+ CPU_PTR_SEG_PROGRAM = 0x2,
+ CPU_PTR_SEG_CONTROL = 0x3,
+ CPU_PTR_SEG_INPUT = 0x4,
+ CPU_PTR_SEG_OUTPUT = 0x5,
+ CPU_PTR_SEG_TRACE = 0x6,
+ CPU_PTR_SEG_HEAP = 0x7
+} cpu_ptr_segment;
+
+#define CPU_PTR_SEG_FIRST_RESERVED 0x8U
+#define CPU_PTR_SEG_MAX 0x0fU
+
+/* CONTROL and INPUT are guest read-only. OUTPUT, TRACE and HEAP are guest
+ read/write. PROGRAM is guest read-only. DATA and STACK remain guest
+ read/write. Reserved PTR64 selectors remain structurally valid pointer
+ values; non-dereferencing pointer arithmetic may preserve them, but any
+ operation requiring address-space meaning faults until a selector is
+ architecturally assigned. */
+
+extern int __cpu_ptr_make ( __mpu_uint64_t *ptr,
+ unsigned int segment,
+ __mpu_uint64_t offset );
+extern unsigned int __cpu_ptr_segment( __mpu_uint64_t ptr );
+extern __mpu_uint64_t __cpu_ptr_offset ( __mpu_uint64_t ptr );
+
+/***************************************************************
+ PROGRAM STATUS WORD.
+ ***************************************************************/
+#define PSW_AF_MASK __mpu_UINT32_C( 0x00000001 )
+#define PSW_CF_MASK __mpu_UINT32_C( 0x00000002 )
+#define PSW_OF_MASK __mpu_UINT32_C( 0x00000004 )
+#define PSW_SF_MASK __mpu_UINT32_C( 0x00000008 )
+#define PSW_PF_MASK __mpu_UINT32_C( 0x00000010 )
+#define PSW_ZF_MASK __mpu_UINT32_C( 0x00000020 )
+#define PSW_RF_MASK __mpu_UINT32_C( 0x00000040 )
+#define PSW_VF_MASK __mpu_UINT32_C( 0x00000080 )
+#define PSW_DOMF_MASK __mpu_UINT32_C( 0x00000100 )
+#define PSW_SNGF_MASK __mpu_UINT32_C( 0x00000200 )
+#define PSW_OVFF_MASK __mpu_UINT32_C( 0x00000400 )
+#define PSW_UDFF_MASK __mpu_UINT32_C( 0x00000800 )
+#define PSW_TLSF_MASK __mpu_UINT32_C( 0x00001000 )
+#define PSW_PLSF_MASK __mpu_UINT32_C( 0x00002000 )
+#define PSW_INDF_MASK __mpu_UINT32_C( 0x00004000 )
+#define PSW_INXF_MASK __mpu_UINT32_C( 0x00008000 )
+#define PSW_HF_MASK __mpu_UINT32_C( 0x00010000 )
+#define PSW_TF_MASK __mpu_UINT32_C( 0x00020000 )
+#define PSW_IF_MASK __mpu_UINT32_C( 0x00040000 )
+#define PSW_MODE_MASK __mpu_UINT32_C( 0x00180000 )
+/* Architectural arithmetic/status partition. The lower byte is the CPU
+ flag domain and the upper byte is the MPU mathematical flag domain. The
+ implementation-level PSW_MPU_MASK name is retained for the full LibMPU-backed
+ PSW[15:0] facade used by existing arithmetic primitives. */
+#define PSW_CPUF_MASK __mpu_UINT32_C( 0x000000ff )
+#define PSW_MPUF_MASK __mpu_UINT32_C( 0x0000ff00 )
+#define PSW_MPU_MASK __mpu_UINT32_C( 0x0000ffff )
+#define PSW_CPU_MASK __mpu_UINT32_C( 0x001f0000 )
+#define PSW_USED_MASK __mpu_UINT32_C( 0x001fffff )
+#define PSW_HF_SHIFT 16
+#define PSW_TF_SHIFT 17
+#define PSW_IF_SHIFT 18
+#define PSW_MODE_SHIFT 19
+
+/*
+ * Normal-function PSW calling convention.
+ *
+ * CALL/CALLP/RET themselves are PSW-neutral: they do not save, restore or
+ * modify PSW. The masks below describe the ABI contract across a normal
+ * function call.
+ *
+ * PSW[15:0] is the arithmetic/status domain and is caller-clobbered.
+ * PSW[7:0] is the CPU flag byte; PSW[15:8] is the MPU mathematical flag byte.
+ * TF, IF and MODE are persistent control state; a callee that changes any of
+ * them must restore the incoming value before an ordinary RET.
+ * HF is execution state, not a caller/callee-saved function value: HALT ends
+ * normal control flow, while CALL/CALLP/RET themselves leave HF unchanged.
+ */
+#define CPU_PSW_ABI_VOLATILE_STATUS_MASK PSW_MPU_MASK
+#define CPU_PSW_ABI_PERSISTENT_CONTROL_MASK \
+ (PSW_TF_MASK | PSW_IF_MASK | PSW_MODE_MASK)
+#define CPU_PSW_ABI_EXECUTION_STATE_MASK PSW_HF_MASK
+
+extern void __cpu_init( void );
+extern void __cpu_free_context( void );
+
+extern __mpu_uint64_t *__ptr_cpu_pc( void );
+extern __mpu_uint64_t *__ptr_cpu_sp( void );
+extern __mpu_uint64_t *__ptr_cpu_fp( void );
+extern __mpu_UNIT_t *__ptr_cpu_registers( void );
+#define __cpu_pc (*__ptr_cpu_pc())
+#define __cpu_sp (*__ptr_cpu_sp())
+#define __cpu_fp (*__ptr_cpu_fp())
+#define __cpu_registers (__ptr_cpu_registers())
+
+/***************************************************************
+ PHYSICAL REGISTER VIEWS.
+
+ REG24 machine encoding:
+
+ bits 23..20 : WIDTH code, 0..13 => 8..65536 bits
+ bits 19..0 : byte address; bit 19 is MBZ for the current
+ 512 KiB register file.
+
+ Source assembler uses r<bits>@addr for integer/real views and
+ c<bits>@addr for complex views. In both forms <bits> is the
+ PHYSICAL register width. A c64 view therefore contains two
+ real32 components and has exactly the same REG24 encoding as
+ r64 at the same address.
+ ***************************************************************/
+typedef struct __cpu_register cpu_register;
+struct __cpu_register
+{
+ unsigned int bits;
+ __mpu_uint32_t address;
+};
+
+extern __mpu_size_t __cpu_reg_size ( unsigned int bits );
+extern int __cpu_reg_valid( unsigned int bits, __mpu_uint32_t address );
+extern __mpu_UNIT_t *__cpu_reg_ptr ( unsigned int bits, __mpu_uint32_t address );
+
+/* Canonical ABI return register: addr = 0x80000 - physical_size. */
+extern int __cpu_return_reg ( cpu_register *reg, unsigned int bits );
+
+extern int __cpu_encode_reg24( __mpu_UNIT_t out[CPU_REG24_SIZE],
+ const cpu_register *reg );
+extern int __cpu_decode_reg24( cpu_register *reg,
+ const __mpu_UNIT_t in[CPU_REG24_SIZE] );
+
+/***************************************************************
+ PSW access.
+ ***************************************************************/
+extern __mpu_uint32_t __cpu_get_psw ( void );
+extern void __cpu_set_psw ( __mpu_uint32_t psw );
+extern void __cpu_clear_psw ( void );
+extern int __cpu_gth ( void );
+extern int __cpu_gtt ( void );
+extern int __cpu_gti ( void );
+extern void __cpu_sth ( void );
+extern void __cpu_stt ( void );
+extern void __cpu_sti ( void );
+extern void __cpu_clh ( void );
+extern void __cpu_clt ( void );
+extern void __cpu_cli ( void );
+extern void __cpu_cmh ( void );
+extern void __cpu_cmt ( void );
+extern void __cpu_cmi ( void );
+extern int __cpu_gtmode ( void );
+extern int __cpu_stmode ( unsigned int mode );
+
+/***************************************************************
+ ARCHITECTURAL MEMORY SPACES.
+
+ PROGRAM, DATA, STACK, CONTROL, INPUT, OUTPUT, TRACE and HEAP are
+ independent byte-addressable guest spaces backed by anonymous
+ mmap() mappings. Architectural bounds always use segment size,
+ never host page-rounded capacity. No guest segment is file-backed.
+
+ PROGRAM is host-protected read-only after loading. CONTROL and
+ INPUT remain host-writable so a runtime/supervisor can update them,
+ but guest STOREP/BMOV destinations to those spaces fault. OUTPUT,
+ TRACE and HEAP are guest read/write.
+
+ STACK grows toward lower addresses; an empty allocated stack has
+ SP == FP == stack_size.
+
+ HEAP is zero-filled runtime storage and has no assembler payload.
+ Offsets [0,CPU_HEAP_BEGIN) are reserved. The current API records
+ initial architectural size and a maximum limit. malloc/free are
+ library concerns; dynamic heap growth is intentionally reserved for
+ a future runtime/system-call ABI.
+ ***************************************************************/
+extern int __cpu_program_alloc ( __mpu_uint64_t size );
+extern void __cpu_program_free ( void );
+extern int __cpu_program_protect ( void );
+extern __mpu_UNIT_t *__cpu_program_ptr ( void );
+extern __mpu_uint64_t __cpu_program_size ( void );
+extern int __cpu_program_set ( const __mpu_UNIT_t *data,
+ __mpu_uint64_t size );
+extern int __cpu_data_alloc ( __mpu_uint64_t size );
+extern void __cpu_data_free ( void );
+extern __mpu_UNIT_t *__cpu_data_ptr ( void );
+extern __mpu_uint64_t __cpu_data_size ( void );
+extern int __cpu_data_set ( const __mpu_UNIT_t *data,
+ __mpu_uint64_t size );
+extern int __cpu_stack_alloc ( __mpu_uint64_t size );
+extern void __cpu_stack_free ( void );
+extern __mpu_UNIT_t *__cpu_stack_ptr ( void );
+extern __mpu_uint64_t __cpu_stack_size ( void );
+extern int __cpu_control_alloc ( __mpu_uint64_t size );
+extern void __cpu_control_free ( void );
+extern __mpu_UNIT_t *__cpu_control_ptr ( void );
+extern __mpu_uint64_t __cpu_control_size ( void );
+extern int __cpu_control_set ( const __mpu_UNIT_t *data, __mpu_uint64_t size );
+extern int __cpu_input_alloc ( __mpu_uint64_t size );
+extern void __cpu_input_free ( void );
+extern __mpu_UNIT_t *__cpu_input_ptr ( void );
+extern __mpu_uint64_t __cpu_input_size ( void );
+extern int __cpu_input_set ( const __mpu_UNIT_t *data, __mpu_uint64_t size );
+extern int __cpu_output_alloc ( __mpu_uint64_t size );
+extern void __cpu_output_free ( void );
+extern __mpu_UNIT_t *__cpu_output_ptr ( void );
+extern __mpu_uint64_t __cpu_output_size ( void );
+extern int __cpu_output_set ( const __mpu_UNIT_t *data, __mpu_uint64_t size );
+extern int __cpu_trace_alloc ( __mpu_uint64_t size );
+extern void __cpu_trace_free ( void );
+extern __mpu_UNIT_t *__cpu_trace_ptr ( void );
+extern __mpu_uint64_t __cpu_trace_size ( void );
+extern int __cpu_trace_set ( const __mpu_UNIT_t *data, __mpu_uint64_t size );
+extern int __cpu_heap_alloc ( __mpu_uint64_t initial_size, __mpu_uint64_t maximum_size );
+extern void __cpu_heap_free ( void );
+extern __mpu_UNIT_t *__cpu_heap_ptr ( void );
+extern __mpu_uint64_t __cpu_heap_size ( void );
+extern __mpu_uint64_t __cpu_heap_limit ( void );
+
+/***************************************************************
+ MACHINE OPCODES.
+
+ The opcode completely determines the number and kind of all
+ following operands. Multi-byte machine fields use canonical
+ MSB-first byte order.
+ ***************************************************************/
+typedef enum __cpu_opcode
+{
+ CPU_OP_NOP = 0x0000,
+ CPU_OP_HALT = 0x0001,
+ CPU_OP_END = 0x0002, /* end current externally managed execution phase */
+ CPU_OP_EXIT = 0x0003, /* r32 signed program/model exit status */
+ CPU_OP_SYSCALL = 0x0004, /* system call through fixed register ABI */
+
+ CPU_OP_SETF = 0x0010, /* set one writable PSW[15:0] flag */
+ CPU_OP_CLRF = 0x0011, /* clear one writable PSW[15:0] flag */
+ CPU_OP_CLRCPUF = 0x0012, /* clear CPU flag byte PSW[7:0] */
+ CPU_OP_CLRMPUF = 0x0013, /* clear MPU flag byte PSW[15:8] */
+
+ CPU_OP_MOV = 0x0100,
+ CPU_OP_CLR = 0x0101,
+ CPU_OP_SWAP = 0x0102,
+ CPU_OP_BSWAP = 0x0103, /* raw byte reversal: Rdst, Rsrc */
+ CPU_OP_LDI = 0x0110, /* R, signed integer64 immediate */
+ CPU_OP_LDR = 0x0111, /* R, IEEE binary64 immediate */
+ CPU_OP_LDC = 0x0112, /* R, 2 x IEEE binary32 */
+ CPU_OP_LOAD = 0x0120, /* R, DATA ADDR64 */
+ CPU_OP_STORE = 0x0121, /* DATA ADDR64, R */
+ CPU_OP_LEA = 0x0130, /* r64, PTR64 immediate */
+ CPU_OP_LEASP = 0x0131, /* r64, signed OFF64 -> PTR64 */
+ CPU_OP_LOADP = 0x0132, /* R/C, r64(PTR64) */
+ CPU_OP_STOREP = 0x0133, /* r64(PTR64), R/C */
+ CPU_OP_PADD = 0x0140, /* r64 = PTR64 + signed r64 */
+ CPU_OP_PADDI = 0x0141, /* r64 = PTR64 + signed OFF64 */
+ CPU_OP_PSUB = 0x0142, /* r64 = PTR64 - signed r64 */
+ CPU_OP_PSUBI = 0x0143, /* r64 = PTR64 - signed OFF64 */
+ CPU_OP_PDIFF = 0x0144, /* r64 = PTR64 - PTR64 bytes */
+ CPU_OP_BMOV = 0x0150, /* PTR64 dst, PTR64 src, r64 byte count */
+ CPU_OP_BMOVI = 0x0151, /* PTR64 dst, PTR64 src, IMM64 byte count */
+
+ CPU_OP_IADD = 0x1000,
+ CPU_OP_IADC = 0x1001,
+ CPU_OP_ISUB = 0x1002,
+ CPU_OP_ISBB = 0x1003,
+ CPU_OP_IAND = 0x1004,
+ CPU_OP_IOR = 0x1005,
+ CPU_OP_IXOR = 0x1006,
+ CPU_OP_INOT = 0x1010,
+ CPU_OP_INEG = 0x1011,
+ CPU_OP_ICMP = 0x1020,
+ CPU_OP_ITEST = 0x1021,
+
+ CPU_OP_ISHL = 0x1030, /* logical shift left by one bit */
+ CPU_OP_ISHR = 0x1031, /* logical shift right by one bit */
+ CPU_OP_ISAL = 0x1032, /* arithmetic shift left by one bit */
+ CPU_OP_ISAR = 0x1033, /* arithmetic shift right by one bit */
+ CPU_OP_IROL = 0x1034, /* rotate left by one bit */
+ CPU_OP_IROR = 0x1035, /* rotate right by one bit */
+ CPU_OP_IRCL = 0x1036, /* rotate left through CF by one bit */
+ CPU_OP_IRCR = 0x1037, /* rotate right through CF by one bit */
+
+ CPU_OP_ISHLN = 0x1040, /* Rdst,Rsrc,r64 count */
+ CPU_OP_ISHRN = 0x1041,
+ CPU_OP_ISALN = 0x1042,
+ CPU_OP_ISARN = 0x1043,
+ CPU_OP_IROLN = 0x1044,
+ CPU_OP_IRORN = 0x1045,
+ CPU_OP_IRCLN = 0x1046,
+ CPU_OP_IRCRN = 0x1047,
+
+ CPU_OP_IINC = 0x1050,
+ CPU_OP_IDEC = 0x1051,
+ CPU_OP_IXCHG = 0x1052,
+ CPU_OP_ICPY = 0x1053, /* width-changing unsigned copy */
+ CPU_OP_ICVT = 0x1054, /* width-changing signed conversion */
+
+ CPU_OP_IMUL = 0x1060, /* unsigned full product */
+ CPU_OP_ISMUL = 0x1061, /* signed full product */
+ CPU_OP_IDIV = 0x1062, /* quot,rem,num,den (unsigned) */
+ CPU_OP_ISDIV = 0x1063, /* quot,rem,num,den (signed) */
+ CPU_OP_IBITSLEN = 0x1064, /* r64 result, integer source */
+
+ CPU_OP_RADD = 0x2000,
+ CPU_OP_RSUB = 0x2001,
+ CPU_OP_RMUL = 0x2002,
+ CPU_OP_RDIV = 0x2003,
+ CPU_OP_RSQRT = 0x2010,
+ CPU_OP_RSIN = 0x2020,
+ CPU_OP_RCOS = 0x2021,
+ CPU_OP_RTAN = 0x2022,
+ CPU_OP_RASIN = 0x2023,
+ CPU_OP_RACOS = 0x2024,
+ CPU_OP_RATAN = 0x2025,
+ CPU_OP_RLOG = 0x2030,
+ CPU_OP_RLOG10 = 0x2031,
+ CPU_OP_RLOG2 = 0x2032,
+ CPU_OP_REXP = 0x2033,
+ CPU_OP_RSINH = 0x2040,
+ CPU_OP_RCOSH = 0x2041,
+ CPU_OP_RTANH = 0x2042,
+ CPU_OP_RPOW = 0x2050,
+ CPU_OP_RHYPOT = 0x2051,
+ CPU_OP_RATAN2 = 0x2052,
+
+ CPU_OP_RNEG = 0x2060,
+ CPU_OP_RABS = 0x2061,
+ CPU_OP_RCMP = 0x2062, /* r64 result {-2,-1,0,+1}, Ra, Rb */
+ CPU_OP_RCPY = 0x2063,
+ CPU_OP_RCVT = 0x2064,
+
+ CPU_OP_RFLOOR = 0x2070,
+ CPU_OP_RCEIL = 0x2071,
+ CPU_OP_RROUND = 0x2072,
+ CPU_OP_RFREXP = 0x2073, /* R significand, I exponent, R source */
+ CPU_OP_RLDEXP = 0x2074, /* R dst, R src, I exponent */
+ CPU_OP_RLOGB = 0x2075, /* I dst, R src */
+ CPU_OP_RMODF = 0x2076, /* R frac, R integer, R source */
+ CPU_OP_RREMAIN = 0x2077,
+
+ CPU_OP_RLOG1P = 0x2080,
+ CPU_OP_REXPM1 = 0x2081,
+ CPU_OP_RASINH = 0x2082,
+ CPU_OP_RACOSH = 0x2083,
+ CPU_OP_RATANH = 0x2084,
+
+ CPU_OP_ITOR = 0x2090, /* signed integer -> real */
+ CPU_OP_UITOR = 0x2091, /* unsigned integer -> real */
+ CPU_OP_RTOI = 0x2092, /* I dst, R frac, R src */
+ CPU_OP_RTOUI = 0x2093, /* UI dst, R frac, R src */
+
+ CPU_OP_RISNEG = 0x20a0, /* r64 predicate, R src */
+ CPU_OP_RSIGN = 0x20a1, /* r64 signed {-3..+1}, R src */
+ CPU_OP_RISIND = 0x20a2,
+ CPU_OP_RISNAN = 0x20a3,
+ CPU_OP_RISNANMAX = 0x20a4,
+ CPU_OP_RISNANMIN = 0x20a5,
+ CPU_OP_RISINF = 0x20a6,
+ CPU_OP_RISSIGNULL = 0x20a7,
+
+ CPU_OP_RCONST = 0x2100, /* R, CONST8 */
+
+ CPU_OP_CADD = 0x3000,
+ CPU_OP_CSUB = 0x3001,
+ CPU_OP_CMUL = 0x3002,
+ CPU_OP_CDIV = 0x3003,
+ CPU_OP_CEXP = 0x3020,
+ CPU_OP_CSIN = 0x3021,
+ CPU_OP_CCOS = 0x3022,
+ CPU_OP_CSINH = 0x3023,
+ CPU_OP_CCOSH = 0x3024,
+ CPU_OP_CLOG = 0x3025,
+ CPU_OP_CSQRT = 0x3026,
+ CPU_OP_CPOW = 0x3050,
+
+ CPU_OP_CREAL = 0x3060, /* R component dst, C src */
+ CPU_OP_CIMAG = 0x3061, /* R component dst, C src */
+ CPU_OP_CRTOC = 0x3062, /* C dst, R src */
+ CPU_OP_CGEN = 0x3063, /* C dst, R real, R imaginary */
+ CPU_OP_CPOLAR = 0x3064, /* C dst, R rho, R theta */
+ CPU_OP_CCONJ = 0x3065,
+ CPU_OP_CABS = 0x3066, /* R dst, C src */
+ CPU_OP_CNORM = 0x3067, /* R dst, C src */
+ CPU_OP_CARG = 0x3068, /* R dst, C src */
+
+ CPU_OP_CISEQ = 0x3070, /* r64 predicate, C a, C b */
+ CPU_OP_CISNE = 0x3071,
+ CPU_OP_CCPY = 0x3072,
+ CPU_OP_CCVT = 0x3073,
+
+ CPU_OP_JMP = 0x4000, /* CODE64 */
+ CPU_OP_JSET = 0x4001, /* PSWBIT8, CODE64 */
+ CPU_OP_JCLR = 0x4002, /* PSWBIT8, CODE64 */
+ CPU_OP_JMPP = 0x4003, /* r64(PROGRAM PTR64) */
+ CPU_OP_CALL = 0x4010, /* CODE64; push next PC */
+ CPU_OP_RET = 0x4011, /* pop PC from STACK */
+ CPU_OP_CALLP = 0x4012, /* r64(PROGRAM PTR64); push next PC */
+
+ CPU_OP_PUSH = 0x5000, /* R/C */
+ CPU_OP_POP = 0x5001, /* R/C */
+ CPU_OP_LDSP = 0x5010, /* R/C, signed OFF64 */
+ CPU_OP_STSP = 0x5011, /* signed OFF64, R/C */
+ CPU_OP_ADJSP = 0x5020, /* signed OFF64 */
+
+ CPU_OP_PUSHFP = 0x5030, /* push current 64-bit FP on STACK */
+ CPU_OP_SETFP = 0x5031, /* FP = SP */
+ CPU_OP_RESTSP = 0x5032, /* SP = FP */
+ CPU_OP_POPFP = 0x5033, /* pop 64-bit FP from STACK */
+
+ CPU_OP_LDFP = 0x5040, /* R/C, signed OFF64 relative to FP */
+ CPU_OP_STFP = 0x5041, /* signed OFF64 relative to FP, R/C */
+ CPU_OP_LEAFP = 0x5042, /* r64, signed OFF64 -> STACK PTR64 */
+
+ CPU_OP_SETSP = 0x5050 /* r64(STACK PTR64) -> SP */
+} cpu_opcode;
+
+
+
+/***************************************************************
+ PSW bit selectors used by JSET/JCLR and by writable-flag
+ instructions where explicitly permitted.
+
+ MODE is a multi-bit field and is intentionally not
+ addressable through JSET/JCLR. Branch selectors cover
+ individual bits 0..18. SETF/CLRF are restricted to bits
+ 0..15 by CPU_PSWBIT_WRITE_MAX.
+ ***************************************************************/
+typedef enum __cpu_psw_bit
+{
+ CPU_PSWBIT_AF = 0,
+ CPU_PSWBIT_CF = 1,
+ CPU_PSWBIT_OF = 2,
+ CPU_PSWBIT_SF = 3,
+ CPU_PSWBIT_PF = 4,
+ CPU_PSWBIT_ZF = 5,
+ CPU_PSWBIT_RF = 6,
+ CPU_PSWBIT_VF = 7,
+ CPU_PSWBIT_DOMF = 8,
+ CPU_PSWBIT_SNGF = 9,
+ CPU_PSWBIT_OVFF = 10,
+ CPU_PSWBIT_UDFF = 11,
+ CPU_PSWBIT_TLSF = 12,
+ CPU_PSWBIT_PLSF = 13,
+ CPU_PSWBIT_INDF = 14,
+ CPU_PSWBIT_INXF = 15,
+ CPU_PSWBIT_HF = 16,
+ CPU_PSWBIT_TF = 17,
+ CPU_PSWBIT_IF = 18
+} cpu_psw_bit;
+
+#define CPU_PSWBIT_MAX CPU_PSWBIT_IF
+#define CPU_PSWBIT_WRITE_MAX CPU_PSWBIT_INXF
+
+/***************************************************************
+ Predefined real mathematical constants for RCONST.
+ ***************************************************************/
+typedef enum __cpu_real_constant
+{
+ CPU_RCONST_ZERO = 0x00,
+ CPU_RCONST_HALF,
+ CPU_RCONST_ONE,
+ CPU_RCONST_TWO,
+ CPU_RCONST_TEN,
+ CPU_RCONST_MTEN,
+ CPU_RCONST_32,
+
+ CPU_RCONST_PI = 0x10,
+ CPU_RCONST_E,
+ CPU_RCONST_1_LN2,
+ CPU_RCONST_LN2,
+ CPU_RCONST_1_LN10,
+ CPU_RCONST_LN10,
+ CPU_RCONST_1_LG2,
+ CPU_RCONST_LG2,
+
+ CPU_RCONST_PI_2 = 0x20,
+ CPU_RCONST_PI_3,
+ CPU_RCONST_PI_4,
+ CPU_RCONST_PI_5,
+ CPU_RCONST_PI_6,
+ CPU_RCONST_1_PI,
+ CPU_RCONST_2_PI,
+ CPU_RCONST_3_PI,
+ CPU_RCONST_4_PI,
+ CPU_RCONST_5_PI,
+ CPU_RCONST_2PI,
+ CPU_RCONST_3PI,
+ CPU_RCONST_1_2PI,
+ CPU_RCONST_1_3PI,
+ CPU_RCONST_1_4PI,
+ CPU_RCONST_1_5PI,
+ CPU_RCONST_1_6PI,
+ CPU_RCONST_3PI_4,
+
+ CPU_RCONST_SQRTPI = 0x40,
+ CPU_RCONST_1_SQRTPI,
+ CPU_RCONST_2_SQRTPI,
+ CPU_RCONST_SQRT2,
+ CPU_RCONST_1_SQRT2,
+ CPU_RCONST_SQRT3,
+ CPU_RCONST_1_SQRT3,
+ CPU_RCONST_DEGREE,
+ CPU_RCONST_1_DEGREE,
+ CPU_RCONST_GOLDENRATIO,
+ CPU_RCONST_EULERGAMMA,
+ CPU_RCONST_CATALAN,
+
+ CPU_RCONST_EPSILON = 0x50,
+ CPU_RCONST_IND,
+ CPU_RCONST_PNAN,
+ CPU_RCONST_NNAN,
+ CPU_RCONST_PNANMAX,
+ CPU_RCONST_NNANMAX,
+ CPU_RCONST_PNANMIN,
+ CPU_RCONST_NNANMIN,
+ CPU_RCONST_PINF,
+ CPU_RCONST_NINF,
+ CPU_RCONST_PREALMIN,
+ CPU_RCONST_NREALMIN,
+ CPU_RCONST_PREALMAX,
+ CPU_RCONST_NREALMAX,
+ CPU_RCONST_PZERO,
+ CPU_RCONST_NZERO
+} cpu_real_constant;
+
+/***************************************************************
+ DECODED INSTRUCTION REPRESENTATION.
+ ***************************************************************/
+typedef enum __cpu_operand_type
+{
+ CPU_OPERAND_NONE = 0,
+ CPU_OPERAND_REGISTER,
+ CPU_OPERAND_IMM64,
+ CPU_OPERAND_ADDR64,
+ CPU_OPERAND_CODE64,
+ CPU_OPERAND_OFF64,
+ CPU_OPERAND_CONST8,
+ CPU_OPERAND_PSWBIT8,
+ CPU_OPERAND_PTR64
+} cpu_operand_type;
+
+#define CPU_OPERAND_IMMEDIATE CPU_OPERAND_IMM64
+
+typedef struct __cpu_operand cpu_operand;
+struct __cpu_operand
+{
+ cpu_operand_type type;
+ union
+ {
+ cpu_register reg;
+ __mpu_uint64_t imm64;
+ __mpu_uint64_t addr64;
+ __mpu_uint64_t code64;
+ __mpu_int64_t off64;
+ __mpu_uint8_t const8;
+ __mpu_uint8_t pswbit8;
+ __mpu_uint64_t ptr64;
+ } value;
+};
+
+#define CPU_INSTRUCTION_MAX_OPERANDS 4
+
+typedef struct __cpu_instruction cpu_instruction;
+struct __cpu_instruction
+{
+ cpu_opcode opcode;
+ cpu_operand operand[CPU_INSTRUCTION_MAX_OPERANDS];
+ __mpu_uint64_t length;
+};
+
+#define CPU_EXEC_SUCCESS 0
+#define CPU_EXEC_INSTRUCTION_FAULT -1
+#define CPU_EXEC_OPCODE_FAULT -2
+#define CPU_EXEC_OPERAND_FAULT -3
+#define CPU_EXEC_REGISTER_FAULT -4
+#define CPU_EXEC_WIDTH_FAULT -5
+#define CPU_EXEC_MEMORY_FAULT -6
+#define CPU_EXEC_DECODE_FAULT -7
+#define CPU_EXEC_STACK_FAULT -8
+#define CPU_EXEC_POINTER_FAULT -9
+#define CPU_EXEC_HALT 1
+#define CPU_EXEC_BRANCH 2
+#define CPU_EXEC_END 3
+#define CPU_EXEC_EXIT 4
+
+typedef enum __cpu_stop_reason
+{
+ CPU_STOP_NONE = 0,
+ CPU_STOP_END,
+ CPU_STOP_EXIT,
+ CPU_STOP_HALT,
+ CPU_STOP_TRAP,
+ CPU_STOP_FAULT,
+ CPU_STOP_KILLED
+} cpu_stop_reason;
+
+extern cpu_stop_reason __cpu_get_stop_reason( void );
+extern __mpu_int32_t __cpu_get_exit_status( void );
+extern void __cpu_clear_stop_reason( void );
+
+extern int __cpu_exec ( const cpu_instruction *instruction );
+extern int __cpu_decode_at( const __mpu_UNIT_t *program,
+ __mpu_uint64_t program_size,
+ __mpu_uint64_t pc,
+ cpu_instruction *instruction );
+extern int __cpu_decode ( cpu_instruction *instruction );
+extern int __cpu_step ( void );
+extern int __cpu_run ( void );
+
+#ifdef __cplusplus
+} /* ... extern "C" */
+#endif
+
+#endif /* __LIB_MCPU_H */