accel/*: Widen pc/saved_insn for *_sw_breakpoint

accel/tcg: Replace remaining target_ulong in system-mode accel
 tcg: spelling fixes
 tcg: Document bswap, hswap, wswap byte patterns
 tcg: Introduce negsetcond opcodes
 tcg: Fold deposit with zero to and
 tcg: Unify TCG_TARGET_HAS_extr[lh]_i64_i32
 tcg/i386: Drop BYTEH deposits for 64-bit
 tcg/i386: Allow immediate as input to deposit
 target/*: Use tcg_gen_negsetcond_*
 -----BEGIN PGP SIGNATURE-----
 
 iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmTnoP4dHHJpY2hhcmQu
 aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV80MAf+NCEN7bwqGWmWGtfz
 YGXp6J51rDwOWVVzTZDv2Gtkc4/Cv0wwtLk4JT5Sg/LQur3tie/bgqOY1SBb4cRq
 UC1ERk3oqvmh8+aUqCc2SsncVtBduxAMqdlIhuD886SuZHgdry5cp2/MaOEFL/Un
 yQoKl238OzTmIuKnf4p/NnfD4PZxEtzKy9vQyHKswDH5f2+egaqpmKOL/6Xtl8rL
 2nXPbd1UTlMu/QLlQ/CLKcW3Z9eBNrYDSQV1+K2J5ZjSFey8H5RUv3UAfqRpY00b
 EObcNCMSc6D9bpb2p34QENZNh9GiHE9Stg9VGNFOGilaaMxoa6yowlgz9Dz9xlWN
 OHG1ug==
 =ed8f
 -----END PGP SIGNATURE-----

Merge tag 'pull-tcg-20230823-2' of https://gitlab.com/rth7680/qemu into staging

accel/*: Widen pc/saved_insn for *_sw_breakpoint
accel/tcg: Replace remaining target_ulong in system-mode accel
tcg: spelling fixes
tcg: Document bswap, hswap, wswap byte patterns
tcg: Introduce negsetcond opcodes
tcg: Fold deposit with zero to and
tcg: Unify TCG_TARGET_HAS_extr[lh]_i64_i32
tcg/i386: Drop BYTEH deposits for 64-bit
tcg/i386: Allow immediate as input to deposit
target/*: Use tcg_gen_negsetcond_*

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmTnoP4dHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV80MAf+NCEN7bwqGWmWGtfz
# YGXp6J51rDwOWVVzTZDv2Gtkc4/Cv0wwtLk4JT5Sg/LQur3tie/bgqOY1SBb4cRq
# UC1ERk3oqvmh8+aUqCc2SsncVtBduxAMqdlIhuD886SuZHgdry5cp2/MaOEFL/Un
# yQoKl238OzTmIuKnf4p/NnfD4PZxEtzKy9vQyHKswDH5f2+egaqpmKOL/6Xtl8rL
# 2nXPbd1UTlMu/QLlQ/CLKcW3Z9eBNrYDSQV1+K2J5ZjSFey8H5RUv3UAfqRpY00b
# EObcNCMSc6D9bpb2p34QENZNh9GiHE9Stg9VGNFOGilaaMxoa6yowlgz9Dz9xlWN
# OHG1ug==
# =ed8f
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 24 Aug 2023 14:27:10 EDT
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* tag 'pull-tcg-20230823-2' of https://gitlab.com/rth7680/qemu: (48 commits)
  tcg: spelling fixes
  docs/devel/tcg-ops: fix missing newlines in "Host vector operations"
  target/cris: Fix a typo in gen_swapr()
  tcg/tcg-op: Document wswap_i64() byte pattern
  tcg/tcg-op: Document hswap_i32/64() byte pattern
  tcg/tcg-op: Document bswap64_i64() byte pattern
  tcg/tcg-op: Document bswap32_i64() byte pattern
  tcg/tcg-op: Document bswap32_i32() byte pattern
  tcg/tcg-op: Document bswap16_i64() byte pattern
  tcg/tcg-op: Document bswap16_i32() byte pattern
  tcg/i386: Implement negsetcond_*
  tcg/i386: Use shift in tcg_out_setcond
  tcg/i386: Clear dest first in tcg_out_setcond if possible
  tcg/i386: Use CMP+SBB in tcg_out_setcond
  tcg/i386: Merge tcg_out_movcond{32,64}
  tcg/i386: Merge tcg_out_setcond{32,64}
  tcg/i386: Merge tcg_out_brcond{32,64}
  tcg/sparc64: Implement negsetcond_*
  tcg/s390x: Implement negsetcond_*
  tcg/riscv: Implement negsetcond_*
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2023-08-28 16:07:04 -04:00
commit f5fe7c17ac
55 changed files with 832 additions and 433 deletions

View File

@ -474,7 +474,7 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
cpu, QEMU_THREAD_JOINABLE); cpu, QEMU_THREAD_JOINABLE);
} }
static int hvf_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len) static int hvf_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len)
{ {
struct hvf_sw_breakpoint *bp; struct hvf_sw_breakpoint *bp;
int err; int err;
@ -512,7 +512,7 @@ static int hvf_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr le
return 0; return 0;
} }
static int hvf_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len) static int hvf_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len)
{ {
struct hvf_sw_breakpoint *bp; struct hvf_sw_breakpoint *bp;
int err; int err;

View File

@ -51,7 +51,7 @@ void assert_hvf_ok(hv_return_t ret)
abort(); abort();
} }
struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu, target_ulong pc) struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu, vaddr pc)
{ {
struct hvf_sw_breakpoint *bp; struct hvf_sw_breakpoint *bp;

View File

@ -3309,8 +3309,7 @@ bool kvm_arm_supports_user_irq(void)
} }
#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, vaddr pc)
target_ulong pc)
{ {
struct kvm_sw_breakpoint *bp; struct kvm_sw_breakpoint *bp;

View File

@ -69,7 +69,7 @@
# define END _le # define END _le
#endif #endif
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr, ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, abi_ptr addr,
ABI_TYPE cmpv, ABI_TYPE newv, ABI_TYPE cmpv, ABI_TYPE newv,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
@ -87,7 +87,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
} }
#if DATA_SIZE < 16 #if DATA_SIZE < 16
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val, ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, abi_ptr addr, ABI_TYPE val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr); DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr);
@ -100,7 +100,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
} }
#define GEN_ATOMIC_HELPER(X) \ #define GEN_ATOMIC_HELPER(X) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \ ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
{ \ { \
DATA_TYPE *haddr, ret; \ DATA_TYPE *haddr, ret; \
@ -131,7 +131,7 @@ GEN_ATOMIC_HELPER(xor_fetch)
* of CF_PARALLEL's value, we'll trace just a read and a write. * of CF_PARALLEL's value, we'll trace just a read and a write.
*/ */
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \ #define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \ ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
{ \ { \
XDATA_TYPE *haddr, cmp, old, new, val = xval; \ XDATA_TYPE *haddr, cmp, old, new, val = xval; \
@ -172,7 +172,7 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
# define END _be # define END _be
#endif #endif
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr, ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, abi_ptr addr,
ABI_TYPE cmpv, ABI_TYPE newv, ABI_TYPE cmpv, ABI_TYPE newv,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
@ -190,7 +190,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
} }
#if DATA_SIZE < 16 #if DATA_SIZE < 16
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val, ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, abi_ptr addr, ABI_TYPE val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr); DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr);
@ -203,7 +203,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
} }
#define GEN_ATOMIC_HELPER(X) \ #define GEN_ATOMIC_HELPER(X) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \ ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
{ \ { \
DATA_TYPE *haddr, ret; \ DATA_TYPE *haddr, ret; \
@ -231,7 +231,7 @@ GEN_ATOMIC_HELPER(xor_fetch)
* of CF_PARALLEL's value, we'll trace just a read and a write. * of CF_PARALLEL's value, we'll trace just a read and a write.
*/ */
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \ #define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \ ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
{ \ { \
XDATA_TYPE *haddr, ldo, ldn, old, new, val = xval; \ XDATA_TYPE *haddr, ldo, ldn, old, new, val = xval; \

View File

@ -74,8 +74,9 @@
} while (0) } while (0)
/* run_on_cpu_data.target_ptr should always be big enough for a /* run_on_cpu_data.target_ptr should always be big enough for a
* target_ulong even on 32 bit builds */ * vaddr even on 32 bit builds
QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data)); */
QEMU_BUILD_BUG_ON(sizeof(vaddr) > sizeof(run_on_cpu_data));
/* We currently can't handle more than 16 bits in the MMUIDX bitmask. /* We currently can't handle more than 16 bits in the MMUIDX bitmask.
*/ */
@ -1108,7 +1109,7 @@ static void tlb_add_large_page(CPUArchState *env, int mmu_idx,
} }
static inline void tlb_set_compare(CPUTLBEntryFull *full, CPUTLBEntry *ent, static inline void tlb_set_compare(CPUTLBEntryFull *full, CPUTLBEntry *ent,
target_ulong address, int flags, vaddr address, int flags,
MMUAccessType access_type, bool enable) MMUAccessType access_type, bool enable)
{ {
if (enable) { if (enable) {
@ -3133,14 +3134,14 @@ static void plugin_store_cb(CPUArchState *env, abi_ptr addr, MemOpIdx oi)
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W); qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
} }
void cpu_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
helper_stb_mmu(env, addr, val, oi, retaddr); helper_stb_mmu(env, addr, val, oi, retaddr);
plugin_store_cb(env, addr, oi); plugin_store_cb(env, addr, oi);
} }
void cpu_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, void cpu_stw_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_16); tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_16);
@ -3148,7 +3149,7 @@ void cpu_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
plugin_store_cb(env, addr, oi); plugin_store_cb(env, addr, oi);
} }
void cpu_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, void cpu_stl_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_32); tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_32);
@ -3156,7 +3157,7 @@ void cpu_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
plugin_store_cb(env, addr, oi); plugin_store_cb(env, addr, oi);
} }
void cpu_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, void cpu_stq_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_64); tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_64);
@ -3164,7 +3165,7 @@ void cpu_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
plugin_store_cb(env, addr, oi); plugin_store_cb(env, addr, oi);
} }
void cpu_st16_mmu(CPUArchState *env, target_ulong addr, Int128 val, void cpu_st16_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)
{ {
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_128); tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_128);

View File

@ -498,6 +498,12 @@ Conditional moves
| |
| Set *dest* to 1 if (*t1* *cond* *t2*) is true, otherwise set to 0. | Set *dest* to 1 if (*t1* *cond* *t2*) is true, otherwise set to 0.
* - negsetcond_i32/i64 *dest*, *t1*, *t2*, *cond*
- | *dest* = -(*t1* *cond* *t2*)
|
| Set *dest* to -1 if (*t1* *cond* *t2*) is true, otherwise set to 0.
* - movcond_i32/i64 *dest*, *c1*, *c2*, *v1*, *v2*, *cond* * - movcond_i32/i64 *dest*, *c1*, *c2*, *v1*, *v2*, *cond*
- | *dest* = (*c1* *cond* *c2* ? *v1* : *v2*) - | *dest* = (*c1* *cond* *c2* ? *v1* : *v2*)
@ -712,7 +718,9 @@ E.g. VECL = 1 -> 64 << 1 -> v128, and VECE = 2 -> 1 << 2 -> i32.
.. list-table:: .. list-table::
* - mov_vec *v0*, *v1* * - mov_vec *v0*, *v1*
ld_vec *v0*, *t1* ld_vec *v0*, *t1*
st_vec *v0*, *t1* st_vec *v0*, *t1*
- | Move, load and store. - | Move, load and store.
@ -882,14 +890,15 @@ sub2_i32, brcond2_i32).
On a 64 bit target, the values are transferred between 32 and 64-bit On a 64 bit target, the values are transferred between 32 and 64-bit
registers using the following ops: registers using the following ops:
- trunc_shr_i64_i32 - extrl_i64_i32
- extrh_i64_i32
- ext_i32_i64 - ext_i32_i64
- extu_i32_i64 - extu_i32_i64
They ensure that the values are correctly truncated or extended when They ensure that the values are correctly truncated or extended when
moved from a 32-bit to a 64-bit register or vice-versa. Note that the moved from a 32-bit to a 64-bit register or vice-versa. Note that the
trunc_shr_i64_i32 is an optional op. It is not necessary to implement extrl_i64_i32 and extrh_i64_i32 are optional ops. It is not necessary
it if all the following conditions are met: to implement them if all the following conditions are met:
- 64-bit registers can hold 32-bit values - 64-bit registers can hold 32-bit values
- 32-bit values in a 64-bit register do not need to stay zero or - 32-bit values in a 64-bit register do not need to stay zero or

View File

@ -397,7 +397,7 @@ QEMU_BUILD_BUG_ON(TLB_FLAGS_MASK & TLB_SLOW_FLAGS_MASK);
* @addr: virtual address to test (must be page aligned) * @addr: virtual address to test (must be page aligned)
* @tlb_addr: TLB entry address (a CPUTLBEntry addr_read/write/code value) * @tlb_addr: TLB entry address (a CPUTLBEntry addr_read/write/code value)
*/ */
static inline bool tlb_hit_page(target_ulong tlb_addr, target_ulong addr) static inline bool tlb_hit_page(uint64_t tlb_addr, vaddr addr)
{ {
return addr == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK)); return addr == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK));
} }
@ -408,7 +408,7 @@ static inline bool tlb_hit_page(target_ulong tlb_addr, target_ulong addr)
* @addr: virtual address to test (need not be page aligned) * @addr: virtual address to test (need not be page aligned)
* @tlb_addr: TLB entry address (a CPUTLBEntry addr_read/write/code value) * @tlb_addr: TLB entry address (a CPUTLBEntry addr_read/write/code value)
*/ */
static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr) static inline bool tlb_hit(uint64_t tlb_addr, vaddr addr)
{ {
return tlb_hit_page(tlb_addr, addr & TARGET_PAGE_MASK); return tlb_hit_page(tlb_addr, addr & TARGET_PAGE_MASK);
} }

View File

