]>
git.proxmox.com Git - mirror_qemu.git/blob - target/loongarch/op_helper.c
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"
10 #include "qemu/main-loop.h"
12 #include "qemu/host-utils.h"
13 #include "exec/helper-proto.h"
14 #include "exec/exec-all.h"
15 #include "exec/cpu_ldst.h"
16 #include "internals.h"
17 #include "qemu/crc32c.h"
21 /* Exceptions helpers */
22 void helper_raise_exception(CPULoongArchState
*env
, uint32_t exception
)
24 do_raise_exception(env
, exception
, GETPC());
27 target_ulong
helper_bitrev_w(target_ulong rj
)
29 return (int32_t)revbit32(rj
);
32 target_ulong
helper_bitrev_d(target_ulong rj
)
37 target_ulong
helper_bitswap(target_ulong v
)
39 v
= ((v
>> 1) & (target_ulong
)0x5555555555555555ULL
) |
40 ((v
& (target_ulong
)0x5555555555555555ULL
) << 1);
41 v
= ((v
>> 2) & (target_ulong
)0x3333333333333333ULL
) |
42 ((v
& (target_ulong
)0x3333333333333333ULL
) << 2);
43 v
= ((v
>> 4) & (target_ulong
)0x0F0F0F0F0F0F0F0FULL
) |
44 ((v
& (target_ulong
)0x0F0F0F0F0F0F0F0FULL
) << 4);
48 /* loongarch assert op */
49 void helper_asrtle_d(CPULoongArchState
*env
, target_ulong rj
, target_ulong rk
)
53 do_raise_exception(env
, EXCCODE_BCE
, GETPC());
57 void helper_asrtgt_d(CPULoongArchState
*env
, target_ulong rj
, target_ulong rk
)
61 do_raise_exception(env
, EXCCODE_BCE
, GETPC());
65 target_ulong
helper_crc32(target_ulong val
, target_ulong m
, uint64_t sz
)
68 target_ulong mask
= ((sz
* 8) == 64) ? -1ULL : ((1ULL << (sz
* 8)) - 1);
72 return (int32_t) (crc32(val
^ 0xffffffff, buf
, sz
) ^ 0xffffffff);
75 target_ulong
helper_crc32c(target_ulong val
, target_ulong m
, uint64_t sz
)
78 target_ulong mask
= ((sz
* 8) == 64) ? -1ULL : ((1ULL << (sz
* 8)) - 1);
81 return (int32_t) (crc32c(val
, buf
, sz
) ^ 0xffffffff);
84 target_ulong
helper_cpucfg(CPULoongArchState
*env
, target_ulong rj
)
86 return rj
>= ARRAY_SIZE(env
->cpucfg
) ? 0 : env
->cpucfg
[rj
];
89 uint64_t helper_rdtime_d(CPULoongArchState
*env
)
91 #ifdef CONFIG_USER_ONLY
92 return cpu_get_host_ticks();
95 LoongArchCPU
*cpu
= env_archcpu(env
);
97 plv
= FIELD_EX64(env
->CSR_CRMD
, CSR_CRMD
, PLV
);
98 if (extract64(env
->CSR_MISC
, R_CSR_MISC_DRDTL_SHIFT
+ plv
, 1)) {
99 do_raise_exception(env
, EXCCODE_IPE
, GETPC());
102 return cpu_loongarch_get_constant_timer_counter(cpu
);
106 #ifndef CONFIG_USER_ONLY
107 void helper_ertn(CPULoongArchState
*env
)
109 uint64_t csr_pplv
, csr_pie
;
110 if (FIELD_EX64(env
->CSR_TLBRERA
, CSR_TLBRERA
, ISTLBR
)) {
111 csr_pplv
= FIELD_EX64(env
->CSR_TLBRPRMD
, CSR_TLBRPRMD
, PPLV
);
112 csr_pie
= FIELD_EX64(env
->CSR_TLBRPRMD
, CSR_TLBRPRMD
, PIE
);
114 env
->CSR_TLBRERA
= FIELD_DP64(env
->CSR_TLBRERA
, CSR_TLBRERA
, ISTLBR
, 0);
115 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, DA
, 0);
116 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, PG
, 1);
117 env
->pc
= env
->CSR_TLBRERA
;
118 qemu_log_mask(CPU_LOG_INT
, "%s: TLBRERA " TARGET_FMT_lx
"\n",
119 __func__
, env
->CSR_TLBRERA
);
121 csr_pplv
= FIELD_EX64(env
->CSR_PRMD
, CSR_PRMD
, PPLV
);
122 csr_pie
= FIELD_EX64(env
->CSR_PRMD
, CSR_PRMD
, PIE
);
124 env
->pc
= env
->CSR_ERA
;
125 qemu_log_mask(CPU_LOG_INT
, "%s: ERA " TARGET_FMT_lx
"\n",
126 __func__
, env
->CSR_ERA
);
128 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, PLV
, csr_pplv
);
129 env
->CSR_CRMD
= FIELD_DP64(env
->CSR_CRMD
, CSR_CRMD
, IE
, csr_pie
);
134 void helper_idle(CPULoongArchState
*env
)
136 CPUState
*cs
= env_cpu(env
);
139 do_raise_exception(env
, EXCP_HLT
, 0);