2 * QEMU MIPS emulation: Special opcode helpers
4 * Copyright (c) 2004-2005 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include "exec/helper-proto.h"
24 #include "exec/exec-all.h"
28 target_ulong
helper_di(CPUMIPSState
*env
)
30 target_ulong t0
= env
->CP0_Status
;
32 env
->CP0_Status
= t0
& ~(1 << CP0St_IE
);
36 target_ulong
helper_ei(CPUMIPSState
*env
)
38 target_ulong t0
= env
->CP0_Status
;
40 env
->CP0_Status
= t0
| (1 << CP0St_IE
);
44 static void debug_pre_eret(CPUMIPSState
*env
)
46 if (qemu_loglevel_mask(CPU_LOG_EXEC
)) {
47 qemu_log("ERET: PC " TARGET_FMT_lx
" EPC " TARGET_FMT_lx
,
48 env
->active_tc
.PC
, env
->CP0_EPC
);
49 if (env
->CP0_Status
& (1 << CP0St_ERL
)) {
50 qemu_log(" ErrorEPC " TARGET_FMT_lx
, env
->CP0_ErrorEPC
);
52 if (env
->hflags
& MIPS_HFLAG_DM
) {
53 qemu_log(" DEPC " TARGET_FMT_lx
, env
->CP0_DEPC
);
59 static void debug_post_eret(CPUMIPSState
*env
)
61 if (qemu_loglevel_mask(CPU_LOG_EXEC
)) {
62 qemu_log(" => PC " TARGET_FMT_lx
" EPC " TARGET_FMT_lx
,
63 env
->active_tc
.PC
, env
->CP0_EPC
);
64 if (env
->CP0_Status
& (1 << CP0St_ERL
)) {
65 qemu_log(" ErrorEPC " TARGET_FMT_lx
, env
->CP0_ErrorEPC
);
67 if (env
->hflags
& MIPS_HFLAG_DM
) {
68 qemu_log(" DEPC " TARGET_FMT_lx
, env
->CP0_DEPC
);
70 switch (cpu_mmu_index(env
, false)) {
84 cpu_abort(env_cpu(env
), "Invalid MMU mode!\n");
90 bool mips_io_recompile_replay_branch(CPUState
*cs
, const TranslationBlock
*tb
)
92 MIPSCPU
*cpu
= MIPS_CPU(cs
);
93 CPUMIPSState
*env
= &cpu
->env
;
95 if ((env
->hflags
& MIPS_HFLAG_BMASK
) != 0
96 && env
->active_tc
.PC
!= tb
->pc
) {
97 env
->active_tc
.PC
-= (env
->hflags
& MIPS_HFLAG_B16
? 2 : 4);
98 env
->hflags
&= ~MIPS_HFLAG_BMASK
;
104 static inline void exception_return(CPUMIPSState
*env
)
107 if (env
->CP0_Status
& (1 << CP0St_ERL
)) {
108 mips_env_set_pc(env
, env
->CP0_ErrorEPC
);
109 env
->CP0_Status
&= ~(1 << CP0St_ERL
);
111 mips_env_set_pc(env
, env
->CP0_EPC
);
112 env
->CP0_Status
&= ~(1 << CP0St_EXL
);
115 debug_post_eret(env
);
118 void helper_eret(CPUMIPSState
*env
)
120 exception_return(env
);
125 void helper_eretnc(CPUMIPSState
*env
)
127 exception_return(env
);
130 void helper_deret(CPUMIPSState
*env
)
134 env
->hflags
&= ~MIPS_HFLAG_DM
;
137 mips_env_set_pc(env
, env
->CP0_DEPC
);
139 debug_post_eret(env
);
142 void helper_cache(CPUMIPSState
*env
, target_ulong addr
, uint32_t op
)
144 static const char *const type_name
[] = {
145 "Primary Instruction",
146 "Primary Data or Unified Primary",
150 uint32_t cache_type
= extract32(op
, 0, 2);
151 uint32_t cache_operation
= extract32(op
, 2, 3);
152 target_ulong index
= addr
& 0x1fffffff;
154 switch (cache_operation
) {
155 case 0b010: /* Index Store Tag */
156 memory_region_dispatch_write(env
->itc_tag
, index
, env
->CP0_TagLo
,
157 MO_64
, MEMTXATTRS_UNSPECIFIED
);
159 case 0b001: /* Index Load Tag */
160 memory_region_dispatch_read(env
->itc_tag
, index
, &env
->CP0_TagLo
,
161 MO_64
, MEMTXATTRS_UNSPECIFIED
);
163 case 0b000: /* Index Invalidate */
164 case 0b100: /* Hit Invalidate */
165 case 0b110: /* Hit Writeback */
169 qemu_log_mask(LOG_UNIMP
, "cache operation:%u (type: %s cache)\n",
170 cache_operation
, type_name
[cache_type
]);