@ -121,8 +121,8 @@ static inline bool guest_range_valid_untagged(abi_ulong start, abi_ulong len)
h2g_nocheck(x); \ h2g_nocheck(x); \
}) })
#else #else
typedef target_ulong abi_ptr; typedef vaddr abi_ptr;
#define TARGET_ABI_FMT_ptr TARGET_FMT_lx #define TARGET_ABI_FMT_ptr "%016" VADDR_PRIx
#endif #endif
uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr); uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr);
@ -223,31 +223,31 @@ void cpu_stq_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
void cpu_st16_mmu(CPUArchState *env, abi_ptr addr, Int128 val, void cpu_st16_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
MemOpIdx oi, uintptr_t ra); MemOpIdx oi, uintptr_t ra);
uint32_t cpu_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr, uint32_t cpu_atomic_cmpxchgb_mmu(CPUArchState *env, abi_ptr addr,
uint32_t cmpv, uint32_t newv, uint32_t cmpv, uint32_t newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
uint32_t cpu_atomic_cmpxchgw_le_mmu(CPUArchState *env, target_ulong addr, uint32_t cpu_atomic_cmpxchgw_le_mmu(CPUArchState *env, abi_ptr addr,
uint32_t cmpv, uint32_t newv, uint32_t cmpv, uint32_t newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
uint32_t cpu_atomic_cmpxchgl_le_mmu(CPUArchState *env, target_ulong addr, uint32_t cpu_atomic_cmpxchgl_le_mmu(CPUArchState *env, abi_ptr addr,
uint32_t cmpv, uint32_t newv, uint32_t cmpv, uint32_t newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
uint64_t cpu_atomic_cmpxchgq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t cpu_atomic_cmpxchgq_le_mmu(CPUArchState *env, abi_ptr addr,
uint64_t cmpv, uint64_t newv, uint64_t cmpv, uint64_t newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
uint32_t cpu_atomic_cmpxchgw_be_mmu(CPUArchState *env, target_ulong addr, uint32_t cpu_atomic_cmpxchgw_be_mmu(CPUArchState *env, abi_ptr addr,
uint32_t cmpv, uint32_t newv, uint32_t cmpv, uint32_t newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
uint32_t cpu_atomic_cmpxchgl_be_mmu(CPUArchState *env, target_ulong addr, uint32_t cpu_atomic_cmpxchgl_be_mmu(CPUArchState *env, abi_ptr addr,
uint32_t cmpv, uint32_t newv, uint32_t cmpv, uint32_t newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
uint64_t cpu_atomic_cmpxchgq_be_mmu(CPUArchState *env, target_ulong addr, uint64_t cpu_atomic_cmpxchgq_be_mmu(CPUArchState *env, abi_ptr addr,
uint64_t cmpv, uint64_t newv, uint64_t cmpv, uint64_t newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
#define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \ #define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \
TYPE cpu_atomic_ ## NAME ## SUFFIX ## _mmu \ TYPE cpu_atomic_ ## NAME ## SUFFIX ## _mmu \
(CPUArchState *env, target_ulong addr, TYPE val, \ (CPUArchState *env, abi_ptr addr, TYPE val, \
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
#ifdef CONFIG_ATOMIC64 #ifdef CONFIG_ATOMIC64
@ -293,10 +293,10 @@ GEN_ATOMIC_HELPER_ALL(xchg)
#undef GEN_ATOMIC_HELPER_ALL #undef GEN_ATOMIC_HELPER_ALL
#undef GEN_ATOMIC_HELPER #undef GEN_ATOMIC_HELPER
Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr, Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, abi_ptr addr,
Int128 cmpv, Int128 newv, Int128 cmpv, Int128 newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);
Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr, Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, abi_ptr addr,
Int128 cmpv, Int128 newv, Int128 cmpv, Int128 newv,
MemOpIdx oi, uintptr_t retaddr); MemOpIdx oi, uintptr_t retaddr);

View File

@ -39,22 +39,20 @@ DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE,
#ifdef NEED_CPU_H #ifdef NEED_CPU_H
struct hvf_sw_breakpoint { struct hvf_sw_breakpoint {
target_ulong pc; vaddr pc;
target_ulong saved_insn; vaddr saved_insn;
int use_count; int use_count;
QTAILQ_ENTRY(hvf_sw_breakpoint) entry; QTAILQ_ENTRY(hvf_sw_breakpoint) entry;
}; };
struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu,
target_ulong pc); vaddr pc);
int hvf_sw_breakpoints_active(CPUState *cpu); int hvf_sw_breakpoints_active(CPUState *cpu);
int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp);
int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp); int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp);
int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type);
int type); int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type);
int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len,
int type);
void hvf_arch_remove_all_hw_breakpoints(void); void hvf_arch_remove_all_hw_breakpoints(void);
/* /*

View File

@ -413,14 +413,14 @@ struct kvm_guest_debug;
struct kvm_debug_exit_arch; struct kvm_debug_exit_arch;
struct kvm_sw_breakpoint { struct kvm_sw_breakpoint {
target_ulong pc; vaddr pc;
target_ulong saved_insn; vaddr saved_insn;
int use_count; int use_count;
QTAILQ_ENTRY(kvm_sw_breakpoint) entry; QTAILQ_ENTRY(kvm_sw_breakpoint) entry;
}; };
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu,
target_ulong pc); vaddr pc);
int kvm_sw_breakpoints_active(CPUState *cpu); int kvm_sw_breakpoints_active(CPUState *cpu);
@ -428,10 +428,8 @@ int kvm_arch_insert_sw_breakpoint(CPUState *cpu,
struct kvm_sw_breakpoint *bp); struct kvm_sw_breakpoint *bp);
int kvm_arch_remove_sw_breakpoint(CPUState *cpu, int kvm_arch_remove_sw_breakpoint(CPUState *cpu,
struct kvm_sw_breakpoint *bp); struct kvm_sw_breakpoint *bp);
int kvm_arch_insert_hw_breakpoint(target_ulong addr, int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type);
target_ulong len, int type); int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type);
int kvm_arch_remove_hw_breakpoint(target_ulong addr,
target_ulong len, int type);
void kvm_arch_remove_all_hw_breakpoints(void); void kvm_arch_remove_all_hw_breakpoints(void);
void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg); void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg);

View File

@ -344,6 +344,8 @@ void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2); TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, int32_t arg2); TCGv_i32 arg1, int32_t arg2);
void tcg_gen_negsetcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2);
void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1, void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2); TCGv_i32 c2, TCGv_i32 v1, TCGv_i32 v2);
void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al, void tcg_gen_add2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 al,
@ -540,6 +542,8 @@ void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2); TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, int64_t arg2); TCGv_i64 arg1, int64_t arg2);
void tcg_gen_negsetcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2);
void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1, void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2); TCGv_i64 c2, TCGv_i64 v1, TCGv_i64 v2);
void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al, void tcg_gen_add2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,

View File

@ -200,6 +200,7 @@ DEF_ATOMIC2(tcg_gen_atomic_umax_fetch, i64)
#define tcg_gen_brcondi_tl tcg_gen_brcondi_i64 #define tcg_gen_brcondi_tl tcg_gen_brcondi_i64
#define tcg_gen_setcond_tl tcg_gen_setcond_i64 #define tcg_gen_setcond_tl tcg_gen_setcond_i64
#define tcg_gen_setcondi_tl tcg_gen_setcondi_i64 #define tcg_gen_setcondi_tl tcg_gen_setcondi_i64
#define tcg_gen_negsetcond_tl tcg_gen_negsetcond_i64
#define tcg_gen_mul_tl tcg_gen_mul_i64 #define tcg_gen_mul_tl tcg_gen_mul_i64
#define tcg_gen_muli_tl tcg_gen_muli_i64 #define tcg_gen_muli_tl tcg_gen_muli_i64
#define tcg_gen_div_tl tcg_gen_div_i64 #define tcg_gen_div_tl tcg_gen_div_i64
@ -317,6 +318,7 @@ DEF_ATOMIC2(tcg_gen_atomic_umax_fetch, i64)
#define tcg_gen_brcondi_tl tcg_gen_brcondi_i32 #define tcg_gen_brcondi_tl tcg_gen_brcondi_i32
#define tcg_gen_setcond_tl tcg_gen_setcond_i32 #define tcg_gen_setcond_tl tcg_gen_setcond_i32
#define tcg_gen_setcondi_tl tcg_gen_setcondi_i32 #define tcg_gen_setcondi_tl tcg_gen_setcondi_i32
#define tcg_gen_negsetcond_tl tcg_gen_negsetcond_i32
#define tcg_gen_mul_tl tcg_gen_mul_i32 #define tcg_gen_mul_tl tcg_gen_mul_i32
#define tcg_gen_muli_tl tcg_gen_muli_i32 #define tcg_gen_muli_tl tcg_gen_muli_i32
#define tcg_gen_div_tl tcg_gen_div_i32 #define tcg_gen_div_tl tcg_gen_div_i32

View File

@ -46,6 +46,7 @@ DEF(mb, 0, 0, 1, 0)
DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT) DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT)
DEF(setcond_i32, 1, 2, 1, 0) DEF(setcond_i32, 1, 2, 1, 0)
DEF(negsetcond_i32, 1, 2, 1, IMPL(TCG_TARGET_HAS_negsetcond_i32))
DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32)) DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
/* load/store */ /* load/store */
DEF(ld8u_i32, 1, 1, 1, 0) DEF(ld8u_i32, 1, 1, 1, 0)
@ -111,6 +112,7 @@ DEF(ctpop_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ctpop_i32))
DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT) DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
DEF(setcond_i64, 1, 2, 1, IMPL64) DEF(setcond_i64, 1, 2, 1, IMPL64)
DEF(negsetcond_i64, 1, 2, 1, IMPL64 | IMPL(TCG_TARGET_HAS_negsetcond_i64))
DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64)) DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
/* load/store */ /* load/store */
DEF(ld8u_i64, 1, 1, 1, IMPL64) DEF(ld8u_i64, 1, 1, 1, IMPL64)
@ -152,10 +154,10 @@ DEF(extract2_i64, 1, 2, 1, IMPL64 | IMPL(TCG_TARGET_HAS_extract2_i64))
DEF(ext_i32_i64, 1, 1, 0, IMPL64) DEF(ext_i32_i64, 1, 1, 0, IMPL64)
DEF(extu_i32_i64, 1, 1, 0, IMPL64) DEF(extu_i32_i64, 1, 1, 0, IMPL64)
DEF(extrl_i64_i32, 1, 1, 0, DEF(extrl_i64_i32, 1, 1, 0,
IMPL(TCG_TARGET_HAS_extrl_i64_i32) IMPL(TCG_TARGET_HAS_extr_i64_i32)
| (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0)) | (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0))
DEF(extrh_i64_i32, 1, 1, 0, DEF(extrh_i64_i32, 1, 1, 0,
IMPL(TCG_TARGET_HAS_extrh_i64_i32) IMPL(TCG_TARGET_HAS_extr_i64_i32)
| (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0)) | (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0))
DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH | IMPL64) DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH | IMPL64)

View File

@ -68,8 +68,7 @@ typedef uint64_t TCGRegSet;
#if TCG_TARGET_REG_BITS == 32 #if TCG_TARGET_REG_BITS == 32
/* Turn some undef macros into false macros. */ /* Turn some undef macros into false macros. */
#define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extrh_i64_i32 0
#define TCG_TARGET_HAS_div_i64 0 #define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_div2_i64 0 #define TCG_TARGET_HAS_div2_i64 0
@ -98,6 +97,7 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0 #define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_movcond_i64 0 #define TCG_TARGET_HAS_movcond_i64 0
#define TCG_TARGET_HAS_negsetcond_i64 0
#define TCG_TARGET_HAS_add2_i64 0 #define TCG_TARGET_HAS_add2_i64 0
#define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_sub2_i64 0
#define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0

View File

@ -517,10 +517,9 @@ static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
case TCG_COND_GE: case TCG_COND_GE:
case TCG_COND_LT: case TCG_COND_LT:
/* For >= or <, map -0.0 to +0.0 via comparison and mask. */ /* For >= or <, map -0.0 to +0.0. */
tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero); tcg_gen_movcond_i64(TCG_COND_NE, dest, src, tcg_constant_i64(mzero),
tcg_gen_neg_i64(dest, dest); src, tcg_constant_i64(0));
tcg_gen_and_i64(dest, dest, src);
break; break;
default: default:

View File

@ -2063,7 +2063,7 @@ int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp)
return 0; return 0;
} }
int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type) int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
{ {
switch (type) { switch (type) {
case GDB_BREAKPOINT_HW: case GDB_BREAKPOINT_HW:
@ -2077,7 +2077,7 @@ int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type)
} }
} }
int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, int type) int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
{ {
switch (type) { switch (type) {
case GDB_BREAKPOINT_HW: case GDB_BREAKPOINT_HW:

View File

@ -49,8 +49,7 @@ void kvm_arm_init_debug(KVMState *s)
return; return;
} }
int kvm_arch_insert_hw_breakpoint(target_ulong addr, int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
switch (type) { switch (type) {
case GDB_BREAKPOINT_HW: case GDB_BREAKPOINT_HW:
@ -65,8 +64,7 @@ int kvm_arch_insert_hw_breakpoint(target_ulong addr,
} }
} }
int kvm_arch_remove_hw_breakpoint(target_ulong addr, int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
switch (type) { switch (type) {
case GDB_BREAKPOINT_HW: case GDB_BREAKPOINT_HW:

View File

@ -4935,9 +4935,12 @@ static void disas_cond_select(DisasContext *s, uint32_t insn)
if (rn == 31 && rm == 31 && (else_inc ^ else_inv)) { if (rn == 31 && rm == 31 && (else_inc ^ else_inv)) {
/* CSET & CSETM. */ /* CSET & CSETM. */
tcg_gen_setcond_i64(tcg_invert_cond(c.cond), tcg_rd, c.value, zero);
if (else_inv) { if (else_inv) {
tcg_gen_neg_i64(tcg_rd, tcg_rd); tcg_gen_negsetcond_i64(tcg_invert_cond(c.cond),
tcg_rd, c.value, zero);
} else {
tcg_gen_setcond_i64(tcg_invert_cond(c.cond),
tcg_rd, c.value, zero);
} }
} else { } else {
TCGv_i64 t_true = cpu_reg(s, rn); TCGv_i64 t_true = cpu_reg(s, rn);
@ -8670,13 +8673,10 @@ static void handle_3same_64(DisasContext *s, int opcode, bool u,
} }
break; break;
case 0x6: /* CMGT, CMHI */ case 0x6: /* CMGT, CMHI */
/* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
* We implement this using setcond (test) and then negating.
*/
cond = u ? TCG_COND_GTU : TCG_COND_GT; cond = u ? TCG_COND_GTU : TCG_COND_GT;
do_cmop: do_cmop:
tcg_gen_setcond_i64(cond, tcg_rd, tcg_rn, tcg_rm); /* 64 bit integer comparison, result = test ? -1 : 0. */
tcg_gen_neg_i64(tcg_rd, tcg_rd); tcg_gen_negsetcond_i64(cond, tcg_rd, tcg_rn, tcg_rm);
break; break;
case 0x7: /* CMGE, CMHS */ case 0x7: /* CMGE, CMHS */
cond = u ? TCG_COND_GEU : TCG_COND_GE; cond = u ? TCG_COND_GEU : TCG_COND_GE;
@ -9265,14 +9265,10 @@ static void handle_2misc_64(DisasContext *s, int opcode, bool u,
} }
break; break;
case 0xa: /* CMLT */ case 0xa: /* CMLT */
/* 64 bit integer comparison against zero, result is
* test ? (2^64 - 1) : 0. We implement via setcond(!test) and
* subtracting 1.
*/
cond = TCG_COND_LT; cond = TCG_COND_LT;
do_cmop: do_cmop:
tcg_gen_setcondi_i64(cond, tcg_rd, tcg_rn, 0); /* 64 bit integer comparison against zero, result is test ? -1 : 0. */
tcg_gen_neg_i64(tcg_rd, tcg_rd); tcg_gen_negsetcond_i64(cond, tcg_rd, tcg_rn, tcg_constant_i64(0));
break; break;
case 0x8: /* CMGT, CMGE */ case 0x8: /* CMGT, CMGE */
cond = u ? TCG_COND_GE : TCG_COND_GT; cond = u ? TCG_COND_GE : TCG_COND_GT;

View File

@ -2946,13 +2946,11 @@ void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
#define GEN_CMP0(NAME, COND) \ #define GEN_CMP0(NAME, COND) \
static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \ static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
{ \ { \
tcg_gen_setcondi_i32(COND, d, a, 0); \ tcg_gen_negsetcond_i32(COND, d, a, tcg_constant_i32(0)); \
tcg_gen_neg_i32(d, d); \
} \ } \
static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \ static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
{ \ { \
tcg_gen_setcondi_i64(COND, d, a, 0); \ tcg_gen_negsetcond_i64(COND, d, a, tcg_constant_i64(0)); \
tcg_gen_neg_i64(d, d); \
} \ } \
static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \ static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
{ \ { \
@ -3863,15 +3861,13 @@ void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
{ {
tcg_gen_and_i32(d, a, b); tcg_gen_and_i32(d, a, b);
tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0); tcg_gen_negsetcond_i32(TCG_COND_NE, d, d, tcg_constant_i32(0));
tcg_gen_neg_i32(d, d);
} }
void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
{ {
tcg_gen_and_i64(d, a, b); tcg_gen_and_i64(d, a, b);
tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0); tcg_gen_negsetcond_i64(TCG_COND_NE, d, d, tcg_constant_i64(0));
tcg_gen_neg_i64(d, d);
} }
static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)

View File

@ -411,15 +411,17 @@ static inline void t_gen_swapw(TCGv d, TCGv s)
tcg_gen_or_tl(d, d, t); tcg_gen_or_tl(d, d, t);
} }
/* Reverse the within each byte. /*
T0 = (((T0 << 7) & 0x80808080) | * Reverse the bits within each byte.
((T0 << 5) & 0x40404040) | *
((T0 << 3) & 0x20202020) | * T0 = ((T0 << 7) & 0x80808080)
((T0 << 1) & 0x10101010) | * | ((T0 << 5) & 0x40404040)
((T0 >> 1) & 0x08080808) | * | ((T0 << 3) & 0x20202020)
((T0 >> 3) & 0x04040404) | * | ((T0 << 1) & 0x10101010)
((T0 >> 5) & 0x02020202) | * | ((T0 >> 1) & 0x08080808)
((T0 >> 7) & 0x01010101)); * | ((T0 >> 3) & 0x04040404)
* | ((T0 >> 5) & 0x02020202)
* | ((T0 >> 7) & 0x01010101);
*/ */
static void t_gen_swapr(TCGv d, TCGv s) static void t_gen_swapr(TCGv d, TCGv s)
{ {

View File

@ -690,12 +690,12 @@ int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp)
return -ENOSYS; return -ENOSYS;
} }
int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type) int hvf_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
{ {
return -ENOSYS; return -ENOSYS;
} }
int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len, int type) int hvf_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
{ {
return -ENOSYS; return -ENOSYS;
} }

