1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * LoongArch emulation helpers for QEMU.
5 * Copyright (c) 2021 Loongson Technology Corporation Limited
8 #include "qemu/osdep.h"
11 #include "qemu/host-utils.h"
12 #include "exec/helper-proto.h"
13 #include "exec/exec-all.h"
14 #include "exec/cpu_ldst.h"
15 #include "internals.h"
16 #include "qemu/crc32c.h"
20 /* Exceptions helpers */
21 void helper_raise_exception(CPULoongArchState
*env
, uint32_t exception
)
23 do_raise_exception(env
, exception
, GETPC());
26 target_ulong
helper_bitrev_w(target_ulong rj
)
28 return (int32_t)revbit32(rj
);
31 target_ulong
helper_bitrev_d(target_ulong rj
)
36 target_ulong
helper_bitswap(target_ulong v
)
38 v
= ((v
>> 1) & (target_ulong
)0x5555555555555555ULL
) |
39 ((v
& (target_ulong
)0x5555555555555555ULL
) << 1);
40 v
= ((v
>> 2) & (target_ulong
)0x3333333333333333ULL
) |
41 ((v
& (target_ulong
)0x3333333333333333ULL
) << 2);
42 v
= ((v
>> 4) & (target_ulong
)0x0F0F0F0F0F0F0F0FULL
) |
43 ((v
& (target_ulong
)0x0F0F0F0F0F0F0F0FULL
) << 4);
47 /* loongarch assert op */
48 void helper_asrtle_d(CPULoongArchState
*env
, target_ulong rj
, target_ulong rk
)
52 do_raise_exception(env
, EXCCODE_BCE
, GETPC());
56 void helper_asrtgt_d(CPULoongArchState
*env
, target_ulong rj
, target_ulong rk
)
60 do_raise_exception(env
, EXCCODE_BCE
, GETPC());
64 target_ulong
helper_crc32(target_ulong val
, target_ulong m
, uint64_t sz
)
67 target_ulong mask
= ((sz
* 8) == 64) ? -1ULL : ((1ULL << (sz
* 8)) - 1);
71 return (int32_t) (crc32(val
^ 0xffffffff, buf
, sz
) ^ 0xffffffff);
74 target_ulong
helper_crc32c(target_ulong val
, target_ulong m
, uint64_t sz
)
77 target_ulong mask
= ((sz
* 8) == 64) ? -1ULL : ((1ULL << (sz
* 8)) - 1);
80 return (int32_t) (crc32c(val
, buf
, sz
) ^ 0xffffffff);
83 target_ulong
helper_cpucfg(CPULoongArchState
*env
, target_ulong rj
)
85 return rj
>= ARRAY_SIZE(env
->cpucfg
) ? 0 : env
->cpucfg
[rj
];
88 uint64_t helper_rdtime_d(CPULoongArchState
*env
)
90 #ifdef CONFIG_USER_ONLY
91 return cpu_get_host_ticks();
94 LoongArchCPU
*cpu
= env_archcpu(env
);
96 plv
= FIELD_EX64(env
->CSR_CRMD
, CSR_CRMD
, PLV
);
97 if (extract64(env
->CSR_MISC
, R_CSR_MISC_DRDTL_SHIFT
+ plv
, 1)) {
98 do_raise_exception(env
, EXCCODE_IPE
, GETPC());
101 return cpu_loongarch_get_constant_timer_counter(cpu
);
105 #ifndef CONFIG_USER_ONLY
106 void helper_ertn(CPULoongArchState
*env
)
108 uint64_t csr_pplv
, csr_pie
;
109 if (FIELD_EX64(env
->CSR_TLBRERA
, CSR_TLBRERA
, ISTLBR
)) {
110 csr_pplv
= FIELD_EX64(env
->CSR_TLBRPRMD
, CSR_TLBRPRMD
, PPLV
);
111 csr_pie
= FIELD_EX64(env
->CSR_TLBRPRMD
, CSR_TLBRPRMD
, PIE
);
113 env
->CSR_TLBRERA
= FIELD_DP64(env
->CSR_TLBRERA
, CSR_TLBRERA
, ISTLBR
, 0);
114 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, DA
, 0);
115 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, PG
, 1);
116 set_pc(env
, env
->CSR_TLBRERA
);
117 qemu_log_mask(CPU_LOG_INT
, "%s: TLBRERA " TARGET_FMT_lx
"\n",
118 __func__
, env
->CSR_TLBRERA
);
120 csr_pplv
= FIELD_EX64(env
->CSR_PRMD
, CSR_PRMD
, PPLV
);
121 csr_pie
= FIELD_EX64(env
->CSR_PRMD
, CSR_PRMD
, PIE
);
123 set_pc(env
, env
->CSR_ERA
);
124 qemu_log_mask(CPU_LOG_INT
, "%s: ERA " TARGET_FMT_lx
"\n",
125 __func__
, env
->CSR_ERA
);
127 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, PLV
, csr_pplv
);
128 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, IE
, csr_pie
);
133 void helper_idle(CPULoongArchState
*env
)
135 CPUState
*cs
= env_cpu(env
);
138 do_raise_exception(env
, EXCP_HLT
, 0);