mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
parent
f4f4460e17
commit
2543e2d97c
7 changed files with 1024 additions and 214 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -575,22 +575,22 @@ const RegisterBitSet = RegisterManager.RegisterBitSet;
|
|||
pub const RegisterClass = struct {
|
||||
pub const gp: RegisterBitSet = blk: {
|
||||
var set = RegisterBitSet.initEmpty();
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.class() == .general_purpose) set.set(index);
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.isClass(.general_purpose)) set.set(index);
|
||||
break :blk set;
|
||||
};
|
||||
pub const gphi: RegisterBitSet = blk: {
|
||||
var set = RegisterBitSet.initEmpty();
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.hasHi8()) set.set(index);
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.isClass(.gphi)) set.set(index);
|
||||
break :blk set;
|
||||
};
|
||||
pub const x87: RegisterBitSet = blk: {
|
||||
var set = RegisterBitSet.initEmpty();
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.class() == .x87) set.set(index);
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.isClass(.x87)) set.set(index);
|
||||
break :blk set;
|
||||
};
|
||||
pub const sse: RegisterBitSet = blk: {
|
||||
var set = RegisterBitSet.initEmpty();
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.class() == .sse) set.set(index);
|
||||
for (allocatable_regs, 0..) |reg, index| if (reg.isClass(.sse)) set.set(index);
|
||||
break :blk set;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -429,6 +429,16 @@ pub const Register = enum(u8) {
|
|||
};
|
||||
}
|
||||
|
||||
pub inline fn isClass(reg: Register, rc: Class) bool {
|
||||
switch (rc) {
|
||||
else => return reg.class() == rc,
|
||||
.gphi => {
|
||||
const reg_id = reg.id();
|
||||
return (reg_id >= comptime Register.ah.id()) and reg_id <= comptime Register.bh.id();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(reg: Register) u7 {
|
||||
const base = switch (@intFromEnum(reg)) {
|
||||
// zig fmt: off
|
||||
|
|
@ -615,22 +625,17 @@ pub const Register = enum(u8) {
|
|||
}
|
||||
|
||||
pub fn toHi8(reg: Register) Register {
|
||||
assert(reg.hasHi8());
|
||||
assert(reg.isClass(.gphi));
|
||||
return @enumFromInt(@intFromEnum(reg) - reg.gpBase() + @intFromEnum(Register.ah));
|
||||
}
|
||||
|
||||
pub fn hasHi8(reg: Register) bool {
|
||||
const reg_id = reg.id();
|
||||
return (reg_id >= comptime Register.ah.id()) and reg_id <= comptime Register.bh.id();
|
||||
}
|
||||
|
||||
pub fn to80(reg: Register) Register {
|
||||
assert(reg.class() == .x87);
|
||||
assert(reg.isClass(.x87));
|
||||
return reg;
|
||||
}
|
||||
|
||||
fn sseBase(reg: Register) u8 {
|
||||
assert(reg.class() == .sse);
|
||||
assert(reg.isClass(.sse));
|
||||
return switch (@intFromEnum(reg)) {
|
||||
@intFromEnum(Register.zmm0)...@intFromEnum(Register.zmm31) => @intFromEnum(Register.zmm0),
|
||||
@intFromEnum(Register.ymm0)...@intFromEnum(Register.ymm31) => @intFromEnum(Register.ymm0),
|
||||
|
|
@ -694,11 +699,13 @@ test "Register enc - different classes" {
|
|||
}
|
||||
|
||||
test "Register classes" {
|
||||
try expect(Register.r11.class() == .general_purpose);
|
||||
try expect(Register.ymm11.class() == .sse);
|
||||
try expect(Register.mm3.class() == .mmx);
|
||||
try expect(Register.st3.class() == .x87);
|
||||
try expect(Register.fs.class() == .segment);
|
||||
try expect(Register.r11.isClass(.general_purpose));
|
||||
try expect(Register.rdx.isClass(.gphi));
|
||||
try expect(!Register.dil.isClass(.gphi));
|
||||
try expect(Register.ymm11.isClass(.sse));
|
||||
try expect(Register.mm3.isClass(.mmx));
|
||||
try expect(Register.st3.isClass(.x87));
|
||||
try expect(Register.fs.isClass(.segment));
|
||||
}
|
||||
|
||||
pub const FrameIndex = enum(u32) {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ pub const Instruction = struct {
|
|||
};
|
||||
|
||||
pub fn initMoffs(reg: Register, offset: u64) Memory {
|
||||
assert(reg.class() == .segment);
|
||||
assert(reg.isClass(.segment));
|
||||
return .{ .moffs = .{ .seg = reg, .offset = offset } };
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ pub const Instruction = struct {
|
|||
.rip => false,
|
||||
.sib => |s| switch (s.base) {
|
||||
.none, .frame, .table, .reloc, .rip_inst => false,
|
||||
.reg => |reg| reg.class() == .segment,
|
||||
.reg => |reg| reg.isClass(.segment),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ pub const Instruction = struct {
|
|||
pub fn isSegmentRegister(op: Operand) bool {
|
||||
return switch (op) {
|
||||
.none => unreachable,
|
||||
.reg => |reg| reg.class() == .segment,
|
||||
.reg => |reg| reg.isClass(.segment),
|
||||
.mem => |mem| mem.isSegmentRegister(),
|
||||
.imm => unreachable,
|
||||
.bytes => unreachable,
|
||||
|
|
@ -776,7 +776,7 @@ pub const LegacyPrefixes = packed struct {
|
|||
padding: u5 = 0,
|
||||
|
||||
pub fn setSegmentOverride(self: *LegacyPrefixes, reg: Register) void {
|
||||
assert(reg.class() == .segment);
|
||||
assert(reg.isClass(.segment));
|
||||
switch (reg) {
|
||||
.cs => self.prefix_2e = true,
|
||||
.ss => self.prefix_36 = true,
|
||||
|
|
@ -2457,7 +2457,7 @@ const Assembler = struct {
|
|||
.general_purpose, .segment => {
|
||||
const tok = try as.expect(.string);
|
||||
const base = registerFromString(as.source(tok)) orelse return error.InvalidMemoryOperand;
|
||||
if (base.class() != cond) return error.InvalidMemoryOperand;
|
||||
if (!base.isClass(cond)) return error.InvalidMemoryOperand;
|
||||
res.base = base;
|
||||
},
|
||||
.rip => {
|
||||
|
|
@ -2498,7 +2498,7 @@ const Assembler = struct {
|
|||
error.Overflow => {
|
||||
if (is_neg) return err;
|
||||
if (res.base) |base| {
|
||||
if (base.class() != .segment) return err;
|
||||
if (!base.isClass(.segment)) return err;
|
||||
}
|
||||
const offset = try std.fmt.parseInt(u64, as.source(tok), 0);
|
||||
res.offset = offset;
|
||||
|
|
|
|||
|
|
@ -1893,13 +1893,13 @@ test "float divide by zero" {
|
|||
|
||||
test "partially-runtime integer vector division would be illegal if vector elements were reordered" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
||||
|
||||
var lhs: @Vector(2, i8) = .{ -128, 5 };
|
||||
const rhs: @Vector(2, i8) = .{ 1, -1 };
|
||||
|
|
|
|||
|
|
@ -559,12 +559,12 @@ test "vector comparison operators" {
|
|||
|
||||
test "vector division operators" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
fn doTheTestDiv(comptime T: type, x: @Vector(4, T), y: @Vector(4, T)) !void {
|
||||
|
|
|
|||
|
|
@ -5181,6 +5181,8 @@ inline fn divFloor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(@divFloor(
|
|||
}
|
||||
test divFloor {
|
||||
const test_div_floor = binary(divFloor, .{ .compare = .approx_int });
|
||||
try test_div_floor.testInts();
|
||||
try test_div_floor.testIntVectors();
|
||||
try test_div_floor.testFloats();
|
||||
try test_div_floor.testFloatVectors();
|
||||
}
|
||||
|
|
@ -5198,7 +5200,7 @@ test rem {
|
|||
|
||||
inline fn mod(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(@mod(lhs, rhs)) {
|
||||
// workaround llvm backend bugs
|
||||
if (@inComptime()) {
|
||||
if (@inComptime() and @typeInfo(Scalar(Type)) == .float) {
|
||||
const scalarMod = struct {
|
||||
fn scalarMod(scalar_lhs: Scalar(Type), scalar_rhs: Scalar(Type)) Scalar(Type) {
|
||||
const scalar_rem = @rem(scalar_lhs, scalar_rhs);
|
||||
|
|
@ -5218,6 +5220,8 @@ inline fn mod(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(@mod(lhs, rhs))
|
|||
}
|
||||
test mod {
|
||||
const test_mod = binary(mod, .{});
|
||||
try test_mod.testInts();
|
||||
try test_mod.testIntVectors();
|
||||
try test_mod.testFloats();
|
||||
try test_mod.testFloatVectors();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue