Second RISC-V PR for QEMU 7.0

- Fix illegal instruction when PMP is disabled
  - SiFive PDMA 64-bit support
  - SiFive PLIC cleanups
  - Mark Hypervisor extension as non experimental
  - Enable Hypervisor extension by default
  - Support 32 cores on the virt machine
  - Corrections for the Vector extension
  - Experimental support for 128-bit CPUs
  - stval and mtval support for illegal instructions
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmHZJhMACgkQIeENKd+X
 cFSzfgf9FTU3spDGSFMQXFdHfFionDbbyRhXqHG785/9193DKAZysSCv1PWrScX1
 i9GwbR963Z03ksGN0yGFleqZAE2wz6jQxzXPbikeL4kNH1CiBTP1HFUM194d4cLA
 4bjZ3l29obkzjD53mlQpi/0siqe3deKbuRu+z55LlS21C3SUkxggb5Fda+V0dzix
 h+Ytd7Qkif16aVDD20Q6O/4g8tZgqYvuDOdY78/V7VSzFd5bV1j8uONsDmp3NTWo
 l2vgMDxtv1f7uggtApNvTeWRHeLkDB3OMMHZHiXYceyIcqYvZecmMfRloVC7qY7t
 TOR378HVElPHJs9iJMzx7xlcJ5xHeQ==
 =ffGh
 -----END PGP SIGNATURE-----

Merge tag 'pull-riscv-to-apply-20220108' of github.com:alistair23/qemu into staging

Second RISC-V PR for QEMU 7.0

 - Fix illegal instruction when PMP is disabled
 - SiFive PDMA 64-bit support
 - SiFive PLIC cleanups
 - Mark Hypervisor extension as non experimental
 - Enable Hypervisor extension by default
 - Support 32 cores on the virt machine
 - Corrections for the Vector extension
 - Experimental support for 128-bit CPUs
 - stval and mtval support for illegal instructions

# gpg: Signature made Fri 07 Jan 2022 09:50:11 PM PST
# gpg:                using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [undefined]
# 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: F6C4 AC46 D493 4868 D3B8  CE8F 21E1 0D29 DF97 7054

* tag 'pull-riscv-to-apply-20220108' of github.com:alistair23/qemu: (37 commits)
  target/riscv: Implement the stval/mtval illegal instruction
  target/riscv: Fixup setting GVA
  target/riscv: Set the opcode in DisasContext
  target/riscv: actual functions to realize crs 128-bit insns
  target/riscv: modification of the trans_csrxx for 128-bit support
  target/riscv: helper functions to wrap calls to 128-bit csr insns
  target/riscv: adding high part of some csrs
  target/riscv: support for 128-bit M extension
  target/riscv: support for 128-bit arithmetic instructions
  target/riscv: support for 128-bit shift instructions
  target/riscv: support for 128-bit U-type instructions
  target/riscv: support for 128-bit bitwise instructions
  target/riscv: accessors to registers upper part and 128-bit load/store
  target/riscv: moving some insns close to similar insns
  target/riscv: setup everything for rv64 to support rv128 execution
  target/riscv: array for the 64 upper bits of 128-bit registers
  target/riscv: separation of bitwise logic and arithmetic helpers
  target/riscv: additional macros to check instruction support
  qemu/int128: addition of div/rem 128-bit operations
  exec/memop: Adding signed quad and octo defines
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-01-07 22:09:24 -08:00
commit afe3326258
81 changed files with 2345 additions and 777 deletions

View file

@ -1885,9 +1885,9 @@ load_memop(const void *haddr, MemOp op)
return (uint32_t)ldl_be_p(haddr);
case MO_LEUL:
return (uint32_t)ldl_le_p(haddr);
case MO_BEQ:
case MO_BEUQ:
return ldq_be_p(haddr);
case MO_LEQ:
case MO_LEUQ:
return ldq_le_p(haddr);
default:
qemu_build_not_reached();
@ -2081,16 +2081,16 @@ tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEQ);
return load_helper(env, addr, oi, retaddr, MO_LEQ, false,
validate_memop(oi, MO_LEUQ);
return load_helper(env, addr, oi, retaddr, MO_LEUQ, false,
helper_le_ldq_mmu);
}
uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEQ);
return load_helper(env, addr, oi, retaddr, MO_BEQ, false,
validate_memop(oi, MO_BEUQ);
return load_helper(env, addr, oi, retaddr, MO_BEUQ, false,
helper_be_ldq_mmu);
}
@ -2166,7 +2166,7 @@ uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, MO_BEQ, helper_be_ldq_mmu);
return cpu_load_helper(env, addr, oi, MO_BEUQ, helper_be_ldq_mmu);
}
uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
@ -2210,10 +2210,10 @@ store_memop(void *haddr, uint64_t val, MemOp op)
case MO_LEUL:
stl_le_p(haddr, val);
break;
case MO_BEQ:
case MO_BEUQ:
stq_be_p(haddr, val);
break;
case MO_LEQ:
case MO_LEUQ:
stq_le_p(haddr, val);
break;
default:
@ -2465,15 +2465,15 @@ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEQ);
store_helper(env, addr, val, oi, retaddr, MO_LEQ);
validate_memop(oi, MO_LEUQ);
store_helper(env, addr, val, oi, retaddr, MO_LEUQ);
}
void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEQ);
store_helper(env, addr, val, oi, retaddr, MO_BEQ);
validate_memop(oi, MO_BEUQ);
store_helper(env, addr, val, oi, retaddr, MO_BEUQ);
}
/*
@ -2609,11 +2609,11 @@ uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr)
static uint64_t full_ldq_code(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, MO_TEQ, true, full_ldq_code);
return load_helper(env, addr, oi, retaddr, MO_TEUQ, true, full_ldq_code);
}
uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr)
{
MemOpIdx oi = make_memop_idx(MO_TEQ, cpu_mmu_index(env, true));
MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true));
return full_ldq_code(env, addr, oi, 0);
}

View file

@ -45,7 +45,7 @@ uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
return cpu_ldq_be_mmu(env, addr, oi, ra);
}
@ -72,7 +72,7 @@ uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
return cpu_ldq_le_mmu(env, addr, oi, ra);
}
@ -100,7 +100,7 @@ void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
cpu_stq_be_mmu(env, addr, val, oi, ra);
}
@ -121,7 +121,7 @@ void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
cpu_stq_le_mmu(env, addr, val, oi, ra);
}

View file

@ -294,7 +294,7 @@ uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
void *haddr;
uint64_t ret;
validate_memop(oi, MO_BEQ);
validate_memop(oi, MO_BEUQ);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldq_be_p(haddr);
@ -339,7 +339,7 @@ uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
void *haddr;
uint64_t ret;
validate_memop(oi, MO_LEQ);
validate_memop(oi, MO_LEUQ);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldq_le_p(haddr);
@ -392,7 +392,7 @@ void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
{
void *haddr;
validate_memop(oi, MO_BEQ);
validate_memop(oi, MO_BEUQ);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stq_be_p(haddr, val);
@ -431,7 +431,7 @@ void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
{
void *haddr;
validate_memop(oi, MO_LEQ);
validate_memop(oi, MO_LEUQ);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stq_le_p(haddr, val);

View file

@ -3090,3 +3090,8 @@ int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_riscv(memaddr, info, rv64);
}
int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_riscv(memaddr, info, rv128);
}

View file

@ -177,6 +177,101 @@ static inline void sifive_pdma_update_irq(SiFivePDMAState *s, int ch)
s->chan[ch].state = DMA_CHAN_STATE_IDLE;
}
static uint64_t sifive_pdma_readq(SiFivePDMAState *s, int ch, hwaddr offset)
{
uint64_t val = 0;
offset &= 0xfff;
switch (offset) {
case DMA_NEXT_BYTES:
val = s->chan[ch].next_bytes;
break;
case DMA_NEXT_DST:
val = s->chan[ch].next_dst;
break;
case DMA_NEXT_SRC:
val = s->chan[ch].next_src;
break;
case DMA_EXEC_BYTES:
val = s->chan[ch].exec_bytes;
break;
case DMA_EXEC_DST:
val = s->chan[ch].exec_dst;
break;
case DMA_EXEC_SRC:
val = s->chan[ch].exec_src;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 64-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
return val;
}
static uint32_t sifive_pdma_readl(SiFivePDMAState *s, int ch, hwaddr offset)
{
uint32_t val = 0;
offset &= 0xfff;
switch (offset) {
case DMA_CONTROL:
val = s->chan[ch].control;
break;
case DMA_NEXT_CONFIG:
val = s->chan[ch].next_config;
break;
case DMA_NEXT_BYTES:
val = extract64(s->chan[ch].next_bytes, 0, 32);
break;
case DMA_NEXT_BYTES + 4:
val = extract64(s->chan[ch].next_bytes, 32, 32);
break;
case DMA_NEXT_DST:
val = extract64(s->chan[ch].next_dst, 0, 32);
break;
case DMA_NEXT_DST + 4:
val = extract64(s->chan[ch].next_dst, 32, 32);
break;
case DMA_NEXT_SRC:
val = extract64(s->chan[ch].next_src, 0, 32);
break;
case DMA_NEXT_SRC + 4:
val = extract64(s->chan[ch].next_src, 32, 32);
break;
case DMA_EXEC_CONFIG:
val = s->chan[ch].exec_config;
break;
case DMA_EXEC_BYTES:
val = extract64(s->chan[ch].exec_bytes, 0, 32);
break;
case DMA_EXEC_BYTES + 4:
val = extract64(s->chan[ch].exec_bytes, 32, 32);
break;
case DMA_EXEC_DST:
val = extract64(s->chan[ch].exec_dst, 0, 32);
break;
case DMA_EXEC_DST + 4:
val = extract64(s->chan[ch].exec_dst, 32, 32);
break;
case DMA_EXEC_SRC:
val = extract64(s->chan[ch].exec_src, 0, 32);
break;
case DMA_EXEC_SRC + 4:
val = extract64(s->chan[ch].exec_src, 32, 32);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 32-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
return val;
}
static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size)
{
SiFivePDMAState *s = opaque;
@ -189,56 +284,53 @@ static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size)
return 0;
}
offset &= 0xfff;
switch (offset) {
case DMA_CONTROL:
val = s->chan[ch].control;
switch (size) {
case 8:
val = sifive_pdma_readq(s, ch, offset);
break;
case DMA_NEXT_CONFIG:
val = s->chan[ch].next_config;
break;
case DMA_NEXT_BYTES:
val = s->chan[ch].next_bytes;
break;
case DMA_NEXT_DST:
val = s->chan[ch].next_dst;
break;
case DMA_NEXT_SRC:
val = s->chan[ch].next_src;
break;
case DMA_EXEC_CONFIG:
val = s->chan[ch].exec_config;
break;
case DMA_EXEC_BYTES:
val = s->chan[ch].exec_bytes;
break;
case DMA_EXEC_DST:
val = s->chan[ch].exec_dst;
break;
case DMA_EXEC_SRC:
val = s->chan[ch].exec_src;
case 4:
val = sifive_pdma_readl(s, ch, offset);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid read size %u to PDMA\n",
__func__, size);
return 0;
}
return val;
}
static void sifive_pdma_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
static void sifive_pdma_writeq(SiFivePDMAState *s, int ch,
hwaddr offset, uint64_t value)
{
SiFivePDMAState *s = opaque;
int ch = SIFIVE_PDMA_CHAN_NO(offset);
bool claimed, run;
if (ch >= SIFIVE_PDMA_CHANS) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
__func__, ch);
return;
offset &= 0xfff;
switch (offset) {
case DMA_NEXT_BYTES:
s->chan[ch].next_bytes = value;
break;
case DMA_NEXT_DST:
s->chan[ch].next_dst = value;
break;
case DMA_NEXT_SRC:
s->chan[ch].next_src = value;
break;
case DMA_EXEC_BYTES:
case DMA_EXEC_DST:
case DMA_EXEC_SRC:
/* these are read-only registers */
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 64-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
}
static void sifive_pdma_writel(SiFivePDMAState *s, int ch,
hwaddr offset, uint32_t value)
{
bool claimed, run;
offset &= 0xfff;
switch (offset) {
@ -282,27 +374,68 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
s->chan[ch].next_config = value;
break;
case DMA_NEXT_BYTES:
s->chan[ch].next_bytes = value;
s->chan[ch].next_bytes =
deposit64(s->chan[ch].next_bytes, 0, 32, value);
break;
case DMA_NEXT_BYTES + 4:
s->chan[ch].next_bytes =
deposit64(s->chan[ch].next_bytes, 32, 32, value);
break;
case DMA_NEXT_DST:
s->chan[ch].next_dst = value;
s->chan[ch].next_dst = deposit64(s->chan[ch].next_dst, 0, 32, value);
break;
case DMA_NEXT_DST + 4:
s->chan[ch].next_dst = deposit64(s->chan[ch].next_dst, 32, 32, value);
break;
case DMA_NEXT_SRC:
s->chan[ch].next_src = value;
s->chan[ch].next_src = deposit64(s->chan[ch].next_src, 0, 32, value);
break;
case DMA_NEXT_SRC + 4:
s->chan[ch].next_src = deposit64(s->chan[ch].next_src, 32, 32, value);
break;
case DMA_EXEC_CONFIG:
case DMA_EXEC_BYTES:
case DMA_EXEC_BYTES + 4:
case DMA_EXEC_DST:
case DMA_EXEC_DST + 4:
case DMA_EXEC_SRC:
case DMA_EXEC_SRC + 4:
/* these are read-only registers */
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 32-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
}
static void sifive_pdma_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
SiFivePDMAState *s = opaque;
int ch = SIFIVE_PDMA_CHAN_NO(offset);
if (ch >= SIFIVE_PDMA_CHANS) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
__func__, ch);
return;
}
switch (size) {
case 8:
sifive_pdma_writeq(s, ch, offset, value);
break;
case 4:
sifive_pdma_writel(s, ch, offset, (uint32_t) value);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid write size %u to PDMA\n",
__func__, size);
break;
}
}
static const MemoryRegionOps sifive_pdma_ops = {
.read = sifive_pdma_read,
.write = sifive_pdma_write,
@ -311,6 +444,10 @@ static const MemoryRegionOps sifive_pdma_ops = {
.impl = {
.min_access_size = 4,
.max_access_size = 8,
},
.valid = {
.min_access_size = 4,
.max_access_size = 8,
}
};

View file

@ -31,7 +31,10 @@
#include "migration/vmstate.h"
#include "hw/irq.h"
#define RISCV_DEBUG_PLIC 0
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
{
return addr >= base && addr - base < num;
}
static PLICMode char_to_mode(char c)
{
@ -46,47 +49,6 @@ static PLICMode char_to_mode(char c)
}
}
static char mode_to_char(PLICMode m)
{
switch (m) {
case PLICMode_U: return 'U';
case PLICMode_S: return 'S';
case PLICMode_H: return 'H';
case PLICMode_M: return 'M';
default: return '?';
}
}
static void sifive_plic_print_state(SiFivePLICState *plic)
{
int i;
int addrid;
/* pending */
qemu_log("pending : ");
for (i = plic->bitfield_words - 1; i >= 0; i--) {
qemu_log("%08x", plic->pending[i]);
}
qemu_log("\n");
/* pending */
qemu_log("claimed : ");
for (i = plic->bitfield_words - 1; i >= 0; i--) {
qemu_log("%08x", plic->claimed[i]);
}
qemu_log("\n");
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
qemu_log("hart%d-%c enable: ",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode));
for (i = plic->bitfield_words - 1; i >= 0; i--) {
qemu_log("%08x", plic->enable[addrid * plic->bitfield_words + i]);
}
qemu_log("\n");
}
}
static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value)
{
uint32_t old, new, cmp = qatomic_read(a);
@ -110,26 +72,34 @@ static void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool level)
atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level);
}
static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
static uint32_t sifive_plic_claimed(SiFivePLICState *plic, uint32_t addrid)
{
uint32_t max_irq = 0;
uint32_t max_prio = plic->target_priority[addrid];
int i, j;
for (i = 0; i < plic->bitfield_words; i++) {
uint32_t pending_enabled_not_claimed =
(plic->pending[i] & ~plic->claimed[i]) &
plic->enable[addrid * plic->bitfield_words + i];
(plic->pending[i] & ~plic->claimed[i]) &
plic->enable[addrid * plic->bitfield_words + i];
if (!pending_enabled_not_claimed) {
continue;
}
for (j = 0; j < 32; j++) {
int irq = (i << 5) + j;
uint32_t prio = plic->source_priority[irq];
int enabled = pending_enabled_not_claimed & (1 << j);
if (enabled && prio > plic->target_priority[addrid]) {
return 1;
if (enabled && prio > max_prio) {
max_irq = irq;
max_prio = prio;
}
}
}
return 0;
return max_irq;
}
static void sifive_plic_update(SiFivePLICState *plic)
@ -140,7 +110,7 @@ static void sifive_plic_update(SiFivePLICState *plic)
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
uint32_t hartid = plic->addr_config[addrid].hartid;
PLICMode mode = plic->addr_config[addrid].mode;
int level = sifive_plic_irqs_pending(plic, addrid);
bool level = !!sifive_plic_claimed(plic, addrid);
switch (mode) {
case PLICMode_M:
@ -153,111 +123,48 @@ static void sifive_plic_update(SiFivePLICState *plic)
break;
}
}
if (RISCV_DEBUG_PLIC) {
sifive_plic_print_state(plic);
}
}
static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid)
{
int i, j;
uint32_t max_irq = 0;
uint32_t max_prio = plic->target_priority[addrid];
for (i = 0; i < plic->bitfield_words; i++) {
uint32_t pending_enabled_not_claimed =
(plic->pending[i] & ~plic->claimed[i]) &
plic->enable[addrid * plic->bitfield_words + i];
if (!pending_enabled_not_claimed) {
continue;
}
for (j = 0; j < 32; j++) {
int irq = (i << 5) + j;
uint32_t prio = plic->source_priority[irq];
int enabled = pending_enabled_not_claimed & (1 << j);
if (enabled && prio > max_prio) {
max_irq = irq;
max_prio = prio;
}
}
}
if (max_irq) {
sifive_plic_set_pending(plic, max_irq, false);
sifive_plic_set_claimed(plic, max_irq, true);
}
return max_irq;
}
static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
{
SiFivePLICState *plic = opaque;
/* writes must be 4 byte words */
if ((addr & 0x3) != 0) {
goto err;
}
if (addr >= plic->priority_base && /* 4 bytes per source */
addr < plic->priority_base + (plic->num_sources << 2))
{
if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) {
uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read priority: irq=%d priority=%d\n",
irq, plic->source_priority[irq]);
}
return plic->source_priority[irq];
} else if (addr >= plic->pending_base && /* 1 bit per source */
addr < plic->pending_base + (plic->num_sources >> 3))
{
} else if (addr_between(addr, plic->pending_base, plic->num_sources >> 3)) {
uint32_t word = (addr - plic->pending_base) >> 2;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read pending: word=%d value=%d\n",
word, plic->pending[word]);
}
return plic->pending[word];
} else if (addr >= plic->enable_base && /* 1 bit per source */
addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
{
} else if (addr_between(addr, plic->enable_base,
plic->num_addrs * plic->enable_stride)) {
uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride;
uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2;
if (wordid < plic->bitfield_words) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read enable: hart%d-%c word=%d value=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode), wordid,
plic->enable[addrid * plic->bitfield_words + wordid]);
}
return plic->enable[addrid * plic->bitfield_words + wordid];
}
} else if (addr >= plic->context_base && /* 1 bit per source */
addr < plic->context_base + plic->num_addrs * plic->context_stride)
{
} else if (addr_between(addr, plic->context_base,
plic->num_addrs * plic->context_stride)) {
uint32_t addrid = (addr - plic->context_base) / plic->context_stride;
uint32_t contextid = (addr & (plic->context_stride - 1));
if (contextid == 0) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read priority: hart%d-%c priority=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
plic->target_priority[addrid]);
}
return plic->target_priority[addrid];
} else if (contextid == 4) {
uint32_t value = sifive_plic_claim(plic, addrid);
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read claim: hart%d-%c irq=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
value);
uint32_t max_irq = sifive_plic_claimed(plic, addrid);
if (max_irq) {
sifive_plic_set_pending(plic, max_irq, false);
sifive_plic_set_claimed(plic, max_irq, true);
}
sifive_plic_update(plic);
return value;
return max_irq;
}
}
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register read 0x%" HWADDR_PRIx "\n",
__func__, addr);
@ -269,80 +176,53 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value,
{
SiFivePLICState *plic = opaque;
/* writes must be 4 byte words */
if ((addr & 0x3) != 0) {
goto err;
}
if (addr >= plic->priority_base && /* 4 bytes per source */
addr < plic->priority_base + (plic->num_sources << 2))
{
if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) {
uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
plic->source_priority[irq] = value & 7;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write priority: irq=%d priority=%d\n",
irq, plic->source_priority[irq]);
}
sifive_plic_update(plic);
return;
} else if (addr >= plic->pending_base && /* 1 bit per source */
addr < plic->pending_base + (plic->num_sources >> 3))
{
} else if (addr_between(addr, plic->pending_base,
plic->num_sources >> 3)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid pending write: 0x%" HWADDR_PRIx "",
__func__, addr);
return;
} else if (addr >= plic->enable_base && /* 1 bit per source */
addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
{
} else if (addr_between(addr, plic->enable_base,
plic->num_addrs * plic->enable_stride)) {
uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride;
uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2;
if (wordid < plic->bitfield_words) {
plic->enable[addrid * plic->bitfield_words + wordid] = value;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write enable: hart%d-%c word=%d value=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode), wordid,
plic->enable[addrid * plic->bitfield_words + wordid]);
}
return;
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid enable write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
} else if (addr >= plic->context_base && /* 4 bytes per reg */
addr < plic->context_base + plic->num_addrs * plic->context_stride)
{
} else if (addr_between(addr, plic->context_base,
plic->num_addrs * plic->context_stride)) {
uint32_t addrid = (addr - plic->context_base) / plic->context_stride;
uint32_t contextid = (addr & (plic->context_stride - 1));
if (contextid == 0) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write priority: hart%d-%c priority=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
plic->target_priority[addrid]);
}
if (value <= plic->num_priorities) {
plic->target_priority[addrid] = value;
sifive_plic_update(plic);
}
return;
} else if (contextid == 4) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write claim: hart%d-%c irq=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
(uint32_t)value);
}
if (value < plic->num_sources) {
sifive_plic_set_claimed(plic, value, false);
sifive_plic_update(plic);
}
return;
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid context write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
static const MemoryRegionOps sifive_plic_ops = {
@ -355,6 +235,23 @@ static const MemoryRegionOps sifive_plic_ops = {
}
};
static void sifive_plic_reset(DeviceState *dev)
{
SiFivePLICState *s = SIFIVE_PLIC(dev);
int i;
memset(s->source_priority, 0, sizeof(uint32_t) * s->num_sources);
memset(s->target_priority, 0, sizeof(uint32_t) * s->num_addrs);
memset(s->pending, 0, sizeof(uint32_t) * s->bitfield_words);
memset(s->claimed, 0, sizeof(uint32_t) * s->bitfield_words);
memset(s->enable, 0, sizeof(uint32_t) * s->num_enables);
for (i = 0; i < s->num_harts; i++) {
qemu_set_irq(s->m_external_irqs[i], 0);
qemu_set_irq(s->s_external_irqs[i], 0);
}
}
/*
* parse PLIC hart/mode address offset config
*
@ -501,6 +398,7 @@ static void sifive_plic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = sifive_plic_reset;
device_class_set_props(dc, sifive_plic_properties);
dc->realize = sifive_plic_realize;
dc->vmsd = &vmstate_sifive_plic;

View file

@ -471,7 +471,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc,
TYPE_MICROCHIP_PFSOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
/* Split RAM into low and high regions using aliases to machine->ram */
mem_low_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size;

