Skip to content

Commit

Permalink
Simplifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Senryoku committed Nov 29, 2024
1 parent 29685a4 commit 5b45e75
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 183 deletions.
4 changes: 1 addition & 3 deletions src/dreamcast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
101 changes: 19 additions & 82 deletions src/holly.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}

Expand Down Expand Up @@ -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,
Expand All @@ -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].*;
Expand All @@ -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) {
Expand Down Expand Up @@ -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)).*),
};
}
},
Expand Down Expand Up @@ -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;
},
}
Expand Down
4 changes: 2 additions & 2 deletions src/jit/jit_block.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
81 changes: 10 additions & 71 deletions src/jit/x86_64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 },
Expand All @@ -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 },
Expand All @@ -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 },
Expand Down Expand Up @@ -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...
Expand Down Expand Up @@ -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) });
Expand Down Expand Up @@ -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?
Expand Down
7 changes: 1 addition & 6 deletions src/maple.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
31 changes: 12 additions & 19 deletions src/renderer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5b45e75

Please sign in to comment.