View File

@ -5000,7 +5000,7 @@ MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
kvm_rate_limit_on_bus_lock(); kvm_rate_limit_on_bus_lock();
} }
#ifdef CONFIG_XEN_EMU #ifdef CONFIG_XEN_EMU
/* /*
* If the callback is asserted as a GSI (or PCI INTx) then check if * If the callback is asserted as a GSI (or PCI INTx) then check if
* vcpu_info->evtchn_upcall_pending has been cleared, and deassert * vcpu_info->evtchn_upcall_pending has been cleared, and deassert
@ -5161,8 +5161,7 @@ static int find_hw_breakpoint(target_ulong addr, int len, int type)
return -1; return -1;
} }
int kvm_arch_insert_hw_breakpoint(target_ulong addr, int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
switch (type) { switch (type) {
case GDB_BREAKPOINT_HW: case GDB_BREAKPOINT_HW:
@ -5202,8 +5201,7 @@ int kvm_arch_insert_hw_breakpoint(target_ulong addr,
return 0; return 0;
} }
int kvm_arch_remove_hw_breakpoint(target_ulong addr, int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
int n; int n;

View File

@ -697,19 +697,12 @@ static inline int ext_opsize(int ext, int pos)
*/ */
static void gen_partset_reg(int opsize, TCGv reg, TCGv val) static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
{ {
TCGv tmp;
switch (opsize) { switch (opsize) {
case OS_BYTE: case OS_BYTE:
tcg_gen_andi_i32(reg, reg, 0xffffff00); tcg_gen_deposit_i32(reg, reg, val, 0, 8);
tmp = tcg_temp_new();
tcg_gen_ext8u_i32(tmp, val);
tcg_gen_or_i32(reg, reg, tmp);
break; break;
case OS_WORD: case OS_WORD:
tcg_gen_andi_i32(reg, reg, 0xffff0000); tcg_gen_deposit_i32(reg, reg, val, 0, 16);
tmp = tcg_temp_new();
tcg_gen_ext16u_i32(tmp, val);
tcg_gen_or_i32(reg, reg, tmp);
break; break;
case OS_LONG: case OS_LONG:
case OS_SINGLE: case OS_SINGLE:
@ -1357,8 +1350,7 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
case 14: /* GT (!(Z || (N ^ V))) */ case 14: /* GT (!(Z || (N ^ V))) */
case 15: /* LE (Z || (N ^ V)) */ case 15: /* LE (Z || (N ^ V)) */
c->v1 = tmp = tcg_temp_new(); c->v1 = tmp = tcg_temp_new();
tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2); tcg_gen_negsetcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
tcg_gen_neg_i32(tmp, tmp);
tmp2 = tcg_temp_new(); tmp2 = tcg_temp_new();
tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V); tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V);
tcg_gen_or_i32(tmp, tmp, tmp2); tcg_gen_or_i32(tmp, tmp, tmp2);
@ -1437,9 +1429,8 @@ DISAS_INSN(scc)
gen_cc_cond(&c, s, cond); gen_cc_cond(&c, s, cond);
tmp = tcg_temp_new(); tmp = tcg_temp_new();
tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2); tcg_gen_negsetcond_i32(c.tcond, tmp, c.v1, c.v2);
tcg_gen_neg_i32(tmp, tmp);
DEST_EA(env, insn, OS_BYTE, tmp, NULL); DEST_EA(env, insn, OS_BYTE, tmp, NULL);
} }
@ -2771,13 +2762,14 @@ DISAS_INSN(mull)
tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12)); tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
/* QREG_CC_V is -(QREG_CC_V != (QREG_CC_N >> 31)) */ /* QREG_CC_V is -(QREG_CC_V != (QREG_CC_N >> 31)) */
tcg_gen_sari_i32(QREG_CC_Z, QREG_CC_N, 31); tcg_gen_sari_i32(QREG_CC_Z, QREG_CC_N, 31);
tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_Z); tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V,
QREG_CC_V, QREG_CC_Z);
} else { } else {
tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12)); tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
/* QREG_CC_V is -(QREG_CC_V != 0), use QREG_CC_C as 0 */ /* QREG_CC_V is -(QREG_CC_V != 0), use QREG_CC_C as 0 */
tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_C); tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V,
QREG_CC_V, QREG_CC_C);
} }
tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N); tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N);
tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
@ -3346,14 +3338,13 @@ static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) { if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
/* if shift count >= bits, V is (reg != 0) */ /* if shift count >= bits, V is (reg != 0) */
if (count >= bits) { if (count >= bits) {
tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V); tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V);
} else { } else {
TCGv t0 = tcg_temp_new(); TCGv t0 = tcg_temp_new();
tcg_gen_sari_i32(QREG_CC_V, reg, bits - 1); tcg_gen_sari_i32(QREG_CC_V, reg, bits - 1);
tcg_gen_sari_i32(t0, reg, bits - count - 1); tcg_gen_sari_i32(t0, reg, bits - count - 1);
tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, t0); tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, t0);
} }
tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
} }
} else { } else {
tcg_gen_shri_i32(QREG_CC_C, reg, count - 1); tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
@ -3437,9 +3428,8 @@ static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
/* Ignore the bits below the sign bit. */ /* Ignore the bits below the sign bit. */
tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1)); tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1));
/* If any bits remain set, we have overflow. */ /* If any bits remain set, we have overflow. */
tcg_gen_setcondi_i64(TCG_COND_NE, t64, t64, 0); tcg_gen_negsetcond_i64(TCG_COND_NE, t64, t64, tcg_constant_i64(0));
tcg_gen_extrl_i64_i32(QREG_CC_V, t64); tcg_gen_extrl_i64_i32(QREG_CC_V, t64);
tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
} }
} else { } else {
tcg_gen_shli_i64(t64, t64, 32); tcg_gen_shli_i64(t64, t64, 32);
@ -5318,9 +5308,8 @@ DISAS_INSN(fscc)
gen_fcc_cond(&c, s, cond); gen_fcc_cond(&c, s, cond);
tmp = tcg_temp_new(); tmp = tcg_temp_new();
tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2); tcg_gen_negsetcond_i32(c.tcond, tmp, c.v1, c.v2);
tcg_gen_neg_i32(tmp, tmp);
DEST_EA(env, insn, OS_BYTE, tmp, NULL); DEST_EA(env, insn, OS_BYTE, tmp, NULL);
} }

View File

@ -253,9 +253,8 @@ static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb); tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1); tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0); tcg_gen_negsetcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
gen_ove_ov(dc); gen_ove_ov(dc);
} }
@ -309,9 +308,8 @@ static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
tcg_gen_muls2_i64(cpu_mac, high, t1, t2); tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
tcg_gen_sari_i64(t1, cpu_mac, 63); tcg_gen_sari_i64(t1, cpu_mac, 63);
tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high); tcg_gen_negsetcond_i64(TCG_COND_NE, t1, t1, high);
tcg_gen_trunc_i64_tl(cpu_sr_ov, t1); tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
gen_ove_ov(dc); gen_ove_ov(dc);
} }

View File

@ -1449,15 +1449,15 @@ static int find_hw_watchpoint(target_ulong addr, int *flag)
return -1; return -1;
} }
int kvm_arch_insert_hw_breakpoint(target_ulong addr, int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
if ((nb_hw_breakpoint + nb_hw_watchpoint) >= ARRAY_SIZE(hw_debug_points)) { const unsigned breakpoint_index = nb_hw_breakpoint + nb_hw_watchpoint;
if (breakpoint_index >= ARRAY_SIZE(hw_debug_points)) {
return -ENOBUFS; return -ENOBUFS;
} }
hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].addr = addr; hw_debug_points[breakpoint_index].addr = addr;
hw_debug_points[nb_hw_breakpoint + nb_hw_watchpoint].type = type; hw_debug_points[breakpoint_index].type = type;
switch (type) { switch (type) {
case GDB_BREAKPOINT_HW: case GDB_BREAKPOINT_HW:
@ -1493,8 +1493,7 @@ int kvm_arch_insert_hw_breakpoint(target_ulong addr,
return 0; return 0;
} }
int kvm_arch_remove_hw_breakpoint(target_ulong addr, int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
int n; int n;

View File

@ -342,12 +342,14 @@ static bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
uint32_t mask = 0x08 >> (a->bi & 0x03); uint32_t mask = 0x08 >> (a->bi & 0x03);
TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE; TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
TCGv temp = tcg_temp_new(); TCGv temp = tcg_temp_new();
TCGv zero = tcg_constant_tl(0);
tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]); tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
tcg_gen_andi_tl(temp, temp, mask); tcg_gen_andi_tl(temp, temp, mask);
tcg_gen_setcondi_tl(cond, cpu_gpr[a->rt], temp, 0);
if (neg) { if (neg) {
tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->rt]); tcg_gen_negsetcond_tl(cond, cpu_gpr[a->rt], temp, zero);
} else {
tcg_gen_setcond_tl(cond, cpu_gpr[a->rt], temp, zero);
} }
return true; return true;
} }

View File

@ -1341,8 +1341,7 @@ static bool trans_VCMPEQUQ(DisasContext *ctx, arg_VC *a)
tcg_gen_xor_i64(t1, t0, t1); tcg_gen_xor_i64(t1, t0, t1);
tcg_gen_or_i64(t1, t1, t2); tcg_gen_or_i64(t1, t1, t2);
tcg_gen_setcondi_i64(TCG_COND_EQ, t1, t1, 0); tcg_gen_negsetcond_i64(TCG_COND_EQ, t1, t1, tcg_constant_i64(0));
tcg_gen_neg_i64(t1, t1);
set_avr64(a->vrt, t1, true); set_avr64(a->vrt, t1, true);
set_avr64(a->vrt, t1, false); set_avr64(a->vrt, t1, false);
@ -1365,15 +1364,14 @@ static bool do_vcmpgtq(DisasContext *ctx, arg_VC *a, bool sign)
get_avr64(t0, a->vra, false); get_avr64(t0, a->vra, false);
get_avr64(t1, a->vrb, false); get_avr64(t1, a->vrb, false);
tcg_gen_setcond_i64(TCG_COND_GTU, t2, t0, t1); tcg_gen_negsetcond_i64(TCG_COND_GTU, t2, t0, t1);
get_avr64(t0, a->vra, true); get_avr64(t0, a->vra, true);
get_avr64(t1, a->vrb, true); get_avr64(t1, a->vrb, true);
tcg_gen_movcond_i64(TCG_COND_EQ, t2, t0, t1, t2, tcg_constant_i64(0)); tcg_gen_movcond_i64(TCG_COND_EQ, t2, t0, t1, t2, tcg_constant_i64(0));
tcg_gen_setcond_i64(sign ? TCG_COND_GT : TCG_COND_GTU, t1, t0, t1); tcg_gen_negsetcond_i64(sign ? TCG_COND_GT : TCG_COND_GTU, t1, t0, t1);
tcg_gen_or_i64(t1, t1, t2); tcg_gen_or_i64(t1, t1, t2);
tcg_gen_neg_i64(t1, t1);
set_avr64(a->vrt, t1, true); set_avr64(a->vrt, t1, true);
set_avr64(a->vrt, t1, false); set_avr64(a->vrt, t1, false);

View File

@ -235,7 +235,7 @@ static inline int vext_elem_mask(void *v0, int index)
} }
/* elements operations for load and store */ /* elements operations for load and store */
typedef void vext_ldst_elem_fn(CPURISCVState *env, target_ulong addr, typedef void vext_ldst_elem_fn(CPURISCVState *env, abi_ptr addr,
uint32_t idx, void *vd, uintptr_t retaddr); uint32_t idx, void *vd, uintptr_t retaddr);
#define GEN_VEXT_LD_ELEM(NAME, ETYPE, H, LDSUF) \ #define GEN_VEXT_LD_ELEM(NAME, ETYPE, H, LDSUF) \

View File

@ -216,19 +216,19 @@ void helper_scmpu(CPURXState *env)
} }
static uint32_t (* const cpu_ldufn[])(CPUArchState *env, static uint32_t (* const cpu_ldufn[])(CPUArchState *env,
target_ulong ptr, abi_ptr ptr,
uintptr_t retaddr) = { uintptr_t retaddr) = {
cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra,
}; };
static uint32_t (* const cpu_ldfn[])(CPUArchState *env, static uint32_t (* const cpu_ldfn[])(CPUArchState *env,
target_ulong ptr, abi_ptr ptr,
uintptr_t retaddr) = { uintptr_t retaddr) = {
cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra, cpu_ldub_data_ra, cpu_lduw_data_ra, cpu_ldl_data_ra,
}; };
static void (* const cpu_stfn[])(CPUArchState *env, static void (* const cpu_stfn[])(CPUArchState *env,
target_ulong ptr, abi_ptr ptr,
uint32_t val, uint32_t val,
uintptr_t retaddr) = { uintptr_t retaddr) = {
cpu_stb_data_ra, cpu_stw_data_ra, cpu_stl_data_ra, cpu_stb_data_ra, cpu_stw_data_ra, cpu_stl_data_ra,

View File

@ -990,8 +990,7 @@ static int insert_hw_breakpoint(target_ulong addr, int len, int type)
return 0; return 0;
} }
int kvm_arch_insert_hw_breakpoint(target_ulong addr, int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
switch (type) { switch (type) {
case GDB_BREAKPOINT_HW: case GDB_BREAKPOINT_HW:
@ -1009,8 +1008,7 @@ int kvm_arch_insert_hw_breakpoint(target_ulong addr,
return insert_hw_breakpoint(addr, len, type); return insert_hw_breakpoint(addr, len, type);
} }
int kvm_arch_remove_hw_breakpoint(target_ulong addr, int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
target_ulong len, int type)
{ {
int size; int size;
struct kvm_hw_breakpoint *bp = find_hw_breakpoint(addr, len, type); struct kvm_hw_breakpoint *bp = find_hw_breakpoint(addr, len, type);

View File

@ -2916,7 +2916,7 @@ static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1); tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1);
tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2); tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2);
tcg_gen_andi_tl(dst, lo1, omask); tcg_gen_andi_tl(lo1, lo1, omask);
tcg_gen_andi_tl(lo2, lo2, omask); tcg_gen_andi_tl(lo2, lo2, omask);
amask = -8; amask = -8;
@ -2926,18 +2926,9 @@ static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2,
tcg_gen_andi_tl(s1, s1, amask); tcg_gen_andi_tl(s1, s1, amask);
tcg_gen_andi_tl(s2, s2, amask); tcg_gen_andi_tl(s2, s2, amask);
/* We want to compute /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */
dst = (s1 == s2 ? lo1 : lo1 & lo2). tcg_gen_and_tl(lo2, lo2, lo1);
We've already done dst = lo1, so this reduces to tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2);
dst &= (s1 == s2 ? -1 : lo2)
Which we perform by
lo2 |= -(s1 == s2)
dst &= lo2
*/
tcg_gen_setcond_tl(TCG_COND_EQ, lo1, s1, s2);
tcg_gen_neg_tl(lo1, lo1);
tcg_gen_or_tl(lo2, lo2, lo1);
tcg_gen_and_tl(dst, dst, lo2);
} }
static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left) static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left)