View file

@ -80,7 +80,7 @@ static void opentitan_board_init(MachineState *machine)
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc,
TYPE_RISCV_IBEX_SOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
memory_region_add_subregion(sys_mem,
memmap[IBEX_DEV_RAM].base, machine->ram);

View file

@ -88,7 +88,7 @@ static void sifive_e_machine_init(MachineState *machine)
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_E_SOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
/* Data Tightly Integrated Memory */
memory_region_add_subregion(sys_mem,

View file

@ -547,7 +547,7 @@ static void sifive_u_machine_init(MachineState *machine)
&error_abort);
object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type,
&error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
/* register RAM */
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base,

View file

@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
int print_insn_xtensa (bfd_vma, disassemble_info*);
int print_insn_riscv32 (bfd_vma, disassemble_info*);
int print_insn_riscv64 (bfd_vma, disassemble_info*);
int print_insn_riscv128 (bfd_vma, disassemble_info*);
int print_insn_rx(bfd_vma, disassemble_info *);
int print_insn_hexagon(bfd_vma, disassemble_info *);

View file

@ -85,29 +85,36 @@ typedef enum MemOp {
MO_UB = MO_8,
MO_UW = MO_16,
MO_UL = MO_32,
MO_UQ = MO_64,
MO_UO = MO_128,
MO_SB = MO_SIGN | MO_8,
MO_SW = MO_SIGN | MO_16,
MO_SL = MO_SIGN | MO_32,
MO_Q = MO_64,
MO_SQ = MO_SIGN | MO_64,
MO_SO = MO_SIGN | MO_128,
MO_LEUW = MO_LE | MO_UW,
MO_LEUL = MO_LE | MO_UL,
MO_LEUQ = MO_LE | MO_UQ,
MO_LESW = MO_LE | MO_SW,
MO_LESL = MO_LE | MO_SL,
MO_LEQ = MO_LE | MO_Q,
MO_LESQ = MO_LE | MO_SQ,
MO_BEUW = MO_BE | MO_UW,
MO_BEUL = MO_BE | MO_UL,
MO_BEUQ = MO_BE | MO_UQ,
MO_BESW = MO_BE | MO_SW,
MO_BESL = MO_BE | MO_SL,
MO_BEQ = MO_BE | MO_Q,
MO_BESQ = MO_BE | MO_SQ,
#ifdef NEED_CPU_H
MO_TEUW = MO_TE | MO_UW,
MO_TEUL = MO_TE | MO_UL,
MO_TEUQ = MO_TE | MO_UQ,
MO_TEUO = MO_TE | MO_UO,
MO_TESW = MO_TE | MO_SW,
MO_TESL = MO_TE | MO_SL,
MO_TEQ = MO_TE | MO_Q,
MO_TESQ = MO_TE | MO_SQ,
#endif
MO_SSIZE = MO_SIZE | MO_SIGN,

View file

@ -24,7 +24,7 @@
#include "hw/block/flash.h"
#include "qom/object.h"
#define VIRT_CPUS_MAX 8
#define VIRT_CPUS_MAX 32
#define VIRT_SOCKETS_MAX 8
#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")

View file

@ -172,6 +172,26 @@ static inline Int128 bswap128(Int128 a)
#endif
}
static inline Int128 int128_divu(Int128 a, Int128 b)
{
return (__uint128_t)a / (__uint128_t)b;
}
static inline Int128 int128_remu(Int128 a, Int128 b)
{
return (__uint128_t)a % (__uint128_t)b;
}
static inline Int128 int128_divs(Int128 a, Int128 b)
{
return a / b;
}
static inline Int128 int128_rems(Int128 a, Int128 b)
{
return a % b;
}
#else /* !CONFIG_INT128 */
typedef struct Int128 Int128;
@ -379,6 +399,11 @@ static inline Int128 bswap128(Int128 a)
return int128_make128(bswap64(a.hi), bswap64(a.lo));
}
Int128 int128_divu(Int128, Int128);
Int128 int128_remu(Int128, Int128);
Int128 int128_divs(Int128, Int128);
Int128 int128_rems(Int128, Int128);
#endif /* CONFIG_INT128 */
static inline void bswap128s(Int128 *s)
@ -386,4 +411,6 @@ static inline void bswap128s(Int128 *s)
*s = bswap128(*s);
}
#define UINT128_MAX int128_make128(~0LL, ~0LL)
#endif /* INT128_H */

View file

@ -894,7 +894,7 @@ static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
{
tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ);
tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ);
}
static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
@ -914,7 +914,7 @@ static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
{
tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ);
tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ);
}
void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGv_i32,

@ -1 +1 @@
Subproject commit 234ed8e427f4d92903123199f6590d144e0d9351
Subproject commit 48f91ee9c960f048c4a7d1da4447d31e04931e38

View file

@ -286,7 +286,7 @@ static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
{
TCGv tmp = tcg_temp_new();
tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
gen_helper_memory_to_g(dest, tmp);
tcg_temp_free(tmp);
}
@ -301,7 +301,7 @@ static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
{
tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
}
static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
@ -358,7 +358,7 @@ static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
{
TCGv tmp = tcg_temp_new();
gen_helper_g_to_memory(tmp, src);
tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
tcg_temp_free(tmp);
}
@ -372,7 +372,7 @@ static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
{
tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
}
static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
@ -1499,7 +1499,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x0B:
/* LDQ_U */
gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 1, 0);
gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 1, 0);
break;
case 0x0C:
/* LDWU */
@ -1518,7 +1518,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x0F:
/* STQ_U */
gen_store_int(ctx, ra, rb, disp16, MO_LEQ, 1);
gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 1);
break;
case 0x10:
@ -2469,7 +2469,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x1:
/* Quadword physical access (hw_ldq/p) */
tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEQ);
tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ);
break;
case 0x2:
/* Longword physical access with lock (hw_ldl_l/p) */
@ -2479,7 +2479,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x3:
/* Quadword physical access with lock (hw_ldq_l/p) */
tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEQ);
tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ);
tcg_gen_mov_i64(cpu_lock_addr, addr);
tcg_gen_mov_i64(cpu_lock_value, va);
break;
@ -2508,7 +2508,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0xB:
/* Quadword virtual access with protection check (hw_ldq/w) */
tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEQ);
tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEUQ);
break;
case 0xC:
/* Longword virtual access with alt access mode (hw_ldl/a)*/
@ -2524,7 +2524,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
case 0xF:
/* Quadword virtual access with alternate access mode and
protection checks (hw_ldq/wa) */
tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEQ);
tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEUQ);
break;
}
tcg_temp_free(addr);
@ -2737,7 +2737,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
vb = load_gpr(ctx, rb);
tmp = tcg_temp_new();
tcg_gen_addi_i64(tmp, vb, disp12);
tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEQ);
tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ);
tcg_temp_free(tmp);
break;
case 0x2:
@ -2748,7 +2748,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
case 0x3:
/* Quadword physical access with lock */
ret = gen_store_conditional(ctx, ra, rb, disp12,
MMU_PHYS_IDX, MO_LEQ);
MMU_PHYS_IDX, MO_LEUQ);
break;
case 0x4:
/* Longword virtual access */
@ -2838,7 +2838,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x29:
/* LDQ */
gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 0, 0);
gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 0);
break;
case 0x2A:
/* LDL_L */
@ -2846,7 +2846,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2B:
/* LDQ_L */
gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 0, 1);
gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 1);
break;
case 0x2C:
/* STL */
@ -2854,7 +2854,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2D:
/* STQ */
gen_store_int(ctx, ra, rb, disp16, MO_LEQ, 0);
gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 0);
break;
case 0x2E:
/* STL_C */
@ -2864,7 +2864,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
case 0x2F:
/* STQ_C */
ret = gen_store_conditional(ctx, ra, rb, disp16,
ctx->mem_idx, MO_LEQ);
ctx->mem_idx, MO_LEUQ);
break;
case 0x30:
/* BR */

View file

@ -513,8 +513,8 @@ uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
uint64_t o0, o1;
bool success;
int mem_idx = cpu_mmu_index(env, false);
MemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
MemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
MemOpIdx oi0 = make_memop_idx(MO_LEUQ | MO_ALIGN_16, mem_idx);
MemOpIdx oi1 = make_memop_idx(MO_LEUQ, mem_idx);
o0 = cpu_ldq_le_mmu(env, addr + 0, oi0, ra);
o1 = cpu_ldq_le_mmu(env, addr + 8, oi1, ra);
@ -565,8 +565,8 @@ uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr,
uint64_t o0, o1;
bool success;
int mem_idx = cpu_mmu_index(env, false);
MemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
MemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
MemOpIdx oi0 = make_memop_idx(MO_BEUQ | MO_ALIGN_16, mem_idx);
MemOpIdx oi1 = make_memop_idx(MO_BEUQ, mem_idx);
o1 = cpu_ldq_be_mmu(env, addr + 0, oi0, ra);
o0 = cpu_ldq_be_mmu(env, addr + 8, oi1, ra);

View file

@ -117,13 +117,13 @@ void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
TCGv_i32 a32, int index)
{
gen_aa32_ld_i64(s, val, a32, index, MO_Q);
gen_aa32_ld_i64(s, val, a32, index, MO_UQ);
}
static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
TCGv_i32 a32, int index)
{
gen_aa32_st_i64(s, val, a32, index, MO_Q);
gen_aa32_st_i64(s, val, a32, index, MO_UQ);
}
DO_GEN_LD(8u, MO_UB)

View file

@ -973,7 +973,7 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
tcg_gen_ld_i64(tmphi, cpu_env, fp_reg_hi_offset(s, srcidx));
mop = s->be_data | MO_Q;
mop = s->be_data | MO_UQ;
tcg_gen_qemu_st_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s),
mop | (s->align_mem ? MO_ALIGN_16 : 0));
tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
@ -1007,7 +1007,7 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
tmphi = tcg_temp_new_i64();
tcg_hiaddr = tcg_temp_new_i64();
mop = s->be_data | MO_Q;
mop = s->be_data | MO_UQ;
tcg_gen_qemu_ld_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s),
mop | (s->align_mem ? MO_ALIGN_16 : 0));
tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
@ -4099,10 +4099,10 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
int i, n = (1 + is_pair) << LOG2_TAG_GRANULE;
tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index,
MO_Q | MO_ALIGN_16);
MO_UQ | MO_ALIGN_16);
for (i = 8; i < n; i += 8) {
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, MO_Q);
tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, MO_UQ);
}
tcg_temp_free_i64(tcg_zero);
}

View file

@ -73,7 +73,7 @@ static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop)
case MO_UL:
tcg_gen_ld32u_i64(var, cpu_env, offset);
break;
case MO_Q:
case MO_UQ:
tcg_gen_ld_i64(var, cpu_env, offset);
break;
default:
@ -1830,7 +1830,7 @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a,
return false;
}
if ((a->vd & 1) || (src1_mop == MO_Q && (a->vn & 1))) {
if ((a->vd & 1) || (src1_mop == MO_UQ && (a->vn & 1))) {
return false;
}
@ -1910,7 +1910,7 @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a,
}; \
int narrow_mop = a->size == MO_32 ? MO_32 | SIGN : -1; \
return do_prewiden_3d(s, a, widenfn[a->size], addfn[a->size], \
SRC1WIDE ? MO_Q : narrow_mop, \
SRC1WIDE ? MO_UQ : narrow_mop, \
narrow_mop); \
}

View file

@ -5087,7 +5087,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
t0 = tcg_temp_new_i64();
for (i = 0; i < len_align; i += 8) {
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEQ);
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
tcg_gen_st_i64(t0, cpu_env, vofs + i);
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
}
@ -5104,7 +5104,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
gen_set_label(loop);
t0 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEQ);
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
tp = tcg_temp_new_ptr();
@ -5177,7 +5177,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
t0 = tcg_temp_new_i64();
for (i = 0; i < len_align; i += 8) {
tcg_gen_ld_i64(t0, cpu_env, vofs + i);
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEQ);
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
}
tcg_temp_free_i64(t0);
@ -5199,7 +5199,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
tcg_gen_addi_ptr(i, i, 8);
tcg_temp_free_ptr(tp);
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEQ);
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
tcg_temp_free_i64(t0);
@ -5283,7 +5283,7 @@ static const MemOp dtype_mop[16] = {
MO_UB, MO_UB, MO_UB, MO_UB,
MO_SL, MO_UW, MO_UW, MO_UW,
MO_SW, MO_SW, MO_UL, MO_UL,
MO_SB, MO_SB, MO_SB, MO_Q
MO_SB, MO_SB, MO_SB, MO_UQ
};
#define dtype_msz(x) (dtype_mop[x] & MO_SIZE)

View file

@ -1170,11 +1170,11 @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
addr = add_reg_for_lit(s, a->rn, offset);
tmp = tcg_temp_new_i64();
if (a->l) {
gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4);
gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4);
vfp_store_reg64(tmp, a->vd);
} else {
vfp_load_reg64(tmp, a->vd);
gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4);
gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4);
}
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(addr);
@ -1322,12 +1322,12 @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
for (i = 0; i < n; i++) {
if (a->l) {
/* load */
gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4);
gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4);
vfp_store_reg64(tmp, a->vd + i);
} else {
/* store */
vfp_load_reg64(tmp, a->vd + i);
gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4);
gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4);
}
tcg_gen_addi_i32(addr, addr, offset);
}

View file

@ -1217,7 +1217,7 @@ void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop)
case MO_UL:
tcg_gen_ld32u_i64(dest, cpu_env, off);
break;
case MO_Q:
case MO_UQ:
tcg_gen_ld_i64(dest, cpu_env, off);
break;
default:

View file

@ -1047,7 +1047,7 @@ static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
cris_store_direct_jmp(dc);
}
tcg_gen_qemu_ld_i64(dst, addr, mem_index, MO_TEQ);
tcg_gen_qemu_ld_i64(dst, addr, mem_index, MO_TEUQ);
}
static void gen_load(DisasContext *dc, TCGv dst, TCGv addr,

View file

@ -1609,7 +1609,7 @@ static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
nullify_over(ctx);
tmp = tcg_temp_new_i64();
do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ);
save_frd(rt, tmp);
tcg_temp_free_i64(tmp);
@ -1665,7 +1665,7 @@ static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
nullify_over(ctx);
tmp = load_frd(rt);
do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ);
tcg_temp_free_i64(tmp);
return nullify_end(ctx);

View file

@ -67,7 +67,7 @@ void helper_cmpxchg8b(CPUX86State *env, target_ulong a0)
{
uintptr_t ra = GETPC();
int mem_idx = cpu_mmu_index(env, false);
MemOpIdx oi = make_memop_idx(MO_TEQ, mem_idx);
MemOpIdx oi = make_memop_idx(MO_TEUQ, mem_idx);
oldv = cpu_atomic_cmpxchgq_le_mmu(env, a0, cmpv, newv, oi, ra);
}

View file

@ -2719,23 +2719,23 @@ static void gen_jmp(DisasContext *s, target_ulong eip)
static inline void gen_ldq_env_A0(DisasContext *s, int offset)
{
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset);
}
static inline void gen_stq_env_A0(DisasContext *s, int offset)
{
tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset);
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ);
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
}
static inline void gen_ldo_env_A0(DisasContext *s, int offset)
{
int mem_index = s->mem_index;
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ);
tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
tcg_gen_addi_tl(s->tmp0, s->A0, 8);
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
}
@ -2743,10 +2743,10 @@ static inline void gen_sto_env_A0(DisasContext *s, int offset)
{
int mem_index = s->mem_index;
tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ);
tcg_gen_addi_tl(s->tmp0, s->A0, 8);
tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ);
}
static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset)
@ -4255,7 +4255,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64);
} else {
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
}
#else
goto illegal_op;
@ -4328,7 +4328,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm);
} else {
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
}
tcg_gen_st_i64(s->tmp1_i64, cpu_env,
offsetof(CPUX86State,
@ -5948,7 +5948,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
break;
case 2:
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
gen_helper_fldl_FT0(cpu_env, s->tmp1_i64);
break;
case 3:
@ -5987,7 +5987,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
break;
case 2:
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
gen_helper_fldl_ST0(cpu_env, s->tmp1_i64);
break;
case 3:
@ -6009,7 +6009,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
case 2:
gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env);
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
break;
case 3:
default:
@ -6035,7 +6035,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
case 2:
gen_helper_fstl_ST0(s->tmp1_i64, cpu_env);
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
break;
case 3:
default:
@ -6104,13 +6104,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
break;
case 0x3d: /* fildll */
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
gen_helper_fildll_ST0(cpu_env, s->tmp1_i64);
break;
case 0x3f: /* fistpll */
gen_helper_fistll_ST0(s->tmp1_i64, cpu_env);
tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
gen_helper_fpop(cpu_env);
break;
default:
@ -7932,10 +7932,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
gen_lea_modrm(env, s, modrm);
if (CODE64(s)) {
tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
tcg_gen_addi_tl(s->A0, s->A0, 8);
tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
} else {
tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
s->mem_index, MO_LEUL);
@ -8039,10 +8039,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
gen_lea_modrm(env, s, modrm);
if (CODE64(s)) {
tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
tcg_gen_addi_tl(s->A0, s->A0, 8);
tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
s->mem_index, MO_LEQ);
s->mem_index, MO_LEUQ);
} else {
tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
s->mem_index, MO_LEUL);

View file

@ -774,7 +774,7 @@ static void do_cas2l(CPUM68KState *env, uint32_t regs, uint32_t a1, uint32_t a2,
uintptr_t ra = GETPC();
#if defined(CONFIG_ATOMIC64)
int mmu_idx = cpu_mmu_index(env, 0);
MemOpIdx oi = make_memop_idx(MO_BEQ, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_BEUQ, mmu_idx);
#endif
if (parallel) {

View file

@ -1001,20 +1001,20 @@ static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
gen_reserved_instruction(ctx);
return;
}
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ);
gen_store_gpr(t1, rd);
tcg_gen_movi_tl(t1, 8);
gen_op_addr_add(ctx, t0, t0, t1);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ);
gen_store_gpr(t1, rd + 1);
break;
case SDP:
gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ);
tcg_gen_movi_tl(t1, 8);
gen_op_addr_add(ctx, t0, t0, t1);
gen_load_gpr(t1, rd + 1);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ);
break;
#endif
}
@ -2578,7 +2578,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
case SCD:
check_insn(ctx, ISA_MIPS3);
check_mips_64(ctx);
gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
gen_st_cond(ctx, rt, rs, offset, MO_TEUQ, false);
break;
#endif
case LD_EVA:

View file

