zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 17e0afd0e5d8850171bdfeba9456ebfd38d11e3a (tree)
parent d092c752f3e2e0e162e9bab57d3f84de6ccde7c9
Author: Sam Connelly <myclevorname@gmail.com>
Date:   Thu, 12 Mar 2026 09:04:39 -0400

feat: init eZ80 arch via CBE

Diffstat:
Mlib/compiler/translate-c/Translator.zig | 4++++
Mlib/std/Target.zig | 53++++++++++++++++++++++++++++++++++++++++++++++++++---
Mlib/std/builtin.zig | 4++++
Mlib/zig.h | 341++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/Type.zig | 3+++
Msrc/Zcu.zig | 5+++++
Msrc/codegen/c.zig | 23+++++++++++++++++++++++
Msrc/codegen/c/type.zig | 27+++++++++++++++++++++++++--
Msrc/codegen/llvm.zig | 8+++++++-
Msrc/target.zig | 4++++
10 files changed, 465 insertions(+), 7 deletions(-)

diff --git a/lib/compiler/translate-c/Translator.zig b/lib/compiler/translate-c/Translator.zig @@ -475,8 +475,12 @@ pub const builtin_typedef_map = std.StaticStringMap([]const u8).initComptime(.{ .{ "int8_t", "i8" }, .{ "uint16_t", "u16" }, .{ "int16_t", "i16" }, + .{ "uint24_t", "u24" }, + .{ "int24_t", "i24" }, .{ "uint32_t", "u32" }, .{ "int32_t", "i32" }, + .{ "uint48_t", "u48" }, + .{ "int48_t", "i48" }, .{ "uint64_t", "u64" }, .{ "int64_t", "i64" }, .{ "intptr_t", "isize" }, diff --git a/lib/std/Target.zig b/lib/std/Target.zig @@ -68,6 +68,8 @@ pub const Os = struct { opengl, vulkan, + tios, + // LLVM tags deliberately omitted: // - bridgeos // - cheriotrtos @@ -207,6 +209,8 @@ pub const Os = struct { .opencl, .opengl, .vulkan, + + .tios, => .semver, .hurd => .hurd, @@ -670,6 +674,12 @@ pub const Os = struct { .max = .{ .major = 4, .minor = 6, .patch = 0 }, }, }, + .tios => .{ + .semver = .{ + .min = .{ .major = 5, .minor = 0, .patch = 0 }, + .max = .{ .major = 5, .minor = 8, .patch = 4 }, + }, + }, .vulkan => .{ .semver = .{ .min = .{ .major = 1, .minor = 2, .patch = 0 }, @@ -758,6 +768,7 @@ pub const wasm = @import("Target/wasm.zig"); pub const x86 = @import("Target/x86.zig"); pub const xcore = @import("Target/xcore.zig"); pub const xtensa = @import("Target/xtensa.zig"); +pub const z80 = @import("Target/generic.zig"); pub const Abi = enum { none, @@ -942,6 +953,7 @@ pub const Abi = enum { .opencl, .opengl, .vulkan, + .tios, => .none, }; } @@ -1068,6 +1080,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM { .avr => .AVR, .bpfeb, .bpfel => .BPF, .csky => .CSKY, + .ez80 => .Z80, .hexagon => .QDSP6, .hppa, .hppa64 => .PARISC, .kalimba => .CSR_KALIMBA, @@ -1130,6 +1143,7 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE { .bpfeb, .bpfel, .csky, + .ez80, .hexagon, .hppa, .hppa64, @@ -1336,6 +1350,7 @@ pub const Cpu = struct { bpfeb, bpfel, csky, + ez80, hexagon, hppa, hppa64, @@ -1437,6 +1452,7 @@ pub const Cpu = struct { x86, xcore, xtensa, + z80, }; pub inline fn family(arch: Arch) Family { @@ -1449,6 +1465,7 @@ pub const Cpu = struct { .avr => .avr, .bpfeb, .bpfel => .bpf, .csky => .csky, + .ez80 => .z80, .hexagon => .hexagon, .hppa, .hppa64 => .hppa, .kalimba => .kalimba, @@ -1678,6 +1695,7 @@ pub const Cpu = struct { .x86_64, .xcore, .xtensa, + .ez80, => .little, .aarch64_be, @@ -1948,6 +1966,10 @@ pub const Cpu = struct { .spirv_fragment, .spirv_vertex, => &.{ .spirv32, .spirv64 }, + + .ez80_cet, + .ez80_tiflags, + => &.{.ez80}, }; } }; @@ -2236,6 +2258,7 @@ pub fn requiresLibC(target: *const Target) bool { .plan9, .other, .@"3ds", + .tios, => false, }; } @@ -2398,6 +2421,8 @@ pub const DynamicLinker = struct { .ps5, .psp, .vita, + + .tios, => .none, }; } @@ -2815,6 +2840,8 @@ pub const DynamicLinker = struct { .opencl, .opengl, .vulkan, + + .tios, => none, // TODO go over each item in this list and either move it to the above list, or @@ -2849,6 +2876,9 @@ pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 { .x86_16, => 16, + .ez80, + => 24, + .arc, .arceb, .arm, @@ -2917,6 +2947,8 @@ pub fn ptrBitWidth(target: *const Target) u16 { pub fn stackAlignment(target: *const Target) u16 { // Overrides for when the stack alignment is not equal to the pointer width. switch (target.cpu.arch) { + .ez80, + => return 1, .m68k, => return 2, .amdgcn, @@ -2997,6 +3029,7 @@ pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { .arc, .arceb, .csky, + .ez80, .hexagon, .msp430, .powerpc, @@ -3364,6 +3397,13 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { .long, .ulong => return 64, .longlong, .ulonglong, .double, .longdouble => return 64, }, + .tios => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint => return 24, + .long, .ulong, .float, .double => return 32, + .longlong, .ulonglong, .longdouble => return 64, + }, .ps3, .contiki, @@ -3376,7 +3416,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { // Overrides for unusual alignments switch (target.cpu.arch) { - .avr => return 1, + .avr, .ez80 => return 1, .x86 => switch (target.os.tag) { .windows, .uefi => switch (c_type) { .longlong, .ulonglong, .double => return 8, @@ -3406,6 +3446,8 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { return @min( std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8), @as(u16, switch (target.cpu.arch) { + .ez80 => 1, + .msp430, .x86_16, => 2, @@ -3484,7 +3526,7 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { .longdouble => return 4, else => {}, }, - .avr => return 1, + .avr, .ez80 => return 1, .x86 => switch (target.os.tag) { .windows, .uefi => switch (c_type) { .longdouble => switch (target.abi) { @@ -3516,6 +3558,8 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { return @min( std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8), @as(u16, switch (target.cpu.arch) { + .ez80 => 1, + .x86_16, .msp430 => 2, .arc, @@ -3587,7 +3631,9 @@ pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { pub fn cMaxIntAlignment(target: *const Target) u16 { return switch (target.cpu.arch) { - .avr => 1, + .avr, + .ez80, + => 1, .msp430, .x86_16 => 2, @@ -3726,6 +3772,7 @@ pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention .amdgcn => .{ .amdgcn_device = .{} }, .nvptx, .nvptx64 => .nvptx_device, .spirv32, .spirv64 => .spirv_device, + .ez80 => .ez80_cet, }; } diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig @@ -341,6 +341,10 @@ pub const CallingConvention = union(enum(u8)) { spirv_fragment, spirv_vertex, + // Calling conventions for the `ez80` architecture. + ez80_cet, + ez80_tiflags, + /// Options shared across most calling conventions. pub const CommonOptions = struct { /// The boundary the stack is aligned to when the function is called. diff --git a/lib/zig.h b/lib/zig.h @@ -79,6 +79,9 @@ #elif defined(__I86__) #define zig_x86_16 #define zig_x86 +#elif defined (__ez80) +#define zig_ez80 +#define zig_z80 #endif #if defined(zig_msvc) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ @@ -409,6 +412,8 @@ #define zig_trap() __asm__ volatile("int $0x3") #elif defined(zig_x86) #define zig_trap() __asm__ volatile("ud2") +#elif defined(zig_z80) +#define zig_trap() __asm__ volatile("rst 00h") #else #define zig_trap() zig_trap_unavailable #endif @@ -511,7 +516,7 @@ zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); zig_extern void *memset (void *, int, size_t); zig_extern void *memmove (void *, void const *, size_t); -/* ================ Bool and 8/16/32/64-bit Integer Support ================= */ +/* ================ Bool and 8/16/24/32/48/64-bit Integer Support ================= */ #include <limits.h> @@ -590,6 +595,16 @@ typedef signed long long int16_t; #define INT16_MAX ( INT16_C(0x7FFF)) #define UINT16_MAX ( INT16_C(0xFFFF)) +#if defined(zig_ez80) +typedef unsigned int uint24_t; +typedef signed int int24_t; +#define INT24_C(c) c +#define UINT24_C(c) c##U +#endif +#define INT24_MIN (~INT24_C(0x7FFF)) +#define INT24_MAX ( INT24_C(0x7FFF)) +#define UINT24_MAX ( INT24_C(0xFFFF)) + #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF typedef unsigned char uint32_t; typedef signed char int32_t; @@ -620,6 +635,17 @@ typedef signed long long int32_t; #define INT32_MAX ( INT32_C(0x7FFFFFFF)) #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) +#if defined(zig_ez80) +typedef unsigned __int48 uint48_t; +typedef signed __int48 int48_t; +#define INT48_C(c) c +/* no suffix */ +#define UINT48_C(c) ((uint48_t)(c)) +#endif +#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) +#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) +#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) + #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF typedef unsigned char uint64_t; typedef signed char int64_t; @@ -663,10 +689,18 @@ typedef ptrdiff_t intptr_t; #define zig_maxInt_i16 INT16_MAX #define zig_minInt_u16 UINT16_C(0) #define zig_maxInt_u16 UINT16_MAX +#define zig_minInt_i24 INT24_MIN +#define zig_maxInt_i24 INT24_MAX +#define zig_minInt_u24 UINT24_C(0) +#define zig_maxInt_u24 UINT24_MAX #define zig_minInt_i32 INT32_MIN #define zig_maxInt_i32 INT32_MAX #define zig_minInt_u32 UINT32_C(0) #define zig_maxInt_u32 UINT32_MAX +#define zig_minInt_i48 INT48_MIN +#define zig_maxInt_i48 INT48_MAX +#define zig_minInt_u48 UINT48_C(0) +#define zig_maxInt_u48 UINT48_MAX #define zig_minInt_i64 INT64_MIN #define zig_maxInt_i64 INT64_MAX #define zig_minInt_u64 UINT64_C(0) @@ -786,6 +820,17 @@ zig_int_helpers(16, unsigned long long) #else zig_int_helpers(16, uint16_t) #endif +#if defined(zig_ez80) +#if UINT24_MAX <= UINT_MAX +zig_int_helpers(24, unsigned int) +#elif UINT24_MAX <= ULONG_MAX +zig_int_helpers(24, unsigned long) +#elif UINT24_MAX <= ULLONG_MAX +zig_int_helpers(24, unsigned long long) +#else +zig_int_helpers(24, uint24_t) +#endif +#endif #if UINT32_MAX <= UINT_MAX zig_int_helpers(32, unsigned int) #elif UINT32_MAX <= ULONG_MAX @@ -795,6 +840,17 @@ zig_int_helpers(32, unsigned long long) #else zig_int_helpers(32, uint32_t) #endif +#if defined(zig_ez80) +#if UINT24_MAX <= UINT_MAX +zig_int_helpers(48, unsigned int) +#elif UINT24_MAX <= ULONG_MAX +zig_int_helpers(48, unsigned long) +#elif UINT24_MAX <= ULLONG_MAX +zig_int_helpers(48, unsigned long long) +#else +zig_int_helpers(48, uint48_t) +#endif +#endif #if UINT64_MAX <= UINT_MAX zig_int_helpers(64, unsigned int) #elif UINT64_MAX <= ULONG_MAX @@ -909,6 +965,66 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #endif } +#if defined(zig_ez80) +static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { +#if zig_has_builtin(add_overflow) || defined(zig_gcc) + uint24_t full_res; + bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_wrap_u24(full_res, bits); + return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); +#else + uint32_t full_res; + bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); + *res = (uint24_t)full_res; + return overflow; +#endif +} + +static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t bits) { +#if zig_has_builtin(add_overflow) || defined(zig_gcc) + int24_t full_res; + bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_wrap_i24(full_res, bits); + return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); +#else + int32_t full_res; + bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); + *res = (int24_t)full_res; + return overflow; +#endif +} +#endif + +#if defined(zig_ez80) +static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { +#if zig_has_builtin(add_overflow) || defined(zig_gcc) + uint48_t full_res; + bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_wrap_u48(full_res, bits); + return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); +#else + uint64_t full_res; + bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits); + *res = (uint48_t)full_res; + return overflow; +#endif +} + +static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t bits) { +#if zig_has_builtin(add_overflow) || defined(zig_gcc) + int48_t full_res; + bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_wrap_i48(full_res, bits); + return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); +#else + int64_t full_res; + bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits); + *res = (int48_t)full_res; + return overflow; +#endif +} +#endif + static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint32_t full_res; @@ -933,6 +1049,7 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } + static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint64_t full_res; @@ -1013,6 +1130,66 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #endif } +#if defined(zig_ez80) +static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) + uint24_t full_res; + bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_wrap_u24(full_res, bits); + return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); +#else + uint32_t full_res; + bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); + *res = (uint24_t)full_res; + return overflow; +#endif +} + +static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t bits) { +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) + int24_t full_res; + bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_wrap_i24(full_res, bits); + return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); +#else + int32_t full_res; + bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); + *res = (int24_t)full_res; + return overflow; +#endif +} +#endif + +#if defined(zig_ez80) +static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) + uint48_t full_res; + bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_wrap_u48(full_res, bits); + return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); +#else + uint64_t full_res; + bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits); + *res = (uint48_t)full_res; + return overflow; +#endif +} + +static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t bits) { +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) + int48_t full_res; + bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_wrap_i48(full_res, bits); + return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); +#else + int64_t full_res; + bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits); + *res = (int48_t)full_res; + return overflow; +#endif +} +#endif + static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint32_t full_res; @@ -1121,6 +1298,66 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #endif } +#if defined(zig_ez80) +static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) + uint24_t full_res; + bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); + *res = zig_wrap_u24(full_res, bits); + return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); +#else + uint32_t full_res; + bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); + *res = (uint24_t)full_res; + return overflow; +#endif +} + +static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t bits) { +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) + int24_t full_res; + bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); + *res = zig_wrap_i24(full_res, bits); + return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); +#else + int32_t full_res; + bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); + *res = (int24_t)full_res; + return overflow; +#endif +} +#endif + +#if defined(zig_ez80) +static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) + uint48_t full_res; + bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); + *res = zig_wrap_u48(full_res, bits); + return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); +#else + uint64_t full_res; + bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits); + *res = (uint48_t)full_res; + return overflow; +#endif +} + +static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t bits) { +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) + int48_t full_res; + bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); + *res = zig_wrap_i48(full_res, bits); + return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); +#else + int64_t full_res; + bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits); + *res = (int48_t)full_res; + return overflow; +#endif +} +#endif + #define zig_int_builtins(w) \ static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ *res = zig_shlw_u##w(lhs, rhs, bits); \ @@ -1180,7 +1417,13 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t } zig_int_builtins(8) zig_int_builtins(16) +#if defined(zig_ez80) +zig_int_builtins(24) +#endif zig_int_builtins(32) +#if defined(zig_ez80) +zig_int_builtins(48) +#endif zig_int_builtins(64) #define zig_builtin8(name, val) __builtin_##name(val) @@ -1189,6 +1432,11 @@ typedef unsigned int zig_Builtin8; #define zig_builtin16(name, val) __builtin_##name(val) typedef unsigned int zig_Builtin16; +#if defined(zig_ez80) +#define zig_builtin24(name, val) __builtin_##name(val) +typedef unsigned int zig_Builtin24; +#endif + #if INT_MIN <= INT32_MIN #define zig_builtin32(name, val) __builtin_##name(val) typedef unsigned int zig_Builtin32; @@ -1197,6 +1445,11 @@ typedef unsigned int zig_Builtin32; typedef unsigned long zig_Builtin32; #endif +#if defined(zig_ez80) +#define zig_builtin48(name, val) __builtin_##name(val) +typedef unsigned long long zig_Builtin48; +#endif + #if INT_MIN <= INT64_MIN #define zig_builtin64(name, val) __builtin_##name(val) typedef unsigned int zig_Builtin64; @@ -1231,6 +1484,23 @@ static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); } +#if defined(zig_ez80) +static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { + uint24_t full_res; +#if zig_has_builtin(bswap24) || defined(zig_gcc) + full_res = __builtin_bswap24(val); +#else + full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | + (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; +#endif + return zig_wrap_u24(full_res >> (24 - bits), bits); +} + +static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { + return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); +} +#endif + static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bswap32) || defined(zig_gcc) @@ -1246,6 +1516,23 @@ static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); } +#if defined(zig_ez80) +static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { + uint48_t full_res; +#if zig_has_builtin(bswap48) || defined(zig_gcc) + full_res = __builtin_bswap48(val); +#else + full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | + (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; +#endif + return zig_wrap_u48(full_res >> (48 - bits), bits); +} + +static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { + return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); +} +#endif + static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bswap64) || defined(zig_gcc) @@ -1294,6 +1581,23 @@ static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); } +#if defined(zig_ez80) +static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { + uint24_t full_res; +#if zig_has_builtin(bitreverse24) + full_res = __builtin_bitreverse24(val); +#else + full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | + (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; +#endif + return zig_wrap_u24(full_res >> (24 - bits), bits); +} + +static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { + return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); +} +#endif + static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bitreverse32) @@ -1309,6 +1613,23 @@ static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); } +#if defined(zig_ez80) +static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { + uint48_t full_res; +#if zig_has_builtin(bitreverse48) + full_res = __builtin_bitreverse48(val); +#else + full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | + (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; +#endif + return zig_wrap_u32(full_res >> (48 - bits), bits); +} + +static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { + return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); +} +#endif + static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bitreverse64) @@ -1350,7 +1671,13 @@ static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { #endif zig_builtin_popcount(8) zig_builtin_popcount(16) +#if defined(zig_ez80) +zig_builtin_popcount(24) +#endif zig_builtin_popcount(32) +#if defined(zig_ez80) +zig_builtin_popcount(48) +#endif zig_builtin_popcount(64) #define zig_builtin_ctz_common(w) \ @@ -1375,7 +1702,13 @@ zig_builtin_popcount(64) #endif zig_builtin_ctz(8) zig_builtin_ctz(16) +#if defined(zig_ez80) +zig_builtin_ctz(24) +#endif zig_builtin_ctz(32) +#if defined(zig_ez80) +zig_builtin_ctz(48) +#endif zig_builtin_ctz(64) #define zig_builtin_clz_common(w) \ @@ -1400,7 +1733,13 @@ zig_builtin_ctz(64) #endif zig_builtin_clz(8) zig_builtin_clz(16) +#if defined(zig_ez80) +zig_builtin_clz(24) +#endif zig_builtin_clz(32) +#if defined(zig_ez80) +zig_builtin_clz(48) +#endif zig_builtin_clz(64) /* ======================== 128-bit Integer Support ========================= */ diff --git a/src/Type.zig b/src/Type.zig @@ -1204,6 +1204,9 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { } pub fn ptrAbiAlignment(target: *const Target) Alignment { + // The eZ80 has 24-bit pointers, which aren't exact powers of two, tripping + // the assert. The alignment of eZ80 pointers is 1, so we bypass the check. + if (target.cpu.arch == .ez80) return .@"1"; return .fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); } pub fn ptrAbiSize(target: *const Target) u64 { diff --git a/src/Zcu.zig b/src/Zcu.zig @@ -4022,6 +4022,9 @@ pub fn atomicPtrAlignment( ) AtomicPtrAlignmentError!Alignment { const target = zcu.getTarget(); const max_atomic_bits: u16 = switch (target.cpu.arch) { + .ez80, + => 8, + .aarch64, .aarch64_be, => 128, @@ -4615,6 +4618,8 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu .avr_signal, => true, + .ez80_tiflags => true, + .naked => true, else => false, diff --git a/src/codegen/c.zig b/src/codegen/c.zig @@ -248,7 +248,9 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ .{ "inline", {} }, .{ "int", {} }, .{ "int16_t", {} }, + .{ "int24_t", {} }, .{ "int32_t", {} }, + .{ "int48_t", {} }, .{ "int64_t", {} }, .{ "int8_t", {} }, .{ "intptr_t", {} }, @@ -270,7 +272,9 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ .{ "typedef", {} }, .{ "typeof", {} }, .{ "uint16_t", {} }, + .{ "uint24_t", {} }, .{ "uint32_t", {} }, + .{ "uint48_t", {} }, .{ "uint64_t", {} }, .{ "uint8_t", {} }, .{ "uintptr_t", {} }, @@ -6992,6 +6996,9 @@ fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 .x86_64_interrupt, => "interrupt", + .ez80_tiflags, + => "__tiflags__", + else => unreachable, // `Zcu.callconvSupported` }; } @@ -7285,7 +7292,9 @@ const FormatInt128 = struct { switch (data.int_cty) { .uint8_t, .uint16_t, + .uint24_t, .uint32_t, + .uint48_t, .uint64_t, .@"unsigned short", .@"unsigned int", @@ -7298,6 +7307,8 @@ const FormatInt128 = struct { .int8_t, .int16_t, + .int24_t, + .int48_t, .int32_t, .int64_t, .char, @@ -7443,13 +7454,17 @@ fn minMaxMacroPrefix(int_cty: CType.Int) []const u8 { .uint8_t => "UINT8", .uint16_t => "UINT16", + .uint24_t => "UINT24", .uint32_t => "UINT32", + .uint48_t => "UINT48", .uint64_t => "UINT64", .zig_u128 => unreachable, .int8_t => "INT8", .int16_t => "INT16", + .int24_t => "INT24", .int32_t => "INT32", + .int48_t => "INT48", .int64_t => "INT64", .zig_i128 => unreachable, @@ -7475,13 +7490,17 @@ fn intLiteralPrefix(cty: CType.Int, is_global: bool) []const u8 { .uint8_t => "UINT8_C(", .uint16_t => "UINT16_C(", + .uint24_t => "UINT24_C(", .uint32_t => "UINT32_C(", + .uint48_t => "UINT48_C(", .uint64_t => "UINT64_C(", .zig_u128 => unreachable, .int8_t => "INT8_C(", .int16_t => "INT16_C(", + .int24_t => "INT24_C(", .int32_t => "INT32_C(", + .int48_t => "INT48_C(", .int64_t => "INT64_C(", .zig_i128 => unreachable, @@ -7507,13 +7526,17 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 { .uint8_t => ")", .uint16_t => ")", + .uint24_t => ")", .uint32_t => ")", + .uint48_t => ")", .uint64_t => ")", .zig_u128 => unreachable, .int8_t => ")", .int16_t => ")", + .int24_t => ")", .int32_t => ")", + .int48_t => ")", .int64_t => ")", .zig_i128 => unreachable, diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig @@ -106,13 +106,21 @@ pub const CType = union(enum) { uint8_t, uint16_t, + /// eZ80-specific + uint24_t, uint32_t, + /// eZ80-specific + uint48_t, uint64_t, zig_u128, int8_t, int16_t, + /// eZ80-specific + int24_t, int32_t, + /// eZ80-specific + int48_t, int64_t, zig_i128, @@ -138,7 +146,9 @@ pub const CType = union(enum) { .uint8_t, .int8_t => 8, .uint16_t, .int16_t => 16, + .uint24_t, .int24_t => 24, .uint32_t, .int32_t => 32, + .uint48_t, .int48_t => 48, .uint64_t, .int64_t => 64, .zig_u128, .zig_i128 => 128, // zig fmt: on @@ -154,6 +164,7 @@ pub const CType = union(enum) { pub const LimbSize = enum { @"8", @"16", + @"24", @"32", @"64", @"128", @@ -161,6 +172,7 @@ pub const CType = union(enum) { return switch (s) { .@"8" => 8, .@"16" => 16, + .@"24" => 24, .@"32" => 32, .@"64" => 64, .@"128" => 128, @@ -170,6 +182,7 @@ pub const CType = union(enum) { return switch (s) { .@"8" => .uint8_t, .@"16" => .uint16_t, + .@"24" => .uint24_t, .@"32" => .uint32_t, .@"64" => .uint64_t, .@"128" => .zig_u128, @@ -179,6 +192,7 @@ pub const CType = union(enum) { return switch (s) { .@"8" => .int8_t, .@"16" => .int16_t, + .@"24" => .int24_t, .@"32" => .int32_t, .@"64" => .int64_t, .@"128" => .zig_i128, @@ -499,6 +513,7 @@ pub const CType = union(enum) { } } fn classifyBitInt(signedness: std.builtin.Signedness, bits: u16, zcu: *const Zcu) IntClass { + const is_ez80 = zcu.getTarget().cpu.arch == .ez80; return switch (bits) { 0 => .void, 1...8 => switch (signedness) { @@ -509,11 +524,19 @@ pub const CType = union(enum) { .unsigned => .{ .small = .uint16_t }, .signed => .{ .small = .int16_t }, }, - 17...32 => switch (signedness) { + 17...24 => switch (signedness) { + .unsigned => .{ .small = if (is_ez80) .uint24_t else .uint32_t }, + .signed => .{ .small = if (is_ez80) .int24_t else .int32_t }, + }, + 25...32 => switch (signedness) { .unsigned => .{ .small = .uint32_t }, .signed => .{ .small = .int32_t }, }, - 33...64 => switch (signedness) { + 33...48 => switch (signedness) { + .unsigned => .{ .small = if (is_ez80) .uint48_t else .uint64_t }, + .signed => .{ .small = if (is_ez80) .int48_t else .int64_t }, + }, + 49...64 => switch (signedness) { .unsigned => .{ .small = .uint64_t }, .signed => .{ .small = .int64_t }, }, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig @@ -107,6 +107,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 .alpha, .arceb, + .ez80, .hppa, .hppa64, .kalimba, @@ -244,6 +245,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 .other, .plan9, .psp, + .tios, .vita, => "unknown", }; @@ -473,6 +475,7 @@ pub fn dataLayout(target: *const std.Target) []const u8 { .alpha, .arceb, + .ez80, .hppa, .hppa64, .kalimba, @@ -1365,7 +1368,7 @@ pub const Object = struct { for (0..field_types.len, llvm_args_start..) |field_i, llvm_arg_index| { const param = wip.arg(@intCast(llvm_arg_index)); const field_ptr = try wip.gepStruct(llvm_ty, arg_ptr, field_i, ""); - const alignment: Builder.Alignment = .fromByteUnits(@divExact(target.ptrBitWidth(), 8)); + const alignment = Type.ptrAbiAlignment(target).toLlvm(); _ = try wip.store(.normal, param, field_ptr, alignment); } @@ -4506,6 +4509,8 @@ pub fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *con .avr_gnu, .bpf_std, .csky_sysv, + .ez80_cet, + .ez80_tiflags, .hexagon_sysv, .hexagon_sysv_hvx, .hppa_elf, @@ -4903,6 +4908,7 @@ pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { // LLVM does does not have a backend for these. .alpha, .arceb, + .ez80, .hppa, .hppa64, .kalimba, diff --git a/src/target.zig b/src/target.zig @@ -234,6 +234,10 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat) .xtensa, => false, + // Third-party LLVM backend exists. + .ez80, + => false, + // No LLVM backend exists. .alpha, .arceb,