View File

@ -2680,13 +2680,6 @@ gen_accumulating_condi(int cond, TCGv ret, TCGv r1, int32_t con,
gen_accumulating_cond(cond, ret, r1, temp, op); gen_accumulating_cond(cond, ret, r1, temp, op);
} }
/* ret = (r1 cond r2) ? 0xFFFFFFFF ? 0x00000000;*/
static inline void gen_cond_w(TCGCond cond, TCGv ret, TCGv r1, TCGv r2)
{
tcg_gen_setcond_tl(cond, ret, r1, r2);
tcg_gen_neg_tl(ret, ret);
}
static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con) static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con)
{ {
TCGv b0 = tcg_temp_new(); TCGv b0 = tcg_temp_new();
@ -5692,7 +5685,8 @@ static void decode_rr_accumulator(DisasContext *ctx)
gen_helper_eq_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); gen_helper_eq_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break; break;
case OPC2_32_RR_EQ_W: case OPC2_32_RR_EQ_W:
gen_cond_w(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); tcg_gen_negsetcond_tl(TCG_COND_EQ, cpu_gpr_d[r3],
cpu_gpr_d[r1], cpu_gpr_d[r2]);
break; break;
case OPC2_32_RR_EQANY_B: case OPC2_32_RR_EQANY_B:
gen_helper_eqany_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); gen_helper_eqany_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
@ -5729,10 +5723,12 @@ static void decode_rr_accumulator(DisasContext *ctx)
gen_helper_lt_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); gen_helper_lt_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break; break;
case OPC2_32_RR_LT_W: case OPC2_32_RR_LT_W:
gen_cond_w(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); tcg_gen_negsetcond_tl(TCG_COND_LT, cpu_gpr_d[r3],
cpu_gpr_d[r1], cpu_gpr_d[r2]);
break; break;
case OPC2_32_RR_LT_WU: case OPC2_32_RR_LT_WU:
gen_cond_w(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); tcg_gen_negsetcond_tl(TCG_COND_LTU, cpu_gpr_d[r3],
cpu_gpr_d[r1], cpu_gpr_d[r2]);
break; break;
case OPC2_32_RR_MAX: case OPC2_32_RR_MAX:
tcg_gen_movcond_tl(TCG_COND_GT, cpu_gpr_d[r3], cpu_gpr_d[r1], tcg_gen_movcond_tl(TCG_COND_GT, cpu_gpr_d[r3], cpu_gpr_d[r1],

View File

@ -2262,6 +2262,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
TCG_REG_XZR, tcg_invert_cond(args[3])); TCG_REG_XZR, tcg_invert_cond(args[3]));
break; break;
case INDEX_op_negsetcond_i32:
a2 = (int32_t)a2;
/* FALLTHRU */
case INDEX_op_negsetcond_i64:
tcg_out_cmp(s, ext, a1, a2, c2);
/* Use CSETM alias of CSINV Wd, WZR, WZR, invert(cond). */
tcg_out_insn(s, 3506, CSINV, ext, a0, TCG_REG_XZR,
TCG_REG_XZR, tcg_invert_cond(args[3]));
break;
case INDEX_op_movcond_i32: case INDEX_op_movcond_i32:
a2 = (int32_t)a2; a2 = (int32_t)a2;
/* FALLTHRU */ /* FALLTHRU */
@ -2868,6 +2878,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_sub_i64: case INDEX_op_sub_i64:
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i32:
case INDEX_op_negsetcond_i64:
return C_O1_I2(r, r, rA); return C_O1_I2(r, r, rA);
case INDEX_op_mul_i32: case INDEX_op_mul_i32:
@ -3086,7 +3098,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
#if !defined(CONFIG_SOFTMMU) #if !defined(CONFIG_SOFTMMU)
/* /*
* Note that XZR cannot be encoded in the address base register slot, * Note that XZR cannot be encoded in the address base register slot,
* as that actaully encodes SP. Depending on the guest, we may need * as that actually encodes SP. Depending on the guest, we may need
* to zero-extend the guest address via the address index register slot, * to zero-extend the guest address via the address index register slot,
* therefore we need to load even a zero guest base into a register. * therefore we need to load even a zero guest base into a register.
*/ */

View File

@ -86,14 +86,14 @@ typedef enum {
#define TCG_TARGET_HAS_sextract_i32 1 #define TCG_TARGET_HAS_sextract_i32 1
#define TCG_TARGET_HAS_extract2_i32 1 #define TCG_TARGET_HAS_extract2_i32 1
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_mulu2_i32 0
#define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extrh_i64_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_div_i64 1
@ -123,6 +123,7 @@ typedef enum {
#define TCG_TARGET_HAS_sextract_i64 1 #define TCG_TARGET_HAS_sextract_i64 1
#define TCG_TARGET_HAS_extract2_i64 1 #define TCG_TARGET_HAS_extract2_i64 1
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1
#define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0

View File

@ -1216,9 +1216,11 @@ static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args,
case TCG_COND_LEU: case TCG_COND_LEU:
case TCG_COND_GTU: case TCG_COND_GTU:
case TCG_COND_GEU: case TCG_COND_GEU:
/* We perform a conditional comparision. If the high half is /*
equal, then overwrite the flags with the comparison of the * We perform a conditional comparison. If the high half is
low half. The resulting flags cover the whole. */ * equal, then overwrite the flags with the comparison of the
* low half. The resulting flags cover the whole.
*/
tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0, ah, bh, const_bh); tcg_out_dat_rI(s, COND_AL, ARITH_CMP, 0, ah, bh, const_bh);
tcg_out_dat_rI(s, COND_EQ, ARITH_CMP, 0, al, bl, const_bl); tcg_out_dat_rI(s, COND_EQ, ARITH_CMP, 0, al, bl, const_bl);
return cond; return cond;
@ -1250,7 +1252,7 @@ static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args,
/* /*
* Note that TCGReg references Q-registers. * Note that TCGReg references Q-registers.
* Q-regno = 2 * D-regno, so shift left by 1 whlie inserting. * Q-regno = 2 * D-regno, so shift left by 1 while inserting.
*/ */
static uint32_t encode_vd(TCGReg rd) static uint32_t encode_vd(TCGReg rd)
{ {
@ -1975,6 +1977,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])], tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
ARITH_MOV, args[0], 0, 0); ARITH_MOV, args[0], 0, 0);
break; break;
case INDEX_op_negsetcond_i32:
tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
args[1], args[2], const_args[2]);
tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
ARITH_MVN, args[0], 0, 0);
tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
ARITH_MOV, args[0], 0, 0);
break;
case INDEX_op_brcond2_i32: case INDEX_op_brcond2_i32:
c = tcg_out_cmp2(s, args, const_args); c = tcg_out_cmp2(s, args, const_args);
@ -2112,6 +2122,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_add_i32: case INDEX_op_add_i32:
case INDEX_op_sub_i32: case INDEX_op_sub_i32:
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_negsetcond_i32:
return C_O1_I2(r, r, rIN); return C_O1_I2(r, r, rIN);
case INDEX_op_and_i32: case INDEX_op_and_i32:

View File

@ -116,6 +116,7 @@ extern bool use_neon_instructions;
#define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions #define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions
#define TCG_TARGET_HAS_extract2_i32 1 #define TCG_TARGET_HAS_extract2_i32 1
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_mulu2_i32 1 #define TCG_TARGET_HAS_mulu2_i32 1
#define TCG_TARGET_HAS_muls2_i32 1 #define TCG_TARGET_HAS_muls2_i32 1
#define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_muluh_i32 0

View File

@ -33,7 +33,7 @@ C_O1_I1(r, q)
C_O1_I1(r, r) C_O1_I1(r, r)
C_O1_I1(x, r) C_O1_I1(x, r)
C_O1_I1(x, x) C_O1_I1(x, x)
C_O1_I2(Q, 0, Q) C_O1_I2(q, 0, qi)
C_O1_I2(q, r, re) C_O1_I2(q, r, re)
C_O1_I2(r, 0, ci) C_O1_I2(r, 0, ci)
C_O1_I2(r, 0, r) C_O1_I2(r, 0, r)

View File