@ -2031,7 +2031,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
gen_store_gpr(t0, rt);
break;
case OPC_LD:
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@ -2053,7 +2053,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
}
tcg_gen_shli_tl(t1, t1, 3);
tcg_gen_andi_tl(t0, t0, ~7);
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ);
tcg_gen_shl_tl(t0, t0, t1);
t2 = tcg_const_tl(-1);
tcg_gen_shl_tl(t2, t2, t1);
@ -2077,7 +2077,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
}
tcg_gen_shli_tl(t1, t1, 3);
tcg_gen_andi_tl(t0, t0, ~7);
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ);
tcg_gen_shr_tl(t0, t0, t1);
tcg_gen_xori_tl(t1, t1, 63);
t2 = tcg_const_tl(0xfffffffffffffffeull);
@ -2093,7 +2093,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
t1 = tcg_const_tl(pc_relative_pc(ctx));
gen_op_addr_add(ctx, t0, t0, t1);
tcg_temp_free(t1);
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ);
gen_store_gpr(t0, rt);
break;
#endif
@ -2224,7 +2224,7 @@ static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
switch (opc) {
#if defined(TARGET_MIPS64)
case OPC_SD:
tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
break;
case OPC_SDL:
@ -2334,7 +2334,7 @@ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
case OPC_LDC1:
{
TCGv_i64 fp0 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_store_fpr64(ctx, fp0, ft);
tcg_temp_free_i64(fp0);
@ -2344,7 +2344,7 @@ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, ft);
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
tcg_temp_free_i64(fp0);
}
@ -3092,7 +3092,7 @@ static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
check_mips_64(ctx);
offset = sextract32(ctx->opcode << 3, 0, 21);
addr = addr_add(ctx, (pc & ~0x7), offset);
gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUQ);
break;
#endif
default:
@ -4344,10 +4344,10 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
case OPC_GSLQ:
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t1, rt);
gen_store_gpr(t0, lsq_rt1);
@ -4357,10 +4357,10 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
check_cp1_enabled(ctx);
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_store_fpr64(ctx, t1, rt);
gen_store_fpr64(ctx, t0, lsq_rt1);
@ -4370,11 +4370,11 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
gen_load_gpr(t1, rt);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
gen_load_gpr(t1, lsq_rt1);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
tcg_temp_free(t1);
break;
@ -4383,11 +4383,11 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
t1 = tcg_temp_new();
gen_base_offset_addr(ctx, t0, rs, lsq_offset);
gen_load_fpr64(ctx, t1, rt);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
gen_load_fpr64(ctx, t1, lsq_rt1);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
tcg_temp_free(t1);
break;
@ -4467,7 +4467,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
}
tcg_gen_shli_tl(t1, t1, 3);
tcg_gen_andi_tl(t0, t0, ~7);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
tcg_gen_shl_tl(t0, t0, t1);
t2 = tcg_const_tl(-1);
tcg_gen_shl_tl(t2, t2, t1);
@ -4489,7 +4489,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
}
tcg_gen_shli_tl(t1, t1, 3);
tcg_gen_andi_tl(t0, t0, ~7);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
tcg_gen_shr_tl(t0, t0, t1);
tcg_gen_xori_tl(t1, t1, 63);
t2 = tcg_const_tl(0xfffffffffffffffeull);
@ -4642,7 +4642,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
if (rd) {
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
}
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_store_gpr(t0, rt);
break;
@ -4664,7 +4664,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
if (rd) {
gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
}
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
gen_store_fpr64(ctx, t0, rt);
break;
@ -4693,7 +4693,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
case OPC_GSSDX:
t1 = tcg_temp_new();
gen_load_gpr(t1, rt);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
tcg_temp_free(t1);
break;
@ -4709,7 +4709,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
case OPC_GSSDXC1:
t1 = tcg_temp_new();
gen_load_fpr64(ctx, t1, rt);
tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEUQ |
ctx->default_tcg_memop_mask);
tcg_temp_free(t1);
break;
@ -11330,7 +11330,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
check_cp1_registers(ctx, fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@ -11341,7 +11341,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@ -11361,7 +11361,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
tcg_temp_free_i64(fp0);
}
break;
@ -11371,7 +11371,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ);
tcg_temp_free_i64(fp0);
}
break;
@ -12187,7 +12187,7 @@ static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
break;
#if defined(TARGET_MIPS64)
case OPC_LDX:
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
gen_store_gpr(t0, rd);
break;
#endif
@ -14403,7 +14403,7 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
#endif
#if defined(TARGET_MIPS64)
case R6_OPC_SCD:
gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false);
break;
case R6_OPC_LLD:
gen_ld(ctx, op1, rt, rs, imm);
@ -15843,7 +15843,7 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
check_insn_opc_user_only(ctx, INSN_R5900);
}
check_mips_64(ctx);
gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false);
break;
case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
if (ctx->insn_flags & ISA_MIPS_R6) {

View file

@ -355,12 +355,12 @@ static bool trans_LQ(DisasContext *ctx, arg_i *a)
tcg_gen_andi_tl(addr, addr, ~0xf);
/* Lower half */
tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
gen_store_gpr(t0, a->rt);
/* Upper half */
tcg_gen_addi_i64(addr, addr, 8);
tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
gen_store_gpr_hi(t0, a->rt);
tcg_temp_free(t0);
@ -383,12 +383,12 @@ static bool trans_SQ(DisasContext *ctx, arg_i *a)
/* Lower half */
gen_load_gpr(t0, a->rt);
tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
/* Upper half */
tcg_gen_addi_i64(addr, addr, 8);
gen_load_gpr_hi(t0, a->rt);
tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
tcg_temp_free(addr);
tcg_temp_free(t0);

View file

@ -3277,10 +3277,10 @@ GEN_QEMU_LOAD_64(ld8u, DEF_MEMOP(MO_UB))
GEN_QEMU_LOAD_64(ld16u, DEF_MEMOP(MO_UW))
GEN_QEMU_LOAD_64(ld32u, DEF_MEMOP(MO_UL))
GEN_QEMU_LOAD_64(ld32s, DEF_MEMOP(MO_SL))
GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_Q))
GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_UQ))
#if defined(TARGET_PPC64)
GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_Q))
GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_UQ))
#endif
#define GEN_QEMU_STORE_TL(stop, op) \
@ -3311,10 +3311,10 @@ static void glue(gen_qemu_, glue(stop, _i64))(DisasContext *ctx, \
GEN_QEMU_STORE_64(st8, DEF_MEMOP(MO_UB))
GEN_QEMU_STORE_64(st16, DEF_MEMOP(MO_UW))
GEN_QEMU_STORE_64(st32, DEF_MEMOP(MO_UL))
GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_Q))
GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_UQ))
#if defined(TARGET_PPC64)
GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q))
GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_UQ))
#endif
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \
@ -3351,7 +3351,7 @@ GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
#if defined(TARGET_PPC64)
GEN_LDEPX(ld, DEF_MEMOP(MO_Q), 0x1D, 0x00)
GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00)
#endif
#if defined(TARGET_PPC64)
@ -3397,7 +3397,7 @@ GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
#if defined(TARGET_PPC64)
GEN_STEPX(std, DEF_MEMOP(MO_Q), 0x1d, 0x04)
GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1d, 0x04)
#endif
#if defined(TARGET_PPC64)
@ -3807,7 +3807,7 @@ static void gen_lwat(DisasContext *ctx)
#ifdef TARGET_PPC64
static void gen_ldat(DisasContext *ctx)
{
gen_ld_atomic(ctx, DEF_MEMOP(MO_Q));
gen_ld_atomic(ctx, DEF_MEMOP(MO_UQ));
}
#endif
@ -3890,7 +3890,7 @@ static void gen_stwat(DisasContext *ctx)
#ifdef TARGET_PPC64
static void gen_stdat(DisasContext *ctx)
{
gen_st_atomic(ctx, DEF_MEMOP(MO_Q));
gen_st_atomic(ctx, DEF_MEMOP(MO_UQ));
}
#endif
@ -3942,9 +3942,9 @@ STCX(stwcx_, DEF_MEMOP(MO_UL))
#if defined(TARGET_PPC64)
/* ldarx */
LARX(ldarx, DEF_MEMOP(MO_Q))
LARX(ldarx, DEF_MEMOP(MO_UQ))
/* stdcx. */
STCX(stdcx_, DEF_MEMOP(MO_Q))
STCX(stdcx_, DEF_MEMOP(MO_UQ))
/* lqarx */
static void gen_lqarx(DisasContext *ctx)
@ -3988,15 +3988,15 @@ static void gen_lqarx(DisasContext *ctx)
return;
}
} else if (ctx->le_mode) {
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ | MO_ALIGN_16);
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEUQ | MO_ALIGN_16);
tcg_gen_mov_tl(cpu_reserve, EA);
gen_addr_add(ctx, EA, EA, 8);
tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEQ);
tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEUQ);
} else {
tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEQ | MO_ALIGN_16);
tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEUQ | MO_ALIGN_16);
tcg_gen_mov_tl(cpu_reserve, EA);
gen_addr_add(ctx, EA, EA, 8);
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEUQ);
}
tcg_temp_free(EA);
@ -8018,7 +8018,7 @@ GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02)
GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08)
GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00)
#if defined(TARGET_PPC64)
GEN_LDEPX(ld, DEF_MEMOP(MO_Q), 0x1D, 0x00)
GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00)
#endif
#undef GEN_STX_E
@ -8044,7 +8044,7 @@ GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06)
GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C)
GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04)
#if defined(TARGET_PPC64)
GEN_STEPX(std, DEF_MEMOP(MO_Q), 0x1D, 0x04)
GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1D, 0x04)
#endif
#undef GEN_CRLOGIC

View file

@ -137,7 +137,7 @@ static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
ctx->base.is_jmp = DISAS_NORETURN;
}
} else {
mop = DEF_MEMOP(MO_Q);
mop = DEF_MEMOP(MO_UQ);
if (store) {
tcg_gen_qemu_st_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
} else {
@ -205,11 +205,11 @@ TRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
/* Load Doubleword */
TRANS64(LD, do_ldst_D, false, false, MO_Q)
TRANS64(LDX, do_ldst_X, false, false, MO_Q)
TRANS64(LDU, do_ldst_D, true, false, MO_Q)
TRANS64(LDUX, do_ldst_X, true, false, MO_Q)
TRANS64(PLD, do_ldst_PLS_D, false, false, MO_Q)
TRANS64(LD, do_ldst_D, false, false, MO_UQ)
TRANS64(LDX, do_ldst_X, false, false, MO_UQ)
TRANS64(LDU, do_ldst_D, true, false, MO_UQ)
TRANS64(LDUX, do_ldst_X, true, false, MO_UQ)
TRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ)
/* Load Quadword */
TRANS64(LQ, do_ldst_quad, false, false);
@ -237,11 +237,11 @@ TRANS(STWUX, do_ldst_X, true, true, MO_UL)
TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
/* Store Doubleword */
TRANS64(STD, do_ldst_D, false, true, MO_Q)
TRANS64(STDX, do_ldst_X, false, true, MO_Q)
TRANS64(STDU, do_ldst_D, true, true, MO_Q)
TRANS64(STDUX, do_ldst_X, true, true, MO_Q)
TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_Q)
TRANS64(STD, do_ldst_D, false, true, MO_UQ)
TRANS64(STDX, do_ldst_X, false, true, MO_UQ)
TRANS64(STDU, do_ldst_D, true, true, MO_UQ)
TRANS64(STDUX, do_ldst_X, true, true, MO_UQ)
TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ)
/* Store Quadword */
TRANS64(STQ, do_ldst_quad, true, false);

View file

@ -863,7 +863,7 @@ static void gen_lfdepx(DisasContext *ctx)
EA = tcg_temp_new();
t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_Q));
tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UQ));
set_fpr(rD(ctx->opcode), t0);
tcg_temp_free(EA);
tcg_temp_free_i64(t0);
@ -1021,7 +1021,7 @@ static void gen_stfdepx(DisasContext *ctx)
t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
get_fpr(t0, rD(ctx->opcode));
tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_Q));
tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_UQ));
tcg_temp_free(EA);
tcg_temp_free_i64(t0);
}

View file

@ -85,19 +85,19 @@ static void gen_lxvw4x(DisasContext *ctx)
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
tcg_gen_shri_i64(t1, t0, 32);
tcg_gen_deposit_i64(xth, t1, t0, 32, 32);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
tcg_gen_shri_i64(t1, t0, 32);
tcg_gen_deposit_i64(xtl, t1, t0, 32, 32);
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
} else {
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
}
set_cpu_vsr(xT(ctx->opcode), xth, true);
set_cpu_vsr(xT(ctx->opcode), xtl, false);
@ -152,8 +152,8 @@ static void gen_lxvdsx(DisasContext *ctx)
gen_addr_reg_index(ctx, EA);
data = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UQ));
tcg_gen_gvec_dup_i64(MO_UQ, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
tcg_temp_free(EA);
tcg_temp_free_i64(data);
@ -217,9 +217,9 @@ static void gen_lxvh8x(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
if (ctx->le_mode) {
gen_bswap16x8(xth, xtl, xth, xtl);
}
@ -245,9 +245,9 @@ static void gen_lxvb16x(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
set_cpu_vsr(xT(ctx->opcode), xth, true);
set_cpu_vsr(xT(ctx->opcode), xtl, false);
tcg_temp_free(EA);
@ -382,17 +382,17 @@ static void gen_stxvw4x(DisasContext *ctx)
tcg_gen_shri_i64(t0, xsh, 32);
tcg_gen_deposit_i64(t1, t0, xsh, 32, 32);
tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_shri_i64(t0, xsl, 32);
tcg_gen_deposit_i64(t1, t0, xsl, 32, 32);
tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
} else {
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
}
tcg_temp_free(EA);
tcg_temp_free_i64(xsh);
@ -421,15 +421,15 @@ static void gen_stxvh8x(DisasContext *ctx)
TCGv_i64 outl = tcg_temp_new_i64();
gen_bswap16x8(outh, outl, xsh, xsl);
tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEUQ);
tcg_temp_free_i64(outh);
tcg_temp_free_i64(outl);
} else {
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
}
tcg_temp_free(EA);
tcg_temp_free_i64(xsh);
@ -453,9 +453,9 @@ static void gen_stxvb16x(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
tcg_temp_free(EA);
tcg_temp_free_i64(xsh);
tcg_temp_free_i64(xsl);
@ -2020,7 +2020,7 @@ static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ,
xt = tcg_temp_new_i64();
mop = DEF_MEMOP(MO_Q);
mop = DEF_MEMOP(MO_UQ);
gen_set_access_type(ctx, ACCESS_INT);
ea = do_ea_calc(ctx, ra, displ);

View file

@ -42,6 +42,15 @@ const char * const riscv_int_regnames[] = {
"x28/t3", "x29/t4", "x30/t5", "x31/t6"
};
const char * const riscv_int_regnamesh[] = {
"x0h/zeroh", "x1h/rah", "x2h/sph", "x3h/gph", "x4h/tph", "x5h/t0h",
"x6h/t1h", "x7h/t2h", "x8h/s0h", "x9h/s1h", "x10h/a0h", "x11h/a1h",
"x12h/a2h", "x13h/a3h", "x14h/a4h", "x15h/a5h", "x16h/a6h", "x17h/a7h",
"x18h/s2h", "x19h/s3h", "x20h/s4h", "x21h/s5h", "x22h/s6h", "x23h/s7h",
"x24h/s8h", "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h",
"x30h/t5h", "x31h/t6h"
};
const char * const riscv_fpr_regnames[] = {
"f0/ft0", "f1/ft1", "f2/ft2", "f3/ft3", "f4/ft4", "f5/ft5",
"f6/ft6", "f7/ft7", "f8/fs0", "f9/fs1", "f10/fa0", "f11/fa1",
@ -169,6 +178,19 @@ static void rv64_sifive_e_cpu_init(Object *obj)
set_priv_version(env, PRIV_VERSION_1_10_0);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
static void rv128_base_cpu_init(Object *obj)
{
if (qemu_tcg_mttcg_enabled()) {
/* Missing 128-bit aligned atomics */
error_report("128-bit RISC-V currently does not work with Multi "
"Threaded TCG. Please use: -accel tcg,thread=single");
exit(EXIT_FAILURE);
}
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
set_misa(env, MXL_RV128, 0);
}
#else
static void rv32_base_cpu_init(Object *obj)
{
@ -393,6 +415,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
case MXL_RV64:
info->print_insn = print_insn_riscv64;
break;
case MXL_RV128:
info->print_insn = print_insn_riscv128;
break;
default:
g_assert_not_reached();
}
@ -455,6 +480,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
#ifdef TARGET_RISCV64
case MXL_RV64:
break;
case MXL_RV128:
break;
#endif
case MXL_RV32:
break;
@ -627,6 +654,7 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
@ -640,12 +668,12 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
/* These are experimental so mark with 'x-' */
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
/* These are experimental so mark with 'x-' */
DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
/* ePMP 0.9.3 */
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
@ -663,6 +691,7 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
case MXL_RV32:
return g_strdup("riscv:rv32");
case MXL_RV64:
case MXL_RV128:
return g_strdup("riscv:rv64");
default:
g_assert_not_reached();
@ -817,6 +846,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init),
#endif
};

View file

@ -25,6 +25,7 @@
#include "exec/cpu-defs.h"
#include "fpu/softfloat-types.h"
#include "qom/object.h"
#include "qemu/int128.h"
#include "cpu_bits.h"
#define TCG_GUEST_DEFAULT_MO 0
@ -38,6 +39,7 @@
#define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
#define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
#define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
#define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128")
#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
#define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
#define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
@ -112,6 +114,7 @@ FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1)
struct CPURISCVState {
target_ulong gpr[32];
target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
uint64_t fpr[32]; /* assume both F and D extensions */
/* vector coprocessor state. */
@ -129,6 +132,8 @@ struct CPURISCVState {
target_ulong frm;
target_ulong badaddr;
uint32_t bins;
target_ulong guest_phys_fault_addr;
target_ulong priv_ver;
@ -141,6 +146,9 @@ struct CPURISCVState {
uint32_t misa_ext; /* current extensions */
uint32_t misa_ext_mask; /* max ext for this cpu */
/* 128-bit helpers upper part return value */
target_ulong retxh;
uint32_t features;
#ifdef CONFIG_USER_ONLY
@ -190,6 +198,10 @@ struct CPURISCVState {
target_ulong hgatp;
uint64_t htimedelta;
/* Upper 64-bits of 128-bit CSRs */
uint64_t mscratchh;
uint64_t sscratchh;
/* Virtual CSRs */
/*
* For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
@ -344,6 +356,7 @@ static inline bool riscv_feature(CPURISCVState *env, int feature)
#include "cpu_user.h"
extern const char * const riscv_int_regnames[];
extern const char * const riscv_int_regnamesh[];
extern const char * const riscv_fpr_regnames[];
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
@ -490,12 +503,23 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
target_ulong new_value,
target_ulong write_mask);
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
Int128 *ret_value,
Int128 new_value, Int128 write_mask);
typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
Int128 *ret_value);
typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno,
Int128 new_value);
typedef struct {
const char *name;
riscv_csr_predicate_fn predicate;
riscv_csr_read_fn read;
riscv_csr_write_fn write;
riscv_csr_op_fn op;
riscv_csr_read128_fn read128;
riscv_csr_write128_fn write128;
} riscv_csr_operations;
/* CSR function table constants */

View file

@ -401,6 +401,7 @@
#define MSTATUS32_SD 0x80000000
#define MSTATUS64_SD 0x8000000000000000ULL
#define MSTATUSH128_SD 0x8000000000000000ULL
#define MISA32_MXL 0xC0000000
#define MISA64_MXL 0xC000000000000000ULL
@ -423,6 +424,8 @@ typedef enum {
#define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */
#define SSTATUS_MXR 0x00080000
#define SSTATUS64_UXL 0x0000000300000000ULL
#define SSTATUS32_SD 0x80000000
#define SSTATUS64_SD 0x8000000000000000ULL

View file

@ -998,6 +998,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
bool write_gva = false;
uint64_t s;
/* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
@ -1006,7 +1007,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
target_ulong deleg = async ? env->mideleg : env->medeleg;
bool write_tval = false;
target_ulong tval = 0;
target_ulong htval = 0;
target_ulong mtval2 = 0;
@ -1035,9 +1035,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
case RISCV_EXCP_INST_PAGE_FAULT:
case RISCV_EXCP_LOAD_PAGE_FAULT:
case RISCV_EXCP_STORE_PAGE_FAULT:
write_tval = true;
write_gva = true;
tval = env->badaddr;
break;
case RISCV_EXCP_ILLEGAL_INST:
tval = env->bins;
break;
default:
break;
}
@ -1072,18 +1075,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
if (riscv_has_ext(env, RVH)) {
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
if (env->two_stage_lookup && write_tval) {
/*
* If we are writing a guest virtual address to stval, set
* this to 1. If we are trapping to VS we will set this to 0
* later.
*/
env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 1);
} else {
/* For other HS-mode traps, we set this to 0. */
env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0);
}
if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1)) {
/* Trap to VS mode */
/*
@ -1094,7 +1085,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
cause == IRQ_VS_EXT) {
cause = cause - 1;
}
env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0);
write_gva = false;
} else if (riscv_cpu_virt_enabled(env)) {
/* Trap into HS mode, from virt */
riscv_cpu_swap_hypervisor_regs(env);
@ -1103,6 +1094,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
riscv_cpu_virt_enabled(env));
htval = env->guest_phys_fault_addr;
riscv_cpu_set_virt_enabled(env, 0);
@ -1110,7 +1102,9 @@ void riscv_cpu_do_interrupt(CPUState *cs)
/* Trap into HS mode */
env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
htval = env->guest_phys_fault_addr;
write_gva = false;
}
env->hstatus = set_field(env->hstatus, HSTATUS_GVA, write_gva);
}
s = env->mstatus;

View file

