pull-loongarch-20230824
-----BEGIN PGP SIGNATURE----- iLMEAAEIAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZOcdAwAKCRBAov/yOSY+ 3w3CA/sH8+Ay+Qnaqa2vEyuhOlFQuxHKeR7mYfsitAdzh8yMK2K8C2iBUzDzL1H3 kZmZbCcYX7ko9RLhsuXmvfBJ7iwzY55ozSHLIjJ/VS4JVE5B0cUSZ5jjIPDqpzDs 7TUt9qpTkwg0e+klzVREWLSWP5xopvkRvFHZM3KZZhGMphOTUQ== =/HHZ -----END PGP SIGNATURE----- Merge tag 'pull-loongarch-20230824' of https://gitlab.com/gaosong/qemu into staging pull-loongarch-20230824 # -----BEGIN PGP SIGNATURE----- # # iLMEAAEIAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZOcdAwAKCRBAov/yOSY+ # 3w3CA/sH8+Ay+Qnaqa2vEyuhOlFQuxHKeR7mYfsitAdzh8yMK2K8C2iBUzDzL1H3 # kZmZbCcYX7ko9RLhsuXmvfBJ7iwzY55ozSHLIjJ/VS4JVE5B0cUSZ5jjIPDqpzDs # 7TUt9qpTkwg0e+klzVREWLSWP5xopvkRvFHZM3KZZhGMphOTUQ== # =/HHZ # -----END PGP SIGNATURE----- # gpg: Signature made Thu 24 Aug 2023 05:04:03 EDT # gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF # gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C 6C2C 40A2 FFF2 3926 3EDF * tag 'pull-loongarch-20230824' of https://gitlab.com/gaosong/qemu: (31 commits) hw/loongarch: Fix ACPI processor id off-by-one error target/loongarch: Split fcc register to fcc0-7 in gdbstub hw/intc/loongarch_pch: fix edge triggered irq handling target/loongarch: cpu: Implement get_arch_id callback target/loongarch: Add avail_IOCSR to check iocsr instructions target/loongarch: Add avail_LSX to check LSX instructions target/loongarch: Add avail_LAM to check atomic instructions target/loongarch: Add avail_LSPW to check LSPW instructions target/loongarch: Add avail_FP/FP_SP/FP_DP to check fpu instructions hw/loongarch: Remove restriction of la464 cores in the virt machine target/loongarch: Add LoongArch32 cpu la132 target/loongarch: Add avail_64 to check la64-only instructions target/loongarch: Add a check parameter to the TRANS macro target/loongarch: Sign extend results in VA32 mode target/loongarch: Truncate high 32 bits of address in VA32 mode target/loongarch: Extract set_pc() helper target/loongarch: Extract make_address_pc() helper target/loongarch: Extract make_address_i() helper target/loongarch: Extract make_address_x() helper target/loongarch: Add LA64 & VA32 to DisasContext ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
6030ef9d41
@ -1,5 +1,5 @@
|
||||
TARGET_ARCH=loongarch64
|
||||
TARGET_BASE_ARCH=loongarch
|
||||
TARGET_SUPPORTS_MTTCG=y
|
||||
TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu.xml
|
||||
TARGET_XML_FILES= gdb-xml/loongarch-base32.xml gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu.xml
|
||||
TARGET_NEED_FDT=y
|
||||
|
45
gdb-xml/loongarch-base32.xml
Normal file
45
gdb-xml/loongarch-base32.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.loongarch.base">
|
||||
<reg name="r0" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r1" bitsize="32" type="code_ptr" group="general"/>
|
||||
<reg name="r2" bitsize="32" type="data_ptr" group="general"/>
|
||||
<reg name="r3" bitsize="32" type="data_ptr" group="general"/>
|
||||
<reg name="r4" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r5" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r6" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r7" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r8" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r9" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r10" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r11" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r12" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r13" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r14" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r15" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r16" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r17" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r18" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r19" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r20" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r21" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r22" bitsize="32" type="data_ptr" group="general"/>
|
||||
<reg name="r23" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r24" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r25" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r26" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r27" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r28" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r29" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r30" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="r31" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="orig_a0" bitsize="32" type="uint32" group="general"/>
|
||||
<reg name="pc" bitsize="32" type="code_ptr" group="general"/>
|
||||
<reg name="badv" bitsize="32" type="code_ptr" group="general"/>
|
||||
</feature>
|
@ -45,6 +45,13 @@
|
||||
<reg name="f29" bitsize="64" type="fputype" group="float"/>
|
||||
<reg name="f30" bitsize="64" type="fputype" group="float"/>
|
||||
<reg name="f31" bitsize="64" type="fputype" group="float"/>
|
||||
<reg name="fcc" bitsize="64" type="uint64" group="float"/>
|
||||
<reg name="fcc0" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc1" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc2" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc3" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc4" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc5" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc6" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc7" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcsr" bitsize="32" type="uint32" group="float"/>
|
||||
</feature>
|
||||
|
@ -30,7 +30,11 @@ static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level)
|
||||
qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
|
||||
}
|
||||
} else {
|
||||
val = mask & s->intisr;
|
||||
/*
|
||||
* intirr means requested pending irq
|
||||
* do not clear pending irq for edge-triggered on lowering edge
|
||||
*/
|
||||
val = mask & s->intisr & ~s->intirr;
|
||||
if (val) {
|
||||
irq = ctz64(val);
|
||||
s->intisr &= ~MAKE_64BIT_MASK(irq, 1);
|
||||
@ -51,6 +55,7 @@ static void pch_pic_irq_handler(void *opaque, int irq, int level)
|
||||
/* Edge triggered */
|
||||
if (level) {
|
||||
if ((s->last_intirr & mask) == 0) {
|
||||
/* marked pending on a rising edge */
|
||||
s->intirr |= mask;
|
||||
}
|
||||
s->last_intirr |= mask;
|
||||
|
@ -127,7 +127,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, LoongArchMachineState *lams)
|
||||
build_append_int_noprefix(table_data, 17, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 15, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, 1, 1); /* Version */
|
||||
build_append_int_noprefix(table_data, i + 1, 4); /* ACPI Processor ID */
|
||||
build_append_int_noprefix(table_data, i, 4); /* ACPI Processor ID */
|
||||
build_append_int_noprefix(table_data, arch_id, 4); /* Core ID */
|
||||
build_append_int_noprefix(table_data, 1, 4); /* Flags */
|
||||
}
|
||||
|
@ -798,11 +798,6 @@ static void loongarch_init(MachineState *machine)
|
||||
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||
}
|
||||
|
||||
if (!strstr(cpu_model, "la464")) {
|
||||
error_report("LoongArch/TCG needs cpu type la464");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ram_size < 1 * GiB) {
|
||||
error_report("ram_size must be greater than 1G.");
|
||||
exit(1);
|
||||
@ -815,6 +810,8 @@ static void loongarch_init(MachineState *machine)
|
||||
cpu = cpu_create(machine->cpu_type);
|
||||
cpu->cpu_index = i;
|
||||
machine->possible_cpus->cpus[i].cpu = OBJECT(cpu);
|
||||
lacpu = LOONGARCH_CPU(cpu);
|
||||
lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id;
|
||||
}
|
||||
fdt_add_cpu_nodes(lams);
|
||||
|
||||
|
@ -57,7 +57,8 @@ FIELD(CSR_TLBIDX, PS, 24, 6)
|
||||
FIELD(CSR_TLBIDX, NE, 31, 1)
|
||||
|
||||
#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */
|
||||
FIELD(CSR_TLBEHI, VPPN, 13, 35)
|
||||
FIELD(CSR_TLBEHI_32, VPPN, 13, 19)
|
||||
FIELD(CSR_TLBEHI_64, VPPN, 13, 35)
|
||||
|
||||
#define LOONGARCH_CSR_TLBELO0 0x12 /* TLB EntryLo0 */
|
||||
#define LOONGARCH_CSR_TLBELO1 0x13 /* TLB EntryLo1 */
|
||||
@ -66,10 +67,11 @@ FIELD(TLBENTRY, D, 1, 1)
|
||||
FIELD(TLBENTRY, PLV, 2, 2)
|
||||
FIELD(TLBENTRY, MAT, 4, 2)
|
||||
FIELD(TLBENTRY, G, 6, 1)
|
||||
FIELD(TLBENTRY, PPN, 12, 36)
|
||||
FIELD(TLBENTRY, NR, 61, 1)
|
||||
FIELD(TLBENTRY, NX, 62, 1)
|
||||
FIELD(TLBENTRY, RPLV, 63, 1)
|
||||
FIELD(TLBENTRY_32, PPN, 8, 24)
|
||||
FIELD(TLBENTRY_64, PPN, 12, 36)
|
||||
FIELD(TLBENTRY_64, NR, 61, 1)
|
||||
FIELD(TLBENTRY_64, NX, 62, 1)
|
||||
FIELD(TLBENTRY_64, RPLV, 63, 1)
|
||||
|
||||
#define LOONGARCH_CSR_ASID 0x18 /* Address space identifier */
|
||||
FIELD(CSR_ASID, ASID, 0, 10)
|
||||
@ -163,7 +165,8 @@ FIELD(CSR_TLBRERA, PC, 2, 62)
|
||||
#define LOONGARCH_CSR_TLBRELO1 0x8d /* TLB refill entrylo1 */
|
||||
#define LOONGARCH_CSR_TLBREHI 0x8e /* TLB refill entryhi */
|
||||
FIELD(CSR_TLBREHI, PS, 0, 6)
|
||||
FIELD(CSR_TLBREHI, VPPN, 13, 35)
|
||||
FIELD(CSR_TLBREHI_32, VPPN, 13, 19)
|
||||
FIELD(CSR_TLBREHI_64, VPPN, 13, 35)
|
||||
#define LOONGARCH_CSR_TLBRPRMD 0x8f /* TLB refill mode info */
|
||||
FIELD(CSR_TLBRPRMD, PPLV, 0, 2)
|
||||
FIELD(CSR_TLBRPRMD, PIE, 2, 1)
|
||||
@ -187,10 +190,9 @@ FIELD(CSR_DMW, PLV1, 1, 1)
|
||||
FIELD(CSR_DMW, PLV2, 2, 1)
|
||||
FIELD(CSR_DMW, PLV3, 3, 1)
|
||||
FIELD(CSR_DMW, MAT, 4, 2)
|
||||
FIELD(CSR_DMW, VSEG, 60, 4)
|
||||
|
||||
#define dmw_va2pa(va) \
|
||||
(va & MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS))
|
||||
FIELD(CSR_DMW_32, PSEG, 25, 3)
|
||||
FIELD(CSR_DMW_32, VSEG, 29, 3)
|
||||
FIELD(CSR_DMW_64, VSEG, 60, 4)
|
||||
|
||||
/* Debug CSRs */
|
||||
#define LOONGARCH_CSR_DBG 0x500 /* debug config */
|
||||
|
@ -81,7 +81,7 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
|
||||
env->pc = value;
|
||||
set_pc(env, value);
|
||||
}
|
||||
|
||||
static vaddr loongarch_cpu_get_pc(CPUState *cs)
|
||||
@ -168,7 +168,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
|
||||
set_DERA:
|
||||
env->CSR_DERA = env->pc;
|
||||
env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1);
|
||||
env->pc = env->CSR_EENTRY + 0x480;
|
||||
set_pc(env, env->CSR_EENTRY + 0x480);
|
||||
break;
|
||||
case EXCCODE_INT:
|
||||
if (FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) {
|
||||
@ -249,7 +249,8 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
|
||||
|
||||
/* Find the highest-priority interrupt. */
|
||||
vector = 31 - clz32(pending);
|
||||
env->pc = env->CSR_EENTRY + (EXCCODE_EXTERNAL_INT + vector) * vec_size;
|
||||
set_pc(env, env->CSR_EENTRY + \
|
||||
(EXCCODE_EXTERNAL_INT + vector) * vec_size);
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx
|
||||
" cause %d\n" " A " TARGET_FMT_lx " D "
|
||||
@ -260,10 +261,9 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
|
||||
env->CSR_ECFG, env->CSR_ESTAT);
|
||||
} else {
|
||||
if (tlbfill) {
|
||||
env->pc = env->CSR_TLBRENTRY;
|
||||
set_pc(env, env->CSR_TLBRENTRY);
|
||||
} else {
|
||||
env->pc = env->CSR_EENTRY;
|
||||
env->pc += EXCODE_MCODE(cause) * vec_size;
|
||||
set_pc(env, env->CSR_EENTRY + EXCODE_MCODE(cause) * vec_size);
|
||||
}
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx
|
||||
@ -324,7 +324,7 @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
|
||||
tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
|
||||
env->pc = tb->pc;
|
||||
set_pc(env, tb->pc);
|
||||
}
|
||||
|
||||
static void loongarch_restore_state_to_opc(CPUState *cs,
|
||||
@ -334,7 +334,7 @@ static void loongarch_restore_state_to_opc(CPUState *cs,
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
|
||||
env->pc = data[0];
|
||||
set_pc(env, data[0]);
|
||||
}
|
||||
#endif /* CONFIG_TCG */
|
||||
|
||||
@ -391,6 +391,7 @@ static void loongarch_la464_initfn(Object *obj)
|
||||
data = FIELD_DP32(data, CPUCFG2, LSX, 1),
|
||||
data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
|
||||
data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
|
||||
data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
|
||||
data = FIELD_DP32(data, CPUCFG2, LAM, 1);
|
||||
env->cpucfg[2] = data;
|
||||
|
||||
@ -439,6 +440,35 @@ static void loongarch_la464_initfn(Object *obj)
|
||||
env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
|
||||
}
|
||||
|
||||
static void loongarch_la132_initfn(Object *obj)
|
||||
{
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 21; i++) {
|
||||
env->cpucfg[i] = 0x0;
|
||||
}
|
||||
|
||||
cpu->dtb_compatible = "loongarch,Loongson-1C103";
|
||||
env->cpucfg[0] = 0x148042; /* PRID */
|
||||
|
||||
uint32_t data = 0;
|
||||
data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
|
||||
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
|
||||
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
|
||||
data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */
|
||||
data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */
|
||||
data = FIELD_DP32(data, CPUCFG1, UAL, 1);
|
||||
data = FIELD_DP32(data, CPUCFG1, RI, 0);
|
||||
data = FIELD_DP32(data, CPUCFG1, EP, 0);
|
||||
data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
|
||||
data = FIELD_DP32(data, CPUCFG1, HP, 1);
|
||||
data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
|
||||
env->cpucfg[1] = data;
|
||||
}
|
||||
|
||||
static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
|
||||
{
|
||||
const char *typename = object_class_get_name(OBJECT_CLASS(data));
|
||||
@ -544,6 +574,8 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
static void loongarch_qemu_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "[%s]: Unimplemented reg 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr);
|
||||
}
|
||||
|
||||
static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
|
||||
@ -690,12 +722,14 @@ static struct TCGCPUOps loongarch_tcg_ops = {
|
||||
static const struct SysemuCPUOps loongarch_sysemu_ops = {
|
||||
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
|
||||
};
|
||||
#endif
|
||||
|
||||
static gchar *loongarch_gdb_arch_name(CPUState *cs)
|
||||
static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
|
||||
{
|
||||
return g_strdup("loongarch64");
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
|
||||
return cpu->phy_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
@ -715,26 +749,51 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||
cc->set_pc = loongarch_cpu_set_pc;
|
||||
cc->get_pc = loongarch_cpu_get_pc;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
cc->get_arch_id = loongarch_cpu_get_arch_id;
|
||||
dc->vmsd = &vmstate_loongarch_cpu;
|
||||
cc->sysemu_ops = &loongarch_sysemu_ops;
|
||||
#endif
|
||||
cc->disas_set_info = loongarch_cpu_disas_set_info;
|
||||
cc->gdb_read_register = loongarch_cpu_gdb_read_register;
|
||||
cc->gdb_write_register = loongarch_cpu_gdb_write_register;
|
||||
cc->disas_set_info = loongarch_cpu_disas_set_info;
|
||||
cc->gdb_num_core_regs = 35;
|
||||
cc->gdb_core_xml_file = "loongarch-base64.xml";
|
||||
cc->gdb_stop_before_watchpoint = true;
|
||||
cc->gdb_arch_name = loongarch_gdb_arch_name;
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
cc->tcg_ops = &loongarch_tcg_ops;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define DEFINE_LOONGARCH_CPU_TYPE(model, initfn) \
|
||||
static gchar *loongarch32_gdb_arch_name(CPUState *cs)
|
||||
{
|
||||
return g_strdup("loongarch32");
|
||||
}
|
||||
|
||||
static void loongarch32_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(c);
|
||||
|
||||
cc->gdb_num_core_regs = 35;
|
||||
cc->gdb_core_xml_file = "loongarch-base32.xml";
|
||||
cc->gdb_arch_name = loongarch32_gdb_arch_name;
|
||||
}
|
||||
|
||||
static gchar *loongarch64_gdb_arch_name(CPUState *cs)
|
||||
{
|
||||
return g_strdup("loongarch64");
|
||||
}
|
||||
|
||||
static void loongarch64_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(c);
|
||||
|
||||
cc->gdb_num_core_regs = 35;
|
||||
cc->gdb_core_xml_file = "loongarch-base64.xml";
|
||||
cc->gdb_arch_name = loongarch64_gdb_arch_name;
|
||||
}
|
||||
|
||||
#define DEFINE_LOONGARCH_CPU_TYPE(size, model, initfn) \
|
||||
{ \
|
||||
.parent = TYPE_LOONGARCH_CPU, \
|
||||
.parent = TYPE_LOONGARCH##size##_CPU, \
|
||||
.instance_init = initfn, \
|
||||
.name = LOONGARCH_CPU_TYPE_NAME(model), \
|
||||
}
|
||||
@ -750,7 +809,22 @@ static const TypeInfo loongarch_cpu_type_infos[] = {
|
||||
.class_size = sizeof(LoongArchCPUClass),
|
||||
.class_init = loongarch_cpu_class_init,
|
||||
},
|
||||
DEFINE_LOONGARCH_CPU_TYPE("la464", loongarch_la464_initfn),
|
||||
{
|
||||
.name = TYPE_LOONGARCH32_CPU,
|
||||
.parent = TYPE_LOONGARCH_CPU,
|
||||
|
||||
.abstract = true,
|
||||
.class_init = loongarch32_cpu_class_init,
|
||||
},
|
||||
{
|
||||
.name = TYPE_LOONGARCH64_CPU,
|
||||
.parent = TYPE_LOONGARCH_CPU,
|
||||
|
||||
.abstract = true,
|
||||
.class_init = loongarch64_cpu_class_init,
|
||||
},
|
||||
DEFINE_LOONGARCH_CPU_TYPE(64, "la464", loongarch_la464_initfn),
|
||||
DEFINE_LOONGARCH_CPU_TYPE(32, "la132", loongarch_la132_initfn),
|
||||
};
|
||||
|
||||
DEFINE_TYPES(loongarch_cpu_type_infos)
|
||||
|
@ -132,6 +132,11 @@ FIELD(CPUCFG1, HP, 24, 1)
|
||||
FIELD(CPUCFG1, IOCSR_BRD, 25, 1)
|
||||
FIELD(CPUCFG1, MSG_INT, 26, 1)
|
||||
|
||||
/* cpucfg[1].arch */
|
||||
#define CPUCFG1_ARCH_LA32R 0
|
||||
#define CPUCFG1_ARCH_LA32 1
|
||||
#define CPUCFG1_ARCH_LA64 2
|
||||
|
||||
/* cpucfg[2] bits */
|
||||
FIELD(CPUCFG2, FP, 0, 1)
|
||||
FIELD(CPUCFG2, FP_SP, 1, 1)
|
||||
@ -371,12 +376,15 @@ struct ArchCPU {
|
||||
CPUNegativeOffsetState neg;
|
||||
CPULoongArchState env;
|
||||
QEMUTimer timer;
|
||||
uint32_t phy_id;
|
||||
|
||||
/* 'compatible' string for this CPU for Linux device trees */
|
||||
const char *dtb_compatible;
|
||||
};
|
||||
|
||||
#define TYPE_LOONGARCH_CPU "loongarch-cpu"
|
||||
#define TYPE_LOONGARCH32_CPU "loongarch32-cpu"
|
||||
#define TYPE_LOONGARCH64_CPU "loongarch64-cpu"
|
||||
|
||||
OBJECT_DECLARE_CPU_TYPE(LoongArchCPU, LoongArchCPUClass,
|
||||
LOONGARCH_CPU)
|
||||
@ -420,6 +428,31 @@ static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool is_la64(CPULoongArchState *env)
|
||||
{
|
||||
return FIELD_EX32(env->cpucfg[1], CPUCFG1, ARCH) == CPUCFG1_ARCH_LA64;
|
||||
}
|
||||
|
||||
static inline bool is_va32(CPULoongArchState *env)
|
||||
{
|
||||
/* VA32 if !LA64 or VA32L[1-3] */
|
||||
bool va32 = !is_la64(env);
|
||||
uint64_t plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
|
||||
if (plv >= 1 && (FIELD_EX64(env->CSR_MISC, CSR_MISC, VA32) & (1 << plv))) {
|
||||
va32 = true;
|
||||
}
|
||||
return va32;
|
||||
}
|
||||
|
||||
static inline void set_pc(CPULoongArchState *env, uint64_t value)
|
||||
{
|
||||
if (is_va32(env)) {
|
||||
env->pc = (uint32_t)value;
|
||||
} else {
|
||||
env->pc = value;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LoongArch CPUs hardware flags.
|
||||
*/
|
||||
@ -427,6 +460,7 @@ static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
|
||||
#define HW_FLAGS_CRMD_PG R_CSR_CRMD_PG_MASK /* 0x10 */
|
||||
#define HW_FLAGS_EUEN_FPE 0x04
|
||||
#define HW_FLAGS_EUEN_SXE 0x08
|
||||
#define HW_FLAGS_VA32 0x20
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
|
||||
uint64_t *cs_base, uint32_t *flags)
|
||||
@ -436,6 +470,7 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
|
||||
*flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK);
|
||||
*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE;
|
||||
*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE;
|
||||
*flags |= is_va32(env) * HW_FLAGS_VA32;
|
||||
}
|
||||
|
||||
void loongarch_cpu_list(void);
|
||||
|
@ -34,16 +34,25 @@ int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
uint64_t val;
|
||||
|
||||
if (0 <= n && n < 32) {
|
||||
return gdb_get_regl(mem_buf, env->gpr[n]);
|
||||
val = env->gpr[n];
|
||||
} else if (n == 32) {
|
||||
/* orig_a0 */
|
||||
return gdb_get_regl(mem_buf, 0);
|
||||
val = 0;
|
||||
} else if (n == 33) {
|
||||
return gdb_get_regl(mem_buf, env->pc);
|
||||
val = env->pc;
|
||||
} else if (n == 34) {
|
||||
return gdb_get_regl(mem_buf, env->CSR_BADV);
|
||||
val = env->CSR_BADV;
|
||||
}
|
||||
|
||||
if (0 <= n && n <= 34) {
|
||||
if (is_la64(env)) {
|
||||
return gdb_get_reg64(mem_buf, val);
|
||||
} else {
|
||||
return gdb_get_reg32(mem_buf, val);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -52,15 +61,24 @@ int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
target_ulong tmp = ldtul_p(mem_buf);
|
||||
target_ulong tmp;
|
||||
int read_length;
|
||||
int length = 0;
|
||||
|
||||
if (is_la64(env)) {
|
||||
tmp = ldq_p(mem_buf);
|
||||
read_length = 8;
|
||||
} else {
|
||||
tmp = ldl_p(mem_buf);
|
||||
read_length = 4;
|
||||
}
|
||||
|
||||
if (0 <= n && n < 32) {
|
||||
env->gpr[n] = tmp;
|
||||
length = sizeof(target_ulong);
|
||||
length = read_length;
|
||||
} else if (n == 33) {
|
||||
env->pc = tmp;
|
||||
length = sizeof(target_ulong);
|
||||
set_pc(env, tmp);
|
||||
length = read_length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
@ -70,10 +88,9 @@ static int loongarch_gdb_get_fpu(CPULoongArchState *env,
|
||||
{
|
||||
if (0 <= n && n < 32) {
|
||||
return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0));
|
||||
} else if (n == 32) {
|
||||
uint64_t val = read_fcc(env);
|
||||
return gdb_get_reg64(mem_buf, val);
|
||||
} else if (n == 33) {
|
||||
} else if (32 <= n && n < 40) {
|
||||
return gdb_get_reg8(mem_buf, env->cf[n - 32]);
|
||||
} else if (n == 40) {
|
||||
return gdb_get_reg32(mem_buf, env->fcsr0);
|
||||
}
|
||||
return 0;
|
||||
@ -87,11 +104,10 @@ static int loongarch_gdb_set_fpu(CPULoongArchState *env,
|
||||
if (0 <= n && n < 32) {
|
||||
env->fpr[n].vreg.D(0) = ldq_p(mem_buf);
|
||||
length = 8;
|
||||
} else if (n == 32) {
|
||||
uint64_t val = ldq_p(mem_buf);
|
||||
write_fcc(env, val);
|
||||
length = 8;
|
||||
} else if (n == 33) {
|
||||
} else if (32 <= n && n < 40) {
|
||||
env->cf[n - 32] = ldub_p(mem_buf);
|
||||
length = 1;
|
||||
} else if (n == 40) {
|
||||
env->fcsr0 = ldl_p(mem_buf);
|
||||
length = 4;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ static bool gen_pc(DisasContext *ctx, arg_r_i *a,
|
||||
target_ulong (*func)(target_ulong, int))
|
||||
{
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
target_ulong addr = func(ctx->base.pc_next, a->imm);
|
||||
target_ulong addr = make_address_pc(ctx, func(ctx->base.pc_next, a->imm));
|
||||
|
||||
tcg_gen_movi_tl(dest, addr);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
@ -199,6 +199,10 @@ static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a)
|
||||
TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
|
||||
TCGv src2 = tcg_constant_tl(a->imm);
|
||||
|
||||
if (!avail_64(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tcg_gen_deposit_tl(dest, src1, src2, 32, 32);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
@ -211,6 +215,10 @@ static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a)
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv src2 = tcg_constant_tl(a->imm);
|
||||
|
||||
if (!avail_64(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tcg_gen_deposit_tl(dest, src1, src2, 52, 12);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
@ -242,51 +250,55 @@ static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a)
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
if (!avail_64(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tcg_gen_addi_tl(dest, src1, a->imm << 16);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(add_w, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_add_tl)
|
||||
TRANS(add_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_add_tl)
|
||||
TRANS(sub_w, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_sub_tl)
|
||||
TRANS(sub_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_sub_tl)
|
||||
TRANS(and, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_and_tl)
|
||||
TRANS(or, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_or_tl)
|
||||
TRANS(xor, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_xor_tl)
|
||||
TRANS(nor, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_nor_tl)
|
||||
TRANS(andn, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_andc_tl)
|
||||
TRANS(orn, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_orc_tl)
|
||||
TRANS(slt, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_slt)
|
||||
TRANS(sltu, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu)
|
||||
TRANS(mul_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl)
|
||||
TRANS(mul_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl)
|
||||
TRANS(mulh_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
|
||||
TRANS(mulh_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_w)
|
||||
TRANS(mulh_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
|
||||
TRANS(mulh_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
|
||||
TRANS(mulw_d_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)
|
||||
TRANS(mulw_d_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl)
|
||||
TRANS(div_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w)
|
||||
TRANS(mod_w, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w)
|
||||
TRANS(div_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
|
||||
TRANS(mod_wu, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_rem_du)
|
||||
TRANS(div_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d)
|
||||
TRANS(mod_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d)
|
||||
TRANS(div_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du)
|
||||
TRANS(mod_du, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du)
|
||||
TRANS(slti, gen_rri_v, EXT_NONE, EXT_NONE, gen_slt)
|
||||
TRANS(sltui, gen_rri_v, EXT_NONE, EXT_NONE, gen_sltu)
|
||||
TRANS(addi_w, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_addi_tl)
|
||||
TRANS(addi_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_addi_tl)
|
||||
TRANS(alsl_w, gen_rrr_sa, EXT_NONE, EXT_SIGN, gen_alsl)
|
||||
TRANS(alsl_wu, gen_rrr_sa, EXT_NONE, EXT_ZERO, gen_alsl)
|
||||
TRANS(alsl_d, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_alsl)
|
||||
TRANS(pcaddi, gen_pc, gen_pcaddi)
|
||||
TRANS(pcalau12i, gen_pc, gen_pcalau12i)
|
||||
TRANS(pcaddu12i, gen_pc, gen_pcaddu12i)
|
||||
TRANS(pcaddu18i, gen_pc, gen_pcaddu18i)
|
||||
TRANS(andi, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_andi_tl)
|
||||
TRANS(ori, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_ori_tl)
|
||||
TRANS(xori, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_xori_tl)
|
||||
TRANS(add_w, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_add_tl)
|
||||
TRANS(add_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_add_tl)
|
||||
TRANS(sub_w, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_SIGN, tcg_gen_sub_tl)
|
||||
TRANS(sub_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_sub_tl)
|
||||
TRANS(and, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_and_tl)
|
||||
TRANS(or, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_or_tl)
|
||||
TRANS(xor, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_xor_tl)
|
||||
TRANS(nor, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_nor_tl)
|
||||
TRANS(andn, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_andc_tl)
|
||||
TRANS(orn, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_orc_tl)
|
||||
TRANS(slt, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_slt)
|
||||
TRANS(sltu, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu)
|
||||
TRANS(mul_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl)
|
||||
TRANS(mul_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl)
|
||||
TRANS(mulh_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
|
||||
TRANS(mulh_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_w)
|
||||
TRANS(mulh_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
|
||||
TRANS(mulh_du, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
|
||||
TRANS(mulw_d_w, 64, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)
|
||||
TRANS(mulw_d_wu, 64, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, tcg_gen_mul_tl)
|
||||
TRANS(div_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_div_w)
|
||||
TRANS(mod_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, gen_rem_w)
|
||||
TRANS(div_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_div_du)
|
||||
TRANS(mod_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_SIGN, gen_rem_du)
|
||||
TRANS(div_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_d)
|
||||
TRANS(mod_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_d)
|
||||
TRANS(div_du, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_div_du)
|
||||
TRANS(mod_du, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rem_du)
|
||||
TRANS(slti, ALL, gen_rri_v, EXT_NONE, EXT_NONE, gen_slt)
|
||||
TRANS(sltui, ALL, gen_rri_v, EXT_NONE, EXT_NONE, gen_sltu)
|
||||
TRANS(addi_w, ALL, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_addi_tl)
|
||||
TRANS(addi_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_addi_tl)
|
||||
TRANS(alsl_w, ALL, gen_rrr_sa, EXT_NONE, EXT_SIGN, gen_alsl)
|
||||
TRANS(alsl_wu, 64, gen_rrr_sa, EXT_NONE, EXT_ZERO, gen_alsl)
|
||||
TRANS(alsl_d, 64, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_alsl)
|
||||
TRANS(pcaddi, ALL, gen_pc, gen_pcaddi)
|
||||
TRANS(pcalau12i, ALL, gen_pc, gen_pcalau12i)
|
||||
TRANS(pcaddu12i, ALL, gen_pc, gen_pcaddu12i)
|
||||
TRANS(pcaddu18i, 64, gen_pc, gen_pcaddu18i)
|
||||
TRANS(andi, ALL, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_andi_tl)
|
||||
TRANS(ori, ALL, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_ori_tl)
|
||||
TRANS(xori, ALL, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_xori_tl)
|
||||
|
@ -7,9 +7,8 @@ static bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop)
|
||||
{
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t0 = make_address_i(ctx, src1, a->imm);
|
||||
|
||||
tcg_gen_addi_tl(t0, src1, a->imm);
|
||||
tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, mop);
|
||||
tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr));
|
||||
tcg_gen_st_tl(dest, cpu_env, offsetof(CPULoongArchState, llval));
|
||||
@ -62,49 +61,51 @@ static bool gen_am(DisasContext *ctx, arg_rrr *a,
|
||||
return false;
|
||||
}
|
||||
|
||||
addr = make_address_i(ctx, addr, 0);
|
||||
|
||||
func(dest, addr, val, ctx->mem_idx, mop);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(ll_w, gen_ll, MO_TESL)
|
||||
TRANS(sc_w, gen_sc, MO_TESL)
|
||||
TRANS(ll_d, gen_ll, MO_TEUQ)
|
||||
TRANS(sc_d, gen_sc, MO_TEUQ)
|
||||
TRANS(amswap_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
|
||||
TRANS(amswap_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
|
||||
TRANS(amadd_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
|
||||
TRANS(amadd_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
|
||||
TRANS(amand_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
|
||||
TRANS(amand_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
|
||||
TRANS(amor_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
|
||||
TRANS(amor_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ)
|
||||
TRANS(amxor_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
|
||||
TRANS(amxor_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ)
|
||||
TRANS(ammax_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
|
||||
TRANS(ammax_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ)
|
||||
TRANS(ammin_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
|
||||
TRANS(ammin_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ)
|
||||
TRANS(ammax_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
|
||||
TRANS(ammax_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ)
|
||||
TRANS(ammin_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
|
||||
TRANS(ammin_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ)
|
||||
TRANS(amswap_db_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
|
||||
TRANS(amswap_db_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
|
||||
TRANS(amadd_db_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
|
||||
TRANS(amadd_db_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
|
||||
TRANS(amand_db_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
|
||||
TRANS(amand_db_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
|
||||
TRANS(amor_db_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
|
||||
TRANS(amor_db_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ)
|
||||
TRANS(amxor_db_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
|
||||
TRANS(amxor_db_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ)
|
||||
TRANS(ammax_db_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
|
||||
TRANS(ammax_db_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ)
|
||||
TRANS(ammin_db_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
|
||||
TRANS(ammin_db_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ)
|
||||
TRANS(ammax_db_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
|
||||
TRANS(ammax_db_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ)
|
||||
TRANS(ammin_db_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
|
||||
TRANS(ammin_db_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ)
|
||||
TRANS(ll_w, ALL, gen_ll, MO_TESL)
|
||||
TRANS(sc_w, ALL, gen_sc, MO_TESL)
|
||||
TRANS(ll_d, 64, gen_ll, MO_TEUQ)
|
||||
TRANS(sc_d, 64, gen_sc, MO_TEUQ)
|
||||
TRANS(amswap_w, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
|
||||
TRANS(amswap_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
|
||||
TRANS(amadd_w, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
|
||||
TRANS(amadd_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
|
||||
TRANS(amand_w, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
|
||||
TRANS(amand_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
|
||||
TRANS(amor_w, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
|
||||
TRANS(amor_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ)
|
||||
TRANS(amxor_w, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
|
||||
TRANS(amxor_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ)
|
||||
TRANS(ammax_w, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
|
||||
TRANS(ammax_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ)
|
||||
TRANS(ammin_w, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
|
||||
TRANS(ammin_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ)
|
||||
TRANS(ammax_wu, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
|
||||
TRANS(ammax_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ)
|
||||
TRANS(ammin_wu, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
|
||||
TRANS(ammin_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ)
|
||||
TRANS(amswap_db_w, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
|
||||
TRANS(amswap_db_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
|
||||
TRANS(amadd_db_w, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
|
||||
TRANS(amadd_db_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
|
||||
TRANS(amand_db_w, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
|
||||
TRANS(amand_db_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
|
||||
TRANS(amor_db_w, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
|
||||
TRANS(amor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ)
|
||||
TRANS(amxor_db_w, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
|
||||
TRANS(amxor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ)
|
||||
TRANS(ammax_db_w, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
|
||||
TRANS(ammax_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ)
|
||||
TRANS(ammin_db_w, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
|
||||
TRANS(ammin_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ)
|
||||
TRANS(ammax_db_wu, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
|
||||
TRANS(ammax_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ)
|
||||
TRANS(ammin_db_wu, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
|
||||
TRANS(ammin_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ)
|
||||
|
@ -178,31 +178,31 @@ static void gen_masknez(TCGv dest, TCGv src1, TCGv src2)
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, zero, zero, src1);
|
||||
}
|
||||
|
||||
TRANS(ext_w_h, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext16s_tl)
|
||||
TRANS(ext_w_b, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext8s_tl)
|
||||
TRANS(clo_w, gen_rr, EXT_NONE, EXT_NONE, gen_clo_w)
|
||||
TRANS(clz_w, gen_rr, EXT_ZERO, EXT_NONE, gen_clz_w)
|
||||
TRANS(cto_w, gen_rr, EXT_NONE, EXT_NONE, gen_cto_w)
|
||||
TRANS(ctz_w, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_w)
|
||||
TRANS(clo_d, gen_rr, EXT_NONE, EXT_NONE, gen_clo_d)
|
||||
TRANS(clz_d, gen_rr, EXT_NONE, EXT_NONE, gen_clz_d)
|
||||
TRANS(cto_d, gen_rr, EXT_NONE, EXT_NONE, gen_cto_d)
|
||||
TRANS(ctz_d, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_d)
|
||||
TRANS(revb_2h, gen_rr, EXT_NONE, EXT_SIGN, gen_revb_2h)
|
||||
TRANS(revb_4h, gen_rr, EXT_NONE, EXT_NONE, gen_revb_4h)
|
||||
TRANS(revb_2w, gen_rr, EXT_NONE, EXT_NONE, gen_revb_2w)
|
||||
TRANS(revb_d, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_bswap64_i64)
|
||||
TRANS(revh_2w, gen_rr, EXT_NONE, EXT_NONE, gen_revh_2w)
|
||||
TRANS(revh_d, gen_rr, EXT_NONE, EXT_NONE, gen_revh_d)
|
||||
TRANS(bitrev_4b, gen_rr, EXT_ZERO, EXT_SIGN, gen_helper_bitswap)
|
||||
TRANS(bitrev_8b, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitswap)
|
||||
TRANS(bitrev_w, gen_rr, EXT_NONE, EXT_SIGN, gen_helper_bitrev_w)
|
||||
TRANS(bitrev_d, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitrev_d)
|
||||
TRANS(maskeqz, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_maskeqz)
|
||||
TRANS(masknez, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_masknez)
|
||||
TRANS(bytepick_w, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_w)
|
||||
TRANS(bytepick_d, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_d)
|
||||
TRANS(bstrins_w, gen_bstrins, EXT_SIGN)
|
||||
TRANS(bstrins_d, gen_bstrins, EXT_NONE)
|
||||
TRANS(bstrpick_w, gen_bstrpick, EXT_SIGN)
|
||||
TRANS(bstrpick_d, gen_bstrpick, EXT_NONE)
|
||||
TRANS(ext_w_h, ALL, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext16s_tl)
|
||||
TRANS(ext_w_b, ALL, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_ext8s_tl)
|
||||
TRANS(clo_w, ALL, gen_rr, EXT_NONE, EXT_NONE, gen_clo_w)
|
||||
TRANS(clz_w, ALL, gen_rr, EXT_ZERO, EXT_NONE, gen_clz_w)
|
||||
TRANS(cto_w, ALL, gen_rr, EXT_NONE, EXT_NONE, gen_cto_w)
|
||||
TRANS(ctz_w, ALL, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_w)
|
||||
TRANS(clo_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_clo_d)
|
||||
TRANS(clz_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_clz_d)
|
||||
TRANS(cto_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_cto_d)
|
||||
TRANS(ctz_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_ctz_d)
|
||||
TRANS(revb_2h, ALL, gen_rr, EXT_NONE, EXT_SIGN, gen_revb_2h)
|
||||
TRANS(revb_4h, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revb_4h)
|
||||
TRANS(revb_2w, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revb_2w)
|
||||
TRANS(revb_d, 64, gen_rr, EXT_NONE, EXT_NONE, tcg_gen_bswap64_i64)
|
||||
TRANS(revh_2w, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revh_2w)
|
||||
TRANS(revh_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_revh_d)
|
||||
TRANS(bitrev_4b, ALL, gen_rr, EXT_ZERO, EXT_SIGN, gen_helper_bitswap)
|
||||
TRANS(bitrev_8b, 64, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitswap)
|
||||
TRANS(bitrev_w, ALL, gen_rr, EXT_NONE, EXT_SIGN, gen_helper_bitrev_w)
|
||||
TRANS(bitrev_d, 64, gen_rr, EXT_NONE, EXT_NONE, gen_helper_bitrev_d)
|
||||
TRANS(maskeqz, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_maskeqz)
|
||||
TRANS(masknez, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_masknez)
|
||||
TRANS(bytepick_w, ALL, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_w)
|
||||
TRANS(bytepick_d, 64, gen_rrr_sa, EXT_NONE, EXT_NONE, gen_bytepick_d)
|
||||
TRANS(bstrins_w, ALL, gen_bstrins, EXT_SIGN)
|
||||
TRANS(bstrins_d, 64, gen_bstrins, EXT_NONE)
|
||||
TRANS(bstrpick_w, ALL, gen_bstrpick, EXT_SIGN)
|
||||
TRANS(bstrpick_d, 64, gen_bstrpick, EXT_NONE)
|
||||
|
@ -12,7 +12,7 @@ static bool trans_b(DisasContext *ctx, arg_b *a)
|
||||
|
||||
static bool trans_bl(DisasContext *ctx, arg_bl *a)
|
||||
{
|
||||
tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4);
|
||||
tcg_gen_movi_tl(cpu_gpr[1], make_address_pc(ctx, ctx->base.pc_next + 4));
|
||||
gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
return true;
|
||||
@ -23,8 +23,9 @@ static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
tcg_gen_addi_tl(cpu_pc, src1, a->imm);
|
||||
tcg_gen_movi_tl(dest, ctx->base.pc_next + 4);
|
||||
TCGv addr = make_address_i(ctx, src1, a->imm);
|
||||
tcg_gen_mov_tl(cpu_pc, addr);
|
||||
tcg_gen_movi_tl(dest, make_address_pc(ctx, ctx->base.pc_next + 4));
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
@ -71,13 +72,13 @@ static bool gen_cz_bc(DisasContext *ctx, arg_c_offs *a, TCGCond cond)
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(beq, gen_rr_bc, TCG_COND_EQ)
|
||||
TRANS(bne, gen_rr_bc, TCG_COND_NE)
|
||||
TRANS(blt, gen_rr_bc, TCG_COND_LT)
|
||||
TRANS(bge, gen_rr_bc, TCG_COND_GE)
|
||||
TRANS(bltu, gen_rr_bc, TCG_COND_LTU)
|
||||
TRANS(bgeu, gen_rr_bc, TCG_COND_GEU)
|
||||
TRANS(beqz, gen_rz_bc, TCG_COND_EQ)
|
||||
TRANS(bnez, gen_rz_bc, TCG_COND_NE)
|
||||
TRANS(bceqz, gen_cz_bc, TCG_COND_EQ)
|
||||
TRANS(bcnez, gen_cz_bc, TCG_COND_NE)
|
||||
TRANS(beq, ALL, gen_rr_bc, TCG_COND_EQ)
|
||||
TRANS(bne, ALL, gen_rr_bc, TCG_COND_NE)
|
||||
TRANS(blt, ALL, gen_rr_bc, TCG_COND_LT)
|
||||
TRANS(bge, ALL, gen_rr_bc, TCG_COND_GE)
|
||||
TRANS(bltu, ALL, gen_rr_bc, TCG_COND_LTU)
|
||||
TRANS(bgeu, ALL, gen_rr_bc, TCG_COND_GEU)
|
||||
TRANS(beqz, ALL, gen_rz_bc, TCG_COND_EQ)
|
||||
TRANS(bnez, ALL, gen_rz_bc, TCG_COND_NE)
|
||||
TRANS(bceqz, 64, gen_cz_bc, TCG_COND_EQ)
|
||||
TRANS(bcnez, 64, gen_cz_bc, TCG_COND_NE)
|
||||
|
@ -20,6 +20,10 @@ static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a)
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
|
||||
if (!avail_64(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gen_helper_asrtle_d(cpu_env, src1, src2);
|
||||
return true;
|
||||
}
|
||||
@ -29,6 +33,10 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a)
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
|
||||
if (!avail_64(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gen_helper_asrtgt_d(cpu_env, src1, src2);
|
||||
return true;
|
||||
}
|
||||
@ -89,11 +97,11 @@ static bool gen_crc(DisasContext *ctx, arg_rrr *a,
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(crc_w_b_w, gen_crc, gen_helper_crc32, tcg_constant_tl(1))
|
||||
TRANS(crc_w_h_w, gen_crc, gen_helper_crc32, tcg_constant_tl(2))
|
||||
TRANS(crc_w_w_w, gen_crc, gen_helper_crc32, tcg_constant_tl(4))
|
||||
TRANS(crc_w_d_w, gen_crc, gen_helper_crc32, tcg_constant_tl(8))
|
||||
TRANS(crcc_w_b_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(1))
|
||||
TRANS(crcc_w_h_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(2))
|
||||
TRANS(crcc_w_w_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(4))
|
||||
TRANS(crcc_w_d_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(8))
|
||||
TRANS(crc_w_b_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(1))
|
||||
TRANS(crc_w_h_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(2))
|
||||
TRANS(crc_w_w_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(4))
|
||||
TRANS(crc_w_d_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(8))
|
||||
TRANS(crcc_w_b_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(1))
|
||||
TRANS(crcc_w_h_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(2))
|
||||
TRANS(crcc_w_w_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(4))
|
||||
TRANS(crcc_w_d_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(8))
|
||||
|
@ -67,6 +67,10 @@ static bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a)
|
||||
TCGv src1 = get_fpr(ctx, a->fk);
|
||||
TCGv src2 = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP_SP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_deposit_i64(dest, src1, src2, 0, 31);
|
||||
@ -81,6 +85,10 @@ static bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a)
|
||||
TCGv src1 = get_fpr(ctx, a->fk);
|
||||
TCGv src2 = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP_DP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_deposit_i64(dest, src1, src2, 0, 63);
|
||||
@ -94,6 +102,10 @@ static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a)
|
||||
TCGv dest = get_fpr(ctx, a->fd);
|
||||
TCGv src = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP_SP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_andi_i64(dest, src, MAKE_64BIT_MASK(0, 31));
|
||||
@ -108,6 +120,10 @@ static bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a)
|
||||
TCGv dest = get_fpr(ctx, a->fd);
|
||||
TCGv src = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP_DP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_andi_i64(dest, src, MAKE_64BIT_MASK(0, 63));
|
||||
@ -121,6 +137,10 @@ static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a)
|
||||
TCGv dest = get_fpr(ctx, a->fd);
|
||||
TCGv src = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP_SP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_xori_i64(dest, src, 0x80000000);
|
||||
@ -135,6 +155,10 @@ static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a)
|
||||
TCGv dest = get_fpr(ctx, a->fd);
|
||||
TCGv src = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP_DP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_xori_i64(dest, src, 0x8000000000000000LL);
|
||||
@ -143,41 +167,41 @@ static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(fadd_s, gen_fff, gen_helper_fadd_s)
|
||||
TRANS(fadd_d, gen_fff, gen_helper_fadd_d)
|
||||
TRANS(fsub_s, gen_fff, gen_helper_fsub_s)
|
||||
TRANS(fsub_d, gen_fff, gen_helper_fsub_d)
|
||||
TRANS(fmul_s, gen_fff, gen_helper_fmul_s)
|
||||
TRANS(fmul_d, gen_fff, gen_helper_fmul_d)
|
||||
TRANS(fdiv_s, gen_fff, gen_helper_fdiv_s)
|
||||
TRANS(fdiv_d, gen_fff, gen_helper_fdiv_d)
|
||||
TRANS(fmax_s, gen_fff, gen_helper_fmax_s)
|
||||
TRANS(fmax_d, gen_fff, gen_helper_fmax_d)
|
||||
TRANS(fmin_s, gen_fff, gen_helper_fmin_s)
|
||||
TRANS(fmin_d, gen_fff, gen_helper_fmin_d)
|
||||
TRANS(fmaxa_s, gen_fff, gen_helper_fmaxa_s)
|
||||
TRANS(fmaxa_d, gen_fff, gen_helper_fmaxa_d)
|
||||
TRANS(fmina_s, gen_fff, gen_helper_fmina_s)
|
||||
TRANS(fmina_d, gen_fff, gen_helper_fmina_d)
|
||||
TRANS(fscaleb_s, gen_fff, gen_helper_fscaleb_s)
|
||||
TRANS(fscaleb_d, gen_fff, gen_helper_fscaleb_d)
|
||||
TRANS(fsqrt_s, gen_ff, gen_helper_fsqrt_s)
|
||||
TRANS(fsqrt_d, gen_ff, gen_helper_fsqrt_d)
|
||||
TRANS(frecip_s, gen_ff, gen_helper_frecip_s)
|
||||
TRANS(frecip_d, gen_ff, gen_helper_frecip_d)
|
||||
TRANS(frsqrt_s, gen_ff, gen_helper_frsqrt_s)
|
||||
TRANS(frsqrt_d, gen_ff, gen_helper_frsqrt_d)
|
||||
TRANS(flogb_s, gen_ff, gen_helper_flogb_s)
|
||||
TRANS(flogb_d, gen_ff, gen_helper_flogb_d)
|
||||
TRANS(fclass_s, gen_ff, gen_helper_fclass_s)
|
||||
TRANS(fclass_d, gen_ff, gen_helper_fclass_d)
|
||||
TRANS(fmadd_s, gen_muladd, gen_helper_fmuladd_s, 0)
|
||||
TRANS(fmadd_d, gen_muladd, gen_helper_fmuladd_d, 0)
|
||||
TRANS(fmsub_s, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_c)
|
||||
TRANS(fmsub_d, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_c)
|
||||
TRANS(fnmadd_s, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_result)
|
||||
TRANS(fnmadd_d, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_result)
|
||||
TRANS(fnmsub_s, gen_muladd, gen_helper_fmuladd_s,
|
||||
TRANS(fadd_s, FP_SP, gen_fff, gen_helper_fadd_s)
|
||||
TRANS(fadd_d, FP_DP, gen_fff, gen_helper_fadd_d)
|
||||
TRANS(fsub_s, FP_SP, gen_fff, gen_helper_fsub_s)
|
||||
TRANS(fsub_d, FP_DP, gen_fff, gen_helper_fsub_d)
|
||||
TRANS(fmul_s, FP_SP, gen_fff, gen_helper_fmul_s)
|
||||
TRANS(fmul_d, FP_DP, gen_fff, gen_helper_fmul_d)
|
||||
TRANS(fdiv_s, FP_SP, gen_fff, gen_helper_fdiv_s)
|
||||
TRANS(fdiv_d, FP_DP, gen_fff, gen_helper_fdiv_d)
|
||||
TRANS(fmax_s, FP_SP, gen_fff, gen_helper_fmax_s)
|
||||
TRANS(fmax_d, FP_DP, gen_fff, gen_helper_fmax_d)
|
||||
TRANS(fmin_s, FP_SP, gen_fff, gen_helper_fmin_s)
|
||||
TRANS(fmin_d, FP_DP, gen_fff, gen_helper_fmin_d)
|
||||
TRANS(fmaxa_s, FP_SP, gen_fff, gen_helper_fmaxa_s)
|
||||
TRANS(fmaxa_d, FP_DP, gen_fff, gen_helper_fmaxa_d)
|
||||
TRANS(fmina_s, FP_SP, gen_fff, gen_helper_fmina_s)
|
||||
TRANS(fmina_d, FP_DP, gen_fff, gen_helper_fmina_d)
|
||||
TRANS(fscaleb_s, FP_SP, gen_fff, gen_helper_fscaleb_s)
|
||||
TRANS(fscaleb_d, FP_DP, gen_fff, gen_helper_fscaleb_d)
|
||||
TRANS(fsqrt_s, FP_SP, gen_ff, gen_helper_fsqrt_s)
|
||||
TRANS(fsqrt_d, FP_DP, gen_ff, gen_helper_fsqrt_d)
|
||||
TRANS(frecip_s, FP_SP, gen_ff, gen_helper_frecip_s)
|
||||
TRANS(frecip_d, FP_DP, gen_ff, gen_helper_frecip_d)
|
||||
TRANS(frsqrt_s, FP_SP, gen_ff, gen_helper_frsqrt_s)
|
||||
TRANS(frsqrt_d, FP_DP, gen_ff, gen_helper_frsqrt_d)
|
||||
TRANS(flogb_s, FP_SP, gen_ff, gen_helper_flogb_s)
|
||||
TRANS(flogb_d, FP_DP, gen_ff, gen_helper_flogb_d)
|
||||
TRANS(fclass_s, FP_SP, gen_ff, gen_helper_fclass_s)
|
||||
TRANS(fclass_d, FP_DP, gen_ff, gen_helper_fclass_d)
|
||||
TRANS(fmadd_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, 0)
|
||||
TRANS(fmadd_d, FP_DP, gen_muladd, gen_helper_fmuladd_d, 0)
|
||||
TRANS(fmsub_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_c)
|
||||
TRANS(fmsub_d, FP_DP, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_c)
|
||||
TRANS(fnmadd_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, float_muladd_negate_result)
|
||||
TRANS(fnmadd_d, FP_DP, gen_muladd, gen_helper_fmuladd_d, float_muladd_negate_result)
|
||||
TRANS(fnmsub_s, FP_SP, gen_muladd, gen_helper_fmuladd_s,
|
||||
float_muladd_negate_c | float_muladd_negate_result)
|
||||
TRANS(fnmsub_d, gen_muladd, gen_helper_fmuladd_d,
|
||||
TRANS(fnmsub_d, FP_DP, gen_muladd, gen_helper_fmuladd_d,
|
||||
float_muladd_negate_c | float_muladd_negate_result)
|
||||
|
@ -29,6 +29,10 @@ static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
|
||||
uint32_t flags;
|
||||
void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
|
||||
|
||||
if (!avail_FP_SP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
var = tcg_temp_new();
|
||||
@ -49,6 +53,10 @@ static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a)
|
||||
uint32_t flags;
|
||||
void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
|
||||
|
||||
if (!avail_FP_DP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
var = tcg_temp_new();
|
||||
|
@ -3,31 +3,31 @@
|
||||
* Copyright (c) 2021 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
TRANS(fcvt_s_d, gen_ff, gen_helper_fcvt_s_d)
|
||||
TRANS(fcvt_d_s, gen_ff, gen_helper_fcvt_d_s)
|
||||
TRANS(ftintrm_w_s, gen_ff, gen_helper_ftintrm_w_s)
|
||||
TRANS(ftintrm_w_d, gen_ff, gen_helper_ftintrm_w_d)
|
||||
TRANS(ftintrm_l_s, gen_ff, gen_helper_ftintrm_l_s)
|
||||
TRANS(ftintrm_l_d, gen_ff, gen_helper_ftintrm_l_d)
|
||||
TRANS(ftintrp_w_s, gen_ff, gen_helper_ftintrp_w_s)
|
||||
TRANS(ftintrp_w_d, gen_ff, gen_helper_ftintrp_w_d)
|
||||
TRANS(ftintrp_l_s, gen_ff, gen_helper_ftintrp_l_s)
|
||||
TRANS(ftintrp_l_d, gen_ff, gen_helper_ftintrp_l_d)
|
||||
TRANS(ftintrz_w_s, gen_ff, gen_helper_ftintrz_w_s)
|
||||
TRANS(ftintrz_w_d, gen_ff, gen_helper_ftintrz_w_d)
|
||||
TRANS(ftintrz_l_s, gen_ff, gen_helper_ftintrz_l_s)
|
||||
TRANS(ftintrz_l_d, gen_ff, gen_helper_ftintrz_l_d)
|
||||
TRANS(ftintrne_w_s, gen_ff, gen_helper_ftintrne_w_s)
|
||||
TRANS(ftintrne_w_d, gen_ff, gen_helper_ftintrne_w_d)
|
||||
TRANS(ftintrne_l_s, gen_ff, gen_helper_ftintrne_l_s)
|
||||
TRANS(ftintrne_l_d, gen_ff, gen_helper_ftintrne_l_d)
|
||||
TRANS(ftint_w_s, gen_ff, gen_helper_ftint_w_s)
|
||||
TRANS(ftint_w_d, gen_ff, gen_helper_ftint_w_d)
|
||||
TRANS(ftint_l_s, gen_ff, gen_helper_ftint_l_s)
|
||||
TRANS(ftint_l_d, gen_ff, gen_helper_ftint_l_d)
|
||||
TRANS(ffint_s_w, gen_ff, gen_helper_ffint_s_w)
|
||||
TRANS(ffint_s_l, gen_ff, gen_helper_ffint_s_l)
|
||||
TRANS(ffint_d_w, gen_ff, gen_helper_ffint_d_w)
|
||||
TRANS(ffint_d_l, gen_ff, gen_helper_ffint_d_l)
|
||||
TRANS(frint_s, gen_ff, gen_helper_frint_s)
|
||||
TRANS(frint_d, gen_ff, gen_helper_frint_d)
|
||||
TRANS(fcvt_s_d, FP_DP, gen_ff, gen_helper_fcvt_s_d)
|
||||
TRANS(fcvt_d_s, FP_DP, gen_ff, gen_helper_fcvt_d_s)
|
||||
TRANS(ftintrm_w_s, FP_SP, gen_ff, gen_helper_ftintrm_w_s)
|
||||
TRANS(ftintrm_w_d, FP_DP, gen_ff, gen_helper_ftintrm_w_d)
|
||||
TRANS(ftintrm_l_s, FP_SP, gen_ff, gen_helper_ftintrm_l_s)
|
||||
TRANS(ftintrm_l_d, FP_DP, gen_ff, gen_helper_ftintrm_l_d)
|
||||
TRANS(ftintrp_w_s, FP_SP, gen_ff, gen_helper_ftintrp_w_s)
|
||||
TRANS(ftintrp_w_d, FP_DP, gen_ff, gen_helper_ftintrp_w_d)
|
||||
TRANS(ftintrp_l_s, FP_SP, gen_ff, gen_helper_ftintrp_l_s)
|
||||
TRANS(ftintrp_l_d, FP_DP, gen_ff, gen_helper_ftintrp_l_d)
|
||||
TRANS(ftintrz_w_s, FP_SP, gen_ff, gen_helper_ftintrz_w_s)
|
||||
TRANS(ftintrz_w_d, FP_DP, gen_ff, gen_helper_ftintrz_w_d)
|
||||
TRANS(ftintrz_l_s, FP_SP, gen_ff, gen_helper_ftintrz_l_s)
|
||||
TRANS(ftintrz_l_d, FP_DP, gen_ff, gen_helper_ftintrz_l_d)
|
||||
TRANS(ftintrne_w_s, FP_SP, gen_ff, gen_helper_ftintrne_w_s)
|
||||
TRANS(ftintrne_w_d, FP_DP, gen_ff, gen_helper_ftintrne_w_d)
|
||||
TRANS(ftintrne_l_s, FP_SP, gen_ff, gen_helper_ftintrne_l_s)
|
||||
TRANS(ftintrne_l_d, FP_DP, gen_ff, gen_helper_ftintrne_l_d)
|
||||
TRANS(ftint_w_s, FP_SP, gen_ff, gen_helper_ftint_w_s)
|
||||
TRANS(ftint_w_d, FP_DP, gen_ff, gen_helper_ftint_w_d)
|
||||
TRANS(ftint_l_s, FP_SP, gen_ff, gen_helper_ftint_l_s)
|
||||
TRANS(ftint_l_d, FP_DP, gen_ff, gen_helper_ftint_l_d)
|
||||
TRANS(ffint_s_w, FP_SP, gen_ff, gen_helper_ffint_s_w)
|
||||
TRANS(ffint_s_l, FP_SP, gen_ff, gen_helper_ffint_s_l)
|
||||
TRANS(ffint_d_w, FP_DP, gen_ff, gen_helper_ffint_d_w)
|
||||
TRANS(ffint_d_l, FP_DP, gen_ff, gen_helper_ffint_d_l)
|
||||
TRANS(frint_s, FP_SP, gen_ff, gen_helper_frint_s)
|
||||
TRANS(frint_d, FP_DP, gen_ff, gen_helper_frint_d)
|
||||
|
@ -17,11 +17,7 @@ static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
if (a->imm) {
|
||||
TCGv temp = tcg_temp_new();
|
||||
tcg_gen_addi_tl(temp, addr, a->imm);
|
||||
addr = temp;
|
||||
}
|
||||
addr = make_address_i(ctx, addr, a->imm);
|
||||
|
||||
tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
|
||||
maybe_nanbox_load(dest, mop);
|
||||
@ -37,11 +33,7 @@ static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
if (a->imm) {
|
||||
TCGv temp = tcg_temp_new();
|
||||
tcg_gen_addi_tl(temp, addr, a->imm);
|
||||
addr = temp;
|
||||
}
|
||||
addr = make_address_i(ctx, addr, a->imm);
|
||||
|
||||
tcg_gen_qemu_st_tl(src, addr, ctx->mem_idx, mop);
|
||||
|
||||
@ -57,8 +49,7 @@ static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
addr = tcg_temp_new();
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
addr = make_address_x(ctx, src1, src2);
|
||||
tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
|
||||
maybe_nanbox_load(dest, mop);
|
||||
set_fpr(a->fd, dest);
|
||||
@ -75,8 +66,7 @@ static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
addr = tcg_temp_new();
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
addr = make_address_x(ctx, src1, src2);
|
||||
tcg_gen_qemu_st_tl(src3, addr, ctx->mem_idx, mop);
|
||||
|
||||
return true;
|
||||
@ -91,9 +81,8 @@ static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
addr = tcg_temp_new();
|
||||
gen_helper_asrtgt_d(cpu_env, src1, src2);
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
addr = make_address_x(ctx, src1, src2);
|
||||
tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
|
||||
maybe_nanbox_load(dest, mop);
|
||||
set_fpr(a->fd, dest);
|
||||
@ -110,9 +99,8 @@ static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
addr = tcg_temp_new();
|
||||
gen_helper_asrtgt_d(cpu_env, src1, src2);
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
addr = make_address_x(ctx, src1, src2);
|
||||
tcg_gen_qemu_st_tl(src3, addr, ctx->mem_idx, mop);
|
||||
|
||||
return true;
|
||||
@ -127,9 +115,8 @@ static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
addr = tcg_temp_new();
|
||||
gen_helper_asrtle_d(cpu_env, src1, src2);
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
addr = make_address_x(ctx, src1, src2);
|
||||
tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
|
||||
maybe_nanbox_load(dest, mop);
|
||||
set_fpr(a->fd, dest);
|
||||
@ -146,27 +133,26 @@ static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop)
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
addr = tcg_temp_new();
|
||||
gen_helper_asrtle_d(cpu_env, src1, src2);
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
addr = make_address_x(ctx, src1, src2);
|
||||
tcg_gen_qemu_st_tl(src3, addr, ctx->mem_idx, mop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(fld_s, gen_fload_i, MO_TEUL)
|
||||
TRANS(fst_s, gen_fstore_i, MO_TEUL)
|
||||
TRANS(fld_d, gen_fload_i, MO_TEUQ)
|
||||
TRANS(fst_d, gen_fstore_i, MO_TEUQ)
|
||||
TRANS(fldx_s, gen_floadx, MO_TEUL)
|
||||
TRANS(fldx_d, gen_floadx, MO_TEUQ)
|
||||
TRANS(fstx_s, gen_fstorex, MO_TEUL)
|
||||
TRANS(fstx_d, gen_fstorex, MO_TEUQ)
|
||||
TRANS(fldgt_s, gen_fload_gt, MO_TEUL)
|
||||
TRANS(fldgt_d, gen_fload_gt, MO_TEUQ)
|
||||
TRANS(fldle_s, gen_fload_le, MO_TEUL)
|
||||
TRANS(fldle_d, gen_fload_le, MO_TEUQ)
|
||||
TRANS(fstgt_s, gen_fstore_gt, MO_TEUL)
|
||||
TRANS(fstgt_d, gen_fstore_gt, MO_TEUQ)
|
||||
TRANS(fstle_s, gen_fstore_le, MO_TEUL)
|
||||
TRANS(fstle_d, gen_fstore_le, MO_TEUQ)
|
||||
TRANS(fld_s, FP_SP, gen_fload_i, MO_TEUL)
|
||||
TRANS(fst_s, FP_SP, gen_fstore_i, MO_TEUL)
|
||||
TRANS(fld_d, FP_DP, gen_fload_i, MO_TEUQ)
|
||||
TRANS(fst_d, FP_DP, gen_fstore_i, MO_TEUQ)
|
||||
TRANS(fldx_s, FP_SP, gen_floadx, MO_TEUL)
|
||||
TRANS(fldx_d, FP_DP, gen_floadx, MO_TEUQ)
|
||||
TRANS(fstx_s, FP_SP, gen_fstorex, MO_TEUL)
|
||||
TRANS(fstx_d, FP_DP, gen_fstorex, MO_TEUQ)
|
||||
TRANS(fldgt_s, FP_SP, gen_fload_gt, MO_TEUL)
|
||||
TRANS(fldgt_d, FP_DP, gen_fload_gt, MO_TEUQ)
|
||||
TRANS(fldle_s, FP_SP, gen_fload_le, MO_TEUL)
|
||||
TRANS(fldle_d, FP_DP, gen_fload_le, MO_TEUQ)
|
||||
TRANS(fstgt_s, FP_SP, gen_fstore_gt, MO_TEUL)
|
||||
TRANS(fstgt_d, FP_DP, gen_fstore_gt, MO_TEUQ)
|
||||
TRANS(fstle_s, FP_SP, gen_fstore_le, MO_TEUL)
|
||||
TRANS(fstle_d, FP_DP, gen_fstore_le, MO_TEUQ)
|
||||
|
@ -15,6 +15,10 @@ static bool trans_fsel(DisasContext *ctx, arg_fsel *a)
|
||||
TCGv src2 = get_fpr(ctx, a->fk);
|
||||
TCGv cond;
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
cond = tcg_temp_new();
|
||||
@ -48,6 +52,10 @@ static bool gen_r2f(DisasContext *ctx, arg_fr *a,
|
||||
TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv dest = get_fpr(ctx, a->fd);
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
func(dest, src);
|
||||
@ -62,6 +70,10 @@ static bool gen_f2r(DisasContext *ctx, arg_rf *a,
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv src = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
func(dest, src);
|
||||
@ -75,6 +87,10 @@ static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a)
|
||||
uint32_t mask = fcsr_mask[a->fcsrd];
|
||||
TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
if (mask == UINT32_MAX) {
|
||||
@ -105,6 +121,10 @@ static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a)
|
||||
{
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_ld32u_i64(dest, cpu_env, offsetof(CPULoongArchState, fcsr0));
|
||||
@ -134,6 +154,10 @@ static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a)
|
||||
TCGv t0;
|
||||
TCGv src = get_fpr(ctx, a->fj);
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
t0 = tcg_temp_new();
|
||||
@ -147,6 +171,10 @@ static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a)
|
||||
{
|
||||
TCGv dest = get_fpr(ctx, a->fd);
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_ld8u_tl(dest, cpu_env,
|
||||
@ -160,6 +188,10 @@ static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a)
|
||||
{
|
||||
TCGv t0;
|
||||
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
t0 = tcg_temp_new();
|
||||
@ -171,6 +203,10 @@ static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a)
|
||||
|
||||
static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a)
|
||||
{
|
||||
if (!avail_FP(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_FPE;
|
||||
|
||||
tcg_gen_ld8u_tl(gpr_dst(ctx, a->rd, EXT_NONE), cpu_env,
|
||||
@ -178,11 +214,11 @@ static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(fmov_s, gen_f2f, tcg_gen_mov_tl, true)
|
||||
TRANS(fmov_d, gen_f2f, tcg_gen_mov_tl, false)
|
||||
TRANS(movgr2fr_w, gen_r2f, gen_movgr2fr_w)
|
||||
TRANS(movgr2fr_d, gen_r2f, tcg_gen_mov_tl)
|
||||
TRANS(movgr2frh_w, gen_r2f, gen_movgr2frh_w)
|
||||
TRANS(movfr2gr_s, gen_f2r, tcg_gen_ext32s_tl)
|
||||
TRANS(movfr2gr_d, gen_f2r, tcg_gen_mov_tl)
|
||||
TRANS(movfrh2gr_s, gen_f2r, gen_movfrh2gr_s)
|
||||
TRANS(fmov_s, FP_SP, gen_f2f, tcg_gen_mov_tl, true)
|
||||
TRANS(fmov_d, FP_DP, gen_f2f, tcg_gen_mov_tl, false)
|
||||
TRANS(movgr2fr_w, FP_SP, gen_r2f, gen_movgr2fr_w)
|
||||
TRANS(movgr2fr_d, 64, gen_r2f, tcg_gen_mov_tl)
|
||||
TRANS(movgr2frh_w, FP_DP, gen_r2f, gen_movgr2frh_w)
|
||||
TRANS(movfr2gr_s, FP_SP, gen_f2r, tcg_gen_ext32s_tl)
|
||||
TRANS(movfr2gr_d, 64, gen_f2r, tcg_gen_mov_tl)
|
||||
TRANS(movfrh2gr_s, FP_DP, gen_f2r, gen_movfrh2gr_s)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,11 +8,7 @@ static bool gen_load(DisasContext *ctx, arg_rr_i *a, MemOp mop)
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
if (a->imm) {
|
||||
TCGv temp = tcg_temp_new();
|
||||
tcg_gen_addi_tl(temp, addr, a->imm);
|
||||
addr = temp;
|
||||
}
|
||||
addr = make_address_i(ctx, addr, a->imm);
|
||||
|
||||
tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
@ -24,11 +20,7 @@ static bool gen_store(DisasContext *ctx, arg_rr_i *a, MemOp mop)
|
||||
TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
|
||||
TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
if (a->imm) {
|
||||
TCGv temp = tcg_temp_new();
|
||||
tcg_gen_addi_tl(temp, addr, a->imm);
|
||||
addr = temp;
|
||||
}
|
||||
addr = make_address_i(ctx, addr, a->imm);
|
||||
|
||||
tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
|
||||
return true;
|
||||
@ -39,9 +31,8 @@ static bool gen_loadx(DisasContext *ctx, arg_rrr *a, MemOp mop)
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
TCGv addr = tcg_temp_new();
|
||||
TCGv addr = make_address_x(ctx, src1, src2);
|
||||
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
@ -53,9 +44,8 @@ static bool gen_storex(DisasContext *ctx, arg_rrr *a, MemOp mop)
|
||||
TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
TCGv addr = tcg_temp_new();
|
||||
TCGv addr = make_address_x(ctx, src1, src2);
|
||||
|
||||
tcg_gen_add_tl(addr, src1, src2);
|
||||
tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
|
||||
|
||||
return true;
|
||||
@ -68,6 +58,7 @@ static bool gen_load_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
|
||||
gen_helper_asrtgt_d(cpu_env, src1, src2);
|
||||
src1 = make_address_i(ctx, src1, 0);
|
||||
tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
@ -81,6 +72,7 @@ static bool gen_load_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
|
||||
gen_helper_asrtle_d(cpu_env, src1, src2);
|
||||
src1 = make_address_i(ctx, src1, 0);
|
||||
tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
@ -94,6 +86,7 @@ static bool gen_store_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
|
||||
gen_helper_asrtgt_d(cpu_env, src1, src2);
|
||||
src1 = make_address_i(ctx, src1, 0);
|
||||
tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
|
||||
|
||||
return true;
|
||||
@ -106,6 +99,7 @@ static bool gen_store_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
|
||||
TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
|
||||
|
||||
gen_helper_asrtle_d(cpu_env, src1, src2);
|
||||
src1 = make_address_i(ctx, src1, 0);
|
||||
tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
|
||||
|
||||
return true;
|
||||
@ -133,11 +127,7 @@ static bool gen_ldptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
if (a->imm) {
|
||||
TCGv temp = tcg_temp_new();
|
||||
tcg_gen_addi_tl(temp, addr, a->imm);
|
||||
addr = temp;
|
||||
}
|
||||
addr = make_address_i(ctx, addr, a->imm);
|
||||
|
||||
tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
@ -149,55 +139,51 @@ static bool gen_stptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
|
||||
TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
|
||||
TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
if (a->imm) {
|
||||
TCGv temp = tcg_temp_new();
|
||||
tcg_gen_addi_tl(temp, addr, a->imm);
|
||||
addr = temp;
|
||||
}
|
||||
addr = make_address_i(ctx, addr, a->imm);
|
||||
|
||||
tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(ld_b, gen_load, MO_SB)
|
||||
TRANS(ld_h, gen_load, MO_TESW)
|
||||
TRANS(ld_w, gen_load, MO_TESL)
|
||||
TRANS(ld_d, gen_load, MO_TEUQ)
|
||||
TRANS(st_b, gen_store, MO_UB)
|
||||
TRANS(st_h, gen_store, MO_TEUW)
|
||||
TRANS(st_w, gen_store, MO_TEUL)
|
||||
TRANS(st_d, gen_store, MO_TEUQ)
|
||||
TRANS(ld_bu, gen_load, MO_UB)
|
||||
TRANS(ld_hu, gen_load, MO_TEUW)
|
||||
TRANS(ld_wu, gen_load, MO_TEUL)
|
||||
TRANS(ldx_b, gen_loadx, MO_SB)
|
||||
TRANS(ldx_h, gen_loadx, MO_TESW)
|
||||
TRANS(ldx_w, gen_loadx, MO_TESL)
|
||||
TRANS(ldx_d, gen_loadx, MO_TEUQ)
|
||||
TRANS(stx_b, gen_storex, MO_UB)
|
||||
TRANS(stx_h, gen_storex, MO_TEUW)
|
||||
TRANS(stx_w, gen_storex, MO_TEUL)
|
||||
TRANS(stx_d, gen_storex, MO_TEUQ)
|
||||
TRANS(ldx_bu, gen_loadx, MO_UB)
|
||||
TRANS(ldx_hu, gen_loadx, MO_TEUW)
|
||||
TRANS(ldx_wu, gen_loadx, MO_TEUL)
|
||||
TRANS(ldptr_w, gen_ldptr, MO_TESL)
|
||||
TRANS(stptr_w, gen_stptr, MO_TEUL)
|
||||
TRANS(ldptr_d, gen_ldptr, MO_TEUQ)
|
||||
TRANS(stptr_d, gen_stptr, MO_TEUQ)
|
||||
TRANS(ldgt_b, gen_load_gt, MO_SB)
|
||||
TRANS(ldgt_h, gen_load_gt, MO_TESW)
|
||||
TRANS(ldgt_w, gen_load_gt, MO_TESL)
|
||||
TRANS(ldgt_d, gen_load_gt, MO_TEUQ)
|
||||
TRANS(ldle_b, gen_load_le, MO_SB)
|
||||
TRANS(ldle_h, gen_load_le, MO_TESW)
|
||||
TRANS(ldle_w, gen_load_le, MO_TESL)
|
||||
TRANS(ldle_d, gen_load_le, MO_TEUQ)
|
||||
TRANS(stgt_b, gen_store_gt, MO_UB)
|
||||
TRANS(stgt_h, gen_store_gt, MO_TEUW)
|
||||
TRANS(stgt_w, gen_store_gt, MO_TEUL)
|
||||
TRANS(stgt_d, gen_store_gt, MO_TEUQ)
|
||||
TRANS(stle_b, gen_store_le, MO_UB)
|
||||
TRANS(stle_h, gen_store_le, MO_TEUW)
|
||||
TRANS(stle_w, gen_store_le, MO_TEUL)
|
||||
TRANS(stle_d, gen_store_le, MO_TEUQ)
|
||||
TRANS(ld_b, ALL, gen_load, MO_SB)
|
||||
TRANS(ld_h, ALL, gen_load, MO_TESW)
|
||||
TRANS(ld_w, ALL, gen_load, MO_TESL)
|
||||
TRANS(ld_d, 64, gen_load, MO_TEUQ)
|
||||
TRANS(st_b, ALL, gen_store, MO_UB)
|
||||
TRANS(st_h, ALL, gen_store, MO_TEUW)
|
||||
TRANS(st_w, ALL, gen_store, MO_TEUL)
|
||||
TRANS(st_d, 64, gen_store, MO_TEUQ)
|
||||
TRANS(ld_bu, ALL, gen_load, MO_UB)
|
||||
TRANS(ld_hu, ALL, gen_load, MO_TEUW)
|
||||
TRANS(ld_wu, 64, gen_load, MO_TEUL)
|
||||
TRANS(ldx_b, 64, gen_loadx, MO_SB)
|
||||
TRANS(ldx_h, 64, gen_loadx, MO_TESW)
|
||||
TRANS(ldx_w, 64, gen_loadx, MO_TESL)
|
||||
TRANS(ldx_d, 64, gen_loadx, MO_TEUQ)
|
||||
TRANS(stx_b, 64, gen_storex, MO_UB)
|
||||
TRANS(stx_h, 64, gen_storex, MO_TEUW)
|
||||
TRANS(stx_w, 64, gen_storex, MO_TEUL)
|
||||
TRANS(stx_d, 64, gen_storex, MO_TEUQ)
|
||||
TRANS(ldx_bu, 64, gen_loadx, MO_UB)
|
||||
TRANS(ldx_hu, 64, gen_loadx, MO_TEUW)
|
||||
TRANS(ldx_wu, 64, gen_loadx, MO_TEUL)
|
||||
TRANS(ldptr_w, 64, gen_ldptr, MO_TESL)
|
||||
TRANS(stptr_w, 64, gen_stptr, MO_TEUL)
|
||||
TRANS(ldptr_d, 64, gen_ldptr, MO_TEUQ)
|
||||
TRANS(stptr_d, 64, gen_stptr, MO_TEUQ)
|
||||
TRANS(ldgt_b, 64, gen_load_gt, MO_SB)
|
||||
TRANS(ldgt_h, 64, gen_load_gt, MO_TESW)
|
||||
TRANS(ldgt_w, 64, gen_load_gt, MO_TESL)
|
||||
TRANS(ldgt_d, 64, gen_load_gt, MO_TEUQ)
|
||||
TRANS(ldle_b, 64, gen_load_le, MO_SB)
|
||||
TRANS(ldle_h, 64, gen_load_le, MO_TESW)
|
||||
TRANS(ldle_w, 64, gen_load_le, MO_TESL)
|
||||
TRANS(ldle_d, 64, gen_load_le, MO_TEUQ)
|
||||
TRANS(stgt_b, 64, gen_store_gt, MO_UB)
|
||||
TRANS(stgt_h, 64, gen_store_gt, MO_TEUW)
|
||||
TRANS(stgt_w, 64, gen_store_gt, MO_TEUL)
|
||||
TRANS(stgt_d, 64, gen_store_gt, MO_TEUQ)
|
||||
TRANS(stle_b, 64, gen_store_le, MO_UB)
|
||||
TRANS(stle_h, 64, gen_store_le, MO_TEUW)
|
||||
TRANS(stle_w, 64, gen_store_le, MO_TEUL)
|
||||
TRANS(stle_d, 64, gen_store_le, MO_TEUQ)
|
||||
|
@ -312,14 +312,14 @@ static bool gen_iocsrwr(DisasContext *ctx, arg_rr *a,
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(iocsrrd_b, gen_iocsrrd, gen_helper_iocsrrd_b)
|
||||
TRANS(iocsrrd_h, gen_iocsrrd, gen_helper_iocsrrd_h)
|
||||
TRANS(iocsrrd_w, gen_iocsrrd, gen_helper_iocsrrd_w)
|
||||
TRANS(iocsrrd_d, gen_iocsrrd, gen_helper_iocsrrd_d)
|
||||
TRANS(iocsrwr_b, gen_iocsrwr, gen_helper_iocsrwr_b)
|
||||
TRANS(iocsrwr_h, gen_iocsrwr, gen_helper_iocsrwr_h)
|
||||
TRANS(iocsrwr_w, gen_iocsrwr, gen_helper_iocsrwr_w)
|
||||
TRANS(iocsrwr_d, gen_iocsrwr, gen_helper_iocsrwr_d)
|
||||
TRANS(iocsrrd_b, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_b)
|
||||
TRANS(iocsrrd_h, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_h)
|
||||
TRANS(iocsrrd_w, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_w)
|
||||
TRANS(iocsrrd_d, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_d)
|
||||
TRANS(iocsrwr_b, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_b)
|
||||
TRANS(iocsrwr_h, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_h)
|
||||
TRANS(iocsrwr_w, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_w)
|
||||
TRANS(iocsrwr_d, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_d)
|
||||
|
||||
static void check_mmu_idx(DisasContext *ctx)
|
||||
{
|
||||
@ -437,6 +437,10 @@ static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a)
|
||||
TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx);
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
|
||||
if (!avail_LSPW(ctx)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (check_plv(ctx)) {
|
||||
return false;
|
||||
}
|
||||
@ -450,6 +454,10 @@ static bool trans_lddir(DisasContext *ctx, arg_lddir *a)
|
||||
TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
|
||||
if (!avail_LSPW(ctx)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (check_plv(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -72,24 +72,28 @@ static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a)
|
||||
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
|
||||
TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
|
||||
|
||||
if (!avail_64(ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tcg_gen_sextract_tl(dest, src1, a->imm, 32 - a->imm);
|
||||
gen_set_gpr(a->rd, dest, EXT_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TRANS(sll_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w)
|
||||
TRANS(srl_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w)
|
||||
TRANS(sra_w, gen_rrr, EXT_SIGN, EXT_NONE, EXT_SIGN, gen_sra_w)
|
||||
TRANS(sll_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d)
|
||||
TRANS(srl_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d)
|
||||
TRANS(sra_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d)
|
||||
TRANS(rotr_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w)
|
||||
TRANS(rotr_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d)
|
||||
TRANS(slli_w, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_shli_tl)
|
||||
TRANS(slli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shli_tl)
|
||||
TRANS(srli_w, gen_rri_c, EXT_ZERO, EXT_SIGN, tcg_gen_shri_tl)
|
||||
TRANS(srli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shri_tl)
|
||||
TRANS(srai_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_sari_tl)
|
||||
TRANS(rotri_w, gen_rri_v, EXT_NONE, EXT_NONE, gen_rotr_w)
|
||||
TRANS(rotri_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_rotri_tl)
|
||||
TRANS(sll_w, ALL, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w)
|
||||
TRANS(srl_w, ALL, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w)
|
||||
TRANS(sra_w, ALL, gen_rrr, EXT_SIGN, EXT_NONE, EXT_SIGN, gen_sra_w)
|
||||
TRANS(sll_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d)
|
||||
TRANS(srl_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d)
|
||||
TRANS(sra_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d)
|
||||
TRANS(rotr_w, 64, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w)
|
||||
TRANS(rotr_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d)
|
||||
TRANS(slli_w, ALL, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_shli_tl)
|
||||
TRANS(slli_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shli_tl)
|
||||
TRANS(srli_w, ALL, gen_rri_c, EXT_ZERO, EXT_SIGN, tcg_gen_shri_tl)
|
||||
TRANS(srli_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shri_tl)
|
||||
TRANS(srai_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_sari_tl)
|
||||
TRANS(rotri_w, 64, gen_rri_v, EXT_NONE, EXT_NONE, gen_rotr_w)
|
||||
TRANS(rotri_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_rotri_tl)
|
||||
|
@ -114,14 +114,14 @@ void helper_ertn(CPULoongArchState *env)
|
||||
env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
|
||||
env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 0);
|
||||
env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 1);
|
||||
env->pc = env->CSR_TLBRERA;
|
||||
set_pc(env, env->CSR_TLBRERA);
|
||||
qemu_log_mask(CPU_LOG_INT, "%s: TLBRERA " TARGET_FMT_lx "\n",
|
||||
__func__, env->CSR_TLBRERA);
|
||||
} else {
|
||||
csr_pplv = FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PPLV);
|
||||
csr_pie = FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PIE);
|
||||
|
||||
env->pc = env->CSR_ERA;
|
||||
set_pc(env, env->CSR_ERA);
|
||||
qemu_log_mask(CPU_LOG_INT, "%s: ERA " TARGET_FMT_lx "\n",
|
||||
__func__, env->CSR_ERA);
|
||||
}
|
||||
|
@ -48,10 +48,17 @@ static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
|
||||
tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
|
||||
tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
|
||||
tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
|
||||
tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY, PPN);
|
||||
tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY, NX);
|
||||
tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY, NR);
|
||||
tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY, RPLV);
|
||||
if (is_la64(env)) {
|
||||
tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
|
||||
tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
|
||||
tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
|
||||
tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
|
||||
} else {
|
||||
tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
|
||||
tlb_nx = 0;
|
||||
tlb_nr = 0;
|
||||
tlb_rplv = 0;
|
||||
}
|
||||
|
||||
/* Check access rights */
|
||||
if (!tlb_v) {
|
||||
@ -79,7 +86,7 @@ static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
|
||||
* tlb_entry contains ppn[47:12] while 16KiB ppn is [47:15]
|
||||
* need adjust.
|
||||
*/
|
||||
*physical = (tlb_ppn << R_TLBENTRY_PPN_SHIFT) |
|
||||
*physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
|
||||
(address & MAKE_64BIT_MASK(0, tlb_ps));
|
||||
*prot = PAGE_READ;
|
||||
if (tlb_d) {
|
||||
@ -166,6 +173,18 @@ static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
|
||||
return TLBRET_NOMATCH;
|
||||
}
|
||||
|
||||
static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
|
||||
target_ulong dmw)
|
||||
{
|
||||
if (is_la64(env)) {
|
||||
return va & TARGET_VIRT_MASK;
|
||||
} else {
|
||||
uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
|
||||
return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
|
||||
(pseg << R_CSR_DMW_32_VSEG_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
static int get_physical_address(CPULoongArchState *env, hwaddr *physical,
|
||||
int *prot, target_ulong address,
|
||||
MMUAccessType access_type, int mmu_idx)
|
||||
@ -185,12 +204,20 @@ static int get_physical_address(CPULoongArchState *env, hwaddr *physical,
|
||||
}
|
||||
|
||||
plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
|
||||
base_v = address >> R_CSR_DMW_VSEG_SHIFT;
|
||||
if (is_la64(env)) {
|
||||
base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
|
||||
} else {
|
||||
base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
|
||||
}
|
||||
/* Check direct map window */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW, VSEG);
|
||||
if (is_la64(env)) {
|
||||
base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_64, VSEG);
|
||||
} else {
|
||||
base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
|
||||
}
|
||||
if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
|
||||
*physical = dmw_va2pa(address);
|
||||
*physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
|
||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
@ -273,8 +300,13 @@ static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
|
||||
|
||||
if (tlb_error == TLBRET_NOMATCH) {
|
||||
env->CSR_TLBRBADV = address;
|
||||
env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI, VPPN,
|
||||
extract64(address, 13, 35));
|
||||
if (is_la64(env)) {
|
||||
env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI_64,
|
||||
VPPN, extract64(address, 13, 35));
|
||||
} else {
|
||||
env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI_32,
|
||||
VPPN, extract64(address, 13, 19));
|
||||
}
|
||||
} else {
|
||||
if (!FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) {
|
||||
env->CSR_BADV = address;
|
||||
@ -339,12 +371,20 @@ static void fill_tlb_entry(CPULoongArchState *env, int index)
|
||||
|
||||
if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) {
|
||||
csr_ps = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, PS);
|
||||
csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, VPPN);
|
||||
if (is_la64(env)) {
|
||||
csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI_64, VPPN);
|
||||
} else {
|
||||
csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI_32, VPPN);
|
||||
}
|
||||
lo0 = env->CSR_TLBRELO0;
|
||||
lo1 = env->CSR_TLBRELO1;
|
||||
} else {
|
||||
csr_ps = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS);
|
||||
csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI, VPPN);
|
||||
if (is_la64(env)) {
|
||||
csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI_64, VPPN);
|
||||
} else {
|
||||
csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI_32, VPPN);
|
||||
}
|
||||
lo0 = env->CSR_TLBELO0;
|
||||
lo1 = env->CSR_TLBELO1;
|
||||
}
|
||||
@ -464,7 +504,7 @@ void helper_tlbfill(CPULoongArchState *env)
|
||||
|
||||
if (pagesize == stlb_ps) {
|
||||
/* Only write into STLB bits [47:13] */
|
||||
address = entryhi & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_VPPN_SHIFT);
|
||||
address = entryhi & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_64_VPPN_SHIFT);
|
||||
|
||||
/* Choose one set ramdomly */
|
||||
set = get_random_tlb(0, 7);
|
||||
|
@ -86,6 +86,10 @@ void generate_exception(DisasContext *ctx, int excp)
|
||||
|
||||
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
{
|
||||
if (ctx->va32) {
|
||||
dest = (uint32_t) dest;
|
||||
}
|
||||
|
||||
if (translator_use_goto_tb(&ctx->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_tl(cpu_pc, dest);
|
||||
@ -119,7 +123,13 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
|
||||
ctx->vl = LSX_LEN;
|
||||
}
|
||||
|
||||
ctx->la64 = is_la64(env);
|
||||
ctx->va32 = (ctx->base.tb->flags & HW_FLAGS_VA32) != 0;
|
||||
|
||||
ctx->zero = tcg_constant_tl(0);
|
||||
|
||||
ctx->cpucfg1 = env->cpucfg[1];
|
||||
ctx->cpucfg2 = env->cpucfg[2];
|
||||
}
|
||||
|
||||
static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
|
||||
@ -205,6 +215,38 @@ static void set_fpr(int reg_num, TCGv val)
|
||||
offsetof(CPULoongArchState, fpr[reg_num].vreg.D(0)));
|
||||
}
|
||||
|
||||
static TCGv make_address_x(DisasContext *ctx, TCGv base, TCGv addend)
|
||||
{
|
||||
TCGv temp = NULL;
|
||||
|
||||
if (addend || ctx->va32) {
|
||||
temp = tcg_temp_new();
|
||||
}
|
||||
if (addend) {
|
||||
tcg_gen_add_tl(temp, base, addend);
|
||||
base = temp;
|
||||
}
|
||||
if (ctx->va32) {
|
||||
tcg_gen_ext32u_tl(temp, base);
|
||||
base = temp;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
static TCGv make_address_i(DisasContext *ctx, TCGv base, target_long ofs)
|
||||
{
|
||||
TCGv addend = ofs ? tcg_constant_tl(ofs) : NULL;
|
||||
return make_address_x(ctx, base, addend);
|
||||
}
|
||||
|
||||
static uint64_t make_address_pc(DisasContext *ctx, uint64_t addr)
|
||||
{
|
||||
if (ctx->va32) {
|
||||
addr = (int32_t)addr;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
#include "decode-insns.c.inc"
|
||||
#include "insn_trans/trans_arith.c.inc"
|
||||
#include "insn_trans/trans_shift.c.inc"
|
||||
@ -236,6 +278,10 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
}
|
||||
|
||||
ctx->base.pc_next += 4;
|
||||
|
||||
if (ctx->va32) {
|
||||
ctx->base.pc_next = (uint32_t)ctx->base.pc_next;
|
||||
}
|
||||
}
|
||||
|
||||
static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
|
||||
|
@ -10,9 +10,20 @@
|
||||
|
||||
#include "exec/translator.h"
|
||||
|
||||
#define TRANS(NAME, FUNC, ...) \
|
||||
#define TRANS(NAME, AVAIL, FUNC, ...) \
|
||||
static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
|
||||
{ return FUNC(ctx, a, __VA_ARGS__); }
|
||||
{ return avail_##AVAIL(ctx) && FUNC(ctx, a, __VA_ARGS__); }
|
||||
|
||||
#define avail_ALL(C) true
|
||||
#define avail_64(C) (FIELD_EX32((C)->cpucfg1, CPUCFG1, ARCH) == \
|
||||
CPUCFG1_ARCH_LA64)
|
||||
#define avail_FP(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, FP))
|
||||
#define avail_FP_SP(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, FP_SP))
|
||||
#define avail_FP_DP(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, FP_DP))
|
||||
#define avail_LSPW(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSPW))
|
||||
#define avail_LAM(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LAM))
|
||||
#define avail_LSX(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSX))
|
||||
#define avail_IOCSR(C) (FIELD_EX32((C)->cpucfg1, CPUCFG1, IOCSR))
|
||||
|
||||
/*
|
||||
* If an operation is being performed on less than TARGET_LONG_BITS,
|
||||
@ -33,6 +44,10 @@ typedef struct DisasContext {
|
||||
uint16_t plv;
|
||||
int vl; /* Vector length */
|
||||
TCGv zero;
|
||||
bool la64; /* LoongArch64 mode */
|
||||
bool va32; /* 32-bit virtual address */
|
||||
uint32_t cpucfg1;
|
||||
uint32_t cpucfg2;
|
||||
} DisasContext;
|
||||
|
||||
void generate_exception(DisasContext *ctx, int excp);
|
||||
|
Loading…
Reference in New Issue
Block a user