@ -19,7 +19,6 @@ REGS('D', 1u << TCG_REG_EDI)
REGS('r', ALL_GENERAL_REGS) REGS('r', ALL_GENERAL_REGS)
REGS('x', ALL_VECTOR_REGS) REGS('x', ALL_VECTOR_REGS)
REGS('q', ALL_BYTEL_REGS) /* regs that can be used as a byte operand */ REGS('q', ALL_BYTEL_REGS) /* regs that can be used as a byte operand */
REGS('Q', ALL_BYTEH_REGS) /* regs with a second byte (e.g. %ah) */
REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_ld/st */ REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_ld/st */
REGS('s', ALL_BYTEL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_st8_i32 data */ REGS('s', ALL_BYTEL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_st8_i32 data */

View File

@ -144,7 +144,6 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
# define TCG_REG_L1 TCG_REG_EDX # define TCG_REG_L1 TCG_REG_EDX
#endif #endif
#define ALL_BYTEH_REGS 0x0000000fu
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
# define ALL_GENERAL_REGS 0x0000ffffu # define ALL_GENERAL_REGS 0x0000ffffu
# define ALL_VECTOR_REGS 0xffff0000u # define ALL_VECTOR_REGS 0xffff0000u
@ -152,7 +151,7 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
#else #else
# define ALL_GENERAL_REGS 0x000000ffu # define ALL_GENERAL_REGS 0x000000ffu
# define ALL_VECTOR_REGS 0x00ff0000u # define ALL_VECTOR_REGS 0x00ff0000u
# define ALL_BYTEL_REGS ALL_BYTEH_REGS # define ALL_BYTEL_REGS 0x0000000fu
#endif #endif
#ifdef CONFIG_SOFTMMU #ifdef CONFIG_SOFTMMU
# define SOFTMMU_RESERVE_REGS ((1 << TCG_REG_L0) | (1 << TCG_REG_L1)) # define SOFTMMU_RESERVE_REGS ((1 << TCG_REG_L0) | (1 << TCG_REG_L1))
@ -277,6 +276,7 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */ #define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
#define OPC_MOVB_EvIz (0xc6) #define OPC_MOVB_EvIz (0xc6)
#define OPC_MOVL_EvIz (0xc7) #define OPC_MOVL_EvIz (0xc7)
#define OPC_MOVB_Ib (0xb0)
#define OPC_MOVL_Iv (0xb8) #define OPC_MOVL_Iv (0xb8)
#define OPC_MOVBE_GyMy (0xf0 | P_EXT38) #define OPC_MOVBE_GyMy (0xf0 | P_EXT38)
#define OPC_MOVBE_MyGy (0xf1 | P_EXT38) #define OPC_MOVBE_MyGy (0xf1 | P_EXT38)
@ -1436,99 +1436,89 @@ static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
} }
} }
static void tcg_out_brcond32(TCGContext *s, TCGCond cond, static void tcg_out_brcond(TCGContext *s, int rexw, TCGCond cond,
TCGArg arg1, TCGArg arg2, int const_arg2, TCGArg arg1, TCGArg arg2, int const_arg2,
TCGLabel *label, int small) TCGLabel *label, bool small)
{ {
tcg_out_cmp(s, arg1, arg2, const_arg2, 0); tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
tcg_out_jxx(s, tcg_cond_to_jcc[cond], label, small); tcg_out_jxx(s, tcg_cond_to_jcc[cond], label, small);
} }
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 32
static void tcg_out_brcond64(TCGContext *s, TCGCond cond,
TCGArg arg1, TCGArg arg2, int const_arg2,
TCGLabel *label, int small)
{
tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
tcg_out_jxx(s, tcg_cond_to_jcc[cond], label, small);
}
#else
/* XXX: we implement it at the target level to avoid having to
handle cross basic blocks temporaries */
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args, static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
const int *const_args, int small) const int *const_args, bool small)
{ {
TCGLabel *label_next = gen_new_label(); TCGLabel *label_next = gen_new_label();
TCGLabel *label_this = arg_label(args[5]); TCGLabel *label_this = arg_label(args[5]);
switch(args[4]) { switch(args[4]) {
case TCG_COND_EQ: case TCG_COND_EQ:
tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_NE, args[0], args[2], const_args[2],
label_next, 1); label_next, 1);
tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_EQ, args[1], args[3], const_args[3],
label_this, small); label_this, small);
break; break;
case TCG_COND_NE: case TCG_COND_NE:
tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_NE, args[0], args[2], const_args[2],
label_this, small); label_this, small);
tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_NE, args[1], args[3], const_args[3],
label_this, small); label_this, small);
break; break;
case TCG_COND_LT: case TCG_COND_LT:
tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_LT, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_LTU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
case TCG_COND_LE: case TCG_COND_LE:
tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_LT, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_LEU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
case TCG_COND_GT: case TCG_COND_GT:
tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_GT, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_GTU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
case TCG_COND_GE: case TCG_COND_GE:
tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_GT, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_GEU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
case TCG_COND_LTU: case TCG_COND_LTU:
tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_LTU, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_LTU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
case TCG_COND_LEU: case TCG_COND_LEU:
tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_LTU, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_LEU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
case TCG_COND_GTU: case TCG_COND_GTU:
tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_GTU, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_GTU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
case TCG_COND_GEU: case TCG_COND_GEU:
tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3], tcg_out_brcond(s, 0, TCG_COND_GTU, args[1], args[3], const_args[3],
label_this, small); label_this, small);
tcg_out_jxx(s, JCC_JNE, label_next, 1); tcg_out_jxx(s, JCC_JNE, label_next, 1);
tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2], tcg_out_brcond(s, 0, TCG_COND_GEU, args[0], args[2], const_args[2],
label_this, small); label_this, small);
break; break;
default: default:
g_assert_not_reached(); g_assert_not_reached();
@ -1537,23 +1527,107 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
} }
#endif #endif
static void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest, static void tcg_out_setcond(TCGContext *s, int rexw, TCGCond cond,
TCGArg arg1, TCGArg arg2, int const_arg2) TCGArg dest, TCGArg arg1, TCGArg arg2,
int const_arg2, bool neg)
{ {
tcg_out_cmp(s, arg1, arg2, const_arg2, 0); bool inv = false;
bool cleared;
switch (cond) {
case TCG_COND_NE:
inv = true;
/* fall through */
case TCG_COND_EQ:
/* If arg2 is 0, convert to LTU/GEU vs 1. */
if (const_arg2 && arg2 == 0) {
arg2 = 1;
goto do_ltu;
}
break;
case TCG_COND_LEU:
inv = true;
/* fall through */
case TCG_COND_GTU:
/* If arg2 is a register, swap for LTU/GEU. */
if (!const_arg2) {
TCGReg t = arg1;
arg1 = arg2;
arg2 = t;
goto do_ltu;
}
break;
case TCG_COND_GEU:
inv = true;
/* fall through */
case TCG_COND_LTU:
do_ltu:
/*
* Relying on the carry bit, use SBB to produce -1 if LTU, 0 if GEU.
* We can then use NEG or INC to produce the desired result.
* This is always smaller than the SETCC expansion.
*/
tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
/* X - X - C = -C = (C ? -1 : 0) */
tgen_arithr(s, ARITH_SBB + (neg ? rexw : 0), dest, dest);
if (inv && neg) {
/* ~(C ? -1 : 0) = (C ? 0 : -1) */
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, dest);
} else if (inv) {
/* (C ? -1 : 0) + 1 = (C ? 0 : 1) */
tgen_arithi(s, ARITH_ADD, dest, 1, 0);
} else if (!neg) {
/* -(C ? -1 : 0) = (C ? 1 : 0) */
tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NEG, dest);
}
return;
case TCG_COND_GE:
inv = true;
/* fall through */
case TCG_COND_LT:
/* If arg2 is 0, extract the sign bit. */
if (const_arg2 && arg2 == 0) {
tcg_out_mov(s, rexw ? TCG_TYPE_I64 : TCG_TYPE_I32, dest, arg1);
if (inv) {
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, dest);
}
tcg_out_shifti(s, (neg ? SHIFT_SAR : SHIFT_SHR) + rexw,
dest, rexw ? 63 : 31);
return;
}
break;
default:
break;
}
/*
* If dest does not overlap the inputs, clearing it first is preferred.
* The XOR breaks any false dependency for the low-byte write to dest,
* and is also one byte smaller than MOVZBL.
*/
cleared = false;
if (dest != arg1 && (const_arg2 || dest != arg2)) {
tgen_arithr(s, ARITH_XOR, dest, dest);
cleared = true;
}
tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest); tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
tcg_out_ext8u(s, dest, dest);
if (!cleared) {
tcg_out_ext8u(s, dest, dest);
}
if (neg) {
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, dest);
}
} }
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 32
static void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
TCGArg arg1, TCGArg arg2, int const_arg2)
{
tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
tcg_out_ext8u(s, dest, dest);
}
#else
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args, static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
const int *const_args) const int *const_args)
{ {
@ -1610,24 +1684,14 @@ static void tcg_out_cmov(TCGContext *s, TCGCond cond, int rexw,
} }
} }
static void tcg_out_movcond32(TCGContext *s, TCGCond cond, TCGReg dest, static void tcg_out_movcond(TCGContext *s, int rexw, TCGCond cond,
TCGReg c1, TCGArg c2, int const_c2, TCGReg dest, TCGReg c1, TCGArg c2, int const_c2,
TCGReg v1) TCGReg v1)
{ {
tcg_out_cmp(s, c1, c2, const_c2, 0); tcg_out_cmp(s, c1, c2, const_c2, rexw);
tcg_out_cmov(s, cond, 0, dest, v1); tcg_out_cmov(s, cond, rexw, dest, v1);
} }
#if TCG_TARGET_REG_BITS == 64
static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGReg dest,
TCGReg c1, TCGArg c2, int const_c2,
TCGReg v1)
{
tcg_out_cmp(s, c1, c2, const_c2, P_REXW);
tcg_out_cmov(s, cond, P_REXW, dest, v1);
}
#endif
static void tcg_out_ctz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1, static void tcg_out_ctz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
TCGArg arg2, bool const_a2) TCGArg arg2, bool const_a2)
{ {
@ -2574,14 +2638,18 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_modrm(s, OPC_POPCNT + rexw, a0, a1); tcg_out_modrm(s, OPC_POPCNT + rexw, a0, a1);
break; break;
case INDEX_op_brcond_i32: OP_32_64(brcond):
tcg_out_brcond32(s, a2, a0, a1, const_args[1], arg_label(args[3]), 0); tcg_out_brcond(s, rexw, a2, a0, a1, const_args[1],
arg_label(args[3]), 0);
break; break;
case INDEX_op_setcond_i32: OP_32_64(setcond):
tcg_out_setcond32(s, args[3], a0, a1, a2, const_a2); tcg_out_setcond(s, rexw, args[3], a0, a1, a2, const_a2, false);
break; break;
case INDEX_op_movcond_i32: OP_32_64(negsetcond):
tcg_out_movcond32(s, args[5], a0, a1, a2, const_a2, args[3]); tcg_out_setcond(s, rexw, args[3], a0, a1, a2, const_a2, true);
break;
OP_32_64(movcond):
tcg_out_movcond(s, rexw, args[5], a0, a1, a2, const_a2, args[3]);
break; break;
OP_32_64(bswap16): OP_32_64(bswap16):
@ -2730,16 +2798,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
} }
break; break;
case INDEX_op_brcond_i64:
tcg_out_brcond64(s, a2, a0, a1, const_args[1], arg_label(args[3]), 0);
break;
case INDEX_op_setcond_i64:
tcg_out_setcond64(s, args[3], a0, a1, a2, const_a2);
break;
case INDEX_op_movcond_i64:
tcg_out_movcond64(s, args[5], a0, a1, a2, const_a2, args[3]);
break;
case INDEX_op_bswap64_i64: case INDEX_op_bswap64_i64:
tcg_out_bswap64(s, a0); tcg_out_bswap64(s, a0);
break; break;
@ -2751,13 +2809,30 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
OP_32_64(deposit): OP_32_64(deposit):
if (args[3] == 0 && args[4] == 8) { if (args[3] == 0 && args[4] == 8) {
/* load bits 0..7 */ /* load bits 0..7 */
tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM, a2, a0); if (const_a2) {
} else if (args[3] == 8 && args[4] == 8) { tcg_out_opc(s, OPC_MOVB_Ib | P_REXB_RM | LOWREGMASK(a0),
0, a0, 0);
tcg_out8(s, a2);
} else {
tcg_out_modrm(s, OPC_MOVB_EvGv | P_REXB_R | P_REXB_RM, a2, a0);
}
} else if (TCG_TARGET_REG_BITS == 32 && args[3] == 8 && args[4] == 8) {
/* load bits 8..15 */ /* load bits 8..15 */
tcg_out_modrm(s, OPC_MOVB_EvGv, a2, a0 + 4); if (const_a2) {
tcg_out8(s, OPC_MOVB_Ib + a0 + 4);
tcg_out8(s, a2);
} else {
tcg_out_modrm(s, OPC_MOVB_EvGv, a2, a0 + 4);
}
} else if (args[3] == 0 && args[4] == 16) { } else if (args[3] == 0 && args[4] == 16) {
/* load bits 0..15 */ /* load bits 0..15 */
tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, a2, a0); if (const_a2) {
tcg_out_opc(s, OPC_MOVL_Iv | P_DATA16 | LOWREGMASK(a0),
0, a0, 0);
tcg_out16(s, a2);
} else {
tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, a2, a0);
}
} else { } else {
g_assert_not_reached(); g_assert_not_reached();
} }
@ -3312,10 +3387,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_deposit_i32: case INDEX_op_deposit_i32:
case INDEX_op_deposit_i64: case INDEX_op_deposit_i64:
return C_O1_I2(Q, 0, Q); return C_O1_I2(q, 0, qi);
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i32:
case INDEX_op_negsetcond_i64:
return C_O1_I2(q, r, re); return C_O1_I2(q, r, re);
case INDEX_op_movcond_i32: case INDEX_op_movcond_i32:

View File

