MIPS patches queue
- minor simplifications in PREF / JR opcodes - merge 32-bit/64-bit Release6 decodetree definitions - converted NEC Vr54xx extension opcodes to decodetree - housekeeping in gen_helper() macros - replace TARGET_WORDS_BIGENDIAN #ifdef'ry by cpu_is_bigendian() - allow Loongson 3A1000 to use up to 48-bit VAddr -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmEmI78ACgkQ4+MsLN6t wN4RLw/+PIBVfaDvASnFa2f9b4SGQ2WiM0LuLh/sN6ieMiFccqJZPq2Dz5GCQsR7 7v2+MZ9gcAoWH/NCft+vbXGwiP9exoChb8c65Gm0GdpQ3sKPYXJJAi/D0vjuPMGe Yk8DrfERavu4bcpXPaC+B3p8krii88W+vEYvmvWfirD+gWxjF/HviLzHQK/62YMK N695BYVav5Fd3fjqn3p7Kw/WdP++NS757G53dSF/r5l1wFEGFZAuYW7R2rWDQsz+ yWvPUkIFoJ9OXitKw01FVaDNXF3a1efMhZjFvCr0EU0eF4qsxAywXomC4CDpAo+Y s15aNZoxWM4D0eEoNLm874QAgNu9txPJPg5kuZVpBDwdTKWMrShj5+m/QlWqVRcA mj7Ff2/B50mmB8aGfkQm82DpnqNXk9Vr1Y4hGzKrSOc1NGZItnpX2XJfqymEF7M9 9SW73jF6X2871FyiRvd5cO9TGlBieMNMlkenuxiyQNvIgocw1FX606EDji/aFp2e KehjWw/2JCmBC1uUhaYqks4db7B8MSeVl8G3Dwx3lxnuz4xson/yscAxengZBR2r clubyAoEa7+6sc2DhflLGlWfQpiOBDW4FFCW37H7KhVnJXFTomuiMBSSBc+njLMi NDT7wAMCyMXtmZtx3zeWZpppqdc3doaGm3Bq6HDWEkiYaOe6TxA= =ceCP -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/philmd/tags/mips-20210825' into staging MIPS patches queue - minor simplifications in PREF / JR opcodes - merge 32-bit/64-bit Release6 decodetree definitions - converted NEC Vr54xx extension opcodes to decodetree - housekeeping in gen_helper() macros - replace TARGET_WORDS_BIGENDIAN #ifdef'ry by cpu_is_bigendian() - allow Loongson 3A1000 to use up to 48-bit VAddr # gpg: Signature made Wed 25 Aug 2021 12:04:31 BST # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * remotes/philmd/tags/mips-20210825: (28 commits) target/mips: Replace TARGET_WORDS_BIGENDIAN by cpu_is_bigendian() target/mips: Store CP0_Config0 in DisasContext target/mips: Replace GET_LMASK64() macro by get_lmask(64) function target/mips: Replace GET_LMASK() macro by get_lmask(32) function target/mips: Call cpu_is_bigendian & inline GET_OFFSET in ld/st helpers target/mips: Define gen_helper() macros in translate.h target/mips: Use tcg_constant_i32() in generate_exception_err() target/mips: Inline gen_helper_0e0i() target/mips: Inline gen_helper_1e1i() call in op_ld_INSN() macros target/mips: Simplify gen_helper() macros by using tcg_constant_i32() target/mips: Use tcg_constant_i32() in gen_helper_0e2i() target/mips: Remove gen_helper_1e2i() target/mips: Remove gen_helper_0e3i() target/mips: Remove duplicated check_cp1_enabled() calls in Loongson EXT target/mips: Allow Loongson 3A1000 to use up to 48-bit VAddr target/mips: Document Loongson-3A CPU definitions target/mips: Convert Vr54xx MSA* opcodes to decodetree target/mips: Convert Vr54xx MUL* opcodes to decodetree target/mips: Convert Vr54xx MACC* opcodes to decodetree target/mips: Introduce decodetree structure for NEC Vr54xx extension ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d8ae530ec0
@ -805,7 +805,7 @@ const mips_def_t mips_defs[] =
|
|||||||
.mmu_type = MMU_TYPE_R4000,
|
.mmu_type = MMU_TYPE_R4000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "Loongson-3A1000",
|
.name = "Loongson-3A1000", /* Loongson-3A R1, GS464-based */
|
||||||
.CP0_PRid = 0x6305,
|
.CP0_PRid = 0x6305,
|
||||||
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
|
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
|
||||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||||
@ -828,14 +828,14 @@ const mips_def_t mips_defs[] =
|
|||||||
(0x1 << FCR0_D) | (0x1 << FCR0_S),
|
(0x1 << FCR0_D) | (0x1 << FCR0_S),
|
||||||
.CP1_fcr31 = 0,
|
.CP1_fcr31 = 0,
|
||||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||||
.SEGBITS = 42,
|
.SEGBITS = 48,
|
||||||
.PABITS = 48,
|
.PABITS = 48,
|
||||||
.insn_flags = CPU_MIPS64R2 | INSN_LOONGSON3A |
|
.insn_flags = CPU_MIPS64R2 | INSN_LOONGSON3A |
|
||||||
ASE_LMMI | ASE_LEXT,
|
ASE_LMMI | ASE_LEXT,
|
||||||
.mmu_type = MMU_TYPE_R4000,
|
.mmu_type = MMU_TYPE_R4000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "Loongson-3A4000", /* GS464V-based */
|
.name = "Loongson-3A4000", /* Loongson-3A R4, GS464V-based */
|
||||||
.CP0_PRid = 0x14C000,
|
.CP0_PRid = 0x14C000,
|
||||||
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
|
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
|
||||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||||
|
@ -16,21 +16,6 @@ DEF_HELPER_3(lld, tl, env, tl, int)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEF_HELPER_3(muls, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(mulsu, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(macc, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(maccu, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(msac, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(msacu, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(mulhi, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(mulhiu, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(mulshi, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(mulshiu, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(macchi, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(macchiu, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(msachi, tl, env, tl, tl)
|
|
||||||
DEF_HELPER_3(msachiu, tl, env, tl, tl)
|
|
||||||
|
|
||||||
DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||||
#ifdef TARGET_MIPS64
|
#ifdef TARGET_MIPS64
|
||||||
DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||||
@ -609,3 +594,6 @@ DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
|
|||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
#include "tcg/msa_helper.h.inc"
|
#include "tcg/msa_helper.h.inc"
|
||||||
|
|
||||||
|
/* Vendor extensions */
|
||||||
|
#include "tcg/vr54xx_helper.h.inc"
|
||||||
|
@ -52,31 +52,45 @@ HELPER_LD_ATOMIC(lld, ldq, 0x7, (target_ulong))
|
|||||||
|
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
static inline bool cpu_is_bigendian(CPUMIPSState *env)
|
||||||
#define GET_LMASK(v) ((v) & 3)
|
{
|
||||||
#define GET_OFFSET(addr, offset) (addr + (offset))
|
return extract32(env->CP0_Config0, CP0C0_BE, 1);
|
||||||
#else
|
}
|
||||||
#define GET_LMASK(v) (((v) & 3) ^ 3)
|
|
||||||
#define GET_OFFSET(addr, offset) (addr - (offset))
|
static inline target_ulong get_lmask(CPUMIPSState *env,
|
||||||
#endif
|
target_ulong value, unsigned bits)
|
||||||
|
{
|
||||||
|
unsigned mask = (bits / BITS_PER_BYTE) - 1;
|
||||||
|
|
||||||
|
value &= mask;
|
||||||
|
|
||||||
|
if (!cpu_is_bigendian(env)) {
|
||||||
|
value ^= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
||||||
int mem_idx)
|
int mem_idx)
|
||||||
{
|
{
|
||||||
|
target_ulong lmask = get_lmask(env, arg2, 32);
|
||||||
|
int dir = cpu_is_bigendian(env) ? 1 : -1;
|
||||||
|
|
||||||
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
|
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
|
||||||
|
|
||||||
if (GET_LMASK(arg2) <= 2) {
|
if (lmask <= 2) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16),
|
cpu_stb_mmuidx_ra(env, arg2 + 1 * dir, (uint8_t)(arg1 >> 16),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK(arg2) <= 1) {
|
if (lmask <= 1) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8),
|
cpu_stb_mmuidx_ra(env, arg2 + 2 * dir, (uint8_t)(arg1 >> 8),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK(arg2) == 0) {
|
if (lmask == 0) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 3), (uint8_t)arg1,
|
cpu_stb_mmuidx_ra(env, arg2 + 3 * dir, (uint8_t)arg1,
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,20 +98,23 @@ void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
|||||||
void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
||||||
int mem_idx)
|
int mem_idx)
|
||||||
{
|
{
|
||||||
|
target_ulong lmask = get_lmask(env, arg2, 32);
|
||||||
|
int dir = cpu_is_bigendian(env) ? 1 : -1;
|
||||||
|
|
||||||
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
|
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
|
||||||
|
|
||||||
if (GET_LMASK(arg2) >= 1) {
|
if (lmask >= 1) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8),
|
cpu_stb_mmuidx_ra(env, arg2 - 1 * dir, (uint8_t)(arg1 >> 8),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK(arg2) >= 2) {
|
if (lmask >= 2) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16),
|
cpu_stb_mmuidx_ra(env, arg2 - 2 * dir, (uint8_t)(arg1 >> 16),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK(arg2) == 3) {
|
if (lmask == 3) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24),
|
cpu_stb_mmuidx_ra(env, arg2 - 3 * dir, (uint8_t)(arg1 >> 24),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,49 +124,47 @@ void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
|||||||
* "half" load and stores. We must do the memory access inline,
|
* "half" load and stores. We must do the memory access inline,
|
||||||
* or fault handling won't work.
|
* or fault handling won't work.
|
||||||
*/
|
*/
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
|
||||||
#define GET_LMASK64(v) ((v) & 7)
|
|
||||||
#else
|
|
||||||
#define GET_LMASK64(v) (((v) & 7) ^ 7)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
||||||
int mem_idx)
|
int mem_idx)
|
||||||
{
|
{
|
||||||
|
target_ulong lmask = get_lmask(env, arg2, 64);
|
||||||
|
int dir = cpu_is_bigendian(env) ? 1 : -1;
|
||||||
|
|
||||||
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
|
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) <= 6) {
|
if (lmask <= 6) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48),
|
cpu_stb_mmuidx_ra(env, arg2 + 1 * dir, (uint8_t)(arg1 >> 48),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) <= 5) {
|
if (lmask <= 5) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40),
|
cpu_stb_mmuidx_ra(env, arg2 + 2 * dir, (uint8_t)(arg1 >> 40),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) <= 4) {
|
if (lmask <= 4) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32),
|
cpu_stb_mmuidx_ra(env, arg2 + 3 * dir, (uint8_t)(arg1 >> 32),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) <= 3) {
|
if (lmask <= 3) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24),
|
cpu_stb_mmuidx_ra(env, arg2 + 4 * dir, (uint8_t)(arg1 >> 24),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) <= 2) {
|
if (lmask <= 2) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16),
|
cpu_stb_mmuidx_ra(env, arg2 + 5 * dir, (uint8_t)(arg1 >> 16),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) <= 1) {
|
if (lmask <= 1) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8),
|
cpu_stb_mmuidx_ra(env, arg2 + 6 * dir, (uint8_t)(arg1 >> 8),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) <= 0) {
|
if (lmask <= 0) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 7), (uint8_t)arg1,
|
cpu_stb_mmuidx_ra(env, arg2 + 7 * dir, (uint8_t)arg1,
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,40 +172,43 @@ void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
|||||||
void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
|
||||||
int mem_idx)
|
int mem_idx)
|
||||||
{
|
{
|
||||||
|
target_ulong lmask = get_lmask(env, arg2, 64);
|
||||||
|
int dir = cpu_is_bigendian(env) ? 1 : -1;
|
||||||
|
|
||||||
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
|
cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) >= 1) {
|
if (lmask >= 1) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8),
|
cpu_stb_mmuidx_ra(env, arg2 - 1 * dir, (uint8_t)(arg1 >> 8),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) >= 2) {
|
if (lmask >= 2) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16),
|
cpu_stb_mmuidx_ra(env, arg2 - 2 * dir, (uint8_t)(arg1 >> 16),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) >= 3) {
|
if (lmask >= 3) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24),
|
cpu_stb_mmuidx_ra(env, arg2 - 3 * dir, (uint8_t)(arg1 >> 24),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) >= 4) {
|
if (lmask >= 4) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32),
|
cpu_stb_mmuidx_ra(env, arg2 - 4 * dir, (uint8_t)(arg1 >> 32),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) >= 5) {
|
if (lmask >= 5) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40),
|
cpu_stb_mmuidx_ra(env, arg2 - 5 * dir, (uint8_t)(arg1 >> 40),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) >= 6) {
|
if (lmask >= 6) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48),
|
cpu_stb_mmuidx_ra(env, arg2 - 6 * dir, (uint8_t)(arg1 >> 48),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_LMASK64(arg2) == 7) {
|
if (lmask == 7) {
|
||||||
cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56),
|
cpu_stb_mmuidx_ra(env, arg2 - 7 * dir, (uint8_t)(arg1 >> 56),
|
||||||
mem_idx, GETPC());
|
mem_idx, GETPC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
gen = [
|
gen = [
|
||||||
decodetree.process('mips32r6.decode', extra_args: '--static-decode=decode_mips32r6'),
|
decodetree.process('rel6.decode', extra_args: ['--decode=decode_isa_rel6']),
|
||||||
decodetree.process('mips64r6.decode', extra_args: '--static-decode=decode_mips64r6'),
|
|
||||||
decodetree.process('msa.decode', extra_args: '--decode=decode_ase_msa'),
|
decodetree.process('msa.decode', extra_args: '--decode=decode_ase_msa'),
|
||||||
decodetree.process('tx79.decode', extra_args: '--static-decode=decode_tx79'),
|
decodetree.process('tx79.decode', extra_args: '--static-decode=decode_tx79'),
|
||||||
|
decodetree.process('vr54xx.decode', extra_args: '--decode=decode_ext_vr54xx'),
|
||||||
]
|
]
|
||||||
|
|
||||||
mips_ss.add(gen)
|
mips_ss.add(gen)
|
||||||
@ -19,6 +19,8 @@ mips_ss.add(files(
|
|||||||
'translate.c',
|
'translate.c',
|
||||||
'translate_addr_const.c',
|
'translate_addr_const.c',
|
||||||
'txx9_translate.c',
|
'txx9_translate.c',
|
||||||
|
'vr54xx_helper.c',
|
||||||
|
'vr54xx_translate.c',
|
||||||
))
|
))
|
||||||
mips_ss.add(when: 'TARGET_MIPS64', if_true: files(
|
mips_ss.add(when: 'TARGET_MIPS64', if_true: files(
|
||||||
'tx79_translate.c',
|
'tx79_translate.c',
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
# MIPS64 Release 6 instruction set
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Philippe Mathieu-Daudé
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
#
|
|
||||||
# Reference:
|
|
||||||
# MIPS Architecture for Programmers Volume II-A
|
|
||||||
# The MIPS64 Instruction Set Reference Manual, Revision 6.06
|
|
||||||
# (Document Number: MD00087-2B-MIPS64BIS-AFP-6.06)
|
|
||||||
#
|
|
||||||
|
|
||||||
&rtype rs rt rd sa !extern
|
|
||||||
|
|
||||||
&REMOVED !extern
|
|
||||||
|
|
||||||
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype
|
|
||||||
|
|
||||||
DLSA 000000 ..... ..... ..... 000 .. 010101 @lsa
|
|
||||||
|
|
||||||
REMOVED 011010 ----- ----- ---------------- # LDL
|
|
||||||
REMOVED 011011 ----- ----- ---------------- # LDR
|
|
||||||
REMOVED 101100 ----- ----- ---------------- # SDL
|
|
||||||
REMOVED 101101 ----- ----- ---------------- # SDR
|
|
||||||
|
|
||||||
REMOVED 110100 ----- ----- ---------------- # LLD
|
|
||||||
REMOVED 111100 ----- ----- ---------------- # SCD
|
|
@ -11,11 +11,11 @@
|
|||||||
# - The MIPS64 SIMD Architecture Module, Revision 1.12
|
# - The MIPS64 SIMD Architecture Module, Revision 1.12
|
||||||
# (Document Number: MD00868-1D-MSA64-AFP-01.12)
|
# (Document Number: MD00868-1D-MSA64-AFP-01.12)
|
||||||
|
|
||||||
&rtype rs rt rd sa
|
&r rs rt rd sa
|
||||||
|
|
||||||
&msa_bz df wt s16
|
&msa_bz df wt s16
|
||||||
|
|
||||||
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype
|
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &r
|
||||||
@bz ...... ... .. wt:5 s16:16 &msa_bz df=3
|
@bz ...... ... .. wt:5 s16:16 &msa_bz df=3
|
||||||
@bz_df ...... ... df:2 wt:5 s16:16 &msa_bz
|
@bz_df ...... ... df:2 wt:5 s16:16 &msa_bz
|
||||||
|
|
||||||
|
@ -2261,12 +2261,12 @@ static bool trans_MSA(DisasContext *ctx, arg_MSA *a)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_LSA(DisasContext *ctx, arg_rtype *a)
|
static bool trans_LSA(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return gen_lsa(ctx, a->rd, a->rt, a->rs, a->sa);
|
return gen_lsa(ctx, a->rd, a->rt, a->rs, a->sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_DLSA(DisasContext *ctx, arg_rtype *a)
|
static bool trans_DLSA(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
if (TARGET_LONG_BITS != 64) {
|
if (TARGET_LONG_BITS != 64) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -999,11 +999,11 @@ static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
|
|||||||
|
|
||||||
gen_base_offset_addr(ctx, taddr, base, offset);
|
gen_base_offset_addr(ctx, taddr, base, offset);
|
||||||
tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
|
tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
if (cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
|
tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
|
||||||
#else
|
} else {
|
||||||
tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
|
tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
|
||||||
#endif
|
}
|
||||||
gen_store_gpr(tmp1, reg1);
|
gen_store_gpr(tmp1, reg1);
|
||||||
tcg_temp_free(tmp1);
|
tcg_temp_free(tmp1);
|
||||||
gen_store_gpr(tmp2, reg2);
|
gen_store_gpr(tmp2, reg2);
|
||||||
@ -1035,11 +1035,11 @@ static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
|
|||||||
gen_load_gpr(tmp1, reg1);
|
gen_load_gpr(tmp1, reg1);
|
||||||
gen_load_gpr(tmp2, reg2);
|
gen_load_gpr(tmp2, reg2);
|
||||||
|
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
if (cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
|
tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
|
||||||
#else
|
} else {
|
||||||
tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
|
tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
|
tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
|
||||||
tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
|
tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
|
||||||
|
@ -26,124 +26,6 @@
|
|||||||
#include "exec/memop.h"
|
#include "exec/memop.h"
|
||||||
#include "fpu_helper.h"
|
#include "fpu_helper.h"
|
||||||
|
|
||||||
/* 64 bits arithmetic for 32 bits hosts */
|
|
||||||
static inline uint64_t get_HILO(CPUMIPSState *env)
|
|
||||||
{
|
|
||||||
return ((uint64_t)(env->active_tc.HI[0]) << 32) |
|
|
||||||
(uint32_t)env->active_tc.LO[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO)
|
|
||||||
{
|
|
||||||
env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
|
|
||||||
return env->active_tc.HI[0] = (int32_t)(HILO >> 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO)
|
|
||||||
{
|
|
||||||
target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
|
|
||||||
env->active_tc.HI[0] = (int32_t)(HILO >> 32);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Multiplication variants of the vr54xx. */
|
|
||||||
target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 *
|
|
||||||
(int64_t)(int32_t)arg2));
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 *
|
|
||||||
(uint64_t)(uint32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
|
|
||||||
(int64_t)(int32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
|
|
||||||
(int64_t)(int32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HI_LOT0(env, (uint64_t)get_HILO(env) +
|
|
||||||
(uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, (uint64_t)get_HILO(env) +
|
|
||||||
(uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
|
|
||||||
(int64_t)(int32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
|
|
||||||
(int64_t)(int32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HI_LOT0(env, (uint64_t)get_HILO(env) -
|
|
||||||
(uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, (uint64_t)get_HILO(env) -
|
|
||||||
(uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 *
|
|
||||||
(uint64_t)(uint32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 *
|
|
||||||
(int64_t)(int32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
|
|
||||||
target_ulong arg2)
|
|
||||||
{
|
|
||||||
return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 *
|
|
||||||
(uint64_t)(uint32_t)arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline target_ulong bitswap(target_ulong v)
|
static inline target_ulong bitswap(target_ulong v)
|
||||||
{
|
{
|
||||||
v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) |
|
v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) |
|
||||||
|
@ -5,21 +5,29 @@
|
|||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
#
|
#
|
||||||
# Reference:
|
# Reference:
|
||||||
|
#
|
||||||
# MIPS Architecture for Programmers Volume II-A
|
# MIPS Architecture for Programmers Volume II-A
|
||||||
# The MIPS32 Instruction Set Reference Manual, Revision 6.06
|
# The MIPS32 Instruction Set Reference Manual, Revision 6.06
|
||||||
# (Document Number: MD00086-2B-MIPS32BIS-AFP-06.06)
|
# (Document Number: MD00086-2B-MIPS32BIS-AFP-06.06)
|
||||||
#
|
#
|
||||||
|
# MIPS Architecture for Programmers Volume II-A
|
||||||
|
# The MIPS64 Instruction Set Reference Manual, Revision 6.06
|
||||||
|
# (Document Number: MD00087-2B-MIPS64BIS-AFP-6.06)
|
||||||
|
|
||||||
&rtype rs rt rd sa
|
&r rs rt rd sa
|
||||||
|
|
||||||
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype
|
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &r
|
||||||
|
|
||||||
LSA 000000 ..... ..... ..... 000 .. 000101 @lsa
|
LSA 000000 ..... ..... ..... 000 .. 000101 @lsa
|
||||||
|
DLSA 000000 ..... ..... ..... 000 .. 010101 @lsa
|
||||||
|
|
||||||
REMOVED 010011 ----- ----- ----- ----- ------ # COP1X (COP3)
|
REMOVED 010011 ----- ----- ----- ----- ------ # COP1X (COP3)
|
||||||
|
|
||||||
REMOVED 011100 ----- ----- ----- ----- ------ # SPECIAL2
|
REMOVED 011100 ----- ----- ----- ----- ------ # SPECIAL2
|
||||||
|
|
||||||
|
REMOVED 011010 ----- ----- ---------------- # LDL
|
||||||
|
REMOVED 011011 ----- ----- ---------------- # LDR
|
||||||
|
|
||||||
REMOVED 011111 ----- ----- ---------- 011001 # LWLE
|
REMOVED 011111 ----- ----- ---------- 011001 # LWLE
|
||||||
REMOVED 011111 ----- ----- ---------- 011010 # LWRE
|
REMOVED 011111 ----- ----- ---------- 011010 # LWRE
|
||||||
REMOVED 011111 ----- ----- ---------- 100001 # SWLE
|
REMOVED 011111 ----- ----- ---------- 100001 # SWLE
|
||||||
@ -28,9 +36,14 @@ REMOVED 011111 ----- ----- ---------- 100010 # SWRE
|
|||||||
REMOVED 100010 ----- ----- ---------------- # LWL
|
REMOVED 100010 ----- ----- ---------------- # LWL
|
||||||
REMOVED 100110 ----- ----- ---------------- # LWR
|
REMOVED 100110 ----- ----- ---------------- # LWR
|
||||||
REMOVED 101010 ----- ----- ---------------- # SWL
|
REMOVED 101010 ----- ----- ---------------- # SWL
|
||||||
|
REMOVED 101100 ----- ----- ---------------- # SDL
|
||||||
|
REMOVED 101101 ----- ----- ---------------- # SDR
|
||||||
REMOVED 101110 ----- ----- ---------------- # SWR
|
REMOVED 101110 ----- ----- ---------------- # SWR
|
||||||
|
|
||||||
REMOVED 101111 ----- ----- ---------------- # CACHE
|
REMOVED 101111 ----- ----- ---------------- # CACHE
|
||||||
|
|
||||||
REMOVED 110000 ----- ----- ---------------- # LL
|
REMOVED 110000 ----- ----- ---------------- # LL
|
||||||
REMOVED 110011 ----- ----- ---------------- # PREF
|
REMOVED 110011 ----- ----- ---------------- # PREF
|
||||||
|
REMOVED 110100 ----- ----- ---------------- # LLD
|
||||||
REMOVED 111000 ----- ----- ---------------- # SC
|
REMOVED 111000 ----- ----- ---------------- # SC
|
||||||
|
REMOVED 111100 ----- ----- ---------------- # SCD
|
@ -13,9 +13,8 @@
|
|||||||
#include "exec/helper-gen.h"
|
#include "exec/helper-gen.h"
|
||||||
#include "translate.h"
|
#include "translate.h"
|
||||||
|
|
||||||
/* Include the auto-generated decoder. */
|
/* Include the auto-generated decoders. */
|
||||||
#include "decode-mips32r6.c.inc"
|
#include "decode-rel6.c.inc"
|
||||||
#include "decode-mips64r6.c.inc"
|
|
||||||
|
|
||||||
bool trans_REMOVED(DisasContext *ctx, arg_REMOVED *a)
|
bool trans_REMOVED(DisasContext *ctx, arg_REMOVED *a)
|
||||||
{
|
{
|
||||||
@ -24,20 +23,15 @@ bool trans_REMOVED(DisasContext *ctx, arg_REMOVED *a)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_LSA(DisasContext *ctx, arg_rtype *a)
|
static bool trans_LSA(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return gen_lsa(ctx, a->rd, a->rt, a->rs, a->sa);
|
return gen_lsa(ctx, a->rd, a->rt, a->rs, a->sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_DLSA(DisasContext *ctx, arg_rtype *a)
|
static bool trans_DLSA(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
|
if (TARGET_LONG_BITS != 64) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return gen_dlsa(ctx, a->rd, a->rt, a->rs, a->sa);
|
return gen_dlsa(ctx, a->rd, a->rt, a->rs, a->sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool decode_isa_rel6(DisasContext *ctx, uint32_t insn)
|
|
||||||
{
|
|
||||||
if (TARGET_LONG_BITS == 64 && decode_mips64r6(ctx, insn)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return decode_mips32r6(ctx, insn);
|
|
||||||
}
|
|
||||||
|
@ -294,26 +294,6 @@ enum {
|
|||||||
R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
|
R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Multiplication variants of the vr54xx. */
|
|
||||||
#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
|
|
||||||
|
|
||||||
enum {
|
|
||||||
OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
|
|
||||||
OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
|
|
||||||
OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
|
|
||||||
OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
|
|
||||||
OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
|
|
||||||
OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
|
|
||||||
OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
|
|
||||||
OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
|
|
||||||
OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
|
|
||||||
OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
|
|
||||||
OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
|
|
||||||
OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
|
|
||||||
OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
|
|
||||||
OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* REGIMM (rt field) opcodes */
|
/* REGIMM (rt field) opcodes */
|
||||||
#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
|
#define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
|
||||||
|
|
||||||
@ -1233,48 +1213,6 @@ TCGv_i64 fpu_f64[32];
|
|||||||
|
|
||||||
#include "exec/gen-icount.h"
|
#include "exec/gen-icount.h"
|
||||||
|
|
||||||
#define gen_helper_0e0i(name, arg) do { \
|
|
||||||
TCGv_i32 helper_tmp = tcg_const_i32(arg); \
|
|
||||||
gen_helper_##name(cpu_env, helper_tmp); \
|
|
||||||
tcg_temp_free_i32(helper_tmp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define gen_helper_0e1i(name, arg1, arg2) do { \
|
|
||||||
TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
|
|
||||||
gen_helper_##name(cpu_env, arg1, helper_tmp); \
|
|
||||||
tcg_temp_free_i32(helper_tmp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define gen_helper_1e0i(name, ret, arg1) do { \
|
|
||||||
TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
|
|
||||||
gen_helper_##name(ret, cpu_env, helper_tmp); \
|
|
||||||
tcg_temp_free_i32(helper_tmp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
|
|
||||||
TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
|
|
||||||
gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
|
|
||||||
tcg_temp_free_i32(helper_tmp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
|
|
||||||
TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
|
|
||||||
gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
|
|
||||||
tcg_temp_free_i32(helper_tmp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
|
|
||||||
TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
|
|
||||||
gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
|
|
||||||
tcg_temp_free_i32(helper_tmp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
|
|
||||||
TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
|
|
||||||
gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
|
|
||||||
tcg_temp_free_i32(helper_tmp); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define DISAS_STOP DISAS_TARGET_0
|
#define DISAS_STOP DISAS_TARGET_0
|
||||||
#define DISAS_EXIT DISAS_TARGET_1
|
#define DISAS_EXIT DISAS_TARGET_1
|
||||||
|
|
||||||
@ -1413,18 +1351,15 @@ static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
|
|
||||||
void generate_exception_err(DisasContext *ctx, int excp, int err)
|
void generate_exception_err(DisasContext *ctx, int excp, int err)
|
||||||
{
|
{
|
||||||
TCGv_i32 texcp = tcg_const_i32(excp);
|
|
||||||
TCGv_i32 terr = tcg_const_i32(err);
|
|
||||||
save_cpu_state(ctx, 1);
|
save_cpu_state(ctx, 1);
|
||||||
gen_helper_raise_exception_err(cpu_env, texcp, terr);
|
gen_helper_raise_exception_err(cpu_env, tcg_constant_i32(excp),
|
||||||
tcg_temp_free_i32(terr);
|
tcg_constant_i32(err));
|
||||||
tcg_temp_free_i32(texcp);
|
|
||||||
ctx->base.is_jmp = DISAS_NORETURN;
|
ctx->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_exception(DisasContext *ctx, int excp)
|
void generate_exception(DisasContext *ctx, int excp)
|
||||||
{
|
{
|
||||||
gen_helper_0e0i(raise_exception, excp);
|
gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_exception_end(DisasContext *ctx, int excp)
|
void generate_exception_end(DisasContext *ctx, int excp)
|
||||||
@ -2033,7 +1968,7 @@ static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
|
|||||||
static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
|
static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
|
||||||
DisasContext *ctx) \
|
DisasContext *ctx) \
|
||||||
{ \
|
{ \
|
||||||
gen_helper_1e1i(insn, ret, arg1, mem_idx); \
|
gen_helper_##insn(ret, cpu_env, arg1, tcg_constant_i32(mem_idx)); \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
OP_LD_ATOMIC(ll, ld32s);
|
OP_LD_ATOMIC(ll, ld32s);
|
||||||
@ -2113,9 +2048,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
|||||||
*/
|
*/
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 7);
|
tcg_gen_andi_tl(t1, t0, 7);
|
||||||
#ifndef TARGET_WORDS_BIGENDIAN
|
if (!cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 7);
|
tcg_gen_xori_tl(t1, t1, 7);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~7);
|
tcg_gen_andi_tl(t0, t0, ~7);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
|
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
|
||||||
@ -2137,9 +2072,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
|||||||
*/
|
*/
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 7);
|
tcg_gen_andi_tl(t1, t0, 7);
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
if (cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 7);
|
tcg_gen_xori_tl(t1, t1, 7);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~7);
|
tcg_gen_andi_tl(t0, t0, ~7);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
|
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
|
||||||
@ -2218,9 +2153,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
|||||||
*/
|
*/
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 3);
|
tcg_gen_andi_tl(t1, t0, 3);
|
||||||
#ifndef TARGET_WORDS_BIGENDIAN
|
if (!cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 3);
|
tcg_gen_xori_tl(t1, t1, 3);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~3);
|
tcg_gen_andi_tl(t0, t0, ~3);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
|
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
|
||||||
@ -2246,9 +2181,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
|||||||
*/
|
*/
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 3);
|
tcg_gen_andi_tl(t1, t0, 3);
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
if (cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 3);
|
tcg_gen_xori_tl(t1, t1, 3);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~3);
|
tcg_gen_andi_tl(t0, t0, ~3);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
|
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
|
||||||
@ -3764,70 +3699,6 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
|
|||||||
tcg_temp_free(t1);
|
tcg_temp_free(t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
|
|
||||||
int rd, int rs, int rt)
|
|
||||||
{
|
|
||||||
TCGv t0 = tcg_temp_new();
|
|
||||||
TCGv t1 = tcg_temp_new();
|
|
||||||
|
|
||||||
gen_load_gpr(t0, rs);
|
|
||||||
gen_load_gpr(t1, rt);
|
|
||||||
|
|
||||||
switch (opc) {
|
|
||||||
case OPC_VR54XX_MULS:
|
|
||||||
gen_helper_muls(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MULSU:
|
|
||||||
gen_helper_mulsu(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MACC:
|
|
||||||
gen_helper_macc(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MACCU:
|
|
||||||
gen_helper_maccu(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MSAC:
|
|
||||||
gen_helper_msac(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MSACU:
|
|
||||||
gen_helper_msacu(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MULHI:
|
|
||||||
gen_helper_mulhi(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MULHIU:
|
|
||||||
gen_helper_mulhiu(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MULSHI:
|
|
||||||
gen_helper_mulshi(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MULSHIU:
|
|
||||||
gen_helper_mulshiu(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MACCHI:
|
|
||||||
gen_helper_macchi(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MACCHIU:
|
|
||||||
gen_helper_macchiu(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MSACHI:
|
|
||||||
gen_helper_msachi(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
case OPC_VR54XX_MSACHIU:
|
|
||||||
gen_helper_msachiu(t0, cpu_env, t0, t1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MIPS_INVAL("mul vr54xx");
|
|
||||||
gen_reserved_instruction(ctx);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
gen_store_gpr(t0, rd);
|
|
||||||
|
|
||||||
out:
|
|
||||||
tcg_temp_free(t0);
|
|
||||||
tcg_temp_free(t1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gen_cl(DisasContext *ctx, uint32_t opc,
|
static void gen_cl(DisasContext *ctx, uint32_t opc,
|
||||||
int rd, int rs)
|
int rd, int rs)
|
||||||
{
|
{
|
||||||
@ -4529,9 +4400,9 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
|||||||
t1 = tcg_temp_new();
|
t1 = tcg_temp_new();
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 3);
|
tcg_gen_andi_tl(t1, t0, 3);
|
||||||
#ifndef TARGET_WORDS_BIGENDIAN
|
if (!cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 3);
|
tcg_gen_xori_tl(t1, t1, 3);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~3);
|
tcg_gen_andi_tl(t0, t0, ~3);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
|
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
|
||||||
@ -4559,9 +4430,9 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
|||||||
t1 = tcg_temp_new();
|
t1 = tcg_temp_new();
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 3);
|
tcg_gen_andi_tl(t1, t0, 3);
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
if (cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 3);
|
tcg_gen_xori_tl(t1, t1, 3);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~3);
|
tcg_gen_andi_tl(t0, t0, ~3);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
|
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
|
||||||
@ -4591,9 +4462,9 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
|||||||
t1 = tcg_temp_new();
|
t1 = tcg_temp_new();
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 7);
|
tcg_gen_andi_tl(t1, t0, 7);
|
||||||
#ifndef TARGET_WORDS_BIGENDIAN
|
if (!cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 7);
|
tcg_gen_xori_tl(t1, t1, 7);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~7);
|
tcg_gen_andi_tl(t0, t0, ~7);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
|
||||||
@ -4613,9 +4484,9 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
|||||||
t1 = tcg_temp_new();
|
t1 = tcg_temp_new();
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
||||||
tcg_gen_andi_tl(t1, t0, 7);
|
tcg_gen_andi_tl(t1, t0, 7);
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
if (cpu_is_bigendian(ctx)) {
|
||||||
tcg_gen_xori_tl(t1, t1, 7);
|
tcg_gen_xori_tl(t1, t1, 7);
|
||||||
#endif
|
}
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
tcg_gen_andi_tl(t0, t0, ~7);
|
tcg_gen_andi_tl(t0, t0, ~7);
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
|
||||||
@ -4777,7 +4648,6 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case OPC_GSLWXC1:
|
case OPC_GSLWXC1:
|
||||||
check_cp1_enabled(ctx);
|
|
||||||
gen_base_offset_addr(ctx, t0, rs, offset);
|
gen_base_offset_addr(ctx, t0, rs, offset);
|
||||||
if (rd) {
|
if (rd) {
|
||||||
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
|
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
|
||||||
@ -4790,7 +4660,6 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
|
|||||||
break;
|
break;
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
case OPC_GSLDXC1:
|
case OPC_GSLDXC1:
|
||||||
check_cp1_enabled(ctx);
|
|
||||||
gen_base_offset_addr(ctx, t0, rs, offset);
|
gen_base_offset_addr(ctx, t0, rs, offset);
|
||||||
if (rd) {
|
if (rd) {
|
||||||
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
|
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
|
||||||
@ -9170,12 +9039,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
|
|||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
/* XXX: For now we support only a single FPU context. */
|
/* XXX: For now we support only a single FPU context. */
|
||||||
{
|
gen_helper_0e2i(ctc1, t0, tcg_constant_i32(rd), rt);
|
||||||
TCGv_i32 fs_tmp = tcg_const_i32(rd);
|
|
||||||
|
|
||||||
gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
|
|
||||||
tcg_temp_free_i32(fs_tmp);
|
|
||||||
}
|
|
||||||
/* Stop translation as we may have changed hflags */
|
/* Stop translation as we may have changed hflags */
|
||||||
ctx->base.is_jmp = DISAS_STOP;
|
ctx->base.is_jmp = DISAS_STOP;
|
||||||
break;
|
break;
|
||||||
@ -9792,12 +9656,7 @@ static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
|
|||||||
case OPC_CTC1:
|
case OPC_CTC1:
|
||||||
gen_load_gpr(t0, rt);
|
gen_load_gpr(t0, rt);
|
||||||
save_cpu_state(ctx, 0);
|
save_cpu_state(ctx, 0);
|
||||||
{
|
gen_helper_0e2i(ctc1, t0, tcg_constant_i32(fs), rt);
|
||||||
TCGv_i32 fs_tmp = tcg_const_i32(fs);
|
|
||||||
|
|
||||||
gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
|
|
||||||
tcg_temp_free_i32(fs_tmp);
|
|
||||||
}
|
|
||||||
/* Stop translation as we may have changed hflags */
|
/* Stop translation as we may have changed hflags */
|
||||||
ctx->base.is_jmp = DISAS_STOP;
|
ctx->base.is_jmp = DISAS_STOP;
|
||||||
break;
|
break;
|
||||||
@ -11550,17 +11409,17 @@ static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
|
|||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
|
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
|
||||||
tcg_temp_free(t0);
|
tcg_temp_free(t0);
|
||||||
#ifdef TARGET_WORDS_BIGENDIAN
|
if (cpu_is_bigendian(ctx)) {
|
||||||
gen_load_fpr32(ctx, fp, fs);
|
gen_load_fpr32(ctx, fp, fs);
|
||||||
gen_load_fpr32h(ctx, fph, ft);
|
gen_load_fpr32h(ctx, fph, ft);
|
||||||
gen_store_fpr32h(ctx, fp, fd);
|
gen_store_fpr32h(ctx, fp, fd);
|
||||||
gen_store_fpr32(ctx, fph, fd);
|
gen_store_fpr32(ctx, fph, fd);
|
||||||
#else
|
} else {
|
||||||
gen_load_fpr32h(ctx, fph, fs);
|
gen_load_fpr32h(ctx, fph, fs);
|
||||||
gen_load_fpr32(ctx, fp, ft);
|
gen_load_fpr32(ctx, fp, ft);
|
||||||
gen_store_fpr32(ctx, fph, fd);
|
gen_store_fpr32(ctx, fph, fd);
|
||||||
gen_store_fpr32h(ctx, fp, fd);
|
gen_store_fpr32h(ctx, fp, fd);
|
||||||
#endif
|
}
|
||||||
gen_set_label(l2);
|
gen_set_label(l2);
|
||||||
tcg_temp_free_i32(fp);
|
tcg_temp_free_i32(fp);
|
||||||
tcg_temp_free_i32(fph);
|
tcg_temp_free_i32(fph);
|
||||||
@ -14144,13 +14003,12 @@ static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
|
|
||||||
static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
||||||
{
|
{
|
||||||
int rs, rt, rd, sa;
|
int rs, rt, rd;
|
||||||
uint32_t op1;
|
uint32_t op1;
|
||||||
|
|
||||||
rs = (ctx->opcode >> 21) & 0x1f;
|
rs = (ctx->opcode >> 21) & 0x1f;
|
||||||
rt = (ctx->opcode >> 16) & 0x1f;
|
rt = (ctx->opcode >> 16) & 0x1f;
|
||||||
rd = (ctx->opcode >> 11) & 0x1f;
|
rd = (ctx->opcode >> 11) & 0x1f;
|
||||||
sa = (ctx->opcode >> 6) & 0x1f;
|
|
||||||
|
|
||||||
op1 = MASK_SPECIAL(ctx->opcode);
|
op1 = MASK_SPECIAL(ctx->opcode);
|
||||||
switch (op1) {
|
switch (op1) {
|
||||||
@ -14180,13 +14038,7 @@ static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
break;
|
break;
|
||||||
case OPC_MULT:
|
case OPC_MULT:
|
||||||
case OPC_MULTU:
|
case OPC_MULTU:
|
||||||
if (sa) {
|
gen_muldiv(ctx, op1, rd & 3, rs, rt);
|
||||||
check_insn(ctx, INSN_VR54XX);
|
|
||||||
op1 = MASK_MUL_VR54XX(ctx->opcode);
|
|
||||||
gen_mul_vr54xx(ctx, op1, rd, rs, rt);
|
|
||||||
} else {
|
|
||||||
gen_muldiv(ctx, op1, rd & 3, rs, rt);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case OPC_DIV:
|
case OPC_DIV:
|
||||||
case OPC_DIVU:
|
case OPC_DIVU:
|
||||||
@ -14203,7 +14055,7 @@ static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case OPC_JR:
|
case OPC_JR:
|
||||||
gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
|
gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
|
||||||
break;
|
break;
|
||||||
case OPC_SPIM:
|
case OPC_SPIM:
|
||||||
#ifdef MIPS_STRICT_STANDARD
|
#ifdef MIPS_STRICT_STANDARD
|
||||||
@ -14317,7 +14169,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
MIPS_INVAL("PMON / selsl");
|
MIPS_INVAL("PMON / selsl");
|
||||||
gen_reserved_instruction(ctx);
|
gen_reserved_instruction(ctx);
|
||||||
#else
|
#else
|
||||||
gen_helper_0e0i(pmon, sa);
|
gen_helper_pmon(cpu_env, tcg_constant_i32(sa));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case OPC_SYSCALL:
|
case OPC_SYSCALL:
|
||||||
@ -15739,12 +15591,8 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
/* Treat as NOP. */
|
/* Treat as NOP. */
|
||||||
break;
|
break;
|
||||||
case OPC_PREF:
|
case OPC_PREF:
|
||||||
if (ctx->insn_flags & INSN_R5900) {
|
check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 | INSN_R5900);
|
||||||
/* Treat as NOP. */
|
/* Treat as NOP. */
|
||||||
} else {
|
|
||||||
check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
|
|
||||||
/* Treat as NOP. */
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Floating point (COP1). */
|
/* Floating point (COP1). */
|
||||||
@ -16098,6 +15946,14 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
|
|
||||||
/* Transition to the auto-generated decoder. */
|
/* Transition to the auto-generated decoder. */
|
||||||
|
|
||||||
|
/* Vendor specific extensions */
|
||||||
|
if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cpu_supports_isa(env, INSN_VR54XX) && decode_ext_vr54xx(ctx, ctx->opcode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* ISA extensions */
|
/* ISA extensions */
|
||||||
if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
|
if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
|
||||||
return;
|
return;
|
||||||
@ -16107,9 +15963,6 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
|
if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decode_opc_legacy(env, ctx)) {
|
if (decode_opc_legacy(env, ctx)) {
|
||||||
return;
|
return;
|
||||||
@ -16126,6 +15979,7 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
|||||||
ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
|
ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
|
||||||
ctx->saved_pc = -1;
|
ctx->saved_pc = -1;
|
||||||
ctx->insn_flags = env->insn_flags;
|
ctx->insn_flags = env->insn_flags;
|
||||||
|
ctx->CP0_Config0 = env->CP0_Config0;
|
||||||
ctx->CP0_Config1 = env->CP0_Config1;
|
ctx->CP0_Config1 = env->CP0_Config1;
|
||||||
ctx->CP0_Config2 = env->CP0_Config2;
|
ctx->CP0_Config2 = env->CP0_Config2;
|
||||||
ctx->CP0_Config3 = env->CP0_Config3;
|
ctx->CP0_Config3 = env->CP0_Config3;
|
||||||
|
@ -18,6 +18,7 @@ typedef struct DisasContext {
|
|||||||
target_ulong page_start;
|
target_ulong page_start;
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
uint64_t insn_flags;
|
uint64_t insn_flags;
|
||||||
|
int32_t CP0_Config0;
|
||||||
int32_t CP0_Config1;
|
int32_t CP0_Config1;
|
||||||
int32_t CP0_Config2;
|
int32_t CP0_Config2;
|
||||||
int32_t CP0_Config3;
|
int32_t CP0_Config3;
|
||||||
@ -113,6 +114,18 @@ enum {
|
|||||||
OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
|
OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define gen_helper_0e1i(name, arg1, arg2) do { \
|
||||||
|
gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define gen_helper_1e0i(name, ret, arg1) do { \
|
||||||
|
gen_helper_##name(ret, cpu_env, tcg_constant_i32(arg1)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
|
||||||
|
gen_helper_##name(cpu_env, arg1, arg2, tcg_constant_i32(arg3));\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
void generate_exception(DisasContext *ctx, int excp);
|
void generate_exception(DisasContext *ctx, int excp);
|
||||||
void generate_exception_err(DisasContext *ctx, int excp, int err);
|
void generate_exception_err(DisasContext *ctx, int excp, int err);
|
||||||
void generate_exception_end(DisasContext *ctx, int excp);
|
void generate_exception_end(DisasContext *ctx, int excp);
|
||||||
@ -201,5 +214,19 @@ bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
|
|||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
|
bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
|
||||||
#endif
|
#endif
|
||||||
|
bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helpers for implementing sets of trans_* functions.
|
||||||
|
* Defer the implementation of NAME to FUNC, with optional extra arguments.
|
||||||
|
*/
|
||||||
|
#define TRANS(NAME, FUNC, ...) \
|
||||||
|
static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
|
||||||
|
{ return FUNC(ctx, a, __VA_ARGS__); }
|
||||||
|
|
||||||
|
static inline bool cpu_is_bigendian(DisasContext *ctx)
|
||||||
|
{
|
||||||
|
return extract32(ctx->CP0_Config0, CP0C0_BE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,20 +11,20 @@
|
|||||||
# when creating helpers common to those for the individual
|
# when creating helpers common to those for the individual
|
||||||
# instruction patterns.
|
# instruction patterns.
|
||||||
|
|
||||||
&rtype rs rt rd sa
|
&r rs rt rd sa
|
||||||
|
|
||||||
&itype base rt offset
|
&i base rt offset
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
# Named instruction formats. These are generally used to
|
# Named instruction formats. These are generally used to
|
||||||
# reduce the amount of duplication between instruction patterns.
|
# reduce the amount of duplication between instruction patterns.
|
||||||
|
|
||||||
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &rtype sa=0
|
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &r sa=0
|
||||||
@rt_rd ...... ..... rt:5 rd:5 ..... ...... &rtype rs=0 sa=0
|
@rt_rd ...... ..... rt:5 rd:5 ..... ...... &r sa=0 rs=0
|
||||||
@rs ...... rs:5 ..... .......... ...... &rtype rt=0 rd=0 sa=0
|
@rs ...... rs:5 ..... .......... ...... &r sa=0 rt=0 rd=0
|
||||||
@rd ...... .......... rd:5 ..... ...... &rtype rs=0 rt=0 sa=0
|
@rd ...... .......... rd:5 ..... ...... &r sa=0 rs=0 rt=0
|
||||||
|
|
||||||
@ldst ...... base:5 rt:5 offset:16 &itype
|
@ldst ...... base:5 rt:5 offset:16 &i
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
|
@ -64,28 +64,28 @@ bool decode_ext_tx79(DisasContext *ctx, uint32_t insn)
|
|||||||
* MTLO1 rs Move To LO1 Register
|
* MTLO1 rs Move To LO1 Register
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool trans_MFHI1(DisasContext *ctx, arg_rtype *a)
|
static bool trans_MFHI1(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
gen_store_gpr(cpu_HI[1], a->rd);
|
gen_store_gpr(cpu_HI[1], a->rd);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_MFLO1(DisasContext *ctx, arg_rtype *a)
|
static bool trans_MFLO1(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
gen_store_gpr(cpu_LO[1], a->rd);
|
gen_store_gpr(cpu_LO[1], a->rd);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_MTHI1(DisasContext *ctx, arg_rtype *a)
|
static bool trans_MTHI1(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
gen_load_gpr(cpu_HI[1], a->rs);
|
gen_load_gpr(cpu_HI[1], a->rs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_MTLO1(DisasContext *ctx, arg_rtype *a)
|
static bool trans_MTLO1(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
gen_load_gpr(cpu_LO[1], a->rs);
|
gen_load_gpr(cpu_LO[1], a->rs);
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ static bool trans_MTLO1(DisasContext *ctx, arg_rtype *a)
|
|||||||
* PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
|
* PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool trans_parallel_arith(DisasContext *ctx, arg_rtype *a,
|
static bool trans_parallel_arith(DisasContext *ctx, arg_r *a,
|
||||||
void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64))
|
void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64))
|
||||||
{
|
{
|
||||||
TCGv_i64 ax, bx;
|
TCGv_i64 ax, bx;
|
||||||
@ -146,19 +146,19 @@ static bool trans_parallel_arith(DisasContext *ctx, arg_rtype *a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Subtract Byte */
|
/* Parallel Subtract Byte */
|
||||||
static bool trans_PSUBB(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PSUBB(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
|
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Subtract Halfword */
|
/* Parallel Subtract Halfword */
|
||||||
static bool trans_PSUBH(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PSUBH(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
|
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Subtract Word */
|
/* Parallel Subtract Word */
|
||||||
static bool trans_PSUBW(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PSUBW(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
|
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
|
||||||
}
|
}
|
||||||
@ -189,25 +189,25 @@ static bool trans_PSUBW(DisasContext *ctx, arg_rtype *a)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Parallel And */
|
/* Parallel And */
|
||||||
static bool trans_PAND(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PAND(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
|
return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Or */
|
/* Parallel Or */
|
||||||
static bool trans_POR(DisasContext *ctx, arg_rtype *a)
|
static bool trans_POR(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
|
return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Exclusive Or */
|
/* Parallel Exclusive Or */
|
||||||
static bool trans_PXOR(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PXOR(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
|
return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Not Or */
|
/* Parallel Not Or */
|
||||||
static bool trans_PNOR(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PNOR(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
|
return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ static bool trans_PNOR(DisasContext *ctx, arg_rtype *a)
|
|||||||
* PCEQW rd, rs, rt Parallel Compare for Equal Word
|
* PCEQW rd, rs, rt Parallel Compare for Equal Word
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool trans_parallel_compare(DisasContext *ctx, arg_rtype *a,
|
static bool trans_parallel_compare(DisasContext *ctx, arg_r *a,
|
||||||
TCGCond cond, unsigned wlen)
|
TCGCond cond, unsigned wlen)
|
||||||
{
|
{
|
||||||
TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
|
TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
|
||||||
@ -286,37 +286,37 @@ static bool trans_parallel_compare(DisasContext *ctx, arg_rtype *a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Compare for Greater Than Byte */
|
/* Parallel Compare for Greater Than Byte */
|
||||||
static bool trans_PCGTB(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PCGTB(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
|
return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Compare for Equal Byte */
|
/* Parallel Compare for Equal Byte */
|
||||||
static bool trans_PCEQB(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PCEQB(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
|
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Compare for Greater Than Halfword */
|
/* Parallel Compare for Greater Than Halfword */
|
||||||
static bool trans_PCGTH(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PCGTH(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
|
return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Compare for Equal Halfword */
|
/* Parallel Compare for Equal Halfword */
|
||||||
static bool trans_PCEQH(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PCEQH(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
|
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Compare for Greater Than Word */
|
/* Parallel Compare for Greater Than Word */
|
||||||
static bool trans_PCGTW(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PCGTW(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
|
return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Compare for Equal Word */
|
/* Parallel Compare for Equal Word */
|
||||||
static bool trans_PCEQW(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PCEQW(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
|
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ static bool trans_PCEQW(DisasContext *ctx, arg_rtype *a)
|
|||||||
* SQ rt, offset(base) Store Quadword
|
* SQ rt, offset(base) Store Quadword
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool trans_LQ(DisasContext *ctx, arg_itype *a)
|
static bool trans_LQ(DisasContext *ctx, arg_i *a)
|
||||||
{
|
{
|
||||||
TCGv_i64 t0;
|
TCGv_i64 t0;
|
||||||
TCGv addr;
|
TCGv addr;
|
||||||
@ -369,7 +369,7 @@ static bool trans_LQ(DisasContext *ctx, arg_itype *a)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_SQ(DisasContext *ctx, arg_itype *a)
|
static bool trans_SQ(DisasContext *ctx, arg_i *a)
|
||||||
{
|
{
|
||||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
@ -437,7 +437,7 @@ static bool trans_SQ(DisasContext *ctx, arg_itype *a)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Parallel Pack to Word */
|
/* Parallel Pack to Word */
|
||||||
static bool trans_PPACW(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PPACW(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
TCGv_i64 a0, b0, t0;
|
TCGv_i64 a0, b0, t0;
|
||||||
|
|
||||||
@ -473,7 +473,7 @@ static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
|
|||||||
tcg_gen_deposit_i64(dh, a, b, 0, 32);
|
tcg_gen_deposit_i64(dh, a, b, 0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_PEXTLx(DisasContext *ctx, arg_rtype *a, unsigned wlen)
|
static bool trans_PEXTLx(DisasContext *ctx, arg_r *a, unsigned wlen)
|
||||||
{
|
{
|
||||||
TCGv_i64 ax, bx;
|
TCGv_i64 ax, bx;
|
||||||
|
|
||||||
@ -514,19 +514,19 @@ static bool trans_PEXTLx(DisasContext *ctx, arg_rtype *a, unsigned wlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Extend Lower from Byte */
|
/* Parallel Extend Lower from Byte */
|
||||||
static bool trans_PEXTLB(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PEXTLB(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_PEXTLx(ctx, a, 8);
|
return trans_PEXTLx(ctx, a, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Extend Lower from Halfword */
|
/* Parallel Extend Lower from Halfword */
|
||||||
static bool trans_PEXTLH(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PEXTLH(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
return trans_PEXTLx(ctx, a, 16);
|
return trans_PEXTLx(ctx, a, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Extend Lower from Word */
|
/* Parallel Extend Lower from Word */
|
||||||
static bool trans_PEXTLW(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PEXTLW(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
TCGv_i64 ax, bx;
|
TCGv_i64 ax, bx;
|
||||||
|
|
||||||
@ -549,7 +549,7 @@ static bool trans_PEXTLW(DisasContext *ctx, arg_rtype *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Extend Upper from Word */
|
/* Parallel Extend Upper from Word */
|
||||||
static bool trans_PEXTUW(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PEXTUW(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
TCGv_i64 ax, bx;
|
TCGv_i64 ax, bx;
|
||||||
|
|
||||||
@ -593,7 +593,7 @@ static bool trans_PEXTUW(DisasContext *ctx, arg_rtype *a)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Parallel Copy Halfword */
|
/* Parallel Copy Halfword */
|
||||||
static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
|
static bool trans_PCPYH(DisasContext *s, arg_r *a)
|
||||||
{
|
{
|
||||||
if (a->rd == 0) {
|
if (a->rd == 0) {
|
||||||
/* nop */
|
/* nop */
|
||||||
@ -615,7 +615,7 @@ static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Copy Lower Doubleword */
|
/* Parallel Copy Lower Doubleword */
|
||||||
static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
|
static bool trans_PCPYLD(DisasContext *s, arg_r *a)
|
||||||
{
|
{
|
||||||
if (a->rd == 0) {
|
if (a->rd == 0) {
|
||||||
/* nop */
|
/* nop */
|
||||||
@ -638,7 +638,7 @@ static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Copy Upper Doubleword */
|
/* Parallel Copy Upper Doubleword */
|
||||||
static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
|
static bool trans_PCPYUD(DisasContext *s, arg_r *a)
|
||||||
{
|
{
|
||||||
if (a->rd == 0) {
|
if (a->rd == 0) {
|
||||||
/* nop */
|
/* nop */
|
||||||
@ -657,7 +657,7 @@ static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parallel Rotate 3 Words Left */
|
/* Parallel Rotate 3 Words Left */
|
||||||
static bool trans_PROT3W(DisasContext *ctx, arg_rtype *a)
|
static bool trans_PROT3W(DisasContext *ctx, arg_r *a)
|
||||||
{
|
{
|
||||||
TCGv_i64 ax;
|
TCGv_i64 ax;
|
||||||
|
|
||||||
|
27
target/mips/tcg/vr54xx.decode
Normal file
27
target/mips/tcg/vr54xx.decode
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# MIPS VR5432 instruction set extensions
|
||||||
|
#
|
||||||
|
# Copyright (C) 2021 Philippe Mathieu-Daudé
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
#
|
||||||
|
# Reference: VR5432 Microprocessor User’s Manual
|
||||||
|
# (Document Number U13751EU5V0UM00)
|
||||||
|
|
||||||
|
&r rs rt rd
|
||||||
|
|
||||||
|
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &r
|
||||||
|
|
||||||
|
MULS 000000 ..... ..... ..... 00011011000 @rs_rt_rd
|
||||||
|
MULSU 000000 ..... ..... ..... 00011011001 @rs_rt_rd
|
||||||
|
MACC 000000 ..... ..... ..... 00101011000 @rs_rt_rd
|
||||||
|
MACCU 000000 ..... ..... ..... 00101011001 @rs_rt_rd
|
||||||
|
MSAC 000000 ..... ..... ..... 00111011000 @rs_rt_rd
|
||||||
|
MSACU 000000 ..... ..... ..... 00111011001 @rs_rt_rd
|
||||||
|
MULHI 000000 ..... ..... ..... 01001011000 @rs_rt_rd
|
||||||
|
MULHIU 000000 ..... ..... ..... 01001011001 @rs_rt_rd
|
||||||
|
MULSHI 000000 ..... ..... ..... 01011011000 @rs_rt_rd
|
||||||
|
MULSHIU 000000 ..... ..... ..... 01011011001 @rs_rt_rd
|
||||||
|
MACCHI 000000 ..... ..... ..... 01101011000 @rs_rt_rd
|
||||||
|
MACCHIU 000000 ..... ..... ..... 01101011001 @rs_rt_rd
|
||||||
|
MSACHI 000000 ..... ..... ..... 01111011000 @rs_rt_rd
|
||||||
|
MSACHIU 000000 ..... ..... ..... 01111011001 @rs_rt_rd
|
142
target/mips/tcg/vr54xx_helper.c
Normal file
142
target/mips/tcg/vr54xx_helper.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* MIPS VR5432 emulation helpers
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2005 Jocelyn Mayer
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "exec/helper-proto.h"
|
||||||
|
|
||||||
|
/* 64 bits arithmetic for 32 bits hosts */
|
||||||
|
static inline uint64_t get_HILO(CPUMIPSState *env)
|
||||||
|
{
|
||||||
|
return ((uint64_t)(env->active_tc.HI[0]) << 32) |
|
||||||
|
(uint32_t)env->active_tc.LO[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO)
|
||||||
|
{
|
||||||
|
env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||||
|
return env->active_tc.HI[0] = (int32_t)(HILO >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO)
|
||||||
|
{
|
||||||
|
target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
|
||||||
|
env->active_tc.HI[0] = (int32_t)(HILO >> 32);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Multiplication variants of the vr54xx. */
|
||||||
|
target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 *
|
||||||
|
(int64_t)(int32_t)arg2));
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 *
|
||||||
|
(uint64_t)(uint32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
|
||||||
|
(int64_t)(int32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 *
|
||||||
|
(int64_t)(int32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HI_LOT0(env, (uint64_t)get_HILO(env) + (uint64_t)(uint32_t)arg1 *
|
||||||
|
(uint64_t)(uint32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, (uint64_t)get_HILO(env) + (uint64_t)(uint32_t)arg1 *
|
||||||
|
(uint64_t)(uint32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
|
||||||
|
(int64_t)(int32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 *
|
||||||
|
(int64_t)(int32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HI_LOT0(env, (uint64_t)get_HILO(env) - (uint64_t)(uint32_t)arg1 *
|
||||||
|
(uint64_t)(uint32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, (uint64_t)get_HILO(env) - (uint64_t)(uint32_t)arg1 *
|
||||||
|
(uint64_t)(uint32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 *
|
||||||
|
(uint64_t)(uint32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 *
|
||||||
|
(int64_t)(int32_t)arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1,
|
||||||
|
target_ulong arg2)
|
||||||
|
{
|
||||||
|
return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 *
|
||||||
|
(uint64_t)(uint32_t)arg2);
|
||||||
|
}
|
24
target/mips/tcg/vr54xx_helper.h.inc
Normal file
24
target/mips/tcg/vr54xx_helper.h.inc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* MIPS NEC Vr54xx instruction emulation helpers for QEMU.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2005 Jocelyn Mayer
|
||||||
|
* Copyright (c) 2006 Marius Groeger (FPU operations)
|
||||||
|
* Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
DEF_HELPER_3(muls, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(mulsu, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(macc, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(maccu, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(msac, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(msacu, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(mulhi, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(mulhiu, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(mulshi, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(mulshiu, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(macchi, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(macchiu, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(msachi, tl, env, tl, tl)
|
||||||
|
DEF_HELPER_3(msachiu, tl, env, tl, tl)
|
72
target/mips/tcg/vr54xx_translate.c
Normal file
72
target/mips/tcg/vr54xx_translate.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* VR5432 extensions translation routines
|
||||||
|
*
|
||||||
|
* Reference: VR5432 Microprocessor User’s Manual
|
||||||
|
* (Document Number U13751EU5V0UM00)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Philippe Mathieu-Daudé
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "tcg/tcg-op.h"
|
||||||
|
#include "exec/helper-gen.h"
|
||||||
|
#include "translate.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/* Include the auto-generated decoder. */
|
||||||
|
#include "decode-vr54xx.c.inc"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Integer Multiply-Accumulate Instructions
|
||||||
|
*
|
||||||
|
* MACC Multiply, accumulate, and move LO
|
||||||
|
* MACCHI Multiply, accumulate, and move HI
|
||||||
|
* MACCHIU Unsigned multiply, accumulate, and move HI
|
||||||
|
* MACCU Unsigned multiply, accumulate, and move LO
|
||||||
|
* MSAC Multiply, negate, accumulate, and move LO
|
||||||
|
* MSACHI Multiply, negate, accumulate, and move HI
|
||||||
|
* MSACHIU Unsigned multiply, negate, accumulate, and move HI
|
||||||
|
* MSACU Unsigned multiply, negate, accumulate, and move LO
|
||||||
|
* MULHI Multiply and move HI
|
||||||
|
* MULHIU Unsigned multiply and move HI
|
||||||
|
* MULS Multiply, negate, and move LO
|
||||||
|
* MULSHI Multiply, negate, and move HI
|
||||||
|
* MULSHIU Unsigned multiply, negate, and move HI
|
||||||
|
* MULSU Unsigned multiply, negate, and move LO
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool trans_mult_acc(DisasContext *ctx, arg_r *a,
|
||||||
|
void (*gen_helper_mult_acc)(TCGv, TCGv_ptr, TCGv, TCGv))
|
||||||
|
{
|
||||||
|
TCGv t0 = tcg_temp_new();
|
||||||
|
TCGv t1 = tcg_temp_new();
|
||||||
|
|
||||||
|
gen_load_gpr(t0, a->rs);
|
||||||
|
gen_load_gpr(t1, a->rt);
|
||||||
|
|
||||||
|
gen_helper_mult_acc(t0, cpu_env, t0, t1);
|
||||||
|
|
||||||
|
gen_store_gpr(t0, a->rd);
|
||||||
|
|
||||||
|
tcg_temp_free(t0);
|
||||||
|
tcg_temp_free(t1);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANS(MACC, trans_mult_acc, gen_helper_macc);
|
||||||
|
TRANS(MACCHI, trans_mult_acc, gen_helper_macchi);
|
||||||
|
TRANS(MACCHIU, trans_mult_acc, gen_helper_macchiu);
|
||||||
|
TRANS(MACCU, trans_mult_acc, gen_helper_maccu);
|
||||||
|
TRANS(MSAC, trans_mult_acc, gen_helper_msac);
|
||||||
|
TRANS(MSACHI, trans_mult_acc, gen_helper_msachi);
|
||||||
|
TRANS(MSACHIU, trans_mult_acc, gen_helper_msachiu);
|
||||||
|
TRANS(MSACU, trans_mult_acc, gen_helper_msacu);
|
||||||
|
TRANS(MULHI, trans_mult_acc, gen_helper_mulhi);
|
||||||
|
TRANS(MULHIU, trans_mult_acc, gen_helper_mulhiu);
|
||||||
|
TRANS(MULS, trans_mult_acc, gen_helper_muls);
|
||||||
|
TRANS(MULSHI, trans_mult_acc, gen_helper_mulshi);
|
||||||
|
TRANS(MULSHIU, trans_mult_acc, gen_helper_mulshiu);
|
||||||
|
TRANS(MULSU, trans_mult_acc, gen_helper_mulsu);
|
Loading…
Reference in New Issue
Block a user