* move SPU code from std to self hosted compiler * change std lib comments to be descriptive rather than prescriptive * avoid usingnamespace * fix case style of error codes * remove duplication of producer_string * generalize handling of less than 64 bit arch pointers * clean up SPU II related test harness code
171 lines
4.2 KiB
Zig
171 lines
4.2 KiB
Zig
const std = @import("std");
|
|
|
|
pub const Interpreter = @import("spu-mk2/interpreter.zig").Interpreter;
|
|
|
|
pub const ExecutionCondition = enum(u3) {
|
|
always = 0,
|
|
when_zero = 1,
|
|
not_zero = 2,
|
|
greater_zero = 3,
|
|
less_than_zero = 4,
|
|
greater_or_equal_zero = 5,
|
|
less_or_equal_zero = 6,
|
|
overflow = 7,
|
|
};
|
|
|
|
pub const InputBehaviour = enum(u2) {
|
|
zero = 0,
|
|
immediate = 1,
|
|
peek = 2,
|
|
pop = 3,
|
|
};
|
|
|
|
pub const OutputBehaviour = enum(u2) {
|
|
discard = 0,
|
|
push = 1,
|
|
jump = 2,
|
|
jump_relative = 3,
|
|
};
|
|
|
|
pub const Command = enum(u5) {
|
|
copy = 0,
|
|
ipget = 1,
|
|
get = 2,
|
|
set = 3,
|
|
store8 = 4,
|
|
store16 = 5,
|
|
load8 = 6,
|
|
load16 = 7,
|
|
undefined0 = 8,
|
|
undefined1 = 9,
|
|
frget = 10,
|
|
frset = 11,
|
|
bpget = 12,
|
|
bpset = 13,
|
|
spget = 14,
|
|
spset = 15,
|
|
add = 16,
|
|
sub = 17,
|
|
mul = 18,
|
|
div = 19,
|
|
mod = 20,
|
|
@"and" = 21,
|
|
@"or" = 22,
|
|
xor = 23,
|
|
not = 24,
|
|
signext = 25,
|
|
rol = 26,
|
|
ror = 27,
|
|
bswap = 28,
|
|
asr = 29,
|
|
lsl = 30,
|
|
lsr = 31,
|
|
};
|
|
|
|
pub const Instruction = packed struct {
|
|
condition: ExecutionCondition,
|
|
input0: InputBehaviour,
|
|
input1: InputBehaviour,
|
|
modify_flags: bool,
|
|
output: OutputBehaviour,
|
|
command: Command,
|
|
reserved: u1 = 0,
|
|
|
|
pub fn format(instr: Instruction, comptime fmt: []const u8, options: std.fmt.FormatOptions, out: anytype) !void {
|
|
try std.fmt.format(out, "0x{x:0<4} ", .{@bitCast(u16, instr)});
|
|
try out.writeAll(switch (instr.condition) {
|
|
.always => " ",
|
|
.when_zero => "== 0",
|
|
.not_zero => "!= 0",
|
|
.greater_zero => " > 0",
|
|
.less_than_zero => " < 0",
|
|
.greater_or_equal_zero => ">= 0",
|
|
.less_or_equal_zero => "<= 0",
|
|
.overflow => "ovfl",
|
|
});
|
|
try out.writeAll(" ");
|
|
try out.writeAll(switch (instr.input0) {
|
|
.zero => "zero",
|
|
.immediate => "imm ",
|
|
.peek => "peek",
|
|
.pop => "pop ",
|
|
});
|
|
try out.writeAll(" ");
|
|
try out.writeAll(switch (instr.input1) {
|
|
.zero => "zero",
|
|
.immediate => "imm ",
|
|
.peek => "peek",
|
|
.pop => "pop ",
|
|
});
|
|
try out.writeAll(" ");
|
|
try out.writeAll(switch (instr.command) {
|
|
.copy => "copy ",
|
|
.ipget => "ipget ",
|
|
.get => "get ",
|
|
.set => "set ",
|
|
.store8 => "store8 ",
|
|
.store16 => "store16 ",
|
|
.load8 => "load8 ",
|
|
.load16 => "load16 ",
|
|
.undefined0 => "undefined",
|
|
.undefined1 => "undefined",
|
|
.frget => "frget ",
|
|
.frset => "frset ",
|
|
.bpget => "bpget ",
|
|
.bpset => "bpset ",
|
|
.spget => "spget ",
|
|
.spset => "spset ",
|
|
.add => "add ",
|
|
.sub => "sub ",
|
|
.mul => "mul ",
|
|
.div => "div ",
|
|
.mod => "mod ",
|
|
.@"and" => "and ",
|
|
.@"or" => "or ",
|
|
.xor => "xor ",
|
|
.not => "not ",
|
|
.signext => "signext ",
|
|
.rol => "rol ",
|
|
.ror => "ror ",
|
|
.bswap => "bswap ",
|
|
.asr => "asr ",
|
|
.lsl => "lsl ",
|
|
.lsr => "lsr ",
|
|
});
|
|
try out.writeAll(" ");
|
|
try out.writeAll(switch (instr.output) {
|
|
.discard => "discard",
|
|
.push => "push ",
|
|
.jump => "jmp ",
|
|
.jump_relative => "rjmp ",
|
|
});
|
|
try out.writeAll(" ");
|
|
try out.writeAll(if (instr.modify_flags)
|
|
"+ flags"
|
|
else
|
|
" ");
|
|
}
|
|
};
|
|
|
|
pub const FlagRegister = packed struct {
|
|
zero: bool,
|
|
negative: bool,
|
|
carry: bool,
|
|
carry_enabled: bool,
|
|
interrupt0_enabled: bool,
|
|
interrupt1_enabled: bool,
|
|
interrupt2_enabled: bool,
|
|
interrupt3_enabled: bool,
|
|
reserved: u8 = 0,
|
|
};
|
|
|
|
pub const Register = enum {
|
|
dummy,
|
|
|
|
pub fn allocIndex(self: Register) ?u4 {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
pub const callee_preserved_regs = [_]Register{};
|