mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
target/loongarch: Add other core instructions support
This includes: -CACOP -LDDIR -LDPTE -ERTN -DBCL -IDLE Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220606124333.2060567-29-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
fcbbeb8ecd
commit
d2cba6f7ce
7 changed files with 233 additions and 0 deletions
|
@ -668,3 +668,96 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||
raise_mmu_exception(env, address, access_type, ret);
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
|
||||
target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
|
||||
target_ulong level, uint32_t mem_idx)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
target_ulong badvaddr, index, phys, ret;
|
||||
int shift;
|
||||
uint64_t dir_base, dir_width;
|
||||
bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
|
||||
|
||||
badvaddr = env->CSR_TLBRBADV;
|
||||
base = base & TARGET_PHYS_MASK;
|
||||
|
||||
/* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
|
||||
shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
|
||||
shift = (shift + 1) * 3;
|
||||
|
||||
if (huge) {
|
||||
return base;
|
||||
}
|
||||
switch (level) {
|
||||
case 1:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
|
||||
break;
|
||||
case 2:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR2_WIDTH);
|
||||
break;
|
||||
case 3:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
|
||||
break;
|
||||
case 4:
|
||||
dir_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_BASE);
|
||||
dir_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR4_WIDTH);
|
||||
break;
|
||||
default:
|
||||
do_raise_exception(env, EXCCODE_INE, GETPC());
|
||||
return 0;
|
||||
}
|
||||
index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
|
||||
phys = base | index << shift;
|
||||
ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
|
||||
uint32_t mem_idx)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
target_ulong phys, tmp0, ptindex, ptoffset0, ptoffset1, ps, badv;
|
||||
int shift;
|
||||
bool huge = (base >> LOONGARCH_PAGE_HUGE_SHIFT) & 0x1;
|
||||
uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
|
||||
uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
|
||||
|
||||
base = base & TARGET_PHYS_MASK;
|
||||
|
||||
if (huge) {
|
||||
/* Huge Page. base is paddr */
|
||||
tmp0 = base ^ (1 << LOONGARCH_PAGE_HUGE_SHIFT);
|
||||
/* Move Global bit */
|
||||
tmp0 = ((tmp0 & (1 << LOONGARCH_HGLOBAL_SHIFT)) >>
|
||||
LOONGARCH_HGLOBAL_SHIFT) << R_TLBENTRY_G_SHIFT |
|
||||
(tmp0 & (~(1 << R_TLBENTRY_G_SHIFT)));
|
||||
ps = ptbase + ptwidth - 1;
|
||||
if (odd) {
|
||||
tmp0 += (1 << ps);
|
||||
}
|
||||
} else {
|
||||
/* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
|
||||
shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
|
||||
shift = (shift + 1) * 3;
|
||||
badv = env->CSR_TLBRBADV;
|
||||
|
||||
ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
|
||||
ptindex = ptindex & ~0x1; /* clear bit 0 */
|
||||
ptoffset0 = ptindex << shift;
|
||||
ptoffset1 = (ptindex + 1) << shift;
|
||||
|
||||
phys = base | (odd ? ptoffset1 : ptoffset0);
|
||||
tmp0 = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
|
||||
ps = ptbase;
|
||||
}
|
||||
|
||||
if (odd) {
|
||||
env->CSR_TLBRELO1 = tmp0;
|
||||
} else {
|
||||
env->CSR_TLBRELO0 = tmp0;
|
||||
}
|
||||
env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI, PS, ps);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue