From 5b45e75036716a282dc2a3867f9bc2bfbf6e1eca Mon Sep 17 00:00:00 2001 From: Senryoku Date: Fri, 29 Nov 2024 04:16:08 +0100 Subject: [PATCH] Simplifications --- src/dreamcast.zig | 4 +- src/holly.zig | 101 ++++++++---------------------------------- src/jit/jit_block.zig | 4 +- src/jit/x86_64.zig | 81 +++++---------------------------- src/maple.zig | 7 +-- src/renderer.zig | 31 +++++-------- 6 files changed, 45 insertions(+), 183 deletions(-) diff --git a/src/dreamcast.zig b/src/dreamcast.zig index 030a93d..e5d0e26 100644 --- a/src/dreamcast.zig +++ b/src/dreamcast.zig @@ -68,10 +68,8 @@ const Callback = struct { }; const ScheduledInterrupt = struct { - const InterruptType = enum { Normal, External }; - trigger_cycle: u64, - interrupt: ?union(InterruptType) { + interrupt: ?union(enum) { Normal: HardwareRegisters.SB_ISTNRM, External: HardwareRegisters.SB_ISTEXT, }, diff --git a/src/holly.zig b/src/holly.zig index 8362b7d..90b4cb3 100644 --- a/src/holly.zig +++ b/src/holly.zig @@ -644,14 +644,9 @@ pub const Polygon = union(enum) { return std.meta.activeTag(self); } - pub fn size(polygon_format: std.meta.Tag(Polygon)) u32 { - return switch (polygon_format) { - .PolygonType0 => @sizeOf(PolygonType0) / 4, - .PolygonType1 => @sizeOf(PolygonType1) / 4, - .PolygonType2 => @sizeOf(PolygonType2) / 4, - .PolygonType3 => @sizeOf(PolygonType3) / 4, - .PolygonType4 => @sizeOf(PolygonType4) / 4, - .Sprite => @sizeOf(Sprite) / 4, + pub fn size(format: std.meta.Tag(@This())) u32 { + return switch (format) { + inline else => |f| @sizeOf(std.meta.TagPayload(@This(), f)) / 4, }; } @@ -1044,27 +1039,7 @@ const VertexParameter_Sprite_1 = packed struct(u512) { cuv: UV16, }; -pub const VertexParameterType = enum { - Type0, - Type1, - Type2, - Type3, - Type4, - Type5, - Type6, - Type7, - Type8, - Type9, - Type10, - Type11, - Type12, - Type13, - Type14, - SpriteType0, - SpriteType1, -}; - -pub const VertexParameter = union(VertexParameterType) { +pub const VertexParameter = union(enum) { Type0: VertexParameter_0, Type1: VertexParameter_1, Type2: VertexParameter_2, @@ -1087,6 +1062,12 @@ pub const VertexParameter = union(VertexParameterType) { return std.meta.activeTag(self); } + // Returns the size in words (4 bytes) of the vertex parameter + pub fn size(format: std.meta.Tag(@This())) u32 { + return switch (format) { + inline else => |f| @sizeOf(std.meta.TagPayload(@This(), f)) / 4, + }; + } pub fn position(self: *const @This()) [3]f32 { std.debug.assert(self.tag() != .SpriteType0 and self.tag() != .SpriteType1); return @as([*]const f32, @alignCast(@ptrCast(self)))[1..4].*; @@ -1099,30 +1080,7 @@ pub const VertexParameter = union(VertexParameterType) { } }; -// Returns the size in words (4 bytes) of the vertex parameter -pub fn vertex_parameter_size(format: VertexParameterType) u32 { - return switch (format) { - .Type0 => @sizeOf(VertexParameter_0) / 4, - .Type1 => @sizeOf(VertexParameter_1) / 4, - .Type2 => @sizeOf(VertexParameter_2) / 4, - .Type3 => @sizeOf(VertexParameter_3) / 4, - .Type4 => @sizeOf(VertexParameter_4) / 4, - .Type5 => @sizeOf(VertexParameter_5) / 4, - .Type6 => @sizeOf(VertexParameter_6) / 4, - .Type7 => @sizeOf(VertexParameter_7) / 4, - .Type8 => @sizeOf(VertexParameter_8) / 4, - .Type9 => @sizeOf(VertexParameter_9) / 4, - .Type10 => @sizeOf(VertexParameter_10) / 4, - .Type11 => @sizeOf(VertexParameter_11) / 4, - .Type12 => @sizeOf(VertexParameter_12) / 4, - .Type13 => @sizeOf(VertexParameter_13) / 4, - .Type14 => @sizeOf(VertexParameter_14) / 4, - .SpriteType0 => @sizeOf(VertexParameter_Sprite_0) / 4, - .SpriteType1 => @sizeOf(VertexParameter_Sprite_1) / 4, - }; -} - -fn obj_control_to_vertex_parameter_format(obj_control: ObjControl) VertexParameterType { +fn obj_control_to_vertex_parameter_format(obj_control: ObjControl) std.meta.Tag(VertexParameter) { // Shadow (Ignored) - Volume - ColType (u2) - Texture - Offset (Ignored) - Gouraud (Ignored) - 16bit UV const masked = @as(u16, @bitCast(obj_control)) & 0b00000000_0_1_11_1_0_0_1; switch (masked) { @@ -1691,12 +1649,8 @@ pub const Holly = struct { if (self._ta_command_buffer_index < Polygon.size(polygon_type)) return; self._ta_current_polygon = switch (polygon_type) { - .PolygonType0 => .{ .PolygonType0 = @as(*PolygonType0, @ptrCast(&self._ta_command_buffer)).* }, - .PolygonType1 => .{ .PolygonType1 = @as(*PolygonType1, @ptrCast(&self._ta_command_buffer)).* }, - .PolygonType2 => .{ .PolygonType2 = @as(*PolygonType2, @ptrCast(&self._ta_command_buffer)).* }, - .PolygonType3 => .{ .PolygonType3 = @as(*PolygonType3, @ptrCast(&self._ta_command_buffer)).* }, - .PolygonType4 => .{ .PolygonType4 = @as(*PolygonType4, @ptrCast(&self._ta_command_buffer)).* }, - else => @panic("Invalid polygon format"), + .Sprite => @panic("Invalid polygon format"), + inline else => |pt| @unionInit(Polygon, @tagName(pt), @as(*std.meta.TagPayload(Polygon, pt), @ptrCast(&self._ta_command_buffer)).*), }; } }, @@ -1727,44 +1681,27 @@ pub const Holly = struct { } else { var display_list = self.ta_current_lists().get_list(list_type); if (self._ta_current_polygon) |*polygon| { - const polygon_obj_control = @as(*const GenericGlobalParameter, @ptrCast(polygon)).*.parameter_control_word.obj_control; + const polygon_obj_control = @as(*const GenericGlobalParameter, @ptrCast(polygon)).parameter_control_word.obj_control; switch (polygon.*) { .Sprite => { if (parameter_control_word.end_of_strip != 1) { // Sanity check: For Sprites/Quads, each vertex parameter describes an entire polygon. holly_log.warn(termcolor.yellow("Unexpected Sprite without end of strip bit:") ++ "\n {any}", .{parameter_control_word}); } if (polygon_obj_control.texture == 0) { - if (self._ta_command_buffer_index < vertex_parameter_size(.SpriteType0)) return; + if (self._ta_command_buffer_index < VertexParameter.size(.SpriteType0)) return; display_list.vertex_parameters.append(.{ .SpriteType0 = @as(*VertexParameter_Sprite_0, @ptrCast(&self._ta_command_buffer)).* }) catch unreachable; } else { - if (self._ta_command_buffer_index < vertex_parameter_size(.SpriteType1)) return; + if (self._ta_command_buffer_index < VertexParameter.size(.SpriteType1)) return; display_list.vertex_parameters.append(.{ .SpriteType1 = @as(*VertexParameter_Sprite_1, @ptrCast(&self._ta_command_buffer)).* }) catch unreachable; } }, else => { const format = obj_control_to_vertex_parameter_format(polygon_obj_control); - if (self._ta_command_buffer_index < vertex_parameter_size(format)) return; + if (self._ta_command_buffer_index < VertexParameter.size(format)) return; display_list.vertex_parameters.append(switch (format) { - .Type0 => .{ .Type0 = @as(*VertexParameter_0, @ptrCast(&self._ta_command_buffer)).* }, - .Type1 => .{ .Type1 = @as(*VertexParameter_1, @ptrCast(&self._ta_command_buffer)).* }, - .Type2 => .{ .Type2 = @as(*VertexParameter_2, @ptrCast(&self._ta_command_buffer)).* }, - .Type3 => .{ .Type3 = @as(*VertexParameter_3, @ptrCast(&self._ta_command_buffer)).* }, - .Type4 => .{ .Type4 = @as(*VertexParameter_4, @ptrCast(&self._ta_command_buffer)).* }, - .Type5 => .{ .Type5 = @as(*VertexParameter_5, @ptrCast(&self._ta_command_buffer)).* }, - .Type6 => .{ .Type6 = @as(*VertexParameter_6, @ptrCast(&self._ta_command_buffer)).* }, - .Type7 => .{ .Type7 = @as(*VertexParameter_7, @ptrCast(&self._ta_command_buffer)).* }, - .Type8 => .{ .Type8 = @as(*VertexParameter_8, @ptrCast(&self._ta_command_buffer)).* }, - .Type9 => .{ .Type9 = @as(*VertexParameter_9, @ptrCast(&self._ta_command_buffer)).* }, - .Type10 => .{ .Type10 = @as(*VertexParameter_10, @ptrCast(&self._ta_command_buffer)).* }, - .Type11 => .{ .Type11 = @as(*VertexParameter_11, @ptrCast(&self._ta_command_buffer)).* }, - .Type12 => .{ .Type12 = @as(*VertexParameter_12, @ptrCast(&self._ta_command_buffer)).* }, - .Type13 => .{ .Type13 = @as(*VertexParameter_13, @ptrCast(&self._ta_command_buffer)).* }, - .Type14 => .{ .Type14 = @as(*VertexParameter_14, @ptrCast(&self._ta_command_buffer)).* }, - else => { - holly_log.err(termcolor.red(" Unexpected vertex parameter type: {any}."), .{format}); - @panic("Unexpected vertex parameter type"); - }, + .SpriteType0, .SpriteType1 => unreachable, + inline else => |t| @unionInit(VertexParameter, @tagName(t), @as(*std.meta.TagPayload(VertexParameter, t), @ptrCast(&self._ta_command_buffer)).*), }) catch unreachable; }, } diff --git a/src/jit/jit_block.zig b/src/jit/jit_block.zig index d0b387e..c2000af 100644 --- a/src/jit/jit_block.zig +++ b/src/jit/jit_block.zig @@ -86,7 +86,7 @@ pub const JITBlock = struct { // Combine shift instructions if possible if (self.instructions.items.len > 0 and amount == .imm8) { const prev = &self.instructions.items[self.instructions.items.len - 1]; - if (prev.* == .Shl and prev.Shl.dst.equal(dst) and prev.Shl.amount == .imm8) { + if (prev.* == .Shl and std.meta.eql(prev.Shl.dst, dst) and prev.Shl.amount == .imm8) { prev.Shl.amount.imm8 += amount.imm8; return; } @@ -98,7 +98,7 @@ pub const JITBlock = struct { // Combine shift instructions if possible if (self.instructions.items.len > 0 and amount == .imm8) { const prev = &self.instructions.items[self.instructions.items.len - 1]; - if (prev.* == .Shr and prev.Shr.dst.equal(dst) and prev.Shr.amount == .imm8) { + if (prev.* == .Shr and std.meta.eql(prev.Shr.dst, dst) and prev.Shr.amount == .imm8) { prev.Shr.amount.imm8 += amount.imm8; return; } diff --git a/src/jit/x86_64.zig b/src/jit/x86_64.zig index 06d32f5..946ec61 100644 --- a/src/jit/x86_64.zig +++ b/src/jit/x86_64.zig @@ -202,10 +202,6 @@ pub const MemOperand = struct { }); } } - - pub fn equal(a: @This(), b: @This()) bool { - return a.base == b.base and a.index == b.index and a.displacement == b.displacement and a.size == b.size; - } }; pub const Operand = union(enum) { @@ -244,72 +240,14 @@ pub const Operand = union(enum) { .mem => |mem| writer.print("{any}", .{mem}), }; } - - pub fn equal(a: @This(), b: @This()) bool { - return switch (a) { - .reg8 => |a_reg| b == .reg8 and a_reg == b.reg8, - .reg16 => |a_reg| b == .reg16 and a_reg == b.reg16, - .reg => |a_reg| b == .reg and a_reg == b.reg, - .reg64 => |a_reg| b == .reg64 and a_reg == b.reg64, - .freg32 => |a_reg| b == .freg32 and a_reg == b.freg32, - .freg64 => |a_reg| b == .freg64 and a_reg == b.freg64, - .freg128 => |a_reg| b == .freg128 and a_reg == b.freg128, - .imm8 => |a_imm| b == .imm8 and a_imm == b.imm8, - .imm16 => |a_imm| b == .imm16 and a_imm == b.imm16, - .imm32 => |a_imm| b == .imm32 and a_imm == b.imm32, - .imm64 => |a_imm| b == .imm64 and a_imm == b.imm64, - .mem => |a_mem| b == .mem and a_mem.equal(b.mem), - }; - } }; -pub const InstructionType = enum { - Nop, - Break, // For Debugging - FunctionCall, - Mov, // Mov with zero extention (NOTE: This is NOT the same as the x86 mov instruction, which doesn't zero extend from 8 and 16-bit memory accesses) - Movsx, // Mov with sign extension - Push, - Pop, - Not, - Neg, - Add, - Adc, - Sub, - Sbb, - Mul, - Div, - Fma, // Fused Multiply Add - Sqrt, - Min, - Max, - And, - Or, - Xor, - Cmp, - SetByteCondition, - BitTest, - Rol, - Ror, - Rcl, - Rcr, - Shl, - Shr, - Sar, - Jmp, - Convert, - Div64_32, // FIXME: This only exists because I haven't added a way to specify the size the GPRs. - - SaveFPRegisters, - RestoreFPRegisters, -}; - -pub const Instruction = union(InstructionType) { +pub const Instruction = union(enum) { Nop, // Usefull to patch out instructions without having to rewrite the entire block. - Break, + Break, // For Debugging FunctionCall: *const anyopaque, // FIXME: Is there a better type for generic function pointers? - Mov: struct { dst: Operand, src: Operand, preserve_flags: bool = false }, - Movsx: struct { dst: Operand, src: Operand }, + Mov: struct { dst: Operand, src: Operand, preserve_flags: bool = false }, // Mov with zero extention (NOTE: This is NOT the same as the x86 mov instruction, which doesn't zero extend from 8 and 16-bit memory accesses) + Movsx: struct { dst: Operand, src: Operand }, // Mov with sign extension Push: Operand, Pop: Operand, Not: struct { dst: Operand }, @@ -320,7 +258,7 @@ pub const Instruction = union(InstructionType) { Sbb: struct { dst: Operand, src: Operand }, Mul: struct { dst: Operand, src: Operand }, Div: struct { dst: Operand, src: Operand }, - Fma: struct { dst: FPRegister, src1: FPRegister, src2: Operand }, + Fma: struct { dst: FPRegister, src1: FPRegister, src2: Operand }, // Fused Multiply Add Sqrt: struct { dst: Operand, src: Operand }, Min: struct { dst: Operand, src: Operand }, Max: struct { dst: Operand, src: Operand }, @@ -339,6 +277,7 @@ pub const Instruction = union(InstructionType) { Sar: struct { dst: Operand, amount: Operand }, Jmp: struct { condition: Condition, dst: struct { rel: i32 } }, Convert: struct { dst: Operand, src: Operand }, + // FIXME: This only exists because I haven't added a way to specify the size the GPRs. Div64_32: struct { dividend_high: Register, dividend_low: Register, divisor: Register, result: Register }, SaveFPRegisters: struct { count: u8 }, @@ -884,10 +823,10 @@ pub const Emitter = struct { }, }; - if (mem.size == 16 or reg.tag() == .freg32 or reg.tag() == .freg64) + if (mem.size == 16 or reg == .freg32 or reg == .freg64) try self.emit(u8, 0x66); - if (reg.tag() == .reg8 and (reg.reg8 == .rsp or reg.reg8 == .rbp or reg.reg8 == .rsi or reg.reg8 == .rdi)) { + if (reg == .reg8 and (reg.reg8 == .rsp or reg.reg8 == .rbp or reg.reg8 == .rsi or reg.reg8 == .rdi)) { // NOTE: Byte access to the lower 8 bits of these registers is only possible with a rex prefix, // emit it unconditionally. // FIXME: This should probably be done elsewhere too... @@ -1019,7 +958,7 @@ pub const Emitter = struct { switch (dst) { // FIXME: We don't keep track of registers sizes and default to 32bit. We might want to support explicit 64bit at some point. .reg, .reg64 => |dst_reg| { - const is_64 = dst.tag() == .reg64; + const is_64 = dst == .reg64; switch (src) { .mem => |src_m| { try self.emit_rex_if_needed(.{ .w = is_64, .r = need_rex(dst_reg), .b = need_rex(src_m.base) }); @@ -1311,7 +1250,7 @@ pub const Emitter = struct { switch (src) { .reg, .reg64 => |src_reg| { if (dst.tag() != src.tag()) return error.MulOperandMismatch; - const is_64 = dst.tag() == .reg64; + const is_64 = dst == .reg64; // FIXME: This is supposed to be a condensed version of the instruction for rax, // but it's measurably slower on my machine. What? diff --git a/src/maple.zig b/src/maple.zig index 99f136e..b8aa4c1 100644 --- a/src/maple.zig +++ b/src/maple.zig @@ -494,12 +494,7 @@ pub const VMU = struct { } }; -const PeripheralType = enum { - Controller, - VMU, -}; - -const Peripheral = union(PeripheralType) { +const Peripheral = union(enum) { Controller: Controller, VMU: VMU, diff --git a/src/renderer.zig b/src/renderer.zig index a9b074e..3f352ba 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -446,20 +446,16 @@ fn gen_sprite_vertices(sprite: HollyModule.VertexParameter) [4]Vertex { r[3].y = v.cy; r[3].z = v.cz; }, - else => unreachable, + else => @panic("Not a Sprite"), } - switch (sprite) { - .SpriteType1 => |v| { - r[0].u = uv16(v.auv.u); - r[0].v = uv16(v.auv.v); - - r[2].u = uv16(v.buv.u); - r[2].v = uv16(v.buv.v); - - r[3].u = uv16(v.cuv.u); - r[3].v = uv16(v.cuv.v); - }, - else => {}, + if (sprite == .SpriteType1) { + const v = sprite.SpriteType1; + r[0].u = uv16(v.auv.u); + r[0].v = uv16(v.auv.v); + r[2].u = uv16(v.buv.u); + r[2].v = uv16(v.buv.v); + r[3].u = uv16(v.cuv.u); + r[3].v = uv16(v.cuv.v); } // dz have to be deduced from the plane equation @@ -2020,12 +2016,9 @@ pub const Renderer = struct { var sprite_base_color: PackedColor = undefined; var sprite_offset_color: PackedColor = undefined; - switch (polygon) { - .Sprite => |p| { - sprite_base_color = p.base_color; - sprite_offset_color = p.offset_color; - }, - else => {}, + if (polygon == .Sprite) { + sprite_base_color = polygon.Sprite.base_color; + sprite_offset_color = polygon.Sprite.offset_color; } var tex_idx: TextureIndex = 0;