@ -481,7 +481,7 @@ static const target_ulong vs_delegable_excps = DELEGABLE_EXCPS &
(1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)));
static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS;
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS | (target_ulong)SSTATUS64_UXL;
static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
static const target_ulong hip_writable_mask = MIP_VSSIP;
static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
@ -527,6 +527,8 @@ static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
return status | MSTATUS32_SD;
case MXL_RV64:
return status | MSTATUS64_SD;
case MXL_RV128:
return MSTATUSH128_SD;
default:
g_assert_not_reached();
}
@ -576,10 +578,11 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
mstatus = (mstatus & ~mask) | (val & mask);
if (riscv_cpu_mxl(env) == MXL_RV64) {
RISCVMXL xl = riscv_cpu_mxl(env);
if (xl > MXL_RV32) {
/* SXL and UXL fields are for now read only */
mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
mstatus = set_field(mstatus, MSTATUS64_UXL, xl);
}
env->mstatus = mstatus;
@ -608,6 +611,20 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno,
Int128 *val)
{
*val = int128_make128(env->mstatus, add_status_sd(MXL_RV128, env->mstatus));
return RISCV_EXCP_NONE;
}
static RISCVException read_misa_i128(CPURISCVState *env, int csrno,
Int128 *val)
{
*val = int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62);
return RISCV_EXCP_NONE;
}
static RISCVException read_misa(CPURISCVState *env, int csrno,
target_ulong *val)
{
@ -765,6 +782,21 @@ static RISCVException write_mcounteren(CPURISCVState *env, int csrno,
}
/* Machine Trap Handling */
static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno,
Int128 *val)
{
*val = int128_make128(env->mscratch, env->mscratchh);
return RISCV_EXCP_NONE;
}
static RISCVException write_mscratch_i128(CPURISCVState *env, int csrno,
Int128 val)
{
env->mscratch = int128_getlo(val);
env->mscratchh = int128_gethi(val);
return RISCV_EXCP_NONE;
}
static RISCVException read_mscratch(CPURISCVState *env, int csrno,
target_ulong *val)
{
@ -844,6 +876,16 @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno,
}
/* Supervisor Trap Setup */
static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
Int128 *val)
{
uint64_t mask = sstatus_v1_10_mask;
uint64_t sstatus = env->mstatus & mask;
*val = int128_make128(sstatus, add_status_sd(MXL_RV128, sstatus));
return RISCV_EXCP_NONE;
}
static RISCVException read_sstatus(CPURISCVState *env, int csrno,
target_ulong *val)
{
@ -937,6 +979,21 @@ static RISCVException write_scounteren(CPURISCVState *env, int csrno,
}
/* Supervisor Trap Handling */
static RISCVException read_sscratch_i128(CPURISCVState *env, int csrno,
Int128 *val)
{
*val = int128_make128(env->sscratch, env->sscratchh);
return RISCV_EXCP_NONE;
}
static RISCVException write_sscratch_i128(CPURISCVState *env, int csrno,
Int128 val)
{
env->sscratch = int128_getlo(val);
env->sscratchh = int128_gethi(val);
return RISCV_EXCP_NONE;
}
static RISCVException read_sscratch(CPURISCVState *env, int csrno,
target_ulong *val)
{
@ -1737,16 +1794,13 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
* csrrc <-> riscv_csrrw(env, csrno, ret_value, 0, value);
*/
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
int csrno,
bool write_mask,
RISCVCPU *cpu)
{
RISCVException ret;
target_ulong old_value;
RISCVCPU *cpu = env_archcpu(env);
int read_only = get_field(csrno, 0xC00) == 3;
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
int read_only = get_field(csrno, 0xC00) == 3;
#if !defined(CONFIG_USER_ONLY)
int effective_priv = env->priv;
@ -1778,10 +1832,17 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
if (!csr_ops[csrno].predicate) {
return RISCV_EXCP_ILLEGAL_INST;
}
ret = csr_ops[csrno].predicate(env, csrno);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
return csr_ops[csrno].predicate(env, csrno);
}
static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value,
target_ulong write_mask)
{
RISCVException ret;
target_ulong old_value;
/* execute combined read/write operation if it exists */
if (csr_ops[csrno].op) {
@ -1817,6 +1878,92 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
RISCVCPU *cpu = env_archcpu(env);
RISCVException ret = riscv_csrrw_check(env, csrno, write_mask, cpu);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
return riscv_csrrw_do64(env, csrno, ret_value, new_value, write_mask);
}
static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno,
Int128 *ret_value,
Int128 new_value,
Int128 write_mask)
{
RISCVException ret;
Int128 old_value;
/* read old value */
ret = csr_ops[csrno].read128(env, csrno, &old_value);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
/* write value if writable and write mask set, otherwise drop writes */
if (int128_nz(write_mask)) {
new_value = int128_or(int128_and(old_value, int128_not(write_mask)),
int128_and(new_value, write_mask));
if (csr_ops[csrno].write128) {
ret = csr_ops[csrno].write128(env, csrno, new_value);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
} else if (csr_ops[csrno].write) {
/* avoids having to write wrappers for all registers */
ret = csr_ops[csrno].write(env, csrno, int128_getlo(new_value));
if (ret != RISCV_EXCP_NONE) {
return ret;
}
}
}
/* return old value */
if (ret_value) {
*ret_value = old_value;
}
return RISCV_EXCP_NONE;
}
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
Int128 *ret_value,
Int128 new_value, Int128 write_mask)
{
RISCVException ret;
RISCVCPU *cpu = env_archcpu(env);
ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask), cpu);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
if (csr_ops[csrno].read128) {
return riscv_csrrw_do128(env, csrno, ret_value, new_value, write_mask);
}
/*
* Fall back to 64-bit version for now, if the 128-bit alternative isn't
* at all defined.
* Note, some CSRs don't need to extend to MXLEN (64 upper bits non
* significant), for those, this fallback is correctly handling the accesses
*/
target_ulong old_value;
ret = riscv_csrrw_do64(env, csrno, &old_value,
int128_getlo(new_value),
int128_getlo(write_mask));
if (ret == RISCV_EXCP_NONE && ret_value) {
*ret_value = int128_make64(old_value);
}
return ret;
}
/*
* Debugger support. If not in user mode, set env->debugger before the
* riscv_csrrw call and clear it after the call.
@ -1878,8 +2025,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MHARTID] = { "mhartid", any, read_mhartid },
/* Machine Trap Setup */
[CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus },
[CSR_MISA] = { "misa", any, read_misa, write_misa },
[CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus, NULL,
read_mstatus_i128 },
[CSR_MISA] = { "misa", any, read_misa, write_misa, NULL,
read_misa_i128 },
[CSR_MIDELEG] = { "mideleg", any, read_mideleg, write_mideleg },
[CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg },
[CSR_MIE] = { "mie", any, read_mie, write_mie },
@ -1889,20 +2038,23 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MSTATUSH] = { "mstatush", any32, read_mstatush, write_mstatush },
/* Machine Trap Handling */
[CSR_MSCRATCH] = { "mscratch", any, read_mscratch, write_mscratch },
[CSR_MSCRATCH] = { "mscratch", any, read_mscratch, write_mscratch, NULL,
read_mscratch_i128, write_mscratch_i128 },
[CSR_MEPC] = { "mepc", any, read_mepc, write_mepc },
[CSR_MCAUSE] = { "mcause", any, read_mcause, write_mcause },
[CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
/* Supervisor Trap Setup */
[CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus },
[CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL,
read_sstatus_i128 },
[CSR_SIE] = { "sie", smode, read_sie, write_sie },
[CSR_STVEC] = { "stvec", smode, read_stvec, write_stvec },
[CSR_SCOUNTEREN] = { "scounteren", smode, read_scounteren, write_scounteren },
/* Supervisor Trap Handling */
[CSR_SSCRATCH] = { "sscratch", smode, read_sscratch, write_sscratch },
[CSR_SSCRATCH] = { "sscratch", smode, read_sscratch, write_sscratch, NULL,
read_sscratch_i128, write_sscratch_i128 },
[CSR_SEPC] = { "sepc", smode, read_sepc, write_sepc },
[CSR_SCAUSE] = { "scause", smode, read_scause, write_scause },
[CSR_STVAL] = { "stval", smode, read_stval, write_stval },

View file

@ -280,6 +280,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
int bitsize = 16 << env->misa_mxl_max;
int i;
/* Until gdb knows about 128-bit registers */
if (bitsize > 64) {
bitsize = 64;
}
g_string_printf(s, "<?xml version=\"1.0\"?>");
g_string_append_printf(s, "<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">");
g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.csr\">");

View file

@ -96,6 +96,9 @@ DEF_HELPER_FLAGS_1(fclass_h, TCG_CALL_NO_RWG_SE, tl, i64)
DEF_HELPER_2(csrr, tl, env, int)
DEF_HELPER_3(csrw, void, env, int, tl)
DEF_HELPER_4(csrrw, tl, env, int, tl, tl)
DEF_HELPER_2(csrr_i128, tl, env, int)
DEF_HELPER_4(csrw_i128, void, env, int, tl, tl)
DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_2(sret, tl, env, tl)
DEF_HELPER_2(mret, tl, env, tl)
@ -1101,3 +1104,9 @@ DEF_HELPER_5(vsext_vf2_d, void, ptr, ptr, ptr, env, i32)
DEF_HELPER_5(vsext_vf4_w, void, ptr, ptr, ptr, env, i32)
DEF_HELPER_5(vsext_vf4_d, void, ptr, ptr, ptr, env, i32)
DEF_HELPER_5(vsext_vf8_d, void, ptr, ptr, ptr, env, i32)
/* 128-bit integer multiplication and division */
DEF_HELPER_5(divu_i128, tl, env, tl, tl, tl, tl)
DEF_HELPER_5(divs_i128, tl, env, tl, tl, tl, tl)
DEF_HELPER_5(remu_i128, tl, env, tl, tl, tl, tl)
DEF_HELPER_5(rems_i128, tl, env, tl, tl, tl, tl)

View file

@ -25,14 +25,17 @@
# Immediates:
%imm_ci 12:s1 2:5
%nzuimm_ciw 7:4 11:2 5:1 6:1 !function=ex_shift_2
%uimm_cl_q 10:1 5:2 11:2 !function=ex_shift_4
%uimm_cl_d 5:2 10:3 !function=ex_shift_3
%uimm_cl_w 5:1 10:3 6:1 !function=ex_shift_2
%imm_cb 12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
%imm_cj 12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
%shimm_6bit 12:1 2:5 !function=ex_rvc_shifti
%uimm_6bit_lq 2:4 12:1 6:1 !function=ex_shift_4
%uimm_6bit_ld 2:3 12:1 5:2 !function=ex_shift_3
%uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2
%uimm_6bit_sq 7:4 11:2 !function=ex_shift_4
%uimm_6bit_sd 7:3 10:3 !function=ex_shift_3
%uimm_6bit_sw 7:2 9:4 !function=ex_shift_2
@ -54,16 +57,20 @@
# Formats 16:
@cr .... ..... ..... .. &r rs2=%rs2_5 rs1=%rd %rd
@ci ... . ..... ..... .. &i imm=%imm_ci rs1=%rd %rd
@cl_q ... . ..... ..... .. &i imm=%uimm_cl_q rs1=%rs1_3 rd=%rs2_3
@cl_d ... ... ... .. ... .. &i imm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3
@cl_w ... ... ... .. ... .. &i imm=%uimm_cl_w rs1=%rs1_3 rd=%rs2_3
@cs_2 ... ... ... .. ... .. &r rs2=%rs2_3 rs1=%rs1_3 rd=%rs1_3
@cs_q ... ... ... .. ... .. &s imm=%uimm_cl_q rs1=%rs1_3 rs2=%rs2_3
@cs_d ... ... ... .. ... .. &s imm=%uimm_cl_d rs1=%rs1_3 rs2=%rs2_3
@cs_w ... ... ... .. ... .. &s imm=%uimm_cl_w rs1=%rs1_3 rs2=%rs2_3
@cj ... ........... .. &j imm=%imm_cj
@cb_z ... ... ... .. ... .. &b imm=%imm_cb rs1=%rs1_3 rs2=0
@c_lqsp ... . ..... ..... .. &i imm=%uimm_6bit_lq rs1=2 %rd
@c_ldsp ... . ..... ..... .. &i imm=%uimm_6bit_ld rs1=2 %rd
@c_lwsp ... . ..... ..... .. &i imm=%uimm_6bit_lw rs1=2 %rd
@c_sqsp ... . ..... ..... .. &s imm=%uimm_6bit_sq rs1=2 rs2=%rs2_5
@c_sdsp ... . ..... ..... .. &s imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
@c_swsp ... . ..... ..... .. &s imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
@c_li ... . ..... ..... .. &i imm=%imm_ci rs1=0 %rd
@ -87,9 +94,15 @@
illegal 000 000 000 00 --- 00
addi 000 ... ... .. ... 00 @c_addi4spn
}
fld 001 ... ... .. ... 00 @cl_d
{
lq 001 ... ... .. ... 00 @cl_q
fld 001 ... ... .. ... 00 @cl_d
}
lw 010 ... ... .. ... 00 @cl_w
fsd 101 ... ... .. ... 00 @cs_d
{
sq 101 ... ... .. ... 00 @cs_q
fsd 101 ... ... .. ... 00 @cs_d
}
sw 110 ... ... .. ... 00 @cs_w
# *** RV32C and RV64C specific Standard Extension (Quadrant 0) ***
@ -132,7 +145,10 @@ addw 100 1 11 ... 01 ... 01 @cs_2
# *** RV32/64C Standard Extension (Quadrant 2) ***
slli 000 . ..... ..... 10 @c_shift2
fld 001 . ..... ..... 10 @c_ldsp
{
lq 001 ... ... .. ... 10 @c_lqsp
fld 001 . ..... ..... 10 @c_ldsp
}
{
illegal 010 - 00000 ----- 10 # c.lwsp, RES rd=0
lw 010 . ..... ..... 10 @c_lwsp
@ -147,7 +163,10 @@ fld 001 . ..... ..... 10 @c_ldsp
jalr 100 1 ..... 00000 10 @c_jalr rd=1 # C.JALR
add 100 1 ..... ..... 10 @cr
}
fsd 101 ...... ..... 10 @c_sdsp
{
sq 101 ... ... .. ... 10 @c_sqsp
fsd 101 ...... ..... 10 @c_sdsp
}
sw 110 . ..... ..... 10 @c_swsp
# *** RV32C and RV64C specific Standard Extension (Quadrant 2) ***

View file

@ -22,6 +22,7 @@
%rs1 15:5
%rd 7:5
%sh5 20:5
%sh6 20:6
%sh7 20:7
%csr 20:12
@ -91,6 +92,9 @@
# Formats 64:
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
# Formats 128:
@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd
# *** Privileged Instructions ***
ecall 000000000000 00000 000 00000 1110011
ebreak 000000000001 00000 000 00000 1110011
@ -162,6 +166,20 @@ sllw 0000000 ..... ..... 001 ..... 0111011 @r
srlw 0000000 ..... ..... 101 ..... 0111011 @r
sraw 0100000 ..... ..... 101 ..... 0111011 @r
# *** RV128I Base Instruction Set (in addition to RV64I) ***
ldu ............ ..... 111 ..... 0000011 @i
lq ............ ..... 010 ..... 0001111 @i
sq ............ ..... 100 ..... 0100011 @s
addid ............ ..... 000 ..... 1011011 @i
sllid 000000 ...... ..... 001 ..... 1011011 @sh6
srlid 000000 ...... ..... 101 ..... 1011011 @sh6
sraid 010000 ...... ..... 101 ..... 1011011 @sh6
addd 0000000 ..... ..... 000 ..... 1111011 @r
subd 0100000 ..... ..... 000 ..... 1111011 @r
slld 0000000 ..... ..... 001 ..... 1111011 @r
srld 0000000 ..... ..... 101 ..... 1111011 @r
srad 0100000 ..... ..... 101 ..... 1111011 @r
# *** RV32M Standard Extension ***
mul 0000001 ..... ..... 000 ..... 0110011 @r
mulh 0000001 ..... ..... 001 ..... 0110011 @r
@ -179,6 +197,13 @@ divuw 0000001 ..... ..... 101 ..... 0111011 @r
remw 0000001 ..... ..... 110 ..... 0111011 @r
remuw 0000001 ..... ..... 111 ..... 0111011 @r
# *** RV128M Standard Extension (in addition to RV64M) ***
muld 0000001 ..... ..... 000 ..... 1111011 @r
divd 0000001 ..... ..... 100 ..... 1111011 @r
divud 0000001 ..... ..... 101 ..... 1111011 @r
remd 0000001 ..... ..... 110 ..... 1111011 @r
remud 0000001 ..... ..... 111 ..... 1111011 @r
# *** RV32A Standard Extension ***
lr_w 00010 . . 00000 ..... 010 ..... 0101111 @atom_ld
sc_w 00011 . . ..... ..... 010 ..... 0101111 @atom_st

View file

@ -162,65 +162,65 @@ static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a)
static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a)
{
REQUIRE_64BIT(ctx);
return gen_lr(ctx, a, MO_ALIGN | MO_TEQ);
return gen_lr(ctx, a, MO_ALIGN | MO_TEUQ);
}
static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a)
{
REQUIRE_64BIT(ctx);
return gen_sc(ctx, a, (MO_ALIGN | MO_TEQ));
return gen_sc(ctx, a, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amoadd_d(DisasContext *ctx, arg_amoadd_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amoxor_d(DisasContext *ctx, arg_amoxor_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amoand_d(DisasContext *ctx, arg_amoand_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amoor_d(DisasContext *ctx, arg_amoor_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amomin_d(DisasContext *ctx, arg_amomin_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amomax_d(DisasContext *ctx, arg_amomax_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amominu_d(DisasContext *ctx, arg_amominu_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TEUQ));
}
static bool trans_amomaxu_d(DisasContext *ctx, arg_amomaxu_d *a)
{
REQUIRE_64BIT(ctx);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEQ));
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEUQ));
}

View file

@ -86,43 +86,43 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
static bool trans_andn(DisasContext *ctx, arg_andn *a)
{
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl);
return gen_logic(ctx, a, tcg_gen_andc_tl);
}
static bool trans_orn(DisasContext *ctx, arg_orn *a)
{
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl);
return gen_logic(ctx, a, tcg_gen_orc_tl);
}
static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
{
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl);
return gen_logic(ctx, a, tcg_gen_eqv_tl);
}
static bool trans_min(DisasContext *ctx, arg_min *a)
{
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smin_tl);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smin_tl, NULL);
}
static bool trans_max(DisasContext *ctx, arg_max *a)
{
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smax_tl);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smax_tl, NULL);
}
static bool trans_minu(DisasContext *ctx, arg_minu *a)
{
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umin_tl);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umin_tl, NULL);
}
static bool trans_maxu(DisasContext *ctx, arg_maxu *a)
{
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umax_tl);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umax_tl, NULL);
}
static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a)
@ -156,7 +156,7 @@ static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_bset(DisasContext *ctx, arg_bset *a)
{
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_bset);
return gen_shift(ctx, a, EXT_NONE, gen_bset, NULL);
}
static bool trans_bseti(DisasContext *ctx, arg_bseti *a)
@ -178,7 +178,7 @@ static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_bclr(DisasContext *ctx, arg_bclr *a)
{
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_bclr);
return gen_shift(ctx, a, EXT_NONE, gen_bclr, NULL);
}
static bool trans_bclri(DisasContext *ctx, arg_bclri *a)
@ -200,7 +200,7 @@ static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_binv(DisasContext *ctx, arg_binv *a)
{
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_binv);
return gen_shift(ctx, a, EXT_NONE, gen_binv, NULL);
}
static bool trans_binvi(DisasContext *ctx, arg_binvi *a)
@ -218,7 +218,7 @@ static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_bext(DisasContext *ctx, arg_bext *a)
{
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_bext);
return gen_shift(ctx, a, EXT_NONE, gen_bext, NULL);
}
static bool trans_bexti(DisasContext *ctx, arg_bexti *a)
@ -248,7 +248,7 @@ static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
static bool trans_ror(DisasContext *ctx, arg_ror *a)
{
REQUIRE_ZBB(ctx);
return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotr_tl, gen_rorw);
return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotr_tl, gen_rorw, NULL);
}
static void gen_roriw(TCGv ret, TCGv arg1, target_long shamt)
@ -266,7 +266,7 @@ static bool trans_rori(DisasContext *ctx, arg_rori *a)
{
REQUIRE_ZBB(ctx);
return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE,
tcg_gen_rotri_tl, gen_roriw);
tcg_gen_rotri_tl, gen_roriw, NULL);
}
static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
@ -290,7 +290,7 @@ static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
static bool trans_rol(DisasContext *ctx, arg_rol *a)
{
REQUIRE_ZBB(ctx);
return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotl_tl, gen_rolw);
return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotl_tl, gen_rolw, NULL);
}
static void gen_rev8_32(TCGv ret, TCGv src1)
@ -357,7 +357,7 @@ GEN_SHADD(3)
static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \
{ \
REQUIRE_ZBA(ctx); \
return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add); \
return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add, NULL); \
}
GEN_TRANS_SHADD(1)
@ -405,7 +405,7 @@ static bool trans_rorw(DisasContext *ctx, arg_rorw *a)
REQUIRE_64BIT(ctx);
REQUIRE_ZBB(ctx);
ctx->ol = MXL_RV32;
return gen_shift(ctx, a, EXT_NONE, gen_rorw);
return gen_shift(ctx, a, EXT_NONE, gen_rorw, NULL);
}
static bool trans_roriw(DisasContext *ctx, arg_roriw *a)
@ -413,7 +413,7 @@ static bool trans_roriw(DisasContext *ctx, arg_roriw *a)
REQUIRE_64BIT(ctx);
REQUIRE_ZBB(ctx);
ctx->ol = MXL_RV32;
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_roriw);
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_roriw, NULL);
}
static bool trans_rolw(DisasContext *ctx, arg_rolw *a)
@ -421,7 +421,7 @@ static bool trans_rolw(DisasContext *ctx, arg_rolw *a)
REQUIRE_64BIT(ctx);
REQUIRE_ZBB(ctx);
ctx->ol = MXL_RV32;
return gen_shift(ctx, a, EXT_NONE, gen_rolw);
return gen_shift(ctx, a, EXT_NONE, gen_rolw, NULL);
}
#define GEN_SHADD_UW(SHAMT) \
@ -447,7 +447,7 @@ static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \
{ \
REQUIRE_64BIT(ctx); \
REQUIRE_ZBA(ctx); \
return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add_uw); \
return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add_uw, NULL); \
}
GEN_TRANS_SHADD_UW(1)
@ -466,7 +466,7 @@ static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_ZBA(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_add_uw);
return gen_arith(ctx, a, EXT_NONE, gen_add_uw, NULL);
}
static void gen_slli_uw(TCGv dest, TCGv src, target_long shamt)
@ -478,13 +478,13 @@ static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_ZBA(ctx);
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_slli_uw);
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_slli_uw, NULL);
}
static bool trans_clmul(DisasContext *ctx, arg_clmul *a)
{
REQUIRE_ZBC(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_helper_clmul);
return gen_arith(ctx, a, EXT_NONE, gen_helper_clmul, NULL);
}
static void gen_clmulh(TCGv dst, TCGv src1, TCGv src2)
@ -496,11 +496,11 @@ static void gen_clmulh(TCGv dst, TCGv src1, TCGv src2)
static bool trans_clmulh(DisasContext *ctx, arg_clmulr *a)
{
REQUIRE_ZBC(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_clmulh);
return gen_arith(ctx, a, EXT_NONE, gen_clmulh, NULL);
}
static bool trans_clmulr(DisasContext *ctx, arg_clmulh *a)
{
REQUIRE_ZBC(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_helper_clmulr);
return gen_arith(ctx, a, EXT_NONE, gen_helper_clmulr, NULL);
}

View file

@ -33,7 +33,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
}
addr = gen_pm_adjust_address(ctx, addr);
tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ);
mark_fs_dirty(ctx);
return true;
@ -54,7 +54,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
}
addr = gen_pm_adjust_address(ctx, addr);
tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEQ);
tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ);
return true;
}

View file

@ -121,14 +121,14 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVH);
return do_hlv(ctx, a, MO_TEQ);
return do_hlv(ctx, a, MO_TEUQ);
}
static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVH);
return do_hsv(ctx, a, MO_TEQ);
return do_hsv(ctx, a, MO_TEUQ);
}
#ifndef CONFIG_USER_ONLY

View file

