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:
Stefan Hajnoczi 2023-08-24 09:17:05 -04:00
commit 6030ef9d41
28 changed files with 1548 additions and 1050 deletions

View File

@ -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

View 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>

View File

@ -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>

View File

@ -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;

View File

@ -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 */
}

View File

@ -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);

View File

@ -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 */

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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();

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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)

View File

@ -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);