Update lightrec 20220910 (#686)
[pcsx_rearmed.git] / deps / lightrec / disassembler.h
index e4c4403..e4685a9 100644 (file)
@@ -1,15 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 /*
- * Copyright (C) 2014 Paul Cercueil <paul@crapouillou.net>
- *
- * 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 <paul@crapouillou.net>
  */
 
 #ifndef __DISASSEMBLER_H__
 
 #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 load/store opcodes */
+#define LIGHTREC_SMC           BIT(2)
+#define LIGHTREC_NO_INVALIDATE BIT(3)
+#define LIGHTREC_NO_MASK       BIT(4)
+
+/* I/O mode for load/store opcodes */
+#define LIGHTREC_IO_MODE_LSB   5
+#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 +107,13 @@ enum standard_opcodes {
        OP_LWC2                 = 0x32,
        OP_SWC2                 = 0x3a,
 
-       OP_META_REG_UNLOAD      = 0x11,
+       OP_META_MOV             = 0x16,
 
-       OP_META_BEQZ            = 0x14,
-       OP_META_BNEZ            = 0x15,
+       OP_META_EXTC            = 0x17,
+       OP_META_EXTS            = 0x18,
 
-       OP_META_MOV             = 0x16,
-       OP_META_SYNC            = 0x17,
+       OP_META_MULT2           = 0x19,
+       OP_META_MULTU2          = 0x1a,
 };
 
 enum special_opcodes {
@@ -124,6 +164,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 {
@@ -194,19 +256,66 @@ struct opcode {
                struct opcode_i i;
                struct opcode_j j;
        };
-       u16 flags;
-       u16 offset;
-       struct opcode *next;
+       u32 flags;
 };
 
-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);
+struct opcode_list {
+       u16 nb_ops;
+       struct opcode ops[];
+};
+
+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_STORES && (flags & LIGHTREC_SMC);
+}
+
+static inline _Bool op_flag_no_invalidate(u32 flags)
+{
+       return (OPT_FLAG_IO || OPT_FLAG_STORES) &&
+               (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_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__ */