@ -26,14 +26,14 @@ static bool trans_illegal(DisasContext *ctx, arg_empty *a)
static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
{
REQUIRE_64BIT(ctx);
return trans_illegal(ctx, a);
REQUIRE_64_OR_128BIT(ctx);
return trans_illegal(ctx, a);
}
static bool trans_lui(DisasContext *ctx, arg_lui *a)
{
if (a->rd != 0) {
tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm);
gen_set_gpri(ctx, a->rd, a->imm);
}
return true;
}
@ -41,7 +41,7 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a)
static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
{
if (a->rd != 0) {
tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm + ctx->base.pc_next);
gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
}
return true;
}
@ -82,13 +82,103 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
return true;
}
static TCGCond gen_compare_i128(bool bz, TCGv rl,
TCGv al, TCGv ah, TCGv bl, TCGv bh,
TCGCond cond)
{
TCGv rh = tcg_temp_new();
bool invert = false;
switch (cond) {
case TCG_COND_EQ:
case TCG_COND_NE:
if (bz) {
tcg_gen_or_tl(rl, al, ah);
} else {
tcg_gen_xor_tl(rl, al, bl);
tcg_gen_xor_tl(rh, ah, bh);
tcg_gen_or_tl(rl, rl, rh);
}
break;
case TCG_COND_GE:
case TCG_COND_LT:
if (bz) {
tcg_gen_mov_tl(rl, ah);
} else {
TCGv tmp = tcg_temp_new();
tcg_gen_sub2_tl(rl, rh, al, ah, bl, bh);
tcg_gen_xor_tl(rl, rh, ah);
tcg_gen_xor_tl(tmp, ah, bh);
tcg_gen_and_tl(rl, rl, tmp);
tcg_gen_xor_tl(rl, rh, rl);
tcg_temp_free(tmp);
}
break;
case TCG_COND_LTU:
invert = true;
/* fallthrough */
case TCG_COND_GEU:
{
TCGv tmp = tcg_temp_new();
TCGv zero = tcg_constant_tl(0);
TCGv one = tcg_constant_tl(1);
cond = TCG_COND_NE;
/* borrow in to second word */
tcg_gen_setcond_tl(TCG_COND_LTU, tmp, al, bl);
/* seed third word with 1, which will be result */
tcg_gen_sub2_tl(tmp, rh, ah, one, tmp, zero);
tcg_gen_sub2_tl(tmp, rl, tmp, rh, bh, zero);
tcg_temp_free(tmp);
}
break;
default:
g_assert_not_reached();
}
if (invert) {
cond = tcg_invert_cond(cond);
}
tcg_temp_free(rh);
return cond;
}
static void gen_setcond_i128(TCGv rl, TCGv rh,
TCGv src1l, TCGv src1h,
TCGv src2l, TCGv src2h,
TCGCond cond)
{
cond = gen_compare_i128(false, rl, src1l, src1h, src2l, src2h, cond);
tcg_gen_setcondi_tl(cond, rl, rl, 0);
tcg_gen_movi_tl(rh, 0);
}
static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
{
TCGLabel *l = gen_new_label();
TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
tcg_gen_brcond_tl(cond, src1, src2, l);
if (get_xl(ctx) == MXL_RV128) {
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv src2h = get_gprh(ctx, a->rs2);
TCGv tmp = tcg_temp_new();
cond = gen_compare_i128(a->rs2 == 0,
tmp, src1, src1h, src2, src2h, cond);
tcg_gen_brcondi_tl(cond, tmp, 0, l);
tcg_temp_free(tmp);
} else {
tcg_gen_brcond_tl(cond, src1, src2, l);
}
gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
gen_set_label(l); /* branch taken */
@ -134,7 +224,7 @@ static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a)
return gen_branch(ctx, a, TCG_COND_GEU);
}
static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
static bool gen_load_tl(DisasContext *ctx, arg_lb *a, MemOp memop)
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@ -151,6 +241,45 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
return true;
}
/* Compute only 64-bit addresses to use the address translation mechanism */
static bool gen_load_i128(DisasContext *ctx, arg_lb *a, MemOp memop)
{
TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv destl = dest_gpr(ctx, a->rd);
TCGv desth = dest_gprh(ctx, a->rd);
TCGv addrl = tcg_temp_new();
tcg_gen_addi_tl(addrl, src1l, a->imm);
if ((memop & MO_SIZE) <= MO_64) {
tcg_gen_qemu_ld_tl(destl, addrl, ctx->mem_idx, memop);
if (memop & MO_SIGN) {
tcg_gen_sari_tl(desth, destl, 63);
} else {
tcg_gen_movi_tl(desth, 0);
}
} else {
/* assume little-endian memory access for now */
tcg_gen_qemu_ld_tl(destl, addrl, ctx->mem_idx, MO_TEUQ);
tcg_gen_addi_tl(addrl, addrl, 8);
tcg_gen_qemu_ld_tl(desth, addrl, ctx->mem_idx, MO_TEUQ);
}
gen_set_gpr128(ctx, a->rd, destl, desth);
tcg_temp_free(addrl);
return true;
}
static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
{
if (get_xl(ctx) == MXL_RV128) {
return gen_load_i128(ctx, a, memop);
} else {
return gen_load_tl(ctx, a, memop);
}
}
static bool trans_lb(DisasContext *ctx, arg_lb *a)
{
return gen_load(ctx, a, MO_SB);
@ -166,6 +295,18 @@ static bool trans_lw(DisasContext *ctx, arg_lw *a)
return gen_load(ctx, a, MO_TESL);
}
static bool trans_ld(DisasContext *ctx, arg_ld *a)
{
REQUIRE_64_OR_128BIT(ctx);
return gen_load(ctx, a, MO_TESQ);
}
static bool trans_lq(DisasContext *ctx, arg_lq *a)
{
REQUIRE_128BIT(ctx);
return gen_load(ctx, a, MO_TEUO);
}
static bool trans_lbu(DisasContext *ctx, arg_lbu *a)
{
return gen_load(ctx, a, MO_UB);
@ -176,7 +317,19 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
return gen_load(ctx, a, MO_TEUW);
}
static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
{
REQUIRE_64_OR_128BIT(ctx);
return gen_load(ctx, a, MO_TEUL);
}
static bool trans_ldu(DisasContext *ctx, arg_ldu *a)
{
REQUIRE_128BIT(ctx);
return gen_load(ctx, a, MO_TEUQ);
}
static bool gen_store_tl(DisasContext *ctx, arg_sb *a, MemOp memop)
{
TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
@ -192,6 +345,37 @@ static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
return true;
}
static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop)
{
TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv src2l = get_gpr(ctx, a->rs2, EXT_NONE);
TCGv src2h = get_gprh(ctx, a->rs2);
TCGv addrl = tcg_temp_new();
tcg_gen_addi_tl(addrl, src1l, a->imm);
if ((memop & MO_SIZE) <= MO_64) {
tcg_gen_qemu_st_tl(src2l, addrl, ctx->mem_idx, memop);
} else {
/* little-endian memory access assumed for now */
tcg_gen_qemu_st_tl(src2l, addrl, ctx->mem_idx, MO_TEUQ);
tcg_gen_addi_tl(addrl, addrl, 8);
tcg_gen_qemu_st_tl(src2h, addrl, ctx->mem_idx, MO_TEUQ);
}
tcg_temp_free(addrl);
return true;
}
static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
{
if (get_xl(ctx) == MXL_RV128) {
return gen_store_i128(ctx, a, memop);
} else {
return gen_store_tl(ctx, a, memop);
}
}
static bool trans_sb(DisasContext *ctx, arg_sb *a)
{
return gen_store(ctx, a, MO_SB);
@ -207,27 +391,50 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
return gen_store(ctx, a, MO_TESL);
}
static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
{
REQUIRE_64BIT(ctx);
return gen_load(ctx, a, MO_TEUL);
}
static bool trans_ld(DisasContext *ctx, arg_ld *a)
{
REQUIRE_64BIT(ctx);
return gen_load(ctx, a, MO_TEQ);
}
static bool trans_sd(DisasContext *ctx, arg_sd *a)
{
REQUIRE_64BIT(ctx);
return gen_store(ctx, a, MO_TEQ);
REQUIRE_64_OR_128BIT(ctx);
return gen_store(ctx, a, MO_TEUQ);
}
static bool trans_sq(DisasContext *ctx, arg_sq *a)
{
REQUIRE_128BIT(ctx);
return gen_store(ctx, a, MO_TEUO);
}
static bool trans_addd(DisasContext *ctx, arg_addd *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, NULL);
}
static bool trans_addid(DisasContext *ctx, arg_addid *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, NULL);
}
static bool trans_subd(DisasContext *ctx, arg_subd *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, NULL);
}
static void gen_addi2_i128(TCGv retl, TCGv reth,
TCGv srcl, TCGv srch, target_long imm)
{
TCGv imml = tcg_constant_tl(imm);
TCGv immh = tcg_constant_tl(-(imm < 0));
tcg_gen_add2_tl(retl, reth, srcl, srch, imml, immh);
}
static bool trans_addi(DisasContext *ctx, arg_addi *a)
{
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl);
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, gen_addi2_i128);
}
static void gen_slt(TCGv ret, TCGv s1, TCGv s2)
@ -235,39 +442,64 @@ static void gen_slt(TCGv ret, TCGv s1, TCGv s2)
tcg_gen_setcond_tl(TCG_COND_LT, ret, s1, s2);
}
static void gen_slt_i128(TCGv retl, TCGv reth,
TCGv s1l, TCGv s1h, TCGv s2l, TCGv s2h)
{
gen_setcond_i128(retl, reth, s1l, s1h, s2l, s2h, TCG_COND_LT);
}
static void gen_sltu(TCGv ret, TCGv s1, TCGv s2)
{
tcg_gen_setcond_tl(TCG_COND_LTU, ret, s1, s2);
}
static void gen_sltu_i128(TCGv retl, TCGv reth,
TCGv s1l, TCGv s1h, TCGv s2l, TCGv s2h)
{
gen_setcond_i128(retl, reth, s1l, s1h, s2l, s2h, TCG_COND_LTU);
}
static bool trans_slti(DisasContext *ctx, arg_slti *a)
{
return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_slt);
return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_slt, gen_slt_i128);
}
static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
{
return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_sltu);
return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_sltu, gen_sltu_i128);
}
static bool trans_xori(DisasContext *ctx, arg_xori *a)
{
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl);
return gen_logic_imm_fn(ctx, a, tcg_gen_xori_tl);
}
static bool trans_ori(DisasContext *ctx, arg_ori *a)
{
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl);
return gen_logic_imm_fn(ctx, a, tcg_gen_ori_tl);
}
static bool trans_andi(DisasContext *ctx, arg_andi *a)
{
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl);
return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl);
}
static void gen_slli_i128(TCGv retl, TCGv reth,
TCGv src1l, TCGv src1h,
target_long shamt)
{
if (shamt >= 64) {
tcg_gen_shli_tl(reth, src1l, shamt - 64);
tcg_gen_movi_tl(retl, 0);
} else {
tcg_gen_extract2_tl(reth, src1l, src1h, 64 - shamt);
tcg_gen_shli_tl(retl, src1l, shamt);
}
}
static bool trans_slli(DisasContext *ctx, arg_slli *a)
{
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl);
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, gen_slli_i128);
}
static void gen_srliw(TCGv dst, TCGv src, target_long shamt)
@ -275,10 +507,23 @@ static void gen_srliw(TCGv dst, TCGv src, target_long shamt)
tcg_gen_extract_tl(dst, src, shamt, 32 - shamt);
}
static void gen_srli_i128(TCGv retl, TCGv reth,
TCGv src1l, TCGv src1h,
target_long shamt)
{
if (shamt >= 64) {
tcg_gen_shri_tl(retl, src1h, shamt - 64);
tcg_gen_movi_tl(reth, 0);
} else {
tcg_gen_extract2_tl(retl, src1l, src1h, shamt);
tcg_gen_shri_tl(reth, src1h, shamt);
}
}
static bool trans_srli(DisasContext *ctx, arg_srli *a)
{
return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE,
tcg_gen_shri_tl, gen_srliw);
tcg_gen_shri_tl, gen_srliw, gen_srli_i128);
}
static void gen_sraiw(TCGv dst, TCGv src, target_long shamt)
@ -286,125 +531,287 @@ static void gen_sraiw(TCGv dst, TCGv src, target_long shamt)
tcg_gen_sextract_tl(dst, src, shamt, 32 - shamt);
}
static void gen_srai_i128(TCGv retl, TCGv reth,
TCGv src1l, TCGv src1h,
target_long shamt)
{
if (shamt >= 64) {
tcg_gen_sari_tl(retl, src1h, shamt - 64);
tcg_gen_sari_tl(reth, src1h, 63);
} else {
tcg_gen_extract2_tl(retl, src1l, src1h, shamt);
tcg_gen_sari_tl(reth, src1h, shamt);
}
}
static bool trans_srai(DisasContext *ctx, arg_srai *a)
{
return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE,
tcg_gen_sari_tl, gen_sraiw);
tcg_gen_sari_tl, gen_sraiw, gen_srai_i128);
}
static bool trans_add(DisasContext *ctx, arg_add *a)
{
return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, tcg_gen_add2_tl);
}
static bool trans_sub(DisasContext *ctx, arg_sub *a)
{
return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, tcg_gen_sub2_tl);
}
static void gen_sll_i128(TCGv destl, TCGv desth,
TCGv src1l, TCGv src1h, TCGv shamt)
{
TCGv ls = tcg_temp_new();
TCGv rs = tcg_temp_new();
TCGv hs = tcg_temp_new();
TCGv ll = tcg_temp_new();
TCGv lr = tcg_temp_new();
TCGv h0 = tcg_temp_new();
TCGv h1 = tcg_temp_new();
TCGv zero = tcg_constant_tl(0);
tcg_gen_andi_tl(hs, shamt, 64);
tcg_gen_andi_tl(ls, shamt, 63);
tcg_gen_neg_tl(shamt, shamt);
tcg_gen_andi_tl(rs, shamt, 63);
tcg_gen_shl_tl(ll, src1l, ls);
tcg_gen_shl_tl(h0, src1h, ls);
tcg_gen_shr_tl(lr, src1l, rs);
tcg_gen_movcond_tl(TCG_COND_NE, lr, shamt, zero, lr, zero);
tcg_gen_or_tl(h1, h0, lr);
tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, zero, ll);
tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, ll, h1);
tcg_temp_free(ls);
tcg_temp_free(rs);
tcg_temp_free(hs);
tcg_temp_free(ll);
tcg_temp_free(lr);
tcg_temp_free(h0);
tcg_temp_free(h1);
}
static bool trans_sll(DisasContext *ctx, arg_sll *a)
{
return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl);
return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, gen_sll_i128);
}
static bool trans_slt(DisasContext *ctx, arg_slt *a)
{
return gen_arith(ctx, a, EXT_SIGN, gen_slt);
return gen_arith(ctx, a, EXT_SIGN, gen_slt, gen_slt_i128);
}
static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
{
return gen_arith(ctx, a, EXT_SIGN, gen_sltu);
return gen_arith(ctx, a, EXT_SIGN, gen_sltu, gen_sltu_i128);
}
static bool trans_xor(DisasContext *ctx, arg_xor *a)
static void gen_srl_i128(TCGv destl, TCGv desth,
TCGv src1l, TCGv src1h, TCGv shamt)
{
return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl);
TCGv ls = tcg_temp_new();
TCGv rs = tcg_temp_new();
TCGv hs = tcg_temp_new();
TCGv ll = tcg_temp_new();
TCGv lr = tcg_temp_new();
TCGv h0 = tcg_temp_new();
TCGv h1 = tcg_temp_new();
TCGv zero = tcg_constant_tl(0);
tcg_gen_andi_tl(hs, shamt, 64);
tcg_gen_andi_tl(rs, shamt, 63);
tcg_gen_neg_tl(shamt, shamt);
tcg_gen_andi_tl(ls, shamt, 63);
tcg_gen_shr_tl(lr, src1l, rs);
tcg_gen_shr_tl(h1, src1h, rs);
tcg_gen_shl_tl(ll, src1h, ls);
tcg_gen_movcond_tl(TCG_COND_NE, ll, shamt, zero, ll, zero);
tcg_gen_or_tl(h0, ll, lr);
tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, h1, h0);
tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, zero, h1);
tcg_temp_free(ls);
tcg_temp_free(rs);
tcg_temp_free(hs);
tcg_temp_free(ll);
tcg_temp_free(lr);
tcg_temp_free(h0);
tcg_temp_free(h1);
}
static bool trans_srl(DisasContext *ctx, arg_srl *a)
{
return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, gen_srl_i128);
}
static void gen_sra_i128(TCGv destl, TCGv desth,
TCGv src1l, TCGv src1h, TCGv shamt)
{
TCGv ls = tcg_temp_new();
TCGv rs = tcg_temp_new();
TCGv hs = tcg_temp_new();
TCGv ll = tcg_temp_new();
TCGv lr = tcg_temp_new();
TCGv h0 = tcg_temp_new();
TCGv h1 = tcg_temp_new();
TCGv zero = tcg_constant_tl(0);
tcg_gen_andi_tl(hs, shamt, 64);
tcg_gen_andi_tl(rs, shamt, 63);
tcg_gen_neg_tl(shamt, shamt);
tcg_gen_andi_tl(ls, shamt, 63);
tcg_gen_shr_tl(lr, src1l, rs);
tcg_gen_sar_tl(h1, src1h, rs);
tcg_gen_shl_tl(ll, src1h, ls);
tcg_gen_movcond_tl(TCG_COND_NE, ll, shamt, zero, ll, zero);
tcg_gen_or_tl(h0, ll, lr);
tcg_gen_sari_tl(lr, src1h, 63);
tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, h1, h0);
tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, lr, h1);
tcg_temp_free(ls);
tcg_temp_free(rs);
tcg_temp_free(hs);
tcg_temp_free(ll);
tcg_temp_free(lr);
tcg_temp_free(h0);
tcg_temp_free(h1);
}
static bool trans_sra(DisasContext *ctx, arg_sra *a)
{
return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, gen_sra_i128);
}
static bool trans_xor(DisasContext *ctx, arg_xor *a)
{
return gen_logic(ctx, a, tcg_gen_xor_tl);
}
static bool trans_or(DisasContext *ctx, arg_or *a)
{
return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl);
return gen_logic(ctx, a, tcg_gen_or_tl);
}
static bool trans_and(DisasContext *ctx, arg_and *a)
{
return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl);
return gen_logic(ctx, a, tcg_gen_and_tl);
}
static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl);
return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, NULL);
}
static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl);
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, NULL);
}
static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw);
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw, NULL);
}
static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw);
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw, NULL);
}
static bool trans_sllid(DisasContext *ctx, arg_sllid *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, NULL);
}
static bool trans_srlid(DisasContext *ctx, arg_srlid *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shri_tl, NULL);
}
static bool trans_sraid(DisasContext *ctx, arg_sraid *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_sari_tl, NULL);
}
static bool trans_addw(DisasContext *ctx, arg_addw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, NULL);
}
static bool trans_subw(DisasContext *ctx, arg_subw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, NULL);
}
static bool trans_sllw(DisasContext *ctx, arg_sllw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl);
return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, NULL);
}
static bool trans_srlw(DisasContext *ctx, arg_srlw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl);
return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, NULL);
}
static bool trans_sraw(DisasContext *ctx, arg_sraw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
ctx->ol = MXL_RV32;
return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl);
return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL);
}
static bool trans_slld(DisasContext *ctx, arg_slld *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, NULL);
}
static bool trans_srld(DisasContext *ctx, arg_srld *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, NULL);
}
static bool trans_srad(DisasContext *ctx, arg_srad *a)
{
REQUIRE_128BIT(ctx);
ctx->ol = MXL_RV64;
return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL);
}
static bool trans_fence(DisasContext *ctx, arg_fence *a)
{
/* FENCE is a full memory barrier. */
@ -474,20 +881,78 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask)
return do_csr_post(ctx);
}
static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
{
TCGv destl = dest_gpr(ctx, rd);
TCGv desth = dest_gprh(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_csrr_i128(destl, cpu_env, csr);
tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
gen_set_gpr128(ctx, rd, destl, desth);
return do_csr_post(ctx);
}
static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
{
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_csrw_i128(cpu_env, csr, srcl, srch);
return do_csr_post(ctx);
}
static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
TCGv srcl, TCGv srch, TCGv maskl, TCGv maskh)
{
TCGv destl = dest_gpr(ctx, rd);
TCGv desth = dest_gprh(ctx, rd);
TCGv_i32 csr = tcg_constant_i32(rc);
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh);
tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh));
gen_set_gpr128(ctx, rd, destl, desth);
return do_csr_post(ctx);
}
static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
{
TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
if (get_xl(ctx) < MXL_RV128) {
TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
/*
* If rd == 0, the insn shall not read the csr, nor cause any of the
* side effects that might occur on a csr read.
*/
if (a->rd == 0) {
return do_csrw(ctx, a->csr, src);
/*
* If rd == 0, the insn shall not read the csr, nor cause any of the
* side effects that might occur on a csr read.
*/
if (a->rd == 0) {
return do_csrw(ctx, a->csr, src);
}
TCGv mask = tcg_constant_tl(-1);
return do_csrrw(ctx, a->rd, a->csr, src, mask);
} else {
TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv srch = get_gprh(ctx, a->rs1);
/*
* If rd == 0, the insn shall not read the csr, nor cause any of the
* side effects that might occur on a csr read.
*/
if (a->rd == 0) {
return do_csrw_i128(ctx, a->csr, srcl, srch);
}
TCGv mask = tcg_constant_tl(-1);
return do_csrrw_i128(ctx, a->rd, a->csr, srcl, srch, mask, mask);
}
TCGv mask = tcg_constant_tl(-1);
return do_csrrw(ctx, a->rd, a->csr, src, mask);
}
static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
@ -499,13 +964,24 @@ static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
* a zero value, the instruction will still attempt to write the
* unmodified value back to the csr and will cause side effects.
*/
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
if (get_xl(ctx) < MXL_RV128) {
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
TCGv ones = tcg_constant_tl(-1);
TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
return do_csrrw(ctx, a->rd, a->csr, ones, mask);
TCGv ones = tcg_constant_tl(-1);
TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
return do_csrrw(ctx, a->rd, a->csr, ones, mask);
} else {
if (a->rs1 == 0) {
return do_csrr_i128(ctx, a->rd, a->csr);
}
TCGv ones = tcg_constant_tl(-1);
TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
TCGv maskh = get_gprh(ctx, a->rs1);
return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, maskl, maskh);
}
}
static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
@ -517,28 +993,54 @@ static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
* a zero value, the instruction will still attempt to write the
* unmodified value back to the csr and will cause side effects.
*/
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
if (get_xl(ctx) < MXL_RV128) {
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
} else {
if (a->rs1 == 0) {
return do_csrr_i128(ctx, a->rd, a->csr);
}
TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
TCGv maskh = get_gprh(ctx, a->rs1);
return do_csrrw_i128(ctx, a->rd, a->csr,
ctx->zero, ctx->zero, maskl, maskh);
}
}
static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a)
{
TCGv src = tcg_constant_tl(a->rs1);
if (get_xl(ctx) < MXL_RV128) {
TCGv src = tcg_constant_tl(a->rs1);
/*
* If rd == 0, the insn shall not read the csr, nor cause any of the
* side effects that might occur on a csr read.
*/
if (a->rd == 0) {
return do_csrw(ctx, a->csr, src);
/*
* If rd == 0, the insn shall not read the csr, nor cause any of the
* side effects that might occur on a csr read.
*/
if (a->rd == 0) {
return do_csrw(ctx, a->csr, src);
}
TCGv mask = tcg_constant_tl(-1);
return do_csrrw(ctx, a->rd, a->csr, src, mask);
} else {
TCGv src = tcg_constant_tl(a->rs1);
/*
* If rd == 0, the insn shall not read the csr, nor cause any of the
* side effects that might occur on a csr read.
*/
if (a->rd == 0) {
return do_csrw_i128(ctx, a->csr, src, ctx->zero);
}
TCGv mask = tcg_constant_tl(-1);
return do_csrrw_i128(ctx, a->rd, a->csr, src, ctx->zero, mask, mask);
}
TCGv mask = tcg_constant_tl(-1);
return do_csrrw(ctx, a->rd, a->csr, src, mask);
}
static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a)
@ -550,16 +1052,26 @@ static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a)
* a zero value, the instruction will still attempt to write the
* unmodified value back to the csr and will cause side effects.
*/
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
if (get_xl(ctx) < MXL_RV128) {
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
TCGv ones = tcg_constant_tl(-1);
TCGv mask = tcg_constant_tl(a->rs1);
return do_csrrw(ctx, a->rd, a->csr, ones, mask);
TCGv ones = tcg_constant_tl(-1);
TCGv mask = tcg_constant_tl(a->rs1);
return do_csrrw(ctx, a->rd, a->csr, ones, mask);
} else {
if (a->rs1 == 0) {
return do_csrr_i128(ctx, a->rd, a->csr);
}
TCGv ones = tcg_constant_tl(-1);
TCGv mask = tcg_constant_tl(a->rs1);
return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, mask, ctx->zero);
}
}
static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a)
static bool trans_csrrci(DisasContext *ctx, arg_csrrci * a)
{
/*
* If rs1 == 0, the insn shall not write to the csr at all, nor
@ -568,10 +1080,20 @@ static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a)
* a zero value, the instruction will still attempt to write the
* unmodified value back to the csr and will cause side effects.
*/
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
if (get_xl(ctx) < MXL_RV128) {
if (a->rs1 == 0) {
return do_csrr(ctx, a->rd, a->csr);
}
TCGv mask = tcg_constant_tl(a->rs1);
return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
TCGv mask = tcg_constant_tl(a->rs1);
return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
} else {
if (a->rs1 == 0) {
return do_csrr_i128(ctx, a->rd, a->csr);
}
TCGv mask = tcg_constant_tl(a->rs1);
return do_csrrw_i128(ctx, a->rd, a->csr,
ctx->zero, ctx->zero, mask, ctx->zero);
}
}

