165 lines
3.3 KiB
C++
165 lines
3.3 KiB
C++
#pragma once
|
|
#include "hw/sh4/sh4_if.h"
|
|
|
|
struct shil_opcode;
|
|
typedef void shil_chfp(shil_opcode* op);
|
|
extern shil_chfp* shil_chf[];
|
|
|
|
enum shil_param_type
|
|
{
|
|
//2 bits
|
|
FMT_NULL,
|
|
FMT_IMM,
|
|
FMT_I32,
|
|
FMT_F32,
|
|
FMT_F64,
|
|
|
|
FMT_V2,
|
|
FMT_V3,
|
|
FMT_V4,
|
|
FMT_V8,
|
|
FMT_V16,
|
|
|
|
FMT_REG_BASE=FMT_I32,
|
|
FMT_VECTOR_BASE=FMT_V2,
|
|
|
|
FMT_MASK=0xFFFF,
|
|
};
|
|
|
|
/*
|
|
formats : 16u 16s 32u 32s, 32f, 64f
|
|
param types: r32, r64
|
|
*/
|
|
|
|
|
|
#define SHIL_MODE 0
|
|
#include "shil_canonical.h"
|
|
|
|
struct shil_param
|
|
{
|
|
shil_param()
|
|
{
|
|
type=FMT_NULL;
|
|
_imm=0xFFFFFFFF;
|
|
memset(version, 0, sizeof(version));
|
|
}
|
|
shil_param(u32 type,u32 imm)
|
|
{
|
|
this->type=type;
|
|
if (type >= FMT_REG_BASE)
|
|
new (this) shil_param((Sh4RegType)imm);
|
|
_imm=imm;
|
|
memset(version, 0, sizeof(version));
|
|
}
|
|
|
|
shil_param(Sh4RegType reg)
|
|
{
|
|
type=FMT_NULL;
|
|
if (reg>=reg_fr_0 && reg<=reg_xf_15)
|
|
{
|
|
type=FMT_F32;
|
|
_imm=reg;
|
|
}
|
|
else if (reg>=regv_dr_0 && reg<=regv_dr_14)
|
|
{
|
|
type=FMT_F64;
|
|
_imm=(reg-regv_dr_0)*2+reg_fr_0;
|
|
}
|
|
else if (reg>=regv_xd_0 && reg<=regv_xd_14)
|
|
{
|
|
type=FMT_F64;
|
|
_imm=(reg-regv_xd_0)*2+reg_xf_0;
|
|
}
|
|
else if (reg>=regv_fv_0 && reg<=regv_fv_12)
|
|
{
|
|
type=FMT_V4;
|
|
_imm=(reg-regv_fv_0)*4+reg_fr_0;
|
|
}
|
|
else if (reg==regv_xmtrx)
|
|
{
|
|
type=FMT_V16;
|
|
_imm=reg_xf_0;
|
|
}
|
|
else if (reg==regv_fmtrx)
|
|
{
|
|
type=FMT_V16;
|
|
_imm=reg_fr_0;
|
|
}
|
|
else
|
|
{
|
|
type=FMT_I32;
|
|
_reg=reg;
|
|
}
|
|
memset(version, 0, sizeof(version));
|
|
}
|
|
union
|
|
{
|
|
u32 _imm;
|
|
Sh4RegType _reg;
|
|
};
|
|
u32 type;
|
|
u16 version[16];
|
|
|
|
bool is_null() const { return type==FMT_NULL; }
|
|
bool is_imm() const { return type==FMT_IMM; }
|
|
bool is_reg() const { return type>=FMT_REG_BASE; }
|
|
|
|
bool is_r32i() const { return type==FMT_I32; }
|
|
bool is_r32f() const { return type==FMT_F32; }
|
|
u32 is_r32fv() const { return type>=FMT_VECTOR_BASE?count():0; }
|
|
bool is_r64f() const { return type==FMT_F64; }
|
|
|
|
bool is_r32() const { return is_r32i() || is_r32f(); }
|
|
bool is_r64() const { return is_r64f(); } //just here for symmetry ...
|
|
|
|
bool is_imm_s8() const { return is_imm() && is_s8(_imm); }
|
|
bool is_imm_u8() const { return is_imm() && is_u8(_imm); }
|
|
bool is_imm_s16() const { return is_imm() && is_s16(_imm); }
|
|
bool is_imm_u16() const { return is_imm() && is_u16(_imm); }
|
|
|
|
u32* reg_ptr() const { verify(is_reg()); return GetRegPtr(_reg); }
|
|
s32 reg_nofs() const { verify(is_reg()); return (s32)((u8*)GetRegPtr(_reg) - (u8*)GetRegPtr(reg_xf_0)-sizeof(Sh4cntx)); }
|
|
u32 reg_aofs() const { return -reg_nofs(); }
|
|
|
|
u32 imm_value() const { verify(is_imm()); return _imm; }
|
|
|
|
bool is_vector() const { return type>=FMT_VECTOR_BASE; }
|
|
|
|
u32 count() const { return type==FMT_F64?2:type==FMT_V2?2:
|
|
type==FMT_V3?3:type==FMT_V4?4:type==FMT_V8?8:
|
|
type==FMT_V16?16:1; } //count of hardware regs
|
|
|
|
/*
|
|
Imms:
|
|
is_imm
|
|
|
|
regs:
|
|
integer regs : is_r32i,is_r32,count=1
|
|
fpu regs, single view : is_r32f,is_r32,count=1
|
|
fpu regs, double view : is_r64f,count=2
|
|
fpu regs, quad view : is_vector,is_r32fv=4, count=4
|
|
fpu regs, matrix view : is_vector,is_r32fv=16, count=16
|
|
*/
|
|
};
|
|
|
|
struct shil_opcode
|
|
{
|
|
shilop op;
|
|
u32 Flow;
|
|
u32 flags;
|
|
u32 flags2;
|
|
|
|
shil_param rd,rd2;
|
|
shil_param rs1,rs2,rs3;
|
|
|
|
u16 host_offs;
|
|
u16 guest_offs;
|
|
bool delay_slot;
|
|
|
|
std::string dissasm() const;
|
|
};
|
|
|
|
const char* shil_opcode_name(int op);
|
|
|
|
std::string name_reg(Sh4RegType reg);
|