@ -150,6 +150,7 @@ typedef enum {
#define TCG_TARGET_HAS_sextract_i32 1 #define TCG_TARGET_HAS_sextract_i32 1
#define TCG_TARGET_HAS_extract2_i32 1 #define TCG_TARGET_HAS_extract2_i32 1
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_mulu2_i32 1 #define TCG_TARGET_HAS_mulu2_i32 1
@ -159,8 +160,7 @@ typedef enum {
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
/* Keep 32-bit values zero-extended in a register. */ /* Keep 32-bit values zero-extended in a register. */
#define TCG_TARGET_HAS_extrl_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_extrh_i64_i32 1
#define TCG_TARGET_HAS_div2_i64 1 #define TCG_TARGET_HAS_div2_i64 1
#define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_ext8s_i64 1 #define TCG_TARGET_HAS_ext8s_i64 1
@ -187,6 +187,7 @@ typedef enum {
#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 1 #define TCG_TARGET_HAS_extract2_i64 1
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1
#define TCG_TARGET_HAS_mulu2_i64 1 #define TCG_TARGET_HAS_mulu2_i64 1
@ -227,8 +228,8 @@ typedef enum {
#define TCG_TARGET_HAS_cmpsel_vec -1 #define TCG_TARGET_HAS_cmpsel_vec -1
#define TCG_TARGET_deposit_i32_valid(ofs, len) \ #define TCG_TARGET_deposit_i32_valid(ofs, len) \
(((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || \ (((ofs) == 0 && ((len) == 8 || (len) == 16)) || \
((ofs) == 0 && (len) == 16)) (TCG_TARGET_REG_BITS == 32 && (ofs) == 8 && (len) == 8))
#define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid #define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid
/* Check for the possibility of high-byte extraction and, for 64-bit, /* Check for the possibility of high-byte extraction and, for 64-bit,

View File

@ -86,6 +86,7 @@ typedef enum {
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 0
#define TCG_TARGET_HAS_div_i32 1 #define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_div2_i32 0 #define TCG_TARGET_HAS_div2_i32 0
@ -122,6 +123,7 @@ typedef enum {
/* 64-bit operations */ /* 64-bit operations */
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 0
#define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1 #define TCG_TARGET_HAS_rem_i64 1
#define TCG_TARGET_HAS_div2_i64 0 #define TCG_TARGET_HAS_div2_i64 0
@ -130,8 +132,7 @@ typedef enum {
#define TCG_TARGET_HAS_extract_i64 1 #define TCG_TARGET_HAS_extract_i64 1
#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0 #define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_extrl_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_extrh_i64_i32 1
#define TCG_TARGET_HAS_ext8s_i64 1 #define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1 #define TCG_TARGET_HAS_ext16s_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1 #define TCG_TARGET_HAS_ext32s_i64 1
@ -157,6 +158,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i64 0 #define TCG_TARGET_HAS_muls2_i64 0
#define TCG_TARGET_HAS_muluh_i64 1 #define TCG_TARGET_HAS_muluh_i64 1
#define TCG_TARGET_HAS_mulsh_i64 1 #define TCG_TARGET_HAS_mulsh_i64 1
#define TCG_TARGET_HAS_qemu_ldst_i128 0 #define TCG_TARGET_HAS_qemu_ldst_i128 0
#define TCG_TARGET_DEFAULT_MO (0) #define TCG_TARGET_DEFAULT_MO (0)

View File

@ -128,12 +128,12 @@ extern bool use_mips32r2_instructions;
#define TCG_TARGET_HAS_muluh_i32 1 #define TCG_TARGET_HAS_muluh_i32 1
#define TCG_TARGET_HAS_mulsh_i32 1 #define TCG_TARGET_HAS_mulsh_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1 #define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 0
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_add2_i32 0 #define TCG_TARGET_HAS_add2_i32 0
#define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_sub2_i32 0
#define TCG_TARGET_HAS_extrl_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_extrh_i64_i32 1
#define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1 #define TCG_TARGET_HAS_rem_i64 1
#define TCG_TARGET_HAS_not_i64 1 #define TCG_TARGET_HAS_not_i64 1
@ -150,6 +150,7 @@ extern bool use_mips32r2_instructions;
#define TCG_TARGET_HAS_mulsh_i64 1 #define TCG_TARGET_HAS_mulsh_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1 #define TCG_TARGET_HAS_ext32s_i64 1
#define TCG_TARGET_HAS_ext32u_i64 1 #define TCG_TARGET_HAS_ext32u_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 0
#endif #endif
/* optional instructions detected at runtime */ /* optional instructions detected at runtime */

View File

@ -1279,6 +1279,8 @@ static bool fold_ctpop(OptContext *ctx, TCGOp *op)
static bool fold_deposit(OptContext *ctx, TCGOp *op) static bool fold_deposit(OptContext *ctx, TCGOp *op)
{ {
TCGOpcode and_opc;
if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) { if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
uint64_t t1 = arg_info(op->args[1])->val; uint64_t t1 = arg_info(op->args[1])->val;
uint64_t t2 = arg_info(op->args[2])->val; uint64_t t2 = arg_info(op->args[2])->val;
@ -1287,6 +1289,41 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
return tcg_opt_gen_movi(ctx, op, op->args[0], t1); return tcg_opt_gen_movi(ctx, op, op->args[0], t1);
} }
switch (ctx->type) {
case TCG_TYPE_I32:
and_opc = INDEX_op_and_i32;
break;
case TCG_TYPE_I64:
and_opc = INDEX_op_and_i64;
break;
default:
g_assert_not_reached();
}
/* Inserting a value into zero at offset 0. */
if (arg_is_const(op->args[1])
&& arg_info(op->args[1])->val == 0
&& op->args[3] == 0) {
uint64_t mask = MAKE_64BIT_MASK(0, op->args[4]);
op->opc = and_opc;
op->args[1] = op->args[2];
op->args[2] = temp_arg(tcg_constant_internal(ctx->type, mask));
ctx->z_mask = mask & arg_info(op->args[1])->z_mask;
return false;
}
/* Inserting zero into a value. */
if (arg_is_const(op->args[2])
&& arg_info(op->args[2])->val == 0) {
uint64_t mask = deposit64(-1, op->args[3], op->args[4], 0);
op->opc = and_opc;
op->args[2] = temp_arg(tcg_constant_internal(ctx->type, mask));
ctx->z_mask = mask & arg_info(op->args[1])->z_mask;
return false;
}
ctx->z_mask = deposit64(arg_info(op->args[1])->z_mask, ctx->z_mask = deposit64(arg_info(op->args[1])->z_mask,
op->args[3], op->args[4], op->args[3], op->args[4],
arg_info(op->args[2])->z_mask); arg_info(op->args[2])->z_mask);
@ -1530,14 +1567,22 @@ static bool fold_movcond(OptContext *ctx, TCGOp *op)
if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) { if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
uint64_t tv = arg_info(op->args[3])->val; uint64_t tv = arg_info(op->args[3])->val;
uint64_t fv = arg_info(op->args[4])->val; uint64_t fv = arg_info(op->args[4])->val;
TCGOpcode opc; TCGOpcode opc, negopc = 0;
switch (ctx->type) { switch (ctx->type) {
case TCG_TYPE_I32: case TCG_TYPE_I32:
opc = INDEX_op_setcond_i32; opc = INDEX_op_setcond_i32;
if (TCG_TARGET_HAS_negsetcond_i32) {
negopc = INDEX_op_negsetcond_i32;
}
tv = (int32_t)tv;
fv = (int32_t)fv;
break; break;
case TCG_TYPE_I64: case TCG_TYPE_I64:
opc = INDEX_op_setcond_i64; opc = INDEX_op_setcond_i64;
if (TCG_TARGET_HAS_negsetcond_i64) {
negopc = INDEX_op_negsetcond_i64;
}
break; break;
default: default:
g_assert_not_reached(); g_assert_not_reached();
@ -1549,6 +1594,14 @@ static bool fold_movcond(OptContext *ctx, TCGOp *op)
} else if (fv == 1 && tv == 0) { } else if (fv == 1 && tv == 0) {
op->opc = opc; op->opc = opc;
op->args[3] = tcg_invert_cond(cond); op->args[3] = tcg_invert_cond(cond);
} else if (negopc) {
if (tv == -1 && fv == 0) {
op->opc = negopc;
op->args[3] = cond;
} else if (fv == -1 && tv == 0) {
op->opc = negopc;
op->args[3] = tcg_invert_cond(cond);
}
} }
} }
return false; return false;
@ -1759,6 +1812,26 @@ static bool fold_setcond(OptContext *ctx, TCGOp *op)
return false; return false;
} }
static bool fold_negsetcond(OptContext *ctx, TCGOp *op)
{
TCGCond cond = op->args[3];
int i;
if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
op->args[3] = cond = tcg_swap_cond(cond);
}
i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
if (i >= 0) {
return tcg_opt_gen_movi(ctx, op, op->args[0], -i);
}
/* Value is {0,-1} so all bits are repetitions of the sign. */
ctx->s_mask = -1;
return false;
}
static bool fold_setcond2(OptContext *ctx, TCGOp *op) static bool fold_setcond2(OptContext *ctx, TCGOp *op)
{ {
TCGCond cond = op->args[5]; TCGCond cond = op->args[5];
@ -2216,6 +2289,9 @@ void tcg_optimize(TCGContext *s)
CASE_OP_32_64(setcond): CASE_OP_32_64(setcond):
done = fold_setcond(&ctx, op); done = fold_setcond(&ctx, op);
break; break;
CASE_OP_32_64(negsetcond):
done = fold_negsetcond(&ctx, op);
break;
case INDEX_op_setcond2_i32: case INDEX_op_setcond2_i32:
done = fold_setcond2(&ctx, op); done = fold_setcond2(&ctx, op);
break; break;

View File

@ -447,6 +447,11 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
#define TW XO31( 4) #define TW XO31( 4)
#define TRAP (TW | TO(31)) #define TRAP (TW | TO(31))
#define SETBC XO31(384) /* v3.10 */
#define SETBCR XO31(416) /* v3.10 */
#define SETNBC XO31(448) /* v3.10 */
#define SETNBCR XO31(480) /* v3.10 */
#define NOP ORI /* ori 0,0,0 */ #define NOP ORI /* ori 0,0,0 */
#define LVX XO31(103) #define LVX XO31(103)
@ -1548,8 +1553,20 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
} }
static void tcg_out_setcond_eq0(TCGContext *s, TCGType type, static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
TCGReg dst, TCGReg src) TCGReg dst, TCGReg src, bool neg)
{ {
if (neg && (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I64)) {
/*
* X != 0 implies X + -1 generates a carry.
* RT = (~X + X) + CA
* = -1 + CA
* = CA ? 0 : -1
*/
tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
tcg_out32(s, SUBFE | TAB(dst, src, src));
return;
}
if (type == TCG_TYPE_I32) { if (type == TCG_TYPE_I32) {
tcg_out32(s, CNTLZW | RS(src) | RA(dst)); tcg_out32(s, CNTLZW | RS(src) | RA(dst));
tcg_out_shri32(s, dst, dst, 5); tcg_out_shri32(s, dst, dst, 5);
@ -1557,18 +1574,28 @@ static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
tcg_out32(s, CNTLZD | RS(src) | RA(dst)); tcg_out32(s, CNTLZD | RS(src) | RA(dst));
tcg_out_shri64(s, dst, dst, 6); tcg_out_shri64(s, dst, dst, 6);
} }
if (neg) {
tcg_out32(s, NEG | RT(dst) | RA(dst));
}
} }
static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src) static void tcg_out_setcond_ne0(TCGContext *s, TCGType type,
TCGReg dst, TCGReg src, bool neg)
{ {
/* X != 0 implies X + -1 generates a carry. Extra addition if (!neg && (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I64)) {
trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C. */ /*
if (dst != src) { * X != 0 implies X + -1 generates a carry. Extra addition
tcg_out32(s, ADDIC | TAI(dst, src, -1)); * trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C.
tcg_out32(s, SUBFE | TAB(dst, dst, src)); */
} else {
tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1)); tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src)); tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
return;
}
tcg_out_setcond_eq0(s, type, dst, src, false);
if (neg) {
tcg_out32(s, ADDI | TAI(dst, dst, -1));
} else {
tcg_out_xori32(s, dst, dst, 1);
} }
} }
@ -1590,9 +1617,10 @@ static TCGReg tcg_gen_setcond_xor(TCGContext *s, TCGReg arg1, TCGArg arg2,
static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond, static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
TCGArg arg0, TCGArg arg1, TCGArg arg2, TCGArg arg0, TCGArg arg1, TCGArg arg2,
int const_arg2) int const_arg2, bool neg)
{ {
int crop, sh; int sh;
bool inv;
tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32); tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
@ -1601,18 +1629,31 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
arg2 = (uint32_t)arg2; arg2 = (uint32_t)arg2;
} }
/* With SETBC/SETBCR, we can always implement with 2 insns. */
if (have_isa_3_10) {
tcg_insn_unit bi, opc;
tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
/* Re-use tcg_to_bc for BI and BO_COND_{TRUE,FALSE}. */
bi = tcg_to_bc[cond] & (0x1f << 16);
if (tcg_to_bc[cond] & BO(8)) {
opc = neg ? SETNBC : SETBC;
} else {
opc = neg ? SETNBCR : SETBCR;
}
tcg_out32(s, opc | RT(arg0) | bi);
return;
}
/* Handle common and trivial cases before handling anything else. */ /* Handle common and trivial cases before handling anything else. */
if (arg2 == 0) { if (arg2 == 0) {
switch (cond) { switch (cond) {
case TCG_COND_EQ: case TCG_COND_EQ:
tcg_out_setcond_eq0(s, type, arg0, arg1); tcg_out_setcond_eq0(s, type, arg0, arg1, neg);
return; return;
case TCG_COND_NE: case TCG_COND_NE:
if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { tcg_out_setcond_ne0(s, type, arg0, arg1, neg);
tcg_out_ext32u(s, TCG_REG_R0, arg1);
arg1 = TCG_REG_R0;
}
tcg_out_setcond_ne0(s, arg0, arg1);
return; return;
case TCG_COND_GE: case TCG_COND_GE:
tcg_out32(s, NOR | SAB(arg1, arg0, arg1)); tcg_out32(s, NOR | SAB(arg1, arg0, arg1));
@ -1621,9 +1662,17 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
case TCG_COND_LT: case TCG_COND_LT:
/* Extract the sign bit. */ /* Extract the sign bit. */
if (type == TCG_TYPE_I32) { if (type == TCG_TYPE_I32) {
tcg_out_shri32(s, arg0, arg1, 31); if (neg) {
tcg_out_sari32(s, arg0, arg1, 31);
} else {
tcg_out_shri32(s, arg0, arg1, 31);
}
} else { } else {
tcg_out_shri64(s, arg0, arg1, 63); if (neg) {
tcg_out_sari64(s, arg0, arg1, 63);
} else {
tcg_out_shri64(s, arg0, arg1, 63);
}
} }
return; return;
default: default:
@ -1641,7 +1690,7 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
isel = tcg_to_isel[cond]; isel = tcg_to_isel[cond];
tcg_out_movi(s, type, arg0, 1); tcg_out_movi(s, type, arg0, neg ? -1 : 1);
if (isel & 1) { if (isel & 1) {
/* arg0 = (bc ? 0 : 1) */ /* arg0 = (bc ? 0 : 1) */
tab = TAB(arg0, 0, arg0); tab = TAB(arg0, 0, arg0);
@ -1655,51 +1704,47 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
return; return;
} }
inv = false;
switch (cond) { switch (cond) {
case TCG_COND_EQ: case TCG_COND_EQ:
arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2); arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
tcg_out_setcond_eq0(s, type, arg0, arg1); tcg_out_setcond_eq0(s, type, arg0, arg1, neg);
return; break;
case TCG_COND_NE: case TCG_COND_NE:
arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2); arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
/* Discard the high bits only once, rather than both inputs. */ tcg_out_setcond_ne0(s, type, arg0, arg1, neg);
if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { break;
tcg_out_ext32u(s, TCG_REG_R0, arg1);
arg1 = TCG_REG_R0;
}
tcg_out_setcond_ne0(s, arg0, arg1);
return;
case TCG_COND_LE:
case TCG_COND_LEU:
inv = true;
/* fall through */
case TCG_COND_GT: case TCG_COND_GT:
case TCG_COND_GTU: case TCG_COND_GTU:
sh = 30; sh = 30; /* CR7 CR_GT */
crop = 0;
goto crtest;
case TCG_COND_LT:
case TCG_COND_LTU:
sh = 29;
crop = 0;
goto crtest; goto crtest;
case TCG_COND_GE: case TCG_COND_GE:
case TCG_COND_GEU: case TCG_COND_GEU:
sh = 31; inv = true;
crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT); /* fall through */
case TCG_COND_LT:
case TCG_COND_LTU:
sh = 29; /* CR7 CR_LT */
goto crtest; goto crtest;
case TCG_COND_LE:
case TCG_COND_LEU:
sh = 31;
crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
crtest: crtest:
tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type); tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
if (crop) {
tcg_out32(s, crop);
}
tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7)); tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31); tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31);
if (neg && inv) {
tcg_out32(s, ADDI | TAI(arg0, arg0, -1));
} else if (neg) {
tcg_out32(s, NEG | RT(arg0) | RA(arg0));
} else if (inv) {
tcg_out_xori32(s, arg0, arg0, 1);
}
break; break;
default: default:
@ -2982,11 +3027,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2], tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
const_args[2]); const_args[2], false);
break; break;
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2], tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
const_args[2]); const_args[2], false);
break;
case INDEX_op_negsetcond_i32:
tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
const_args[2], true);
break;
case INDEX_op_negsetcond_i64:
tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
const_args[2], true);
break; break;
case INDEX_op_setcond2_i32: case INDEX_op_setcond2_i32:
tcg_out_setcond2(s, args, const_args); tcg_out_setcond2(s, args, const_args);
@ -3724,6 +3777,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_rotl_i32: case INDEX_op_rotl_i32:
case INDEX_op_rotr_i32: case INDEX_op_rotr_i32:
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_negsetcond_i32:
case INDEX_op_and_i64: case INDEX_op_and_i64:
case INDEX_op_andc_i64: case INDEX_op_andc_i64:
case INDEX_op_shl_i64: case INDEX_op_shl_i64:
@ -3732,6 +3786,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_rotl_i64: case INDEX_op_rotl_i64:
case INDEX_op_rotr_i64: case INDEX_op_rotr_i64:
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i64:
return C_O1_I2(r, r, ri); return C_O1_I2(r, r, ri);
case INDEX_op_mul_i32: case INDEX_op_mul_i32:

View File