View file

@ -18,11 +18,79 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
static void gen_mulhu_i128(TCGv r2, TCGv r3, TCGv al, TCGv ah, TCGv bl, TCGv bh)
{
TCGv tmpl = tcg_temp_new();
TCGv tmph = tcg_temp_new();
TCGv r0 = tcg_temp_new();
TCGv r1 = tcg_temp_new();
TCGv zero = tcg_constant_tl(0);
tcg_gen_mulu2_tl(r0, r1, al, bl);
tcg_gen_mulu2_tl(tmpl, tmph, al, bh);
tcg_gen_add2_tl(r1, r2, r1, zero, tmpl, tmph);
tcg_gen_mulu2_tl(tmpl, tmph, ah, bl);
tcg_gen_add2_tl(r1, tmph, r1, r2, tmpl, tmph);
/* Overflow detection into r3 */
tcg_gen_setcond_tl(TCG_COND_LTU, r3, tmph, r2);
tcg_gen_mov_tl(r2, tmph);
tcg_gen_mulu2_tl(tmpl, tmph, ah, bh);
tcg_gen_add2_tl(r2, r3, r2, r3, tmpl, tmph);
tcg_temp_free(tmpl);
tcg_temp_free(tmph);
}
static void gen_mul_i128(TCGv rl, TCGv rh,
TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h)
{
TCGv tmpl = tcg_temp_new();
TCGv tmph = tcg_temp_new();
TCGv tmpx = tcg_temp_new();
TCGv zero = tcg_constant_tl(0);
tcg_gen_mulu2_tl(rl, rh, rs1l, rs2l);
tcg_gen_mulu2_tl(tmpl, tmph, rs1l, rs2h);
tcg_gen_add2_tl(rh, tmpx, rh, zero, tmpl, tmph);
tcg_gen_mulu2_tl(tmpl, tmph, rs1h, rs2l);
tcg_gen_add2_tl(rh, tmph, rh, tmpx, tmpl, tmph);
tcg_temp_free(tmpl);
tcg_temp_free(tmph);
tcg_temp_free(tmpx);
}
static bool trans_mul(DisasContext *ctx, arg_mul *a)
{
REQUIRE_EXT(ctx, RVM);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, gen_mul_i128);
}
static void gen_mulh_i128(TCGv rl, TCGv rh,
TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h)
{
TCGv t0l = tcg_temp_new();
TCGv t0h = tcg_temp_new();
TCGv t1l = tcg_temp_new();
TCGv t1h = tcg_temp_new();
gen_mulhu_i128(rl, rh, rs1l, rs1h, rs2l, rs2h);
tcg_gen_sari_tl(t0h, rs1h, 63);
tcg_gen_and_tl(t0l, t0h, rs2l);
tcg_gen_and_tl(t0h, t0h, rs2h);
tcg_gen_sari_tl(t1h, rs2h, 63);
tcg_gen_and_tl(t1l, t1h, rs1l);
tcg_gen_and_tl(t1h, t1h, rs1h);
tcg_gen_sub2_tl(t0l, t0h, rl, rh, t0l, t0h);
tcg_gen_sub2_tl(rl, rh, t0l, t0h, t1l, t1h);
tcg_temp_free(t0l);
tcg_temp_free(t0h);
tcg_temp_free(t1l);
tcg_temp_free(t1h);
}
static void gen_mulh(TCGv ret, TCGv s1, TCGv s2)
@ -42,7 +110,25 @@ static void gen_mulh_w(TCGv ret, TCGv s1, TCGv s2)
static bool trans_mulh(DisasContext *ctx, arg_mulh *a)
{
REQUIRE_EXT(ctx, RVM);
return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w);
return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w,
gen_mulh_i128);
}
static void gen_mulhsu_i128(TCGv rl, TCGv rh,
TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h)
{
TCGv t0l = tcg_temp_new();
TCGv t0h = tcg_temp_new();
gen_mulhu_i128(rl, rh, rs1l, rs1h, rs2l, rs2h);
tcg_gen_sari_tl(t0h, rs1h, 63);
tcg_gen_and_tl(t0l, t0h, rs2l);
tcg_gen_and_tl(t0h, t0h, rs2h);
tcg_gen_sub2_tl(rl, rh, rl, rh, t0l, t0h);
tcg_temp_free(t0l);
tcg_temp_free(t0h);
}
static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2)
@ -76,7 +162,8 @@ static void gen_mulhsu_w(TCGv ret, TCGv arg1, TCGv arg2)
static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a)
{
REQUIRE_EXT(ctx, RVM);
return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w);
return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w,
gen_mulhsu_i128);
}
static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2)
@ -91,7 +178,15 @@ static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a)
{
REQUIRE_EXT(ctx, RVM);
/* gen_mulh_w works for either sign as input. */
return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w);
return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w,
gen_mulhu_i128);
}
static void gen_div_i128(TCGv rdl, TCGv rdh,
TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h)
{
gen_helper_divs_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h);
tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh));
}
static void gen_div(TCGv ret, TCGv source1, TCGv source2)
@ -130,7 +225,14 @@ static void gen_div(TCGv ret, TCGv source1, TCGv source2)
static bool trans_div(DisasContext *ctx, arg_div *a)
{
REQUIRE_EXT(ctx, RVM);
return gen_arith(ctx, a, EXT_SIGN, gen_div);
return gen_arith(ctx, a, EXT_SIGN, gen_div, gen_div_i128);
}
static void gen_divu_i128(TCGv rdl, TCGv rdh,
TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h)
{
gen_helper_divu_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h);
tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh));
}
static void gen_divu(TCGv ret, TCGv source1, TCGv source2)
@ -158,7 +260,14 @@ static void gen_divu(TCGv ret, TCGv source1, TCGv source2)
static bool trans_divu(DisasContext *ctx, arg_divu *a)
{
REQUIRE_EXT(ctx, RVM);
return gen_arith(ctx, a, EXT_ZERO, gen_divu);
return gen_arith(ctx, a, EXT_ZERO, gen_divu, gen_divu_i128);
}
static void gen_rem_i128(TCGv rdl, TCGv rdh,
TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h)
{
gen_helper_rems_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h);
tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh));
}
static void gen_rem(TCGv ret, TCGv source1, TCGv source2)
@ -199,7 +308,14 @@ static void gen_rem(TCGv ret, TCGv source1, TCGv source2)
static bool trans_rem(DisasContext *ctx, arg_rem *a)
{
REQUIRE_EXT(ctx, RVM);
return gen_arith(ctx, a, EXT_SIGN, gen_rem);
return gen_arith(ctx, a, EXT_SIGN, gen_rem, gen_rem_i128);
}
static void gen_remu_i128(TCGv rdl, TCGv rdh,
TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h)
{
gen_helper_remu_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h);
tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh));
}
static void gen_remu(TCGv ret, TCGv source1, TCGv source2)
@ -227,45 +343,85 @@ static void gen_remu(TCGv ret, TCGv source1, TCGv source2)
static bool trans_remu(DisasContext *ctx, arg_remu *a)
{
REQUIRE_EXT(ctx, RVM);
return gen_arith(ctx, a, EXT_ZERO, gen_remu);
return gen_arith(ctx, a, EXT_ZERO, gen_remu, gen_remu_i128);
}
static bool trans_mulw(DisasContext *ctx, arg_mulw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV32;
return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL);
}
static bool trans_divw(DisasContext *ctx, arg_divw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV32;
return gen_arith(ctx, a, EXT_SIGN, gen_div);
return gen_arith(ctx, a, EXT_SIGN, gen_div, NULL);
}
static bool trans_divuw(DisasContext *ctx, arg_divuw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV32;
return gen_arith(ctx, a, EXT_ZERO, gen_divu);
return gen_arith(ctx, a, EXT_ZERO, gen_divu, NULL);
}
static bool trans_remw(DisasContext *ctx, arg_remw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV32;
return gen_arith(ctx, a, EXT_SIGN, gen_rem);
return gen_arith(ctx, a, EXT_SIGN, gen_rem, NULL);
}
static bool trans_remuw(DisasContext *ctx, arg_remuw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_64_OR_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV32;
return gen_arith(ctx, a, EXT_ZERO, gen_remu);
return gen_arith(ctx, a, EXT_ZERO, gen_remu, NULL);
}
static bool trans_muld(DisasContext *ctx, arg_muld *a)
{
REQUIRE_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV64;
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_mul_tl, NULL);
}
static bool trans_divd(DisasContext *ctx, arg_divd *a)
{
REQUIRE_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV64;
return gen_arith(ctx, a, EXT_SIGN, gen_div, NULL);
}
static bool trans_divud(DisasContext *ctx, arg_divud *a)
{
REQUIRE_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV64;
return gen_arith(ctx, a, EXT_ZERO, gen_divu, NULL);
}
static bool trans_remd(DisasContext *ctx, arg_remd *a)
{
REQUIRE_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV64;
return gen_arith(ctx, a, EXT_SIGN, gen_rem, NULL);
}
static bool trans_remud(DisasContext *ctx, arg_remud *a)
{
REQUIRE_128BIT(ctx);
REQUIRE_EXT(ctx, RVM);
ctx->ol = MXL_RV64;
return gen_arith(ctx, a, EXT_ZERO, gen_remu, NULL);
}

View file

@ -2254,7 +2254,8 @@ GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check)
static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
require_rvf(s) &&
require_scale_rvf(s) &&
(s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
}
@ -2292,7 +2293,8 @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
require_rvf(s) &&
require_scale_rvf(s) &&
(s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_ds(s, a->rd, a->rs2, a->vm);
}
@ -2321,7 +2323,8 @@ GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
require_rvf(s) &&
require_scale_rvf(s) &&
(s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
}
@ -2359,7 +2362,8 @@ GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
require_rvf(s) &&
require_scale_rvf(s) &&
(s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dd(s, a->rd, a->rs2, a->vm);
}
@ -2609,16 +2613,27 @@ GEN_OPFV_CVT_TRANS(vfcvt_rtz_x_f_v, vfcvt_x_f_v, RISCV_FRM_RTZ)
static bool opfv_widen_check(DisasContext *s, arg_rmr *a)
{
return require_rvv(s) &&
require_scale_rvf(s) &&
(s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_ds(s, a->rd, a->rs2, a->vm);
}
#define GEN_OPFV_WIDEN_TRANS(NAME, HELPER, FRM) \
static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
{
return opfv_widen_check(s, a) &&
require_rvf(s);
}
static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
{
return opfv_widen_check(s, a) &&
require_scale_rvf(s) &&
(s->sew != MO_8);
}
#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
{ \
if (opfv_widen_check(s, a)) { \
if (CHECK(s, a)) { \
if (FRM != RISCV_FRM_DYN) { \
gen_set_rm(s, RISCV_FRM_DYN); \
} \
@ -2645,12 +2660,17 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
return false; \
}
GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, vfwcvt_xu_f_v, RISCV_FRM_DYN)
GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, vfwcvt_x_f_v, RISCV_FRM_DYN)
GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, vfwcvt_f_f_v, RISCV_FRM_DYN)
GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
RISCV_FRM_DYN)
GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
RISCV_FRM_DYN)
GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, opffv_widen_check, vfwcvt_f_f_v,
RISCV_FRM_DYN)
/* Reuse the helper functions from vfwcvt.xu.f.v and vfwcvt.x.f.v */
GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, vfwcvt_xu_f_v, RISCV_FRM_RTZ)
GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, vfwcvt_x_f_v, RISCV_FRM_RTZ)
GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
RISCV_FRM_RTZ)
GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
RISCV_FRM_RTZ)
static bool opfxv_widen_check(DisasContext *s, arg_rmr *a)
{
@ -2699,17 +2719,29 @@ GEN_OPFXV_WIDEN_TRANS(vfwcvt_f_x_v)
static bool opfv_narrow_check(DisasContext *s, arg_rmr *a)
{
return require_rvv(s) &&
require_rvf(s) &&
(s->sew != MO_64) &&
vext_check_isa_ill(s) &&
/* OPFV narrowing instructions ignore vs1 check */
vext_check_sd(s, a->rd, a->rs2, a->vm);
}
#define GEN_OPFV_NARROW_TRANS(NAME, HELPER, FRM) \
static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
{
return opfv_narrow_check(s, a) &&
require_rvf(s) &&
(s->sew != MO_64);
}
static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
{
return opfv_narrow_check(s, a) &&
require_scale_rvf(s) &&
(s->sew != MO_8);
}
#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \
static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
{ \
if (opfv_narrow_check(s, a)) { \
if (CHECK(s, a)) { \
if (FRM != RISCV_FRM_DYN) { \
gen_set_rm(s, RISCV_FRM_DYN); \
} \
@ -2736,11 +2768,15 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
return false; \
}
GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, vfncvt_f_xu_w, RISCV_FRM_DYN)
GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, vfncvt_f_x_w, RISCV_FRM_DYN)
GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, vfncvt_f_f_w, RISCV_FRM_DYN)
GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, opfxv_narrow_check, vfncvt_f_xu_w,
RISCV_FRM_DYN)
GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, opfxv_narrow_check, vfncvt_f_x_w,
RISCV_FRM_DYN)
GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
RISCV_FRM_DYN)
/* Reuse the helper function from vfncvt.f.f.w */
GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, vfncvt_f_f_w, RISCV_FRM_ROD)
GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
RISCV_FRM_ROD)
static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a)
{

109
target/riscv/m128_helper.c Normal file
View file

@ -0,0 +1,109 @@
/*
* RISC-V Emulation Helpers for QEMU.
*
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
* Copyright (c) 2017-2018 SiFive, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "qemu/main-loop.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
target_ulong HELPER(divu_i128)(CPURISCVState *env,
target_ulong ul, target_ulong uh,
target_ulong vl, target_ulong vh)
{
target_ulong ql, qh;
Int128 q;
if (vl == 0 && vh == 0) { /* Handle special behavior on div by zero */
ql = ~0x0;
qh = ~0x0;
} else {
q = int128_divu(int128_make128(ul, uh), int128_make128(vl, vh));
ql = int128_getlo(q);
qh = int128_gethi(q);
}
env->retxh = qh;
return ql;
}
target_ulong HELPER(remu_i128)(CPURISCVState *env,
target_ulong ul, target_ulong uh,
target_ulong vl, target_ulong vh)
{
target_ulong rl, rh;
Int128 r;
if (vl == 0 && vh == 0) {
rl = ul;
rh = uh;
} else {
r = int128_remu(int128_make128(ul, uh), int128_make128(vl, vh));
rl = int128_getlo(r);
rh = int128_gethi(r);
}
env->retxh = rh;
return rl;
}
target_ulong HELPER(divs_i128)(CPURISCVState *env,
target_ulong ul, target_ulong uh,
target_ulong vl, target_ulong vh)
{
target_ulong qh, ql;
Int128 q;
if (vl == 0 && vh == 0) { /* Div by zero check */
ql = ~0x0;
qh = ~0x0;
} else if (uh == (1ULL << (TARGET_LONG_BITS - 1)) && ul == 0 &&
vh == ~0x0 && vl == ~0x0) {
/* Signed div overflow check (-2**127 / -1) */
ql = ul;
qh = uh;
} else {
q = int128_divs(int128_make128(ul, uh), int128_make128(vl, vh));
ql = int128_getlo(q);
qh = int128_gethi(q);
}
env->retxh = qh;
return ql;
}
target_ulong HELPER(rems_i128)(CPURISCVState *env,
target_ulong ul, target_ulong uh,
target_ulong vl, target_ulong vh)
{
target_ulong rh, rl;
Int128 r;
if (vl == 0 && vh == 0) {
rl = ul;
rh = uh;
} else {
r = int128_rems(int128_make128(ul, uh), int128_make128(vl, vh));
rl = int128_getlo(r);
rh = int128_gethi(r);
}
env->retxh = rh;
return rl;
}

View file

@ -164,6 +164,27 @@ static const VMStateDescription vmstate_pointermasking = {
}
};
static bool rv128_needed(void *opaque)
{
RISCVCPU *cpu = opaque;
CPURISCVState *env = &cpu->env;
return env->misa_mxl_max == MXL_RV128;
}
static const VMStateDescription vmstate_rv128 = {
.name = "cpu/rv128",
.version_id = 1,
.minimum_version_id = 1,
.needed = rv128_needed,
.fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
VMSTATE_UINT64(env.mscratchh, RISCVCPU),
VMSTATE_UINT64(env.sscratchh, RISCVCPU),
VMSTATE_END_OF_LIST()
}
};
const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
.version_id = 3,
@ -218,6 +239,7 @@ const VMStateDescription vmstate_riscv_cpu = {
&vmstate_hyper,
&vmstate_vector,
&vmstate_pointermasking,
&vmstate_rv128,
NULL
}
};

View file

@ -18,6 +18,7 @@ riscv_ss.add(files(
'vector_helper.c',
'bitmanip_helper.c',
'translate.c',
'm128_helper.c'
))
riscv_softmmu_ss = ss.source_set()

View file

@ -69,6 +69,50 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
return val;
}
target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
{
Int128 rv = int128_zero();
RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
int128_zero(),
int128_zero());
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
}
env->retxh = int128_gethi(rv);
return int128_getlo(rv);
}
void helper_csrw_i128(CPURISCVState *env, int csr,
target_ulong srcl, target_ulong srch)
{
RISCVException ret = riscv_csrrw_i128(env, csr, NULL,
int128_make128(srcl, srch),
UINT128_MAX);
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
}
}
target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
target_ulong srcl, target_ulong srch,
target_ulong maskl, target_ulong maskh)
{
Int128 rv = int128_zero();
RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
int128_make128(srcl, srch),
int128_make128(maskl, maskh));
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
}
env->retxh = int128_gethi(rv);
return int128_getlo(rv);
}
#ifndef CONFIG_USER_ONLY
target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
@ -146,7 +190,8 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
uint64_t mstatus = env->mstatus;
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
if (!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}

View file

