xref: /qemu/target/mips/tcg/translate.h (revision d051d0e1)
1 /*
2  *  MIPS translation routines.
3  *
4  *  Copyright (c) 2004-2005 Jocelyn Mayer
5  *
6  * SPDX-License-Identifier: LGPL-2.1-or-later
7  */
8 #ifndef TARGET_MIPS_TRANSLATE_H
9 #define TARGET_MIPS_TRANSLATE_H
10 
11 #include "exec/translator.h"
12 
13 #define MIPS_DEBUG_DISAS 0
14 
15 typedef struct DisasContext {
16     DisasContextBase base;
17     target_ulong saved_pc;
18     target_ulong page_start;
19     uint32_t opcode;
20     uint64_t insn_flags;
21     int32_t CP0_Config0;
22     int32_t CP0_Config1;
23     int32_t CP0_Config2;
24     int32_t CP0_Config3;
25     int32_t CP0_Config5;
26     /* Routine used to access memory */
27     int mem_idx;
28     MemOp default_tcg_memop_mask;
29     uint32_t hflags, saved_hflags;
30     target_ulong btarget;
31     bool ulri;
32     int kscrexist;
33     bool rxi;
34     int ie;
35     bool bi;
36     bool bp;
37     uint64_t PAMask;
38     bool mvh;
39     bool eva;
40     bool sc;
41     int CP0_LLAddr_shift;
42     bool ps;
43     bool vp;
44     bool cmgcr;
45     bool mrp;
46     bool nan2008;
47     bool abs2008;
48     bool saar;
49     bool mi;
50     int gi;
51 } DisasContext;
52 
53 /* MIPS major opcodes */
54 #define MASK_OP_MAJOR(op)   (op & (0x3F << 26))
55 
56 #define OPC_CP1 (0x11 << 26)
57 
58 /* Coprocessor 1 (rs field) */
59 #define MASK_CP1(op)                (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
60 
61 /* Values for the fmt field in FP instructions */
62 enum {
63     /* 0 - 15 are reserved */
64     FMT_S = 16,          /* single fp */
65     FMT_D = 17,          /* double fp */
66     FMT_E = 18,          /* extended fp */
67     FMT_Q = 19,          /* quad fp */
68     FMT_W = 20,          /* 32-bit fixed */
69     FMT_L = 21,          /* 64-bit fixed */
70     FMT_PS = 22,         /* paired single fp */
71     /* 23 - 31 are reserved */
72 };
73 
74 enum {
75     OPC_MFC1     = (0x00 << 21) | OPC_CP1,
76     OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
77     OPC_CFC1     = (0x02 << 21) | OPC_CP1,
78     OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
79     OPC_MTC1     = (0x04 << 21) | OPC_CP1,
80     OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
81     OPC_CTC1     = (0x06 << 21) | OPC_CP1,
82     OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
83     OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
84     OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
85     OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
86     OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,
87     OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,
88     OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,
89     OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,
90     OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,
91     OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,
92     OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1,
93     OPC_BC1EQZ   = (0x09 << 21) | OPC_CP1,
94     OPC_BC1NEZ   = (0x0D << 21) | OPC_CP1,
95 };
96 
97 #define MASK_CP1_FUNC(op)           (MASK_CP1(op) | (op & 0x3F))
98 #define MASK_BC1(op)                (MASK_CP1(op) | (op & (0x3 << 16)))
99 
100 enum {
101     OPC_BC1F     = (0x00 << 16) | OPC_BC1,
102     OPC_BC1T     = (0x01 << 16) | OPC_BC1,
103     OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
104     OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
105 };
106 
107 enum {
108     OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
109     OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
110 };
111 
112 enum {
113     OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
114     OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
115 };
116 
117 #define gen_helper_0e1i(name, arg1, arg2) do { \
118     gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
119     } while (0)
120 
121 #define gen_helper_1e0i(name, ret, arg1) do { \
122     gen_helper_##name(ret, cpu_env, tcg_constant_i32(arg1)); \
123     } while (0)
124 
125 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
126     gen_helper_##name(cpu_env, arg1, arg2, tcg_constant_i32(arg3));\
127     } while (0)
128 
129 void generate_exception(DisasContext *ctx, int excp);
130 void generate_exception_err(DisasContext *ctx, int excp, int err);
131 void generate_exception_end(DisasContext *ctx, int excp);
132 void gen_reserved_instruction(DisasContext *ctx);
133 
134 void check_insn(DisasContext *ctx, uint64_t flags);
135 void check_mips_64(DisasContext *ctx);
136 /**
137  * check_cp0_enabled:
138  * Return %true if CP0 is enabled, otherwise return %false
139  * and emit a 'coprocessor unusable' exception.
140  */
141 bool check_cp0_enabled(DisasContext *ctx);
142 void check_cp1_enabled(DisasContext *ctx);
143 void check_cp1_64bitmode(DisasContext *ctx);
144 void check_cp1_registers(DisasContext *ctx, int regs);
145 void check_cop1x(DisasContext *ctx);
146 
147 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset);
148 void gen_move_low32(TCGv ret, TCGv_i64 arg);
149 void gen_move_high32(TCGv ret, TCGv_i64 arg);
150 void gen_load_gpr(TCGv t, int reg);
151 void gen_store_gpr(TCGv t, int reg);
152 #if defined(TARGET_MIPS64)
153 void gen_load_gpr_hi(TCGv_i64 t, int reg);
154 void gen_store_gpr_hi(TCGv_i64 t, int reg);
155 #endif /* TARGET_MIPS64 */
156 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
157 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
158 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
159 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
160 int get_fp_bit(int cc);
161 
162 void gen_ldxs(DisasContext *ctx, int base, int index, int rd);
163 void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp);
164 void gen_addiupc(DisasContext *ctx, int rx, int imm,
165                  int is_64_bit, int extended);
166 
167 /*
168  * Address Computation and Large Constant Instructions
169  */
170 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1);
171 bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
172 bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
173 
174 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel);
175 
176 extern TCGv cpu_gpr[32], cpu_PC;
177 #if defined(TARGET_MIPS64)
178 extern TCGv_i64 cpu_gpr_hi[32];
179 #endif
180 extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
181 extern TCGv_i32 fpu_fcr0, fpu_fcr31;
182 extern TCGv_i64 fpu_f64[32];
183 extern TCGv bcond;
184 
185 #define LOG_DISAS(...)                                                        \
186     do {                                                                      \
187         if (MIPS_DEBUG_DISAS) {                                               \
188             qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__);                 \
189         }                                                                     \
190     } while (0)
191 
192 #define MIPS_INVAL(op)                                                        \
193     do {                                                                      \
194         if (MIPS_DEBUG_DISAS) {                                               \
195             qemu_log_mask(CPU_LOG_TB_IN_ASM,                                  \
196                           TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
197                           ctx->base.pc_next, ctx->opcode, op,                 \
198                           ctx->opcode >> 26, ctx->opcode & 0x3F,              \
199                           ((ctx->opcode >> 16) & 0x1F));                      \
200         }                                                                     \
201     } while (0)
202 
203 /* MSA */
204 void msa_translate_init(void);
205 
206 /* MXU */
207 void mxu_translate_init(void);
208 bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
209 
210 /* decodetree generated */
211 bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
212 bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
213 bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
214 #if defined(TARGET_MIPS64)
215 bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
216 #endif
217 bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
218 
219 /*
220  * Helpers for implementing sets of trans_* functions.
221  * Defer the implementation of NAME to FUNC, with optional extra arguments.
222  */
223 #define TRANS(NAME, FUNC, ...) \
224     static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
225     { return FUNC(ctx, a, __VA_ARGS__); }
226 
227 static inline bool cpu_is_bigendian(DisasContext *ctx)
228 {
229     return extract32(ctx->CP0_Config0, CP0C0_BE, 1);
230 }
231 
232 #endif
233