@ -97,6 +97,7 @@ typedef enum {
#define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_sextract_i32 0
#define TCG_TARGET_HAS_extract2_i32 0 #define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_mulu2_i32 0
#define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 1 #define TCG_TARGET_HAS_muluh_i32 1
@ -106,8 +107,7 @@ typedef enum {
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_add2_i32 0 #define TCG_TARGET_HAS_add2_i32 0
#define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_sub2_i32 0
#define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extrh_i64_i32 0
#define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 have_isa_3_00 #define TCG_TARGET_HAS_rem_i64 have_isa_3_00
#define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_rot_i64 1
@ -135,6 +135,7 @@ typedef enum {
#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0 #define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1
#define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0

View File

@ -69,7 +69,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
static const int tcg_target_reg_alloc_order[] = { static const int tcg_target_reg_alloc_order[] = {
/* Call saved registers */ /* Call saved registers */
/* TCG_REG_S0 reservered for TCG_AREG0 */ /* TCG_REG_S0 reserved for TCG_AREG0 */
TCG_REG_S1, TCG_REG_S1,
TCG_REG_S2, TCG_REG_S2,
TCG_REG_S3, TCG_REG_S3,
@ -260,7 +260,7 @@ typedef enum {
/* Zba: Bit manipulation extension, address generation */ /* Zba: Bit manipulation extension, address generation */
OPC_ADD_UW = 0x0800003b, OPC_ADD_UW = 0x0800003b,
/* Zbb: Bit manipulation extension, basic bit manipulaton */ /* Zbb: Bit manipulation extension, basic bit manipulation */
OPC_ANDN = 0x40007033, OPC_ANDN = 0x40007033,
OPC_CLZ = 0x60001013, OPC_CLZ = 0x60001013,
OPC_CLZW = 0x6000101b, OPC_CLZW = 0x6000101b,
@ -936,6 +936,44 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
} }
} }
static void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg arg1, tcg_target_long arg2, bool c2)
{
int tmpflags;
TCGReg tmp;
/* For LT/GE comparison against 0, replicate the sign bit. */
if (c2 && arg2 == 0) {
switch (cond) {
case TCG_COND_GE:
tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1);
arg1 = ret;
/* fall through */
case TCG_COND_LT:
tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1);
return;
default:
break;
}
}
tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
tmp = tmpflags & ~SETCOND_FLAGS;
/* If intermediate result is zero/non-zero: test != 0. */
if (tmpflags & SETCOND_NEZ) {
tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
tmp = ret;
}
/* Produce the 0/-1 result. */
if (tmpflags & SETCOND_INV) {
tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1);
} else {
tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp);
}
}
static void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne, static void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
int val1, bool c_val1, int val1, bool c_val1,
int val2, bool c_val2) int val2, bool c_val2)
@ -1782,6 +1820,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_setcond(s, args[3], a0, a1, a2, c2); tcg_out_setcond(s, args[3], a0, a1, a2, c2);
break; break;
case INDEX_op_negsetcond_i32:
case INDEX_op_negsetcond_i64:
tcg_out_negsetcond(s, args[3], a0, a1, a2, c2);
break;
case INDEX_op_movcond_i32: case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64: case INDEX_op_movcond_i64:
tcg_out_movcond(s, args[5], a0, a1, a2, c2, tcg_out_movcond(s, args[5], a0, a1, a2, c2,
@ -1910,6 +1953,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_xor_i64: case INDEX_op_xor_i64:
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i32:
case INDEX_op_negsetcond_i64:
return C_O1_I2(r, r, rI); return C_O1_I2(r, r, rI);
case INDEX_op_andc_i32: case INDEX_op_andc_i32:

View File

@ -88,6 +88,7 @@ extern bool have_zbb;
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_div_i32 1 #define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_div2_i32 0 #define TCG_TARGET_HAS_div2_i32 0
@ -123,6 +124,7 @@ extern bool have_zbb;
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1 #define TCG_TARGET_HAS_rem_i64 1
#define TCG_TARGET_HAS_div2_i64 0 #define TCG_TARGET_HAS_div2_i64 0
@ -131,8 +133,7 @@ extern bool have_zbb;
#define TCG_TARGET_HAS_extract_i64 0 #define TCG_TARGET_HAS_extract_i64 0
#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0 #define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_extrl_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_extrh_i64_i32 1
#define TCG_TARGET_HAS_ext8s_i64 1 #define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1 #define TCG_TARGET_HAS_ext16s_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1 #define TCG_TARGET_HAS_ext32s_i64 1

View File

@ -1266,7 +1266,8 @@ static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
} }
static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond, static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
TCGReg dest, TCGReg c1, TCGArg c2, int c2const) TCGReg dest, TCGReg c1, TCGArg c2,
bool c2const, bool neg)
{ {
int cc; int cc;
@ -1275,11 +1276,27 @@ static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
/* Emit: d = 0, d = (cc ? 1 : d). */ /* Emit: d = 0, d = (cc ? 1 : d). */
cc = tgen_cmp(s, type, cond, c1, c2, c2const, false); cc = tgen_cmp(s, type, cond, c1, c2, c2const, false);
tcg_out_movi(s, TCG_TYPE_I64, dest, 0); tcg_out_movi(s, TCG_TYPE_I64, dest, 0);
tcg_out_insn(s, RIEg, LOCGHI, dest, 1, cc); tcg_out_insn(s, RIEg, LOCGHI, dest, neg ? -1 : 1, cc);
return; return;
} }
restart: switch (cond) {
case TCG_COND_GEU:
case TCG_COND_LTU:
case TCG_COND_LT:
case TCG_COND_GE:
/* Swap operands so that we can use LEU/GTU/GT/LE. */
if (!c2const) {
TCGReg t = c1;
c1 = c2;
c2 = t;
cond = tcg_swap_cond(cond);
}
break;
default:
break;
}
switch (cond) { switch (cond) {
case TCG_COND_NE: case TCG_COND_NE:
/* X != 0 is X > 0. */ /* X != 0 is X > 0. */
@ -1292,11 +1309,20 @@ static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
case TCG_COND_GTU: case TCG_COND_GTU:
case TCG_COND_GT: case TCG_COND_GT:
/* The result of a compare has CC=2 for GT and CC=3 unused. /*
ADD LOGICAL WITH CARRY considers (CC & 2) the carry bit. */ * The result of a compare has CC=2 for GT and CC=3 unused.
* ADD LOGICAL WITH CARRY considers (CC & 2) the carry bit.
*/
tgen_cmp(s, type, cond, c1, c2, c2const, true); tgen_cmp(s, type, cond, c1, c2, c2const, true);
tcg_out_movi(s, type, dest, 0); tcg_out_movi(s, type, dest, 0);
tcg_out_insn(s, RRE, ALCGR, dest, dest); tcg_out_insn(s, RRE, ALCGR, dest, dest);
if (neg) {
if (type == TCG_TYPE_I32) {
tcg_out_insn(s, RR, LCR, dest, dest);
} else {
tcg_out_insn(s, RRE, LCGR, dest, dest);
}
}
return; return;
case TCG_COND_EQ: case TCG_COND_EQ:
@ -1310,27 +1336,17 @@ static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
case TCG_COND_LEU: case TCG_COND_LEU:
case TCG_COND_LE: case TCG_COND_LE:
/* As above, but we're looking for borrow, or !carry. /*
The second insn computes d - d - borrow, or -1 for true * As above, but we're looking for borrow, or !carry.
and 0 for false. So we must mask to 1 bit afterward. */ * The second insn computes d - d - borrow, or -1 for true
* and 0 for false. So we must mask to 1 bit afterward.
*/
tgen_cmp(s, type, cond, c1, c2, c2const, true); tgen_cmp(s, type, cond, c1, c2, c2const, true);
tcg_out_insn(s, RRE, SLBGR, dest, dest); tcg_out_insn(s, RRE, SLBGR, dest, dest);
tgen_andi(s, type, dest, 1); if (!neg) {
return; tgen_andi(s, type, dest, 1);
case TCG_COND_GEU:
case TCG_COND_LTU:
case TCG_COND_LT:
case TCG_COND_GE:
/* Swap operands so that we can use LEU/GTU/GT/LE. */
if (!c2const) {
TCGReg t = c1;
c1 = c2;
c2 = t;
cond = tcg_swap_cond(cond);
goto restart;
} }
break; return;
default: default:
g_assert_not_reached(); g_assert_not_reached();
@ -1339,7 +1355,7 @@ static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
cc = tgen_cmp(s, type, cond, c1, c2, c2const, false); cc = tgen_cmp(s, type, cond, c1, c2, c2const, false);
/* Emit: d = 0, t = 1, d = (cc ? t : d). */ /* Emit: d = 0, t = 1, d = (cc ? t : d). */
tcg_out_movi(s, TCG_TYPE_I64, dest, 0); tcg_out_movi(s, TCG_TYPE_I64, dest, 0);
tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, 1); tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, neg ? -1 : 1);
tcg_out_insn(s, RRFc, LOCGR, dest, TCG_TMP0, cc); tcg_out_insn(s, RRFc, LOCGR, dest, TCG_TMP0, cc);
} }
@ -2288,7 +2304,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break; break;
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
tgen_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], tgen_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1],
args[2], const_args[2]); args[2], const_args[2], false);
break;
case INDEX_op_negsetcond_i32:
tgen_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1],
args[2], const_args[2], true);
break; break;
case INDEX_op_movcond_i32: case INDEX_op_movcond_i32:
tgen_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], tgen_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1],
@ -2566,7 +2586,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break; break;
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
tgen_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], tgen_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1],
args[2], const_args[2]); args[2], const_args[2], false);
break;
case INDEX_op_negsetcond_i64:
tgen_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1],
args[2], const_args[2], true);
break; break;
case INDEX_op_movcond_i64: case INDEX_op_movcond_i64:
tgen_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1], tgen_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1],
@ -3109,8 +3133,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_rotr_i32: case INDEX_op_rotr_i32:
case INDEX_op_rotr_i64: case INDEX_op_rotr_i64:
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_negsetcond_i32:
return C_O1_I2(r, r, ri); return C_O1_I2(r, r, ri);
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i64:
return C_O1_I2(r, r, rA); return C_O1_I2(r, r, rA);
case INDEX_op_clz_i64: case INDEX_op_clz_i64:

View File

@ -96,14 +96,14 @@ extern uint64_t s390_facilities[3];
#define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_sextract_i32 0
#define TCG_TARGET_HAS_extract2_i32 0 #define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_mulu2_i32 0
#define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extrh_i64_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_div2_i64 1 #define TCG_TARGET_HAS_div2_i64 1
@ -132,6 +132,7 @@ extern uint64_t s390_facilities[3];
#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0 #define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1
#define TCG_TARGET_HAS_mulu2_i64 1 #define TCG_TARGET_HAS_mulu2_i64 1

View File