@ -33,7 +33,7 @@
#include "internals.h"
/* global register indices */
static TCGv cpu_gpr[32], cpu_pc, cpu_vl, cpu_vstart;
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
static TCGv load_res;
static TCGv load_val;
@ -59,6 +59,7 @@ typedef struct DisasContext {
/* pc_succ_insn points to the instruction following base.pc_next */
target_ulong pc_succ_insn;
target_ulong priv_ver;
RISCVMXL misa_mxl_max;
RISCVMXL xl;
uint32_t misa_ext;
uint32_t opcode;
@ -141,6 +142,13 @@ static inline int get_olen(DisasContext *ctx)
return 16 << get_ol(ctx);
}
/* The maximum register length */
#ifdef TARGET_RISCV32
#define get_xl_max(ctx) MXL_RV32
#else
#define get_xl_max(ctx) ((ctx)->misa_mxl_max)
#endif
/*
* RISC-V requires NaN-boxing of narrower width floating point values.
* This applies when a 32-bit value is assigned to a 64-bit FP register.
@ -200,6 +208,9 @@ static void generate_exception_mtval(DisasContext *ctx, int excp)
static void gen_exception_illegal(DisasContext *ctx)
{
tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
offsetof(CPURISCVState, bins));
generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
}
@ -260,6 +271,7 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext)
}
break;
case MXL_RV64:
case MXL_RV128:
break;
default:
g_assert_not_reached();
@ -267,6 +279,15 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext)
return cpu_gpr[reg_num];
}
static TCGv get_gprh(DisasContext *ctx, int reg_num)
{
assert(get_xl(ctx) == MXL_RV128);
if (reg_num == 0) {
return ctx->zero;
}
return cpu_gprh[reg_num];
}
static TCGv dest_gpr(DisasContext *ctx, int reg_num)
{
if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) {
@ -275,6 +296,14 @@ static TCGv dest_gpr(DisasContext *ctx, int reg_num)
return cpu_gpr[reg_num];
}
static TCGv dest_gprh(DisasContext *ctx, int reg_num)
{
if (reg_num == 0) {
return temp_new(ctx);
}
return cpu_gprh[reg_num];
}
static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
{
if (reg_num != 0) {
@ -283,11 +312,46 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
break;
case MXL_RV64:
case MXL_RV128:
tcg_gen_mov_tl(cpu_gpr[reg_num], t);
break;
default:
g_assert_not_reached();
}
if (get_xl_max(ctx) == MXL_RV128) {
tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63);
}
}
}
static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
{
if (reg_num != 0) {
switch (get_ol(ctx)) {
case MXL_RV32:
tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
break;
case MXL_RV64:
case MXL_RV128:
tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
break;
default:
g_assert_not_reached();
}
if (get_xl_max(ctx) == MXL_RV128) {
tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
}
}
}
static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
{
assert(get_ol(ctx) == MXL_RV128);
if (reg_num != 0) {
tcg_gen_mov_tl(cpu_gpr[reg_num], rl);
tcg_gen_mov_tl(cpu_gprh[reg_num], rh);
}
}
@ -443,10 +507,22 @@ EX_SH(12)
} \
} while (0)
#define REQUIRE_64BIT(ctx) do { \
if (get_xl(ctx) < MXL_RV64) { \
return false; \
} \
#define REQUIRE_64BIT(ctx) do { \
if (get_xl(ctx) != MXL_RV64) { \
return false; \
} \
} while (0)
#define REQUIRE_128BIT(ctx) do { \
if (get_xl(ctx) != MXL_RV128) { \
return false; \
} \
} while (0)
#define REQUIRE_64_OR_128BIT(ctx) do { \
if (get_xl(ctx) == MXL_RV32) { \
return false; \
} \
} while (0)
static int ex_rvc_register(DisasContext *ctx, int reg)
@ -463,62 +539,146 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm)
/* Include the auto-generated decoder for 32 bit insn */
#include "decode-insn32.c.inc"
static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
void (*func)(TCGv, TCGv, target_long))
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
func(dest, src1, a->imm);
if (get_xl(ctx) == MXL_RV128) {
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv desth = dest_gprh(ctx, a->rd);
func(desth, src1h, -(a->imm < 0));
gen_set_gpr128(ctx, a->rd, dest, desth);
} else {
gen_set_gpr(ctx, a->rd, dest);
}
return true;
}
static bool gen_logic(DisasContext *ctx, arg_r *a,
void (*func)(TCGv, TCGv, TCGv))
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
func(dest, src1, src2);
if (get_xl(ctx) == MXL_RV128) {
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv src2h = get_gprh(ctx, a->rs2);
TCGv desth = dest_gprh(ctx, a->rd);
func(desth, src1h, src2h);
gen_set_gpr128(ctx, a->rd, dest, desth);
} else {
gen_set_gpr(ctx, a->rd, dest);
}
return true;
}
static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
void (*func)(TCGv, TCGv, target_long),
void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, ext);
func(dest, src1, a->imm);
if (get_ol(ctx) < MXL_RV128) {
func(dest, src1, a->imm);
gen_set_gpr(ctx, a->rd, dest);
} else {
if (f128 == NULL) {
return false;
}
gen_set_gpr(ctx, a->rd, dest);
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv desth = dest_gprh(ctx, a->rd);
f128(dest, desth, src1, src1h, a->imm);
gen_set_gpr128(ctx, a->rd, dest, desth);
}
return true;
}
static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
void (*func)(TCGv, TCGv, TCGv))
void (*func)(TCGv, TCGv, TCGv),
void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, ext);
TCGv src2 = tcg_constant_tl(a->imm);
func(dest, src1, src2);
if (get_ol(ctx) < MXL_RV128) {
func(dest, src1, src2);
gen_set_gpr(ctx, a->rd, dest);
} else {
if (f128 == NULL) {
return false;
}
gen_set_gpr(ctx, a->rd, dest);
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv src2h = tcg_constant_tl(-(a->imm < 0));
TCGv desth = dest_gprh(ctx, a->rd);
f128(dest, desth, src1, src1h, src2, src2h);
gen_set_gpr128(ctx, a->rd, dest, desth);
}
return true;
}
static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
void (*func)(TCGv, TCGv, TCGv))
void (*func)(TCGv, TCGv, TCGv),
void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, ext);
TCGv src2 = get_gpr(ctx, a->rs2, ext);
func(dest, src1, src2);
if (get_ol(ctx) < MXL_RV128) {
func(dest, src1, src2);
gen_set_gpr(ctx, a->rd, dest);
} else {
if (f128 == NULL) {
return false;
}
gen_set_gpr(ctx, a->rd, dest);
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv src2h = get_gprh(ctx, a->rs2);
TCGv desth = dest_gprh(ctx, a->rd);
f128(dest, desth, src1, src1h, src2, src2h);
gen_set_gpr128(ctx, a->rd, dest, desth);
}
return true;
}
static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
void (*f_tl)(TCGv, TCGv, TCGv),
void (*f_32)(TCGv, TCGv, TCGv))
void (*f_32)(TCGv, TCGv, TCGv),
void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
{
int olen = get_olen(ctx);
if (olen != TARGET_LONG_BITS) {
if (olen == 32) {
f_tl = f_32;
} else {
} else if (olen != 128) {
g_assert_not_reached();
}
}
return gen_arith(ctx, a, ext, f_tl);
return gen_arith(ctx, a, ext, f_tl, f_128);
}
static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
void (*func)(TCGv, TCGv, target_long))
void (*func)(TCGv, TCGv, target_long),
void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
{
TCGv dest, src1;
int max_len = get_olen(ctx);
@ -530,26 +690,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
dest = dest_gpr(ctx, a->rd);
src1 = get_gpr(ctx, a->rs1, ext);
func(dest, src1, a->shamt);
if (max_len < 128) {
func(dest, src1, a->shamt);
gen_set_gpr(ctx, a->rd, dest);
} else {
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv desth = dest_gprh(ctx, a->rd);
gen_set_gpr(ctx, a->rd, dest);
if (f128 == NULL) {
return false;
}
f128(dest, desth, src1, src1h, a->shamt);
gen_set_gpr128(ctx, a->rd, dest, desth);
}
return true;
}
static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
DisasExtend ext,
void (*f_tl)(TCGv, TCGv, target_long),
void (*f_32)(TCGv, TCGv, target_long))
void (*f_32)(TCGv, TCGv, target_long),
void (*f_128)(TCGv, TCGv, TCGv, TCGv,
target_long))
{
int olen = get_olen(ctx);
if (olen != TARGET_LONG_BITS) {
if (olen == 32) {
f_tl = f_32;
} else {
} else if (olen != 128) {
g_assert_not_reached();
}
}
return gen_shift_imm_fn(ctx, a, ext, f_tl);
return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
}
static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
@ -573,34 +745,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
}
static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
void (*func)(TCGv, TCGv, TCGv))
void (*func)(TCGv, TCGv, TCGv),
void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, ext);
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
TCGv ext2 = tcg_temp_new();
int max_len = get_olen(ctx);
tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
func(dest, src1, ext2);
tcg_gen_andi_tl(ext2, src2, max_len - 1);
gen_set_gpr(ctx, a->rd, dest);
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, ext);
if (max_len < 128) {
func(dest, src1, ext2);
gen_set_gpr(ctx, a->rd, dest);
} else {
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv desth = dest_gprh(ctx, a->rd);
if (f128 == NULL) {
return false;
}
f128(dest, desth, src1, src1h, ext2);
gen_set_gpr128(ctx, a->rd, dest, desth);
}
tcg_temp_free(ext2);
return true;
}
static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
void (*f_tl)(TCGv, TCGv, TCGv),
void (*f_32)(TCGv, TCGv, TCGv))
void (*f_32)(TCGv, TCGv, TCGv),
void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv))
{
int olen = get_olen(ctx);
if (olen != TARGET_LONG_BITS) {
if (olen == 32) {
f_tl = f_32;
} else {
} else if (olen != 128) {
g_assert_not_reached();
}
}
return gen_shift(ctx, a, ext, f_tl);
return gen_shift(ctx, a, ext, f_tl, f_128);
}
static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
@ -662,6 +849,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
if (!has_ext(ctx, RVC)) {
gen_exception_illegal(ctx);
} else {
ctx->opcode = opcode;
ctx->pc_succ_insn = ctx->base.pc_next + 2;
if (!decode_insn16(ctx, opcode)) {
gen_exception_illegal(ctx);
@ -672,6 +860,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
opcode32 = deposit32(opcode32, 16, 16,
translator_lduw(env, &ctx->base,
ctx->base.pc_next + 2));
ctx->opcode = opcode32;
ctx->pc_succ_insn = ctx->base.pc_next + 4;
if (!decode_insn32(ctx, opcode32)) {
gen_exception_illegal(ctx);
@ -715,6 +904,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
ctx->vstart = env->vstart;
ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
ctx->misa_mxl_max = env->misa_mxl_max;
ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
ctx->cs = cs;
ctx->ntemp = 0;
@ -819,10 +1009,13 @@ void riscv_translate_init(void)
* unless you specifically block reads/writes to reg 0.
*/
cpu_gpr[0] = NULL;
cpu_gprh[0] = NULL;
for (i = 1; i < 32; i++) {
cpu_gpr[i] = tcg_global_mem_new(cpu_env,
offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
cpu_gprh[i] = tcg_global_mem_new(cpu_env,
offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
}
for (i = 0; i < 32; i++) {

View file

@ -45,7 +45,7 @@
D(0xeb6a, ASI, SIY, GIE, la1, i2, new, 0, asi, adds32, MO_TESL)
C(0xecd8, AHIK, RIE_d, DO, r3, i2, new, r1_32, add, adds32)
C(0xc208, AGFI, RIL_a, EI, r1, i2, r1, 0, add, adds64)
D(0xeb7a, AGSI, SIY, GIE, la1, i2, new, 0, asi, adds64, MO_TEQ)
D(0xeb7a, AGSI, SIY, GIE, la1, i2, new, 0, asi, adds64, MO_TEUQ)
C(0xecd9, AGHIK, RIE_d, DO, r3, i2, r1, 0, add, adds64)
/* ADD IMMEDIATE HIGH */
C(0xcc08, AIH, RIL_a, HW, r1_sr32, i2, new, r1_32h, add, adds32)
@ -76,7 +76,7 @@
/* ADD LOGICAL WITH SIGNED IMMEDIATE */
D(0xeb6e, ALSI, SIY, GIE, la1, i2_32u, new, 0, asi, addu32, MO_TEUL)
C(0xecda, ALHSIK, RIE_d, DO, r3_32u, i2_32u, new, r1_32, add, addu32)
D(0xeb7e, ALGSI, SIY, GIE, la1, i2, new, 0, asiu64, addu64, MO_TEQ)
D(0xeb7e, ALGSI, SIY, GIE, la1, i2, new, 0, asiu64, addu64, MO_TEUQ)
C(0xecdb, ALGHSIK, RIE_d, DO, r3, i2, r1, 0, addu64, addu64)
/* ADD LOGICAL WITH SIGNED IMMEDIATE HIGH */
C(0xcc0a, ALSIH, RIL_a, HW, r1_sr32, i2_32u, new, r1_32h, add, addu32)
@ -269,10 +269,10 @@
/* COMPARE AND SWAP */
D(0xba00, CS, RS_a, Z, r3_32u, r1_32u, new, r1_32, cs, 0, MO_TEUL)
D(0xeb14, CSY, RSY_a, LD, r3_32u, r1_32u, new, r1_32, cs, 0, MO_TEUL)
D(0xeb30, CSG, RSY_a, Z, r3_o, r1_o, new, r1, cs, 0, MO_TEQ)
D(0xeb30, CSG, RSY_a, Z, r3_o, r1_o, new, r1, cs, 0, MO_TEUQ)
/* COMPARE DOUBLE AND SWAP */
D(0xbb00, CDS, RS_a, Z, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEQ)
D(0xeb31, CDSY, RSY_a, LD, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEQ)
D(0xbb00, CDS, RS_a, Z, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEUQ)
D(0xeb31, CDSY, RSY_a, LD, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEUQ)
C(0xeb3e, CDSG, RSY_a, Z, 0, 0, 0, 0, cdsg, 0)
/* COMPARE AND SWAP AND STORE */
C(0xc802, CSST, SSF, CASS, la1, a2, 0, 0, csst, 0)
@ -436,19 +436,19 @@
C(0xc000, LARL, RIL_b, Z, 0, ri2, 0, r1, mov2, 0)
/* LOAD AND ADD */
D(0xebf8, LAA, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, laa, adds32, MO_TESL)
D(0xebe8, LAAG, RSY_a, ILA, r3, a2, new, in2_r1, laa, adds64, MO_TEQ)
D(0xebe8, LAAG, RSY_a, ILA, r3, a2, new, in2_r1, laa, adds64, MO_TEUQ)
/* LOAD AND ADD LOGICAL */
D(0xebfa, LAAL, RSY_a, ILA, r3_32u, a2, new, in2_r1_32, laa, addu32, MO_TEUL)
D(0xebea, LAALG, RSY_a, ILA, r3, a2, new, in2_r1, laa, addu64, MO_TEQ)
D(0xebea, LAALG, RSY_a, ILA, r3, a2, new, in2_r1, laa, addu64, MO_TEUQ)
/* LOAD AND AND */
D(0xebf4, LAN, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, lan, nz32, MO_TESL)
D(0xebe4, LANG, RSY_a, ILA, r3, a2, new, in2_r1, lan, nz64, MO_TEQ)
D(0xebe4, LANG, RSY_a, ILA, r3, a2, new, in2_r1, lan, nz64, MO_TEUQ)
/* LOAD AND EXCLUSIVE OR */
D(0xebf7, LAX, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, lax, nz32, MO_TESL)
D(0xebe7, LAXG, RSY_a, ILA, r3, a2, new, in2_r1, lax, nz64, MO_TEQ)
D(0xebe7, LAXG, RSY_a, ILA, r3, a2, new, in2_r1, lax, nz64, MO_TEUQ)
/* LOAD AND OR */
D(0xebf6, LAO, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, lao, nz32, MO_TESL)
D(0xebe6, LAOG, RSY_a, ILA, r3, a2, new, in2_r1, lao, nz64, MO_TEQ)
D(0xebe6, LAOG, RSY_a, ILA, r3, a2, new, in2_r1, lao, nz64, MO_TEUQ)
/* LOAD AND TEST */
C(0x1200, LTR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, s32)
C(0xb902, LTGR, RRE, Z, 0, r2_o, 0, r1, mov2, s64)
@ -565,7 +565,7 @@
C(0xebe0, LOCFH, RSY_b, LOC2, r1_sr32, m2_32u, new, r1_32h, loc, 0)
/* LOAD PAIR DISJOINT */
D(0xc804, LPD, SSF, ILA, 0, 0, new_P, r3_P32, lpd, 0, MO_TEUL)
D(0xc805, LPDG, SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEQ)
D(0xc805, LPDG, SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEUQ)
/* LOAD PAIR FROM QUADWORD */
C(0xe38f, LPQ, RXY_a, Z, 0, a2, r1_P, 0, lpq, 0)
/* LOAD POSITIVE */
@ -1279,7 +1279,7 @@
#ifndef CONFIG_USER_ONLY
/* COMPARE AND SWAP AND PURGE */
E(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL, IF_PRIV)
E(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ, IF_PRIV)
E(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEUQ, IF_PRIV)
/* DIAGNOSE (KVM hypercall) */
F(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0, IF_PRIV | IF_IO)
/* INSERT STORAGE KEY EXTENDED */
@ -1303,7 +1303,7 @@
F(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0, IF_PRIV)
/* LOAD USING REAL ADDRESS */
E(0xb24b, LURA, RRE, Z, 0, ra2, new, r1_32, lura, 0, MO_TEUL, IF_PRIV)
E(0xb905, LURAG, RRE, Z, 0, ra2, r1, 0, lura, 0, MO_TEQ, IF_PRIV)
E(0xb905, LURAG, RRE, Z, 0, ra2, r1, 0, lura, 0, MO_TEUQ, IF_PRIV)
/* MOVE TO PRIMARY */
F(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0, IF_PRIV)
/* MOVE TO SECONDARY */
@ -1357,7 +1357,7 @@
F(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0, IF_PRIV)
/* STORE USING REAL ADDRESS */
E(0xb246, STURA, RRE, Z, r1_o, ra2, 0, 0, stura, 0, MO_TEUL, IF_PRIV)
E(0xb925, STURG, RRE, Z, r1_o, ra2, 0, 0, stura, 0, MO_TEQ, IF_PRIV)
E(0xb925, STURG, RRE, Z, r1_o, ra2, 0, 0, stura, 0, MO_TEUQ, IF_PRIV)
/* TEST BLOCK */
F(0xb22c, TB, RRE, Z, 0, r2_o, 0, 0, testblock, 0, IF_PRIV)
/* TEST PROTECTION */

View file

@ -1895,7 +1895,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
if (parallel) {
#ifdef CONFIG_ATOMIC64
MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN, mem_idx);
MemOpIdx oi = make_memop_idx(MO_TEUQ | MO_ALIGN, mem_idx);
ov = cpu_atomic_cmpxchgq_be_mmu(env, a1, cv, nv, oi, ra);
#else
/* Note that we asserted !parallel above. */
@ -1970,7 +1970,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
cpu_stq_data_ra(env, a2 + 0, svh, ra);
cpu_stq_data_ra(env, a2 + 8, svl, ra);
} else if (HAVE_ATOMIC128) {
MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
MemOpIdx oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx);
Int128 sv = int128_make128(svl, svh);
cpu_atomic_sto_be_mmu(env, a2, sv, oi, ra);
} else {
@ -2494,7 +2494,7 @@ uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
assert(HAVE_ATOMIC128);
mem_idx = cpu_mmu_index(env, false);
oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx);
v = cpu_atomic_ldo_be_mmu(env, addr, oi, ra);
hi = int128_gethi(v);
lo = int128_getlo(v);
@ -2525,7 +2525,7 @@ void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
assert(HAVE_ATOMIC128);
mem_idx = cpu_mmu_index(env, false);
oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx);
v = int128_make128(low, high);
cpu_atomic_sto_be_mmu(env, addr, v, oi, ra);
}

View file

@ -3063,7 +3063,7 @@ static DisasJumpType op_lpswe(DisasContext *s, DisasOps *o)
t1 = tcg_temp_new_i64();
t2 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s),
MO_TEQ | MO_ALIGN_8);
MO_TEUQ | MO_ALIGN_8);
tcg_gen_addi_i64(o->in2, o->in2, 8);
tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
gen_helper_load_psw(cpu_env, t1, t2);
@ -4295,7 +4295,7 @@ static DisasJumpType op_stcke(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static DisasJumpType op_sck(DisasContext *s, DisasOps *o)
{
tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUQ | MO_ALIGN);
gen_helper_sck(cc_op, cpu_env, o->in1);
set_cc_static(s);
return DISAS_NEXT;
@ -5521,7 +5521,7 @@ static void wout_m1_64(DisasContext *s, DisasOps *o)
#ifndef CONFIG_USER_ONLY
static void wout_m1_64a(DisasContext *s, DisasOps *o)
{
tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUQ | MO_ALIGN);
}
#define SPEC_wout_m1_64a 0
#endif
@ -5997,7 +5997,7 @@ static void in2_m2_64w(DisasContext *s, DisasOps *o)
static void in2_m2_64a(DisasContext *s, DisasOps *o)
{
in2_a2(s, o);
tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEQ | MO_ALIGN);
tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUQ | MO_ALIGN);
}
#define SPEC_in2_m2_64a 0
#endif

View file

@ -424,9 +424,9 @@ static DisasJumpType op_vl(DisasContext *s, DisasOps *o)
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(t0, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_ld_i64(t0, o->addr1, get_mem_index(s), MO_TEUQ);
gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEUQ);
write_vec_element_i64(t0, get_field(s, v1), 0, ES_64);
write_vec_element_i64(t1, get_field(s, v1), 1, ES_64);
tcg_temp_free(t0);
@ -592,16 +592,16 @@ static DisasJumpType op_vlm(DisasContext *s, DisasOps *o)
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_addi_and_wrap_i64(s, t0, o->addr1, (v3 - v1) * 16 + 8);
tcg_gen_qemu_ld_i64(t0, t0, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_ld_i64(t0, t0, get_mem_index(s), MO_TEUQ);
for (;; v1++) {
tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEUQ);
write_vec_element_i64(t1, v1, 0, ES_64);
if (v1 == v3) {
break;
}
gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEUQ);
write_vec_element_i64(t1, v1, 1, ES_64);
gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
}
@ -950,10 +950,10 @@ static DisasJumpType op_vst(DisasContext *s, DisasOps *o)
gen_helper_probe_write_access(cpu_env, o->addr1, tmp);
read_vec_element_i64(tmp, get_field(s, v1), 0, ES_64);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ);
gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
read_vec_element_i64(tmp, get_field(s, v1), 1, ES_64);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ);
tcg_temp_free_i64(tmp);
return DISAS_NEXT;
}
@ -993,10 +993,10 @@ static DisasJumpType op_vstm(DisasContext *s, DisasOps *o)
for (;; v1++) {
read_vec_element_i64(tmp, v1, 0, ES_64);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ);
gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8);
read_vec_element_i64(tmp, v1, 1, ES_64);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ);
if (v1 == v3) {
break;
}

View file

@ -1010,7 +1010,7 @@ static void _decode_opc(DisasContext * ctx)
if (ctx->tbflags & FPSCR_SZ) {
TCGv_i64 fp = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp, XHACK(B7_4));
tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEQ);
tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEUQ);
tcg_temp_free_i64(fp);
} else {
tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
@ -1020,7 +1020,7 @@ static void _decode_opc(DisasContext * ctx)
CHECK_FPU_ENABLED
if (ctx->tbflags & FPSCR_SZ) {
TCGv_i64 fp = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ);
tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ);
gen_store_fpr64(ctx, fp, XHACK(B11_8));
tcg_temp_free_i64(fp);
} else {
@ -1031,7 +1031,7 @@ static void _decode_opc(DisasContext * ctx)
CHECK_FPU_ENABLED
if (ctx->tbflags & FPSCR_SZ) {
TCGv_i64 fp = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ);
tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ);
gen_store_fpr64(ctx, fp, XHACK(B11_8));
tcg_temp_free_i64(fp);
tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8);
@ -1048,7 +1048,7 @@ static void _decode_opc(DisasContext * ctx)
TCGv_i64 fp = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp, XHACK(B7_4));
tcg_gen_subi_i32(addr, REG(B11_8), 8);
tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ);
tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEUQ);
tcg_temp_free_i64(fp);
} else {
tcg_gen_subi_i32(addr, REG(B11_8), 4);
@ -1065,7 +1065,7 @@ static void _decode_opc(DisasContext * ctx)
tcg_gen_add_i32(addr, REG(B7_4), REG(0));
if (ctx->tbflags & FPSCR_SZ) {
TCGv_i64 fp = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEQ);
tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEUQ);
gen_store_fpr64(ctx, fp, XHACK(B11_8));
tcg_temp_free_i64(fp);
} else {
@ -1082,7 +1082,7 @@ static void _decode_opc(DisasContext * ctx)
if (ctx->tbflags & FPSCR_SZ) {
TCGv_i64 fp = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp, XHACK(B7_4));
tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ);
tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEUQ);
tcg_temp_free_i64(fp);
} else {
tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL);

View file

