mirror of
https://github.com/n64dev/cen64.git
synced 2024-06-20 21:17:58 -04:00
Replaced all references to simulation with emulation Updated copyright year Updated .gitignore to reduce chances of random files being uploaded to the repo Added .gitattributes to normalize all text files, and to ignore binary files (which includes the logo and the NEC PDF)
339 lines
16 KiB
C
339 lines
16 KiB
C
//
|
|
// vr4300/decoder.c: VR4300 decoder.
|
|
//
|
|
// CEN64: Cycle-Accurate Nintendo 64 Emulator.
|
|
// Copyright (C) 2015, Tyler J. Stachecki.
|
|
//
|
|
// This file is subject to the terms and conditions defined in
|
|
// 'LICENSE', which is part of this source code package.
|
|
//
|
|
|
|
#define VR4300_BUILD_OP(op, func, flags) \
|
|
(VR4300_OPCODE_##op), (flags)
|
|
|
|
#include "common.h"
|
|
#include "vr4300/decoder.h"
|
|
#include "vr4300/opcodes.h"
|
|
#include "vr4300/opcodes_priv.h"
|
|
|
|
// ============================================================================
|
|
// Escaped opcode table: Special.
|
|
//
|
|
// 31---------26------------------------------------------5--------0
|
|
// | SPECIAL/6 | | FMT/6 |
|
|
// ------6----------------------------------------------------6-----
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 000 | SLL | | SRL | SRA | SLLV | | SRLV | SRAV |
|
|
// 001 | JR | JALR | | |SYSCALL| BREAK | | SYNC |
|
|
// 010 | MFHI | MTHI | MFLO | MTLO | DSLLV | | DSRLV | DSRAV |
|
|
// 011 | MULT | MULTU | DIV | DIVU | DMULT | DMULTU| DDIV | DDIVU |
|
|
// 100 | ADD | ADDU | SUB | SUBU | AND | OR | XOR | NOR |
|
|
// 101 | | | SLT | SLTU | DADD | DADDU | DSUB | DSUBU |
|
|
// 110 | TGE | TGEU | TLT | TLTU | TEQ | | TNE | |
|
|
// 111 | DSLL | | DSRL | DSRA |DSLL32 | |DSRL32 |DSRA32 |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
//
|
|
// ============================================================================
|
|
cen64_align(static const struct vr4300_opcode
|
|
vr4300_opcode_table[], CACHE_LINE_SIZE) = {
|
|
{SLL}, {INVALID}, {SRL}, {SRA},
|
|
{SLLV}, {INVALID}, {SRLV}, {SRAV},
|
|
{JR}, {JALR}, {INVALID}, {INVALID},
|
|
{SYSCALL}, {BREAK}, {INVALID}, {SYNC},
|
|
{MFHI}, {MTHI}, {MFLO}, {MTLO},
|
|
{DSLLV}, {INVALID}, {DSRLV}, {DSRAV},
|
|
{MULT}, {MULTU}, {DIV}, {DIVU},
|
|
{DMULT}, {DMULTU}, {DDIV}, {DDIVU},
|
|
{ADD}, {ADDU}, {SUB}, {SUBU},
|
|
{AND}, {OR}, {XOR}, {NOR},
|
|
{INVALID}, {INVALID}, {SLT}, {SLTU},
|
|
{DADD}, {DADDU}, {DSUB}, {DSUBU},
|
|
{TGE}, {TGEU}, {TLT}, {TLTU},
|
|
{TEQ}, {INVALID}, {TNE}, {INVALID},
|
|
{DSLL}, {INVALID}, {DSRL}, {DSRA},
|
|
{DSLL32}, {INVALID}, {DSRL32}, {DSRA32},
|
|
|
|
// ============================================================================
|
|
// Escaped opcode table: RegImm.
|
|
//
|
|
// 31---------26----------20-------16------------------------------0
|
|
// | = REGIMM | | FMT/5 | |
|
|
// ------6---------------------5------------------------------------
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 00 | BLTZ | BGEZ | BLTZL | BGEZL | | | | |
|
|
// 01 | TGEI | TGEIU | TLTI | TLTIU | TEQI | | TNEI | |
|
|
// 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| | | | |
|
|
// 11 | | | | | | | | |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
//
|
|
// ============================================================================
|
|
{BLTZ}, {BGEZ}, {BLTZL}, {BGEZL},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{TGEI}, {TGEIU}, {TLTI}, {TLTIU},
|
|
{TEQI}, {INVALID}, {TNEI}, {INVALID},
|
|
{BLTZAL}, {BGEZAL}, {BLTZALL}, {BGEZALL},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
|
|
// ============================================================================
|
|
// Escaped opcode table: COP0/1.
|
|
//
|
|
// 31--------26-25--24-----21--------------------------------------0
|
|
// | COP0/6 | 0 | FMT/4 | |
|
|
// ------6-------1------4------------------------------------------0
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 00 | MFC0 | DMFC0 | CFC0 | --- | MTC0 | DMTC0 | CTC0 | --- |
|
|
// 01 | BC0 | --- | --- | --- | --- | --- | --- | --- |
|
|
// 10 | TLB | --- | --- | --- | --- | --- | --- | --- |
|
|
// 11 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
// ============================================================================
|
|
{MFC0}, {DMFC0}, {CFC0}, {INVALID},
|
|
{MTC0}, {DMTC0}, {CTC0}, {INVALID},
|
|
{BC0}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
|
|
// ============================================================================
|
|
// Escaped opcode table: COP0/2.
|
|
//
|
|
// 31--------26-25 -24-----------------------------------5---------0
|
|
// | COP0/6 | 1 | | FMT/6 |
|
|
// ------6-------1--------------------------------------------6-----
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 000 | --- | TLBR | TLBWI | --- | --- | --- | TLBWR | --- |
|
|
// 001 | TLBP | --- | --- | --- | --- | --- | --- | --- |
|
|
// 010 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 011 | ERET | --- | --- | --- | --- | --- | --- | --- |
|
|
// 100 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 101 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 110 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 111 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
// ========================================================================= */
|
|
{INVALID}, {TLBR}, {TLBWI}, {INVALID},
|
|
{INVALID}, {INVALID}, {TLBWR}, {INVALID},
|
|
{TLBP}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{ERET}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
|
|
// ============================================================================
|
|
// Escaped opcode table: COP1/1.
|
|
//
|
|
// 31--------26-25------21 ----------------------------------------0
|
|
// | COP1/6 | FMT/5 | |
|
|
// ------6----------5-----------------------------------------------
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 00 | MFC1 | DMFC1 | CFC1 | --- | MTC1 | DMTC1 | CTC1 | --- |
|
|
// 01 | BC1 | --- | --- | --- | --- | --- | --- | --- |
|
|
// 10 | FPUS | FPUD | --- | --- | FPUW | FPUL | --- | --- |
|
|
// 11 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
// ============================================================================
|
|
{MFC1}, {DMFC1}, {CFC1}, {INVALID},
|
|
{MTC1}, {DMTC1}, {CTC1}, {INVALID},
|
|
{BC1}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
|
|
// ============================================================================
|
|
// Escaped opcode table: COP1/2.
|
|
//
|
|
// 31--------26-25 -24-----------------------------------5---------0
|
|
// | COP1/6 | 1 | | FMT/6 |
|
|
// ------6-------1--------------------------------------------6-----
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 000 | ADD | SUB | MUL | DIV | SQRT | ABS | MOV | NEG |
|
|
// 001 |ROUND.L|TRUNC.L|CEIL.L |FLOOR.L|ROUND.W|TRUNC.W|CEIL.W |FLOOR.W|
|
|
// 010 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 011 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 100 | CVT.S | CVT.D | --- | --- | CVT.W | CVT.L | --- | --- |
|
|
// 101 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 110 | C.F | C.UN | C.EQ | C.UEQ | C.OLT | C.ULT | C.OLE | C.ULE |
|
|
// 111 | C.SF |C.NGLE | C.SEQ | C.NGL | C.LT | C.NGE | C.LE | C.NGT |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
// ========================================================================= */
|
|
{CP1_ADD}, {CP1_SUB}, {CP1_MUL}, {CP1_DIV},
|
|
{CP1_SQRT}, {CP1_ABS}, {CP1_MOV}, {CP1_NEG},
|
|
{CP1_ROUND_L}, {CP1_TRUNC_L}, {CP1_CEIL_L}, {CP1_FLOOR_L},
|
|
{CP1_ROUND_W}, {CP1_TRUNC_W}, {CP1_CEIL_W}, {CP1_FLOOR_W},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{CP1_CVT_S}, {CP1_CVT_D}, {INVALID}, {INVALID},
|
|
{CP1_CVT_W}, {CP1_CVT_L}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{CP1_C_F}, {CP1_C_UN}, {CP1_C_EQ}, {CP1_C_UEQ},
|
|
{CP1_C_OLT}, {CP1_C_ULT}, {CP1_C_OLE}, {CP1_C_ULE},
|
|
{CP1_C_SF}, {CP1_C_NGLE}, {CP1_C_SEQ}, {CP1_C_NGL},
|
|
{CP1_C_LT}, {CP1_C_NGE}, {CP1_C_LE}, {CP1_C_NGT},
|
|
|
|
// ============================================================================
|
|
// Escaped opcode table: COP2.
|
|
//
|
|
// 31--------26-25------21 ----------------------------------------0
|
|
// | COP2/6 | FMT/5 | |
|
|
// ------6----------5-----------------------------------------------
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 00 | MFC2 | DMFC2 | CFC2 | --- | MTC2 | DMTC2 | CTC2 | --- |
|
|
// 01 | BC2 | --- | --- | --- | --- | --- | --- | --- |
|
|
// 10 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// 11 | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
//
|
|
// ============================================================================
|
|
{MFC2}, {DMFC2}, {CFC2}, {INVALID},
|
|
{MTC2}, {DMTC2}, {CTC2}, {INVALID},
|
|
{BC2}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
|
|
// ============================================================================
|
|
// First-order opcode table.
|
|
//
|
|
// 0b000000 => Lookup in 0.
|
|
// 0b000001 => Lookup in 64.
|
|
// 0b010000 => Lookup in vr4300_cop0_opcode_table.
|
|
// 0b010001 => Lookup in vr4300_cop1_opcode_table.
|
|
// 0b010010 => Lookup in 256.
|
|
//
|
|
// 31---------26---------------------------------------------------0
|
|
// | OPCODE/6 | |
|
|
// ------6----------------------------------------------------------
|
|
// |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--|
|
|
// 000 | *SPEC | *RGIM | J | JAL | BEQ | BNE | BLEZ | BGTZ |
|
|
// 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI |
|
|
// 010 | *COP0 | *COP1 | *COP2 | | BEQL | BNEL | BLEZL | BGTZL |
|
|
// 011 | DADDI |DADDIU | LDL | LDR | | | | |
|
|
// 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU |
|
|
// 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE |
|
|
// 110 | LL | LWC1 | LWC2 | | LLD | LDC1 | LDC2 | LD |
|
|
// 111 | SC | SWC1 | SWC2 | | SCD | SDC1 | SDC2 | SD |
|
|
// |-------|-------|-------|-------|-------|-------|-------|-------|
|
|
//
|
|
// ============================================================================
|
|
{INVALID}, {INVALID}, {J}, {JAL},
|
|
{BEQ}, {BNE}, {BLEZ}, {BGTZ},
|
|
{ADDI}, {ADDIU}, {SLTI}, {SLTIU},
|
|
{ANDI}, {ORI}, {XORI}, {LUI},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{BEQL}, {BNEL}, {BLEZL}, {BGTZL},
|
|
{DADDI}, {DADDIU}, {LDL}, {LDR},
|
|
{INVALID}, {INVALID}, {INVALID}, {INVALID},
|
|
{LB}, {LH}, {LWL}, {LW},
|
|
{LBU}, {LHU}, {LWR}, {LWU},
|
|
{SB}, {SH}, {SWL}, {SW},
|
|
{SDL}, {SDR}, {SWR}, {CACHE},
|
|
{LL}, {LWC1}, {LWC2}, {INVALID},
|
|
{LLD}, {LDC1}, {LDC2}, {LD},
|
|
{SC}, {SWC1}, {SWC2}, {INVALID},
|
|
{SCD}, {SDC1}, {SDC2}, {SD}
|
|
};
|
|
|
|
struct vr4300_opcode_escape {
|
|
uint16_t offset;
|
|
uint8_t shift, mask;
|
|
};
|
|
|
|
// Escaped table listings. Most of these will never
|
|
// see a processor cache line, so not much waste here.
|
|
cen64_align(static const struct vr4300_opcode_escape
|
|
vr4300_escape_table[128], CACHE_LINE_SIZE) = {
|
|
{0, 0, 0x3F}, {0, 0, 0x3F},
|
|
{64, 16, 0x1F}, {64, 16, 0x1F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
|
|
{96, 21, 0x0F}, {112, 0, 0x3F},
|
|
{176, 21, 0x0F}, {192, 0, 0x3F},
|
|
{256, 21, 0x1F}, {256, 21, 0x1F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
{288, 26, 0x3F}, {288, 26, 0x3F},
|
|
};
|
|
|
|
// Decodes an instruction word.
|
|
const struct vr4300_opcode* vr4300_decode_instruction(uint32_t iw) {
|
|
const struct vr4300_opcode_escape *escape = vr4300_escape_table + (iw >> 25);
|
|
unsigned index = iw >> escape->shift & escape->mask;
|
|
|
|
const struct vr4300_opcode *group = vr4300_opcode_table + escape->offset;
|
|
return group + index;
|
|
}
|
|
|