@ -720,7 +720,7 @@ static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
} }
static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret, static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg c1, int32_t c2, int c2const) TCGReg c1, int32_t c2, int c2const, bool neg)
{ {
/* For 32-bit comparisons, we can play games with ADDC/SUBC. */ /* For 32-bit comparisons, we can play games with ADDC/SUBC. */
switch (cond) { switch (cond) {
@ -760,22 +760,34 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
default: default:
tcg_out_cmp(s, c1, c2, c2const); tcg_out_cmp(s, c1, c2, c2const);
tcg_out_movi_s13(s, ret, 0); tcg_out_movi_s13(s, ret, 0);
tcg_out_movcc(s, cond, MOVCC_ICC, ret, 1, 1); tcg_out_movcc(s, cond, MOVCC_ICC, ret, neg ? -1 : 1, 1);
return; return;
} }
tcg_out_cmp(s, c1, c2, c2const); tcg_out_cmp(s, c1, c2, c2const);
if (cond == TCG_COND_LTU) { if (cond == TCG_COND_LTU) {
tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDC); if (neg) {
/* 0 - 0 - C = -C = (C ? -1 : 0) */
tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_SUBC);
} else {
/* 0 + 0 + C = C = (C ? 1 : 0) */
tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDC);
}
} else { } else {
tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBC); if (neg) {
/* 0 + -1 + C = C - 1 = (C ? 0 : -1) */
tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_ADDC);
} else {
/* 0 - -1 - C = 1 - C = (C ? 0 : 1) */
tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBC);
}
} }
} }
static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret, static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg c1, int32_t c2, int c2const) TCGReg c1, int32_t c2, int c2const, bool neg)
{ {
if (use_vis3_instructions) { if (use_vis3_instructions && !neg) {
switch (cond) { switch (cond) {
case TCG_COND_NE: case TCG_COND_NE:
if (c2 != 0) { if (c2 != 0) {
@ -796,11 +808,11 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
if the input does not overlap the output. */ if the input does not overlap the output. */
if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) { if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) {
tcg_out_movi_s13(s, ret, 0); tcg_out_movi_s13(s, ret, 0);
tcg_out_movr(s, cond, ret, c1, 1, 1); tcg_out_movr(s, cond, ret, c1, neg ? -1 : 1, 1);
} else { } else {
tcg_out_cmp(s, c1, c2, c2const); tcg_out_cmp(s, c1, c2, c2const);
tcg_out_movi_s13(s, ret, 0); tcg_out_movi_s13(s, ret, 0);
tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1); tcg_out_movcc(s, cond, MOVCC_XCC, ret, neg ? -1 : 1, 1);
} }
} }
@ -1355,7 +1367,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_brcond_i32(s, a2, a0, a1, const_args[1], arg_label(args[3])); tcg_out_brcond_i32(s, a2, a0, a1, const_args[1], arg_label(args[3]));
break; break;
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
tcg_out_setcond_i32(s, args[3], a0, a1, a2, c2); tcg_out_setcond_i32(s, args[3], a0, a1, a2, c2, false);
break;
case INDEX_op_negsetcond_i32:
tcg_out_setcond_i32(s, args[3], a0, a1, a2, c2, true);
break; break;
case INDEX_op_movcond_i32: case INDEX_op_movcond_i32:
tcg_out_movcond_i32(s, args[5], a0, a1, a2, c2, args[3], const_args[3]); tcg_out_movcond_i32(s, args[5], a0, a1, a2, c2, args[3], const_args[3]);
@ -1437,7 +1452,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_brcond_i64(s, a2, a0, a1, const_args[1], arg_label(args[3])); tcg_out_brcond_i64(s, a2, a0, a1, const_args[1], arg_label(args[3]));
break; break;
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
tcg_out_setcond_i64(s, args[3], a0, a1, a2, c2); tcg_out_setcond_i64(s, args[3], a0, a1, a2, c2, false);
break;
case INDEX_op_negsetcond_i64:
tcg_out_setcond_i64(s, args[3], a0, a1, a2, c2, true);
break; break;
case INDEX_op_movcond_i64: case INDEX_op_movcond_i64:
tcg_out_movcond_i64(s, args[5], a0, a1, a2, c2, args[3], const_args[3]); tcg_out_movcond_i64(s, args[5], a0, a1, a2, c2, args[3], const_args[3]);
@ -1564,6 +1582,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_sar_i64: case INDEX_op_sar_i64:
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i32:
case INDEX_op_negsetcond_i64:
return C_O1_I2(r, rZ, rJ); return C_O1_I2(r, rZ, rJ);
case INDEX_op_brcond_i32: case INDEX_op_brcond_i32:

View File

@ -106,6 +106,7 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_sextract_i32 0
#define TCG_TARGET_HAS_extract2_i32 0 #define TCG_TARGET_HAS_extract2_i32 0
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_mulu2_i32 1 #define TCG_TARGET_HAS_mulu2_i32 1
@ -114,8 +115,7 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#define TCG_TARGET_HAS_extrl_i64_i32 1 #define TCG_TARGET_HAS_extr_i64_i32 1
#define TCG_TARGET_HAS_extrh_i64_i32 1
#define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_rot_i64 0 #define TCG_TARGET_HAS_rot_i64 0
@ -143,6 +143,7 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0 #define TCG_TARGET_HAS_extract2_i64 0
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1
#define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0

View File

@ -3692,8 +3692,7 @@ static void expand_cmp_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs,
for (i = 0; i < oprsz; i += 4) { for (i = 0; i < oprsz; i += 4) {
tcg_gen_ld_i32(t0, cpu_env, aofs + i); tcg_gen_ld_i32(t0, cpu_env, aofs + i);
tcg_gen_ld_i32(t1, cpu_env, bofs + i); tcg_gen_ld_i32(t1, cpu_env, bofs + i);
tcg_gen_setcond_i32(cond, t0, t0, t1); tcg_gen_negsetcond_i32(cond, t0, t0, t1);
tcg_gen_neg_i32(t0, t0);
tcg_gen_st_i32(t0, cpu_env, dofs + i); tcg_gen_st_i32(t0, cpu_env, dofs + i);
} }
tcg_temp_free_i32(t1); tcg_temp_free_i32(t1);
@ -3710,8 +3709,7 @@ static void expand_cmp_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs,
for (i = 0; i < oprsz; i += 8) { for (i = 0; i < oprsz; i += 8) {
tcg_gen_ld_i64(t0, cpu_env, aofs + i); tcg_gen_ld_i64(t0, cpu_env, aofs + i);
tcg_gen_ld_i64(t1, cpu_env, bofs + i); tcg_gen_ld_i64(t1, cpu_env, bofs + i);
tcg_gen_setcond_i64(cond, t0, t0, t1); tcg_gen_negsetcond_i64(cond, t0, t0, t1);
tcg_gen_neg_i64(t0, t0);
tcg_gen_st_i64(t0, cpu_env, dofs + i); tcg_gen_st_i64(t0, cpu_env, dofs + i);
} }
tcg_temp_free_i64(t1); tcg_temp_free_i64(t1);

View File

@ -276,6 +276,21 @@ void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2)); tcg_gen_setcond_i32(cond, ret, arg1, tcg_constant_i32(arg2));
} }
void tcg_gen_negsetcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2)
{
if (cond == TCG_COND_ALWAYS) {
tcg_gen_movi_i32(ret, -1);
} else if (cond == TCG_COND_NEVER) {
tcg_gen_movi_i32(ret, 0);
} else if (TCG_TARGET_HAS_negsetcond_i32) {
tcg_gen_op4i_i32(INDEX_op_negsetcond_i32, ret, arg1, arg2, cond);
} else {
tcg_gen_setcond_i32(cond, ret, arg1, arg2);
tcg_gen_neg_i32(ret, ret);
}
}
void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{ {
if (arg2 == 0) { if (arg2 == 0) {
@ -848,8 +863,7 @@ void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
} else { } else {
TCGv_i32 t0 = tcg_temp_ebb_new_i32(); TCGv_i32 t0 = tcg_temp_ebb_new_i32();
TCGv_i32 t1 = tcg_temp_ebb_new_i32(); TCGv_i32 t1 = tcg_temp_ebb_new_i32();
tcg_gen_setcond_i32(cond, t0, c1, c2); tcg_gen_negsetcond_i32(cond, t0, c1, c2);
tcg_gen_neg_i32(t0, t0);
tcg_gen_and_i32(t1, v1, t0); tcg_gen_and_i32(t1, v1, t0);
tcg_gen_andc_i32(ret, v2, t0); tcg_gen_andc_i32(ret, v2, t0);
tcg_gen_or_i32(ret, ret, t1); tcg_gen_or_i32(ret, ret, t1);
@ -1021,6 +1035,14 @@ void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
} }
} }
/*
* bswap16_i32: 16-bit byte swap on the low bits of a 32-bit value.
*
* Byte pattern: xxab -> yyba
*
* With TCG_BSWAP_IZ, x == zero, else undefined.
* With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined.
*/
void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags) void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
{ {
/* Only one extension flag may be present. */ /* Only one extension flag may be present. */
@ -1032,27 +1054,35 @@ void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg, int flags)
TCGv_i32 t0 = tcg_temp_ebb_new_i32(); TCGv_i32 t0 = tcg_temp_ebb_new_i32();
TCGv_i32 t1 = tcg_temp_ebb_new_i32(); TCGv_i32 t1 = tcg_temp_ebb_new_i32();
tcg_gen_shri_i32(t0, arg, 8); /* arg = ..ab (IZ) xxab (!IZ) */
tcg_gen_shri_i32(t0, arg, 8); /* t0 = ...a (IZ) .xxa (!IZ) */
if (!(flags & TCG_BSWAP_IZ)) { if (!(flags & TCG_BSWAP_IZ)) {
tcg_gen_ext8u_i32(t0, t0); tcg_gen_ext8u_i32(t0, t0); /* t0 = ...a */
} }
if (flags & TCG_BSWAP_OS) { if (flags & TCG_BSWAP_OS) {
tcg_gen_shli_i32(t1, arg, 24); tcg_gen_shli_i32(t1, arg, 24); /* t1 = b... */
tcg_gen_sari_i32(t1, t1, 16); tcg_gen_sari_i32(t1, t1, 16); /* t1 = ssb. */
} else if (flags & TCG_BSWAP_OZ) { } else if (flags & TCG_BSWAP_OZ) {
tcg_gen_ext8u_i32(t1, arg); tcg_gen_ext8u_i32(t1, arg); /* t1 = ...b */
tcg_gen_shli_i32(t1, t1, 8); tcg_gen_shli_i32(t1, t1, 8); /* t1 = ..b. */
} else { } else {
tcg_gen_shli_i32(t1, arg, 8); tcg_gen_shli_i32(t1, arg, 8); /* t1 = xab. */
} }
tcg_gen_or_i32(ret, t0, t1); tcg_gen_or_i32(ret, t0, t1); /* ret = ..ba (OZ) */
/* = ssba (OS) */
/* = xaba (no flag) */
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1); tcg_temp_free_i32(t1);
} }
} }
/*
* bswap32_i32: 32-bit byte swap on a 32-bit value.
*
* Byte pattern: abcd -> dcba
*/
void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg) void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
{ {
if (TCG_TARGET_HAS_bswap32_i32) { if (TCG_TARGET_HAS_bswap32_i32) {
@ -1078,6 +1108,11 @@ void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
} }
} }
/*
* hswap_i32: Swap 16-bit halfwords within a 32-bit value.
*
* Byte pattern: abcd -> cdab
*/
void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg) void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg)
{ {
/* Swapping 2 16-bit elements is a rotate. */ /* Swapping 2 16-bit elements is a rotate. */
@ -1567,6 +1602,27 @@ void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
} }
} }
void tcg_gen_negsetcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2)
{
if (cond == TCG_COND_ALWAYS) {
tcg_gen_movi_i64(ret, -1);
} else if (cond == TCG_COND_NEVER) {
tcg_gen_movi_i64(ret, 0);
} else if (TCG_TARGET_HAS_negsetcond_i64) {
tcg_gen_op4i_i64(INDEX_op_negsetcond_i64, ret, arg1, arg2, cond);
} else if (TCG_TARGET_REG_BITS == 32) {
tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
TCGV_LOW(arg1), TCGV_HIGH(arg1),
TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
tcg_gen_neg_i32(TCGV_LOW(ret), TCGV_LOW(ret));
tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_LOW(ret));
} else {
tcg_gen_setcond_i64(cond, ret, arg1, arg2);
tcg_gen_neg_i64(ret, ret);
}
}
void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{ {
if (arg2 == 0) { if (arg2 == 0) {
@ -1721,6 +1777,14 @@ void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
} }
} }
/*
* bswap16_i64: 16-bit byte swap on the low bits of a 64-bit value.
*
* Byte pattern: xxxxxxxxab -> yyyyyyyyba
*
* With TCG_BSWAP_IZ, x == zero, else undefined.
* With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined.
*/
void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
{ {
/* Only one extension flag may be present. */ /* Only one extension flag may be present. */
@ -1739,27 +1803,38 @@ void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
TCGv_i64 t0 = tcg_temp_ebb_new_i64(); TCGv_i64 t0 = tcg_temp_ebb_new_i64();
TCGv_i64 t1 = tcg_temp_ebb_new_i64(); TCGv_i64 t1 = tcg_temp_ebb_new_i64();
tcg_gen_shri_i64(t0, arg, 8); /* arg = ......ab or xxxxxxab */
tcg_gen_shri_i64(t0, arg, 8); /* t0 = .......a or .xxxxxxa */
if (!(flags & TCG_BSWAP_IZ)) { if (!(flags & TCG_BSWAP_IZ)) {
tcg_gen_ext8u_i64(t0, t0); tcg_gen_ext8u_i64(t0, t0); /* t0 = .......a */
} }
if (flags & TCG_BSWAP_OS) { if (flags & TCG_BSWAP_OS) {
tcg_gen_shli_i64(t1, arg, 56); tcg_gen_shli_i64(t1, arg, 56); /* t1 = b....... */
tcg_gen_sari_i64(t1, t1, 48); tcg_gen_sari_i64(t1, t1, 48); /* t1 = ssssssb. */
} else if (flags & TCG_BSWAP_OZ) { } else if (flags & TCG_BSWAP_OZ) {
tcg_gen_ext8u_i64(t1, arg); tcg_gen_ext8u_i64(t1, arg); /* t1 = .......b */
tcg_gen_shli_i64(t1, t1, 8); tcg_gen_shli_i64(t1, t1, 8); /* t1 = ......b. */
} else { } else {
tcg_gen_shli_i64(t1, arg, 8); tcg_gen_shli_i64(t1, arg, 8); /* t1 = xxxxxab. */
} }
tcg_gen_or_i64(ret, t0, t1); tcg_gen_or_i64(ret, t0, t1); /* ret = ......ba (OZ) */
/* ssssssba (OS) */
/* xxxxxaba (no flag) */
tcg_temp_free_i64(t0); tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1); tcg_temp_free_i64(t1);
} }
} }
/*
* bswap32_i64: 32-bit byte swap on the low bits of a 64-bit value.
*
* Byte pattern: xxxxabcd -> yyyydcba
*
* With TCG_BSWAP_IZ, x == zero, else undefined.
* With TCG_BSWAP_OZ, y == zero, with TCG_BSWAP_OS y == sign, else undefined.
*/
void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags) void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
{ {
/* Only one extension flag may be present. */ /* Only one extension flag may be present. */
@ -1793,13 +1868,19 @@ void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg, int flags)
} else { } else {
tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */ tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */
} }
tcg_gen_or_i64(ret, t0, t1); /* ret = ssssdcba */ tcg_gen_or_i64(ret, t0, t1); /* ret = ssssdcba (OS) */
/* ....dcba (else) */
tcg_temp_free_i64(t0); tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1); tcg_temp_free_i64(t1);
} }
} }
/*
* bswap64_i64: 64-bit byte swap on a 64-bit value.
*
* Byte pattern: abcdefgh -> hgfedcba
*/
void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg) void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
{ {
if (TCG_TARGET_REG_BITS == 32) { if (TCG_TARGET_REG_BITS == 32) {
@ -1845,24 +1926,35 @@ void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
} }
} }
/*
* hswap_i64: Swap 16-bit halfwords within a 64-bit value.
* See also include/qemu/bitops.h, hswap64.
*
* Byte pattern: abcdefgh -> ghefcdab
*/
void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg) void tcg_gen_hswap_i64(TCGv_i64 ret, TCGv_i64 arg)
{ {
uint64_t m = 0x0000ffff0000ffffull; uint64_t m = 0x0000ffff0000ffffull;
TCGv_i64 t0 = tcg_temp_ebb_new_i64(); TCGv_i64 t0 = tcg_temp_ebb_new_i64();
TCGv_i64 t1 = tcg_temp_ebb_new_i64(); TCGv_i64 t1 = tcg_temp_ebb_new_i64();
/* See include/qemu/bitops.h, hswap64. */ /* arg = abcdefgh */
tcg_gen_rotli_i64(t1, arg, 32); tcg_gen_rotli_i64(t1, arg, 32); /* t1 = efghabcd */
tcg_gen_andi_i64(t0, t1, m); tcg_gen_andi_i64(t0, t1, m); /* t0 = ..gh..cd */
tcg_gen_shli_i64(t0, t0, 16); tcg_gen_shli_i64(t0, t0, 16); /* t0 = gh..cd.. */
tcg_gen_shri_i64(t1, t1, 16); tcg_gen_shri_i64(t1, t1, 16); /* t1 = ..efghab */
tcg_gen_andi_i64(t1, t1, m); tcg_gen_andi_i64(t1, t1, m); /* t1 = ..ef..ab */
tcg_gen_or_i64(ret, t0, t1); tcg_gen_or_i64(ret, t0, t1); /* ret = ghefcdab */
tcg_temp_free_i64(t0); tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1); tcg_temp_free_i64(t1);
} }
/*
* wswap_i64: Swap 32-bit words within a 64-bit value.
*
* Byte pattern: abcdefgh -> efghabcd
*/
void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg) void tcg_gen_wswap_i64(TCGv_i64 ret, TCGv_i64 arg)
{ {
/* Swapping 2 32-bit elements is a rotate. */ /* Swapping 2 32-bit elements is a rotate. */
@ -2527,8 +2619,7 @@ void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
} else { } else {
TCGv_i64 t0 = tcg_temp_ebb_new_i64(); TCGv_i64 t0 = tcg_temp_ebb_new_i64();
TCGv_i64 t1 = tcg_temp_ebb_new_i64(); TCGv_i64 t1 = tcg_temp_ebb_new_i64();
tcg_gen_setcond_i64(cond, t0, c1, c2); tcg_gen_negsetcond_i64(cond, t0, c1, c2);
tcg_gen_neg_i64(t0, t0);
tcg_gen_and_i64(t1, v1, t0); tcg_gen_and_i64(t1, v1, t0);
tcg_gen_andc_i64(ret, v2, t0); tcg_gen_andc_i64(ret, v2, t0);
tcg_gen_or_i64(ret, ret, t1); tcg_gen_or_i64(ret, ret, t1);
@ -2681,7 +2772,7 @@ void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
{ {
if (TCG_TARGET_REG_BITS == 32) { if (TCG_TARGET_REG_BITS == 32) {
tcg_gen_mov_i32(ret, TCGV_LOW(arg)); tcg_gen_mov_i32(ret, TCGV_LOW(arg));
} else if (TCG_TARGET_HAS_extrl_i64_i32) { } else if (TCG_TARGET_HAS_extr_i64_i32) {
tcg_gen_op2(INDEX_op_extrl_i64_i32, tcg_gen_op2(INDEX_op_extrl_i64_i32,
tcgv_i32_arg(ret), tcgv_i64_arg(arg)); tcgv_i32_arg(ret), tcgv_i64_arg(arg));
} else { } else {
@ -2693,7 +2784,7 @@ void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
{ {
if (TCG_TARGET_REG_BITS == 32) { if (TCG_TARGET_REG_BITS == 32) {
tcg_gen_mov_i32(ret, TCGV_HIGH(arg)); tcg_gen_mov_i32(ret, TCGV_HIGH(arg));
} else if (TCG_TARGET_HAS_extrh_i64_i32) { } else if (TCG_TARGET_HAS_extr_i64_i32) {
tcg_gen_op2(INDEX_op_extrh_i64_i32, tcg_gen_op2(INDEX_op_extrh_i64_i32,
tcgv_i32_arg(ret), tcgv_i64_arg(arg)); tcgv_i32_arg(ret), tcgv_i64_arg(arg));
} else { } else {

View File

@ -1879,6 +1879,8 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_sar_i32: case INDEX_op_sar_i32:
return true; return true;
case INDEX_op_negsetcond_i32:
return TCG_TARGET_HAS_negsetcond_i32;
case INDEX_op_movcond_i32: case INDEX_op_movcond_i32:
return TCG_TARGET_HAS_movcond_i32; return TCG_TARGET_HAS_movcond_i32;
case INDEX_op_div_i32: case INDEX_op_div_i32:
@ -1977,6 +1979,8 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_extu_i32_i64: case INDEX_op_extu_i32_i64:
return TCG_TARGET_REG_BITS == 64; return TCG_TARGET_REG_BITS == 64;
case INDEX_op_negsetcond_i64:
return TCG_TARGET_HAS_negsetcond_i64;
case INDEX_op_movcond_i64: case INDEX_op_movcond_i64:
return TCG_TARGET_HAS_movcond_i64; return TCG_TARGET_HAS_movcond_i64;
case INDEX_op_div_i64: case INDEX_op_div_i64:
@ -2000,9 +2004,8 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_extract2_i64: case INDEX_op_extract2_i64:
return TCG_TARGET_HAS_extract2_i64; return TCG_TARGET_HAS_extract2_i64;
case INDEX_op_extrl_i64_i32: case INDEX_op_extrl_i64_i32:
return TCG_TARGET_HAS_extrl_i64_i32;
case INDEX_op_extrh_i64_i32: case INDEX_op_extrh_i64_i32:
return TCG_TARGET_HAS_extrh_i64_i32; return TCG_TARGET_HAS_extr_i64_i32;
case INDEX_op_ext8s_i64: case INDEX_op_ext8s_i64:
return TCG_TARGET_HAS_ext8s_i64; return TCG_TARGET_HAS_ext8s_i64;
case INDEX_op_ext16s_i64: case INDEX_op_ext16s_i64:
@ -2510,11 +2513,13 @@ static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
switch (c) { switch (c) {
case INDEX_op_brcond_i32: case INDEX_op_brcond_i32:
case INDEX_op_setcond_i32: case INDEX_op_setcond_i32:
case INDEX_op_negsetcond_i32:
case INDEX_op_movcond_i32: case INDEX_op_movcond_i32:
case INDEX_op_brcond2_i32: case INDEX_op_brcond2_i32:
case INDEX_op_setcond2_i32: case INDEX_op_setcond2_i32:
case INDEX_op_brcond_i64: case INDEX_op_brcond_i64:
case INDEX_op_setcond_i64: case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i64:
case INDEX_op_movcond_i64: case INDEX_op_movcond_i64:
case INDEX_op_cmp_vec: case INDEX_op_cmp_vec:
case INDEX_op_cmpsel_vec: case INDEX_op_cmpsel_vec:

View File

@ -70,14 +70,14 @@
#define TCG_TARGET_HAS_orc_i32 1 #define TCG_TARGET_HAS_orc_i32 1
#define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 0
#define TCG_TARGET_HAS_muls2_i32 1 #define TCG_TARGET_HAS_muls2_i32 1
#define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_qemu_st8_i32 0 #define TCG_TARGET_HAS_qemu_st8_i32 0
#if TCG_TARGET_REG_BITS == 64 #if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extr_i64_i32 0
#define TCG_TARGET_HAS_extrh_i64_i32 0
#define TCG_TARGET_HAS_bswap16_i64 1 #define TCG_TARGET_HAS_bswap16_i64 1
#define TCG_TARGET_HAS_bswap32_i64 1 #define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1 #define TCG_TARGET_HAS_bswap64_i64 1
@ -105,6 +105,7 @@
#define TCG_TARGET_HAS_orc_i64 1 #define TCG_TARGET_HAS_orc_i64 1
#define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 0
#define TCG_TARGET_HAS_muls2_i64 1 #define TCG_TARGET_HAS_muls2_i64 1
#define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1