@ -2464,7 +2464,7 @@ static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn)
static void gen_ldf_asi(DisasContext *dc, TCGv addr,
int insn, int size, int rd)
{
DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ));
TCGv_i32 d32;
TCGv_i64 d64;
@ -2578,7 +2578,7 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr,
static void gen_stf_asi(DisasContext *dc, TCGv addr,
int insn, int size, int rd)
{
DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ));
DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ));
TCGv_i32 d32;
switch (da.type) {
@ -2660,7 +2660,7 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr,
static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
{
DisasASI da = get_asi(dc, insn, MO_TEQ);
DisasASI da = get_asi(dc, insn, MO_TEUQ);
TCGv_i64 hi = gen_dest_gpr(dc, rd);
TCGv_i64 lo = gen_dest_gpr(dc, rd + 1);
@ -2727,7 +2727,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
int insn, int rd)
{
DisasASI da = get_asi(dc, insn, MO_TEQ);
DisasASI da = get_asi(dc, insn, MO_TEUQ);
TCGv lo = gen_load_gpr(dc, rd + 1);
switch (da.type) {
@ -2787,7 +2787,7 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv cmpv,
int insn, int rd)
{
DisasASI da = get_asi(dc, insn, MO_TEQ);
DisasASI da = get_asi(dc, insn, MO_TEUQ);
TCGv oldv;
switch (da.type) {
@ -2817,7 +2817,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
TCGv lo = gen_dest_gpr(dc, rd | 1);
TCGv hi = gen_dest_gpr(dc, rd);
TCGv_i64 t64 = tcg_temp_new_i64();
DisasASI da = get_asi(dc, insn, MO_TEQ);
DisasASI da = get_asi(dc, insn, MO_TEUQ);
switch (da.type) {
case GET_ASI_EXCP:
@ -2830,7 +2830,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
default:
{
TCGv_i32 r_asi = tcg_const_i32(da.asi);
TCGv_i32 r_mop = tcg_const_i32(MO_Q);
TCGv_i32 r_mop = tcg_const_i32(MO_UQ);
save_state(dc);
gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop);
@ -2849,7 +2849,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd)
static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
int insn, int rd)
{
DisasASI da = get_asi(dc, insn, MO_TEQ);
DisasASI da = get_asi(dc, insn, MO_TEUQ);
TCGv lo = gen_load_gpr(dc, rd + 1);
TCGv_i64 t64 = tcg_temp_new_i64();
@ -2886,7 +2886,7 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
default:
{
TCGv_i32 r_asi = tcg_const_i32(da.asi);
TCGv_i32 r_mop = tcg_const_i32(MO_Q);
TCGv_i32 r_mop = tcg_const_i32(MO_UQ);
save_state(dc);
gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop);
@ -5479,7 +5479,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL);
break;
case 0x1b: /* V9 ldxa */
gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ);
break;
case 0x2d: /* V9 prefetch, no effect */
goto skip_move;
@ -5533,7 +5533,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if (rd == 1) {
TCGv_i64 t64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(t64, cpu_addr,
dc->mem_idx, MO_TEQ);
dc->mem_idx, MO_TEUQ);
gen_helper_ldxfsr(cpu_fsr, cpu_env, cpu_fsr, t64);
tcg_temp_free_i64(t64);
break;
@ -5549,11 +5549,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_address_mask(dc, cpu_addr);
cpu_src1_64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
MO_TEQ | MO_ALIGN_4);
MO_TEUQ | MO_ALIGN_4);
tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
cpu_src2_64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(cpu_src2_64, cpu_addr, dc->mem_idx,
MO_TEQ | MO_ALIGN_4);
MO_TEUQ | MO_ALIGN_4);
gen_store_fpr_Q(dc, rd, cpu_src1_64, cpu_src2_64);
tcg_temp_free_i64(cpu_src1_64);
tcg_temp_free_i64(cpu_src2_64);
@ -5562,7 +5562,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_address_mask(dc, cpu_addr);
cpu_dst_64 = gen_dest_fpr_D(dc, rd);
tcg_gen_qemu_ld_i64(cpu_dst_64, cpu_addr, dc->mem_idx,
MO_TEQ | MO_ALIGN_4);
MO_TEUQ | MO_ALIGN_4);
gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
default:
@ -5623,7 +5623,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx);
break;
case 0x1e: /* V9 stxa */
gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ);
gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ);
break;
#endif
default:
@ -5664,11 +5664,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
before performing the first write. */
cpu_src1_64 = gen_load_fpr_Q0(dc, rd);
tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
dc->mem_idx, MO_TEQ | MO_ALIGN_16);
dc->mem_idx, MO_TEUQ | MO_ALIGN_16);
tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
cpu_src2_64 = gen_load_fpr_Q1(dc, rd);
tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
dc->mem_idx, MO_TEQ);
dc->mem_idx, MO_TEUQ);
break;
#else /* !TARGET_SPARC64 */
/* stdfq, store floating point queue */
@ -5687,7 +5687,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
gen_address_mask(dc, cpu_addr);
cpu_src1_64 = gen_load_fpr_D(dc, rd);
tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
MO_TEQ | MO_ALIGN_4);
MO_TEUQ | MO_ALIGN_4);
break;
default:
goto illegal_insn;

View file

@ -246,7 +246,7 @@ static void gen_st_2regs_64(TCGv rh, TCGv rl, TCGv address, DisasContext *ctx)
TCGv_i64 temp = tcg_temp_new_i64();
tcg_gen_concat_i32_i64(temp, rl, rh);
tcg_gen_qemu_st_i64(temp, address, ctx->mem_idx, MO_LEQ);
tcg_gen_qemu_st_i64(temp, address, ctx->mem_idx, MO_LEUQ);
tcg_temp_free_i64(temp);
}
@ -264,7 +264,7 @@ static void gen_ld_2regs_64(TCGv rh, TCGv rl, TCGv address, DisasContext *ctx)
{
TCGv_i64 temp = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(temp, address, ctx->mem_idx, MO_LEQ);
tcg_gen_qemu_ld_i64(temp, address, ctx->mem_idx, MO_LEUQ);
/* write back to two 32 bit regs */
tcg_gen_extr_i64_i32(rl, rh, temp);

View file

@ -7077,7 +7077,7 @@ static void translate_ldsti_d(DisasContext *dc, const OpcodeArg arg[],
} else {
addr = arg[1].in;
}
mop = gen_load_store_alignment(dc, MO_TEQ, addr);
mop = gen_load_store_alignment(dc, MO_TEUQ, addr);
if (par[0]) {
tcg_gen_qemu_st_i64(arg[0].in, addr, dc->cring, mop);
} else {
@ -7142,7 +7142,7 @@ static void translate_ldstx_d(DisasContext *dc, const OpcodeArg arg[],
} else {
addr = arg[1].in;
}
mop = gen_load_store_alignment(dc, MO_TEQ, addr);
mop = gen_load_store_alignment(dc, MO_TEUQ, addr);
if (par[0]) {
tcg_gen_qemu_st_i64(arg[0].in, addr, dc->cring, mop);
} else {

View file

@ -1744,7 +1744,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
case MO_SL:
tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r);
break;
case MO_Q:
case MO_UQ:
tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
break;
default:

View file

@ -1443,13 +1443,13 @@ static void * const qemu_ld_helpers[MO_SSIZE + 1] = {
#ifdef HOST_WORDS_BIGENDIAN
[MO_UW] = helper_be_lduw_mmu,
[MO_UL] = helper_be_ldul_mmu,
[MO_Q] = helper_be_ldq_mmu,
[MO_UQ] = helper_be_ldq_mmu,
[MO_SW] = helper_be_ldsw_mmu,
[MO_SL] = helper_be_ldul_mmu,
#else
[MO_UW] = helper_le_lduw_mmu,
[MO_UL] = helper_le_ldul_mmu,
[MO_Q] = helper_le_ldq_mmu,
[MO_UQ] = helper_le_ldq_mmu,
[MO_SW] = helper_le_ldsw_mmu,
[MO_SL] = helper_le_ldul_mmu,
#endif
@ -1694,7 +1694,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
default:
tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
break;
case MO_Q:
case MO_UQ:
if (datalo != TCG_REG_R1) {
tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
@ -1781,7 +1781,7 @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc,
case MO_UL:
tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
break;
case MO_Q:
case MO_UQ:
/* Avoid ldrd for user-only emulation, to handle unaligned. */
if (USING_SOFTMMU && use_armv6_instructions
&& (datalo & 1) == 0 && datahi == datalo + 1) {
@ -1824,7 +1824,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo,
case MO_UL:
tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
break;
case MO_Q:
case MO_UQ:
/* Avoid ldrd for user-only emulation, to handle unaligned. */
if (USING_SOFTMMU && use_armv6_instructions
&& (datalo & 1) == 0 && datahi == datalo + 1) {

View file

@ -1615,10 +1615,10 @@ static void * const qemu_ld_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
[MO_LEQ] = helper_le_ldq_mmu,
[MO_LEUQ] = helper_le_ldq_mmu,
[MO_BEUW] = helper_be_lduw_mmu,
[MO_BEUL] = helper_be_ldul_mmu,
[MO_BEQ] = helper_be_ldq_mmu,
[MO_BEUQ] = helper_be_ldq_mmu,
};
/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
@ -1628,10 +1628,10 @@ static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
[MO_LEQ] = helper_le_stq_mmu,
[MO_LEUQ] = helper_le_stq_mmu,
[MO_BEUW] = helper_be_stw_mmu,
[MO_BEUL] = helper_be_stl_mmu,
[MO_BEQ] = helper_be_stq_mmu,
[MO_BEUQ] = helper_be_stq_mmu,
};
/* Perform the TLB load and compare.
@ -1827,7 +1827,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
case MO_UL:
tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
break;
case MO_Q:
case MO_UQ:
if (TCG_TARGET_REG_BITS == 64) {
tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
} else if (data_reg == TCG_REG_EDX) {
@ -2019,7 +2019,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
}
break;
#endif
case MO_Q:
case MO_UQ:
if (TCG_TARGET_REG_BITS == 64) {
tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo,
base, index, 0, ofs);

View file

@ -1023,11 +1023,11 @@ static void * const qemu_ld_helpers[(MO_SSIZE | MO_BSWAP) + 1] = {
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LESW] = helper_le_ldsw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
[MO_LEQ] = helper_le_ldq_mmu,
[MO_LEUQ] = helper_le_ldq_mmu,
[MO_BEUW] = helper_be_lduw_mmu,
[MO_BESW] = helper_be_ldsw_mmu,
[MO_BEUL] = helper_be_ldul_mmu,
[MO_BEQ] = helper_be_ldq_mmu,
[MO_BEUQ] = helper_be_ldq_mmu,
#if TCG_TARGET_REG_BITS == 64
[MO_LESL] = helper_le_ldsl_mmu,
[MO_BESL] = helper_be_ldsl_mmu,
@ -1038,10 +1038,10 @@ static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
[MO_LEQ] = helper_le_stq_mmu,
[MO_LEUQ] = helper_le_stq_mmu,
[MO_BEUW] = helper_be_stw_mmu,
[MO_BEUL] = helper_be_stl_mmu,
[MO_BEQ] = helper_be_stq_mmu,
[MO_BEUQ] = helper_be_stq_mmu,
};
/* Helper routines for marshalling helper function arguments into
@ -1384,7 +1384,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
case MO_SL:
tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
break;
case MO_Q | MO_BSWAP:
case MO_UQ | MO_BSWAP:
if (TCG_TARGET_REG_BITS == 64) {
if (use_mips32r2_instructions) {
tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
@ -1413,7 +1413,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? hi : lo, TCG_TMP3);
}
break;
case MO_Q:
case MO_UQ:
/* Prefer to load from offset 0 first, but allow for overlap. */
if (TCG_TARGET_REG_BITS == 64) {
tcg_out_opc_imm(s, OPC_LD, lo, base, 0);

View file

@ -1935,24 +1935,24 @@ static const uint32_t qemu_ldx_opc[(MO_SSIZE + MO_BSWAP) + 1] = {
[MO_UB] = LBZX,
[MO_UW] = LHZX,
[MO_UL] = LWZX,
[MO_Q] = LDX,
[MO_UQ] = LDX,
[MO_SW] = LHAX,
[MO_SL] = LWAX,
[MO_BSWAP | MO_UB] = LBZX,
[MO_BSWAP | MO_UW] = LHBRX,
[MO_BSWAP | MO_UL] = LWBRX,
[MO_BSWAP | MO_Q] = LDBRX,
[MO_BSWAP | MO_UQ] = LDBRX,
};
static const uint32_t qemu_stx_opc[(MO_SIZE + MO_BSWAP) + 1] = {
[MO_UB] = STBX,
[MO_UW] = STHX,
[MO_UL] = STWX,
[MO_Q] = STDX,
[MO_UQ] = STDX,
[MO_BSWAP | MO_UB] = STBX,
[MO_BSWAP | MO_UW] = STHBRX,
[MO_BSWAP | MO_UL] = STWBRX,
[MO_BSWAP | MO_Q] = STDBRX,
[MO_BSWAP | MO_UQ] = STDBRX,
};
static const uint32_t qemu_exts_opc[4] = {
@ -1969,10 +1969,10 @@ static void * const qemu_ld_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
[MO_LEQ] = helper_le_ldq_mmu,
[MO_LEUQ] = helper_le_ldq_mmu,
[MO_BEUW] = helper_be_lduw_mmu,
[MO_BEUL] = helper_be_ldul_mmu,
[MO_BEQ] = helper_be_ldq_mmu,
[MO_BEUQ] = helper_be_ldq_mmu,
};
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
@ -1982,10 +1982,10 @@ static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
[MO_LEQ] = helper_le_stq_mmu,
[MO_LEUQ] = helper_le_stq_mmu,
[MO_BEUW] = helper_be_stw_mmu,
[MO_BEUL] = helper_be_stl_mmu,
[MO_BEQ] = helper_be_stq_mmu,
[MO_BEUQ] = helper_be_stq_mmu,
};
/* We expect to use a 16-bit negative offset from ENV. */

View file

@ -862,7 +862,7 @@ static void * const qemu_ld_helpers[MO_SSIZE + 1] = {
#if TCG_TARGET_REG_BITS == 64
[MO_SL] = helper_be_ldsl_mmu,
#endif
[MO_Q] = helper_be_ldq_mmu,
[MO_UQ] = helper_be_ldq_mmu,
#else
[MO_UW] = helper_le_lduw_mmu,
[MO_SW] = helper_le_ldsw_mmu,
@ -870,7 +870,7 @@ static void * const qemu_ld_helpers[MO_SSIZE + 1] = {
#if TCG_TARGET_REG_BITS == 64
[MO_SL] = helper_le_ldsl_mmu,
#endif
[MO_Q] = helper_le_ldq_mmu,
[MO_UQ] = helper_le_ldq_mmu,
#endif
};
@ -1083,7 +1083,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
case MO_SL:
tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
break;
case MO_Q:
case MO_UQ:
/* Prefer to load from offset 0 first, but allow for overlap. */
if (TCG_TARGET_REG_BITS == 64) {
tcg_out_opc_imm(s, OPC_LD, lo, base, 0);

View file

@ -438,22 +438,22 @@ static void * const qemu_ld_helpers[(MO_SSIZE | MO_BSWAP) + 1] = {
[MO_LESW] = helper_le_ldsw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
[MO_LESL] = helper_le_ldsl_mmu,
[MO_LEQ] = helper_le_ldq_mmu,
[MO_LEUQ] = helper_le_ldq_mmu,
[MO_BEUW] = helper_be_lduw_mmu,
[MO_BESW] = helper_be_ldsw_mmu,
[MO_BEUL] = helper_be_ldul_mmu,
[MO_BESL] = helper_be_ldsl_mmu,
[MO_BEQ] = helper_be_ldq_mmu,
[MO_BEUQ] = helper_be_ldq_mmu,
};
static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
[MO_LEQ] = helper_le_stq_mmu,
[MO_LEUQ] = helper_le_stq_mmu,
[MO_BEUW] = helper_be_stw_mmu,
[MO_BEUL] = helper_be_stl_mmu,
[MO_BEQ] = helper_be_stq_mmu,
[MO_BEUQ] = helper_be_stq_mmu,
};
#endif
@ -1745,10 +1745,10 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
tcg_out_insn(s, RXY, LGF, data, base, index, disp);
break;
case MO_Q | MO_BSWAP:
case MO_UQ | MO_BSWAP:
tcg_out_insn(s, RXY, LRVG, data, base, index, disp);
break;
case MO_Q:
case MO_UQ:
tcg_out_insn(s, RXY, LG, data, base, index, disp);
break;
@ -1791,10 +1791,10 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg data,
}
break;
case MO_Q | MO_BSWAP:
case MO_UQ | MO_BSWAP:
tcg_out_insn(s, RXY, STRVG, data, base, index, disp);
break;
case MO_Q:
case MO_UQ:
tcg_out_insn(s, RXY, STG, data, base, index, disp);
break;
@ -1928,7 +1928,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
case MO_UL:
tgen_ext32u(s, TCG_REG_R4, data_reg);
break;
case MO_Q:
case MO_UQ:
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, data_reg);
break;
default:

View file

@ -889,20 +889,20 @@ static void build_trampolines(TCGContext *s)
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LESW] = helper_le_ldsw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
[MO_LEQ] = helper_le_ldq_mmu,
[MO_LEUQ] = helper_le_ldq_mmu,
[MO_BEUW] = helper_be_lduw_mmu,
[MO_BESW] = helper_be_ldsw_mmu,
[MO_BEUL] = helper_be_ldul_mmu,
[MO_BEQ] = helper_be_ldq_mmu,
[MO_BEUQ] = helper_be_ldq_mmu,
};
static void * const qemu_st_helpers[] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
[MO_LEQ] = helper_le_stq_mmu,
[MO_LEUQ] = helper_le_stq_mmu,
[MO_BEUW] = helper_be_stw_mmu,
[MO_BEUL] = helper_be_stl_mmu,
[MO_BEQ] = helper_be_stq_mmu,
[MO_BEUQ] = helper_be_stq_mmu,
};
int i;
@ -1126,13 +1126,13 @@ static const int qemu_ld_opc[(MO_SSIZE | MO_BSWAP) + 1] = {
[MO_BESW] = LDSH,
[MO_BEUL] = LDUW,
[MO_BESL] = LDSW,
[MO_BEQ] = LDX,
[MO_BEUQ] = LDX,
[MO_LEUW] = LDUH_LE,
[MO_LESW] = LDSH_LE,
[MO_LEUL] = LDUW_LE,
[MO_LESL] = LDSW_LE,
[MO_LEQ] = LDX_LE,
[MO_LEUQ] = LDX_LE,
};
static const int qemu_st_opc[(MO_SIZE | MO_BSWAP) + 1] = {
@ -1140,11 +1140,11 @@ static const int qemu_st_opc[(MO_SIZE | MO_BSWAP) + 1] = {
[MO_BEUW] = STH,
[MO_BEUL] = STW,
[MO_BEQ] = STX,
[MO_BEUQ] = STX,
[MO_LEUW] = STH_LE,
[MO_LEUL] = STW_LE,
[MO_LEQ] = STX_LE,
[MO_LEUQ] = STX_LE,
};
static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,

View file

@ -1751,12 +1751,12 @@ static const char * const ldst_name[] =
[MO_LESW] = "lesw",
[MO_LEUL] = "leul",
[MO_LESL] = "lesl",
[MO_LEQ] = "leq",
[MO_LEUQ] = "leq",
[MO_BEUW] = "beuw",
[MO_BESW] = "besw",
[MO_BEUL] = "beul",
[MO_BESL] = "besl",
[MO_BEQ] = "beq",
[MO_BEUQ] = "beq",
};
static const char * const alignment_name[(MO_AMASK >> MO_ASHIFT) + 1] = {

View file

@ -309,7 +309,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr,
return helper_le_ldul_mmu(env, taddr, oi, ra);
case MO_LESL:
return helper_le_ldsl_mmu(env, taddr, oi, ra);
case MO_LEQ:
case MO_LEUQ:
return helper_le_ldq_mmu(env, taddr, oi, ra);
case MO_BEUW:
return helper_be_lduw_mmu(env, taddr, oi, ra);
@ -319,7 +319,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr,
return helper_be_ldul_mmu(env, taddr, oi, ra);
case MO_BESL:
return helper_be_ldsl_mmu(env, taddr, oi, ra);
case MO_BEQ:
case MO_BEUQ:
return helper_be_ldq_mmu(env, taddr, oi, ra);
default:
g_assert_not_reached();
@ -348,7 +348,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr,
case MO_LESL:
ret = (int32_t)ldl_le_p(haddr);
break;
case MO_LEQ:
case MO_LEUQ:
ret = ldq_le_p(haddr);
break;
case MO_BEUW:
@ -363,7 +363,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr,
case MO_BESL:
ret = (int32_t)ldl_be_p(haddr);
break;
case MO_BEQ:
case MO_BEUQ:
ret = ldq_be_p(haddr);
break;
default:
@ -391,7 +391,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val,
case MO_LEUL:
helper_le_stl_mmu(env, taddr, val, oi, ra);
break;
case MO_LEQ:
case MO_LEUQ:
helper_le_stq_mmu(env, taddr, val, oi, ra);
break;
case MO_BEUW:
@ -400,7 +400,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val,
case MO_BEUL:
helper_be_stl_mmu(env, taddr, val, oi, ra);
break;
case MO_BEQ:
case MO_BEUQ:
helper_be_stq_mmu(env, taddr, val, oi, ra);
break;
default:
@ -420,7 +420,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val,
case MO_LEUL:
stl_le_p(haddr, val);
break;
case MO_LEQ:
case MO_LEUQ:
stq_le_p(haddr, val);
break;
case MO_BEUW:
@ -429,7 +429,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val,
case MO_BEUL:
stl_be_p(haddr, val);
break;
case MO_BEQ:
case MO_BEUQ:
stq_be_p(haddr, val);
break;
default:

147
util/int128.c Normal file
View file

@ -0,0 +1,147 @@
/*
* 128-bit division and remainder for compilers not supporting __int128
*
* Copyright (c) 2021 Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "qemu/host-utils.h"
#include "qemu/int128.h"
#ifndef CONFIG_INT128
/*
* Division and remainder algorithms for 128-bit due to Stefan Kanthak,
* https://skanthak.homepage.t-online.de/integer.html#udivmodti4
* Preconditions:
* - function should never be called with v equals to 0, it has to
* be dealt with beforehand
* - quotien pointer must be valid
*/
static Int128 divrem128(Int128 u, Int128 v, Int128 *q)
{
Int128 qq;
uint64_t hi, lo, tmp;
int s = clz64(v.hi);
if (s == 64) {
/* we have uu÷0v => let's use divu128 */
hi = u.hi;
lo = u.lo;
tmp = divu128(&lo, &hi, v.lo);
*q = int128_make128(lo, hi);
return int128_make128(tmp, 0);
} else {
hi = int128_gethi(int128_lshift(v, s));
if (hi > u.hi) {
lo = u.lo;
tmp = u.hi;
divu128(&lo, &tmp, hi);
lo = int128_gethi(int128_lshift(int128_make128(lo, 0), s));
} else { /* prevent overflow */
lo = u.lo;
tmp = u.hi - hi;
divu128(&lo, &tmp, hi);
lo = int128_gethi(int128_lshift(int128_make128(lo, 1), s));
}
qq = int128_make64(lo);
tmp = lo * v.hi;
mulu64(&lo, &hi, lo, v.lo);
hi += tmp;
if (hi < tmp /* quotient * divisor >= 2**128 > dividend */
|| hi > u.hi /* quotient * divisor > dividend */
|| (hi == u.hi && lo > u.lo)) {
qq.lo -= 1;
mulu64(&lo, &hi, qq.lo, v.lo);
hi += qq.lo * v.hi;
}
*q = qq;
u.hi -= hi + (u.lo < lo);
u.lo -= lo;
return u;
}
}
Int128 int128_divu(Int128 a, Int128 b)
{
Int128 q;
divrem128(a, b, &q);
return q;
}
Int128 int128_remu(Int128 a, Int128 b)
{
Int128 q;
return divrem128(a, b, &q);
}
Int128 int128_divs(Int128 a, Int128 b)
{
Int128 q;
bool sgna = !int128_nonneg(a);
bool sgnb = !int128_nonneg(b);
if (sgna) {
a = int128_neg(a);
}
if (sgnb) {
b = int128_neg(b);
}
divrem128(a, b, &q);
if (sgna != sgnb) {
q = int128_neg(q);
}
return q;
}
Int128 int128_rems(Int128 a, Int128 b)
{
Int128 q, r;
bool sgna = !int128_nonneg(a);
bool sgnb = !int128_nonneg(b);
if (sgna) {
a = int128_neg(a);
}
if (sgnb) {
b = int128_neg(b);
}
r = divrem128(a, b, &q);
if (sgna) {
r = int128_neg(r);
}
return r;
}
#endif

View file

@ -48,6 +48,7 @@ util_ss.add(files('transactions.c'))
util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c'))
util_ss.add(files('guest-random.c'))
util_ss.add(files('yank.c'))
util_ss.add(files('int128.c'))
if have_user
util_ss.add(files('selfmap.c'))