X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Fdisassembler.h;h=e05a093ce9c985800a4999bbada2bc826e1879a4;hb=e26c79a878ed1c0ee25cf7dffbb023dca7a871b9;hp=249d094c34186c25153a30663f0013dbf1142e76;hpb=3918505613cb814f8f5e0e8e0471f7b2a2cd8464;p=pcsx_rearmed.git diff --git a/deps/lightrec/disassembler.h b/deps/lightrec/disassembler.h index 249d094c..e05a093c 100644 --- a/deps/lightrec/disassembler.h +++ b/deps/lightrec/disassembler.h @@ -1,15 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2014-2020 Paul Cercueil - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Copyright (C) 2014-2021 Paul Cercueil */ #ifndef __DISASSEMBLER_H__ @@ -17,19 +8,72 @@ #include "debug.h" #include "lightrec.h" +#include "lightrec-config.h" #ifndef __packed #define __packed __attribute__((packed)) #endif -#define LIGHTREC_DIRECT_IO (1 << 0) -#define LIGHTREC_NO_INVALIDATE (1 << 1) -#define LIGHTREC_NO_DS (1 << 2) -#define LIGHTREC_SMC (1 << 3) -#define LIGHTREC_EMULATE_BRANCH (1 << 4) -#define LIGHTREC_LOCAL_BRANCH (1 << 5) -#define LIGHTREC_HW_IO (1 << 6) -#define LIGHTREC_MULT32 (1 << 7) +#define BIT(x) (1ULL << (x)) + +/* Flags for all opcodes */ +#define LIGHTREC_NO_DS BIT(0) +#define LIGHTREC_SYNC BIT(1) + +/* Flags for LUI, ORI, ADDIU */ +#define LIGHTREC_MOVI BIT(2) + +/* Flags for load/store opcodes */ +#define LIGHTREC_SMC BIT(2) +#define LIGHTREC_NO_INVALIDATE BIT(3) +#define LIGHTREC_NO_MASK BIT(4) +#define LIGHTREC_LOAD_DELAY BIT(5) + +/* I/O mode for load/store opcodes */ +#define LIGHTREC_IO_MODE_LSB 6 +#define LIGHTREC_IO_MODE(x) ((x) << LIGHTREC_IO_MODE_LSB) +#define LIGHTREC_IO_UNKNOWN 0x0 +#define LIGHTREC_IO_DIRECT 0x1 +#define LIGHTREC_IO_HW 0x2 +#define LIGHTREC_IO_RAM 0x3 +#define LIGHTREC_IO_BIOS 0x4 +#define LIGHTREC_IO_SCRATCH 0x5 +#define LIGHTREC_IO_DIRECT_HW 0x6 +#define LIGHTREC_IO_MASK LIGHTREC_IO_MODE(0x7) +#define LIGHTREC_FLAGS_GET_IO_MODE(x) \ + (((x) & LIGHTREC_IO_MASK) >> LIGHTREC_IO_MODE_LSB) + +/* Flags for branches */ +#define LIGHTREC_EMULATE_BRANCH BIT(2) +#define LIGHTREC_LOCAL_BRANCH BIT(3) + +/* Flags for div/mult opcodes */ +#define LIGHTREC_NO_LO BIT(2) +#define LIGHTREC_NO_HI BIT(3) +#define LIGHTREC_NO_DIV_CHECK BIT(4) + +#define LIGHTREC_REG_RS_LSB 26 +#define LIGHTREC_REG_RS(x) ((x) << LIGHTREC_REG_RS_LSB) +#define LIGHTREC_REG_RS_MASK LIGHTREC_REG_RS(0x3) +#define LIGHTREC_FLAGS_GET_RS(x) \ + (((x) & LIGHTREC_REG_RS_MASK) >> LIGHTREC_REG_RS_LSB) + +#define LIGHTREC_REG_RT_LSB 28 +#define LIGHTREC_REG_RT(x) ((x) << LIGHTREC_REG_RT_LSB) +#define LIGHTREC_REG_RT_MASK LIGHTREC_REG_RT(0x3) +#define LIGHTREC_FLAGS_GET_RT(x) \ + (((x) & LIGHTREC_REG_RT_MASK) >> LIGHTREC_REG_RT_LSB) + +#define LIGHTREC_REG_RD_LSB 30 +#define LIGHTREC_REG_RD(x) ((x) << LIGHTREC_REG_RD_LSB) +#define LIGHTREC_REG_RD_MASK LIGHTREC_REG_RD(0x3) +#define LIGHTREC_FLAGS_GET_RD(x) \ + (((x) & LIGHTREC_REG_RD_MASK) >> LIGHTREC_REG_RD_LSB) + +#define LIGHTREC_REG_NOOP 0x0 +#define LIGHTREC_REG_UNLOAD 0x1 +#define LIGHTREC_REG_DISCARD 0x2 +#define LIGHTREC_REG_CLEAN 0x3 struct block; @@ -67,13 +111,10 @@ enum standard_opcodes { OP_LWC2 = 0x32, OP_SWC2 = 0x3a, - OP_META_REG_UNLOAD = 0x11, + OP_META = 0x3c, - OP_META_BEQZ = 0x14, - OP_META_BNEZ = 0x15, - - OP_META_MOV = 0x16, - OP_META_SYNC = 0x17, + OP_META_MULT2 = 0x19, + OP_META_MULTU2 = 0x1a, }; enum special_opcodes { @@ -124,6 +165,28 @@ enum cp0_opcodes { enum cp2_opcodes { OP_CP2_BASIC = 0x00, + OP_CP2_RTPS = 0x01, + OP_CP2_NCLIP = 0x06, + OP_CP2_OP = 0x0c, + OP_CP2_DPCS = 0x10, + OP_CP2_INTPL = 0x11, + OP_CP2_MVMVA = 0x12, + OP_CP2_NCDS = 0x13, + OP_CP2_CDP = 0x14, + OP_CP2_NCDT = 0x16, + OP_CP2_NCCS = 0x1b, + OP_CP2_CC = 0x1c, + OP_CP2_NCS = 0x1e, + OP_CP2_NCT = 0x20, + OP_CP2_SQR = 0x28, + OP_CP2_DCPL = 0x29, + OP_CP2_DPCT = 0x2a, + OP_CP2_AVSZ3 = 0x2d, + OP_CP2_AVSZ4 = 0x2e, + OP_CP2_RTPT = 0x30, + OP_CP2_GPF = 0x3d, + OP_CP2_GPL = 0x3e, + OP_CP2_NCCT = 0x3f, }; enum cp2_basic_opcodes { @@ -133,6 +196,15 @@ enum cp2_basic_opcodes { OP_CP2_BASIC_CTC2 = 0x06, }; +enum meta_opcodes { + OP_META_MOV = 0x00, + + OP_META_EXTC = 0x01, + OP_META_EXTS = 0x02, + + OP_META_COM = 0x03, +}; + struct opcode_r { #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ u32 zero :6; @@ -175,12 +247,31 @@ struct opcode_j { #endif } __packed; +struct opcode_m { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u32 meta :6; + u32 rs :5; + u32 rt :5; + u32 rd :5; + u32 imm :6; + u32 op :5; +#else + u32 op :5; + u32 imm :6; + u32 rd :5; + u32 rt :5; + u32 rs :5; + u32 meta :6; +#endif +}; + union code { /* Keep in sync with struct opcode */ u32 opcode; struct opcode_r r; struct opcode_i i; struct opcode_j j; + struct opcode_m m; }; struct opcode { @@ -193,20 +284,72 @@ struct opcode { struct opcode_r r; struct opcode_i i; struct opcode_j j; + struct opcode_m m; }; - u16 flags; - u16 offset; - struct opcode *next; + u32 flags; +}; + +struct opcode_list { + u16 nb_ops; + struct opcode ops[]; }; -struct opcode * lightrec_disassemble(struct lightrec_state *state, - const u32 *src, unsigned int *len); -void lightrec_free_opcode_list(struct lightrec_state *state, - struct opcode *list); +void lightrec_print_disassembly(const struct block *block, const u32 *code); + +static inline _Bool op_flag_no_ds(u32 flags) +{ + return OPT_SWITCH_DELAY_SLOTS && (flags & LIGHTREC_NO_DS); +} + +static inline _Bool op_flag_sync(u32 flags) +{ + return OPT_LOCAL_BRANCHES && (flags & LIGHTREC_SYNC); +} + +static inline _Bool op_flag_smc(u32 flags) +{ + return OPT_FLAG_IO && (flags & LIGHTREC_SMC); +} + +static inline _Bool op_flag_no_invalidate(u32 flags) +{ + return OPT_FLAG_IO && (flags & LIGHTREC_NO_INVALIDATE); +} + +static inline _Bool op_flag_no_mask(u32 flags) +{ + return OPT_FLAG_IO && (flags & LIGHTREC_NO_MASK); +} + +static inline _Bool op_flag_load_delay(u32 flags) +{ + return OPT_HANDLE_LOAD_DELAYS && (flags & LIGHTREC_LOAD_DELAY); +} + +static inline _Bool op_flag_emulate_branch(u32 flags) +{ + return OPT_DETECT_IMPOSSIBLE_BRANCHES && + (flags & LIGHTREC_EMULATE_BRANCH); +} + +static inline _Bool op_flag_local_branch(u32 flags) +{ + return OPT_LOCAL_BRANCHES && (flags & LIGHTREC_LOCAL_BRANCH); +} + +static inline _Bool op_flag_no_lo(u32 flags) +{ + return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_LO); +} -unsigned int lightrec_cycles_of_opcode(union code code); +static inline _Bool op_flag_no_hi(u32 flags) +{ + return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_HI); +} -void lightrec_print_disassembly(const struct block *block, - const u32 *code, unsigned int length); +static inline _Bool op_flag_no_div_check(u32 flags) +{ + return OPT_FLAG_MULT_DIV && (flags & LIGHTREC_NO_DIV_CHECK); +} #endif /* __DISASSEMBLER_H__ */