mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20170110' into staging
TCG opcodes for extract, clz, ctz, ctpop # gpg: Signature made Wed 11 Jan 2017 02:12:41 GMT # gpg: using RSA key 0xAD1270CC4DD0279B # gpg: Good signature from "Richard Henderson <rth7680@gmail.com>" # gpg: aka "Richard Henderson <rth@redhat.com>" # gpg: aka "Richard Henderson <rth@twiddle.net>" # Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC 16A4 AD12 70CC 4DD0 279B * remotes/rth/tags/pull-tcg-20170110: (65 commits) tcg/i386: Handle ctpop opcode tcg/ppc: Handle ctpop opcode tcg: Use ctpop to generate ctz if needed tests: New test-bitcnt qemu/host-utils.h: Reduce the operation count in the fallback ctpop target-i386: Use ctpop helper target-tilegx: Use ctpop helper target-sparc: Use ctpop helper target-s390x: Avoid a loop for popcnt target-ppc: Use ctpop helper target-alpha: Use ctpop helper tcg: Add opcode for ctpop target-xtensa: Use clrsb helper target-tricore: Use clrsb helper target-arm: Use clrsb helper tcg: Add helpers for clrsb tcg/i386: Rely on undefined/undocumented behaviour of BSF/BSR tcg/i386: Handle ctz and clz opcodes tcg/i386: Allow bmi2 shiftx to have non-matching operands tcg/i386: Hoist common arguments in tcg_out_op ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+10
-2
@@ -682,6 +682,7 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr)
|
||||
#define PREGRP104 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 104 } }
|
||||
#define PREGRP105 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 105 } }
|
||||
#define PREGRP106 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 106 } }
|
||||
#define PREGRP107 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 107 } }
|
||||
|
||||
#define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } }
|
||||
#define X86_64_1 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 1 } }
|
||||
@@ -1247,7 +1248,7 @@ static const struct dis386 dis386_twobyte[] = {
|
||||
{ "ud2b", { XX } },
|
||||
{ GRP8 },
|
||||
{ "btcS", { Ev, Gv } },
|
||||
{ "bsfS", { Gv, Ev } },
|
||||
{ PREGRP107 },
|
||||
{ PREGRP36 },
|
||||
{ "movs{bR|x|bR|x}", { Gv, Eb } },
|
||||
{ "movs{wR|x|wR|x}", { Gv, Ew } }, /* yes, there really is movsww ! */
|
||||
@@ -1431,7 +1432,7 @@ static const unsigned char twobyte_uses_REPZ_prefix[256] = {
|
||||
/* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
|
||||
/* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
|
||||
/* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
|
||||
/* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, /* bf */
|
||||
/* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0, /* bf */
|
||||
/* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
|
||||
/* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
|
||||
/* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
|
||||
@@ -2800,6 +2801,13 @@ static const struct dis386 prefix_user_table[][4] = {
|
||||
{ "shrxS", { Gv, Ev, Bv } },
|
||||
},
|
||||
|
||||
/* PREGRP107 */
|
||||
{
|
||||
{ "bsfS", { Gv, Ev } },
|
||||
{ "tzcntS", { Gv, Ev } },
|
||||
{ "bsfS", { Gv, Ev } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dis386 x86_64_table[][2] = {
|
||||
|
||||
+10
@@ -1955,6 +1955,9 @@ extract_tbr (unsigned long insn,
|
||||
#define POWER4 PPC_OPCODE_POWER4
|
||||
#define POWER5 PPC_OPCODE_POWER5
|
||||
#define POWER6 PPC_OPCODE_POWER6
|
||||
/* Documentation purposes only; we don't actually check the isa for disas. */
|
||||
#define POWER7 PPC_OPCODE_POWER6
|
||||
#define POWER9 PPC_OPCODE_POWER6
|
||||
#define CELL PPC_OPCODE_CELL
|
||||
#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC
|
||||
#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC
|
||||
@@ -3589,6 +3592,13 @@ const struct powerpc_opcode powerpc_opcodes[] = {
|
||||
{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } },
|
||||
|
||||
{ "popcntb", X(31,122), XRB_MASK, POWER5, { RA, RS } },
|
||||
{ "popcntw", X(31,378), XRB_MASK, POWER7, { RA, RS } },
|
||||
{ "popcntd", X(31,506), XRB_MASK, POWER7, { RA, RS } },
|
||||
|
||||
{ "cnttzw", XRC(31,538,0), XRB_MASK, POWER9, { RA, RS } },
|
||||
{ "cnttzw.", XRC(31,538,1), XRB_MASK, POWER9, { RA, RS } },
|
||||
{ "cnttzd", XRC(31,570,0), XRB_MASK, POWER9, { RA, RS } },
|
||||
{ "cnttzd.", XRC(31,570,1), XRB_MASK, POWER9, { RA, RS } },
|
||||
|
||||
{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } },
|
||||
{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } },
|
||||
|
||||
+11
-14
@@ -327,7 +327,7 @@ static inline int ctpop8(uint8_t val)
|
||||
#else
|
||||
val = (val & 0x55) + ((val >> 1) & 0x55);
|
||||
val = (val & 0x33) + ((val >> 2) & 0x33);
|
||||
val = (val & 0x0f) + ((val >> 4) & 0x0f);
|
||||
val = (val + (val >> 4)) & 0x0f;
|
||||
|
||||
return val;
|
||||
#endif
|
||||
@@ -344,8 +344,8 @@ static inline int ctpop16(uint16_t val)
|
||||
#else
|
||||
val = (val & 0x5555) + ((val >> 1) & 0x5555);
|
||||
val = (val & 0x3333) + ((val >> 2) & 0x3333);
|
||||
val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
|
||||
val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
|
||||
val = (val + (val >> 4)) & 0x0f0f;
|
||||
val = (val + (val >> 8)) & 0x00ff;
|
||||
|
||||
return val;
|
||||
#endif
|
||||
@@ -360,11 +360,10 @@ static inline int ctpop32(uint32_t val)
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return __builtin_popcount(val);
|
||||
#else
|
||||
val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
|
||||
val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
|
||||
val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
|
||||
val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
|
||||
val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
|
||||
val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
|
||||
val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
|
||||
val = (val + (val >> 4)) & 0x0f0f0f0f;
|
||||
val = (val * 0x01010101) >> 24;
|
||||
|
||||
return val;
|
||||
#endif
|
||||
@@ -379,12 +378,10 @@ static inline int ctpop64(uint64_t val)
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return __builtin_popcountll(val);
|
||||
#else
|
||||
val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
|
||||
val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
|
||||
val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL);
|
||||
val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 0x00ff00ff00ff00ffULL);
|
||||
val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
|
||||
val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
|
||||
val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
|
||||
val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
|
||||
val = (val + (val >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
|
||||
val = (val * 0x0101010101010101ULL) >> 56;
|
||||
|
||||
return val;
|
||||
#endif
|
||||
|
||||
@@ -3,10 +3,6 @@ DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env)
|
||||
|
||||
DEF_HELPER_FLAGS_3(check_overflow, TCG_CALL_NO_WG, void, env, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(cttz, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(zap, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
|
||||
@@ -24,21 +24,6 @@
|
||||
#include "qemu/host-utils.h"
|
||||
|
||||
|
||||
uint64_t helper_ctpop(uint64_t arg)
|
||||
{
|
||||
return ctpop64(arg);
|
||||
}
|
||||
|
||||
uint64_t helper_ctlz(uint64_t arg)
|
||||
{
|
||||
return clz64(arg);
|
||||
}
|
||||
|
||||
uint64_t helper_cttz(uint64_t arg)
|
||||
{
|
||||
return ctz64(arg);
|
||||
}
|
||||
|
||||
uint64_t helper_zapnot(uint64_t val, uint64_t mskb)
|
||||
{
|
||||
uint64_t mask;
|
||||
|
||||
+45
-28
@@ -949,7 +949,13 @@ static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
|
||||
uint8_t lit, uint8_t byte_mask)
|
||||
{
|
||||
if (islit) {
|
||||
tcg_gen_shli_i64(vc, va, (64 - lit * 8) & 0x3f);
|
||||
int pos = (64 - lit * 8) & 0x3f;
|
||||
int len = cto32(byte_mask) * 8;
|
||||
if (pos < len) {
|
||||
tcg_gen_deposit_z_i64(vc, va, pos, len - pos);
|
||||
} else {
|
||||
tcg_gen_movi_i64(vc, 0);
|
||||
}
|
||||
} else {
|
||||
TCGv tmp = tcg_temp_new();
|
||||
tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
|
||||
@@ -966,38 +972,44 @@ static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
|
||||
uint8_t lit, uint8_t byte_mask)
|
||||
{
|
||||
if (islit) {
|
||||
tcg_gen_shri_i64(vc, va, (lit & 7) * 8);
|
||||
int pos = (lit & 7) * 8;
|
||||
int len = cto32(byte_mask) * 8;
|
||||
if (pos + len >= 64) {
|
||||
len = 64 - pos;
|
||||
}
|
||||
tcg_gen_extract_i64(vc, va, pos, len);
|
||||
} else {
|
||||
TCGv tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
|
||||
tcg_gen_shli_i64(tmp, tmp, 3);
|
||||
tcg_gen_shr_i64(vc, va, tmp);
|
||||
tcg_temp_free(tmp);
|
||||
gen_zapnoti(vc, vc, byte_mask);
|
||||
}
|
||||
gen_zapnoti(vc, vc, byte_mask);
|
||||
}
|
||||
|
||||
/* INSWH, INSLH, INSQH */
|
||||
static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
|
||||
uint8_t lit, uint8_t byte_mask)
|
||||
{
|
||||
TCGv tmp = tcg_temp_new();
|
||||
|
||||
/* The instruction description has us left-shift the byte mask and extract
|
||||
bits <15:8> and apply that zap at the end. This is equivalent to simply
|
||||
performing the zap first and shifting afterward. */
|
||||
gen_zapnoti(tmp, va, byte_mask);
|
||||
|
||||
if (islit) {
|
||||
lit &= 7;
|
||||
if (unlikely(lit == 0)) {
|
||||
tcg_gen_movi_i64(vc, 0);
|
||||
int pos = 64 - (lit & 7) * 8;
|
||||
int len = cto32(byte_mask) * 8;
|
||||
if (pos < len) {
|
||||
tcg_gen_extract_i64(vc, va, pos, len - pos);
|
||||
} else {
|
||||
tcg_gen_shri_i64(vc, tmp, 64 - lit * 8);
|
||||
tcg_gen_movi_i64(vc, 0);
|
||||
}
|
||||
} else {
|
||||
TCGv tmp = tcg_temp_new();
|
||||
TCGv shift = tcg_temp_new();
|
||||
|
||||
/* The instruction description has us left-shift the byte mask
|
||||
and extract bits <15:8> and apply that zap at the end. This
|
||||
is equivalent to simply performing the zap first and shifting
|
||||
afterward. */
|
||||
gen_zapnoti(tmp, va, byte_mask);
|
||||
|
||||
/* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this
|
||||
portably by splitting the shift into two parts: shift_count-1 and 1.
|
||||
Arrange for the -1 by using ones-complement instead of
|
||||
@@ -1010,32 +1022,37 @@ static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
|
||||
tcg_gen_shr_i64(vc, tmp, shift);
|
||||
tcg_gen_shri_i64(vc, vc, 1);
|
||||
tcg_temp_free(shift);
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
|
||||
/* INSBL, INSWL, INSLL, INSQL */
|
||||
static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
|
||||
uint8_t lit, uint8_t byte_mask)
|
||||
{
|
||||
TCGv tmp = tcg_temp_new();
|
||||
|
||||
/* The instruction description has us left-shift the byte mask
|
||||
the same number of byte slots as the data and apply the zap
|
||||
at the end. This is equivalent to simply performing the zap
|
||||
first and shifting afterward. */
|
||||
gen_zapnoti(tmp, va, byte_mask);
|
||||
|
||||
if (islit) {
|
||||
tcg_gen_shli_i64(vc, tmp, (lit & 7) * 8);
|
||||
int pos = (lit & 7) * 8;
|
||||
int len = cto32(byte_mask) * 8;
|
||||
if (pos + len > 64) {
|
||||
len = 64 - pos;
|
||||
}
|
||||
tcg_gen_deposit_z_i64(vc, va, pos, len);
|
||||
} else {
|
||||
TCGv tmp = tcg_temp_new();
|
||||
TCGv shift = tcg_temp_new();
|
||||
|
||||
/* The instruction description has us left-shift the byte mask
|
||||
and extract bits <15:8> and apply that zap at the end. This
|
||||
is equivalent to simply performing the zap first and shifting
|
||||
afterward. */
|
||||
gen_zapnoti(tmp, va, byte_mask);
|
||||
|
||||
tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
|
||||
tcg_gen_shli_i64(shift, shift, 3);
|
||||
tcg_gen_shl_i64(vc, tmp, shift);
|
||||
tcg_temp_free(shift);
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
|
||||
/* MSKWH, MSKLH, MSKQH */
|
||||
@@ -2524,7 +2541,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
|
||||
REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
|
||||
REQUIRE_REG_31(ra);
|
||||
REQUIRE_NO_LIT;
|
||||
gen_helper_ctpop(vc, vb);
|
||||
tcg_gen_ctpop_i64(vc, vb);
|
||||
break;
|
||||
case 0x31:
|
||||
/* PERR */
|
||||
@@ -2538,14 +2555,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
|
||||
REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
|
||||
REQUIRE_REG_31(ra);
|
||||
REQUIRE_NO_LIT;
|
||||
gen_helper_ctlz(vc, vb);
|
||||
tcg_gen_clzi_i64(vc, vb, 64);
|
||||
break;
|
||||
case 0x33:
|
||||
/* CTTZ */
|
||||
REQUIRE_TB_FLAG(TB_FLAGS_AMASK_CIX);
|
||||
REQUIRE_REG_31(ra);
|
||||
REQUIRE_NO_LIT;
|
||||
gen_helper_cttz(vc, vb);
|
||||
tcg_gen_ctzi_i64(vc, vb, 64);
|
||||
break;
|
||||
case 0x34:
|
||||
/* UNPKBW */
|
||||
|
||||
@@ -54,26 +54,6 @@ int64_t HELPER(sdiv64)(int64_t num, int64_t den)
|
||||
return num / den;
|
||||
}
|
||||
|
||||
uint64_t HELPER(clz64)(uint64_t x)
|
||||
{
|
||||
return clz64(x);
|
||||
}
|
||||
|
||||
uint64_t HELPER(cls64)(uint64_t x)
|
||||
{
|
||||
return clrsb64(x);
|
||||
}
|
||||
|
||||
uint32_t HELPER(cls32)(uint32_t x)
|
||||
{
|
||||
return clrsb32(x);
|
||||
}
|
||||
|
||||
uint32_t HELPER(clz32)(uint32_t x)
|
||||
{
|
||||
return clz32(x);
|
||||
}
|
||||
|
||||
uint64_t HELPER(rbit64)(uint64_t x)
|
||||
{
|
||||
return revbit64(x);
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
*/
|
||||
DEF_HELPER_FLAGS_2(udiv64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
|
||||
DEF_HELPER_FLAGS_1(clz64, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(cls64, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(cls32, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(clz32, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
|
||||
DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
|
||||
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
|
||||
|
||||
@@ -5725,11 +5725,6 @@ uint32_t HELPER(uxtb16)(uint32_t x)
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(clz)(uint32_t x)
|
||||
{
|
||||
return clz32(x);
|
||||
}
|
||||
|
||||
int32_t HELPER(sdiv)(int32_t num, int32_t den)
|
||||
{
|
||||
if (den == 0)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(sxtb16, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(uxtb16, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
|
||||
|
||||
+39
-62
@@ -3216,67 +3216,44 @@ static void disas_bitfield(DisasContext *s, uint32_t insn)
|
||||
low 32-bits anyway. */
|
||||
tcg_tmp = read_cpu_reg(s, rn, 1);
|
||||
|
||||
/* Recognize the common aliases. */
|
||||
if (opc == 0) { /* SBFM */
|
||||
if (ri == 0) {
|
||||
if (si == 7) { /* SXTB */
|
||||
tcg_gen_ext8s_i64(tcg_rd, tcg_tmp);
|
||||
goto done;
|
||||
} else if (si == 15) { /* SXTH */
|
||||
tcg_gen_ext16s_i64(tcg_rd, tcg_tmp);
|
||||
goto done;
|
||||
} else if (si == 31) { /* SXTW */
|
||||
tcg_gen_ext32s_i64(tcg_rd, tcg_tmp);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (si == 63 || (si == 31 && ri <= si)) { /* ASR */
|
||||
if (si == 31) {
|
||||
tcg_gen_ext32s_i64(tcg_tmp, tcg_tmp);
|
||||
}
|
||||
tcg_gen_sari_i64(tcg_rd, tcg_tmp, ri);
|
||||
goto done;
|
||||
}
|
||||
} else if (opc == 2) { /* UBFM */
|
||||
if (ri == 0) { /* UXTB, UXTH, plus non-canonical AND */
|
||||
tcg_gen_andi_i64(tcg_rd, tcg_tmp, bitmask64(si + 1));
|
||||
return;
|
||||
}
|
||||
if (si == 63 || (si == 31 && ri <= si)) { /* LSR */
|
||||
if (si == 31) {
|
||||
tcg_gen_ext32u_i64(tcg_tmp, tcg_tmp);
|
||||
}
|
||||
tcg_gen_shri_i64(tcg_rd, tcg_tmp, ri);
|
||||
return;
|
||||
}
|
||||
if (si + 1 == ri && si != bitsize - 1) { /* LSL */
|
||||
int shift = bitsize - 1 - si;
|
||||
tcg_gen_shli_i64(tcg_rd, tcg_tmp, shift);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (opc != 1) { /* SBFM or UBFM */
|
||||
tcg_gen_movi_i64(tcg_rd, 0);
|
||||
}
|
||||
|
||||
/* do the bit move operation */
|
||||
if (si >= ri) {
|
||||
/* Recognize simple(r) extractions. */
|
||||
if (si <= ri) {
|
||||
/* Wd<s-r:0> = Wn<s:r> */
|
||||
tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
|
||||
pos = 0;
|
||||
len = (si - ri) + 1;
|
||||
if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
|
||||
tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
|
||||
goto done;
|
||||
} else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
|
||||
tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
|
||||
return;
|
||||
}
|
||||
/* opc == 1, BXFIL fall through to deposit */
|
||||
tcg_gen_extract_i64(tcg_tmp, tcg_tmp, ri, len);
|
||||
pos = 0;
|
||||
} else {
|
||||
/* Wd<32+s-r,32-r> = Wn<s:0> */
|
||||
pos = bitsize - ri;
|
||||
/* Handle the ri > si case with a deposit
|
||||
* Wd<32+s-r,32-r> = Wn<s:0>
|
||||
*/
|
||||
len = si + 1;
|
||||
pos = (bitsize - ri) & (bitsize - 1);
|
||||
}
|
||||
|
||||
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
|
||||
if (opc == 0 && len < ri) {
|
||||
/* SBFM: sign extend the destination field from len to fill
|
||||
the balance of the word. Let the deposit below insert all
|
||||
of those sign bits. */
|
||||
tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
|
||||
len = ri;
|
||||
}
|
||||
|
||||
if (opc == 0) { /* SBFM - sign extend the destination field */
|
||||
tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
|
||||
tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
|
||||
if (opc == 1) { /* BFM, BXFIL */
|
||||
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
|
||||
} else {
|
||||
/* SBFM or UBFM: We start with zero, and we haven't modified
|
||||
any bits outside bitsize, therefore the zero-extension
|
||||
below is unneeded. */
|
||||
tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
|
||||
return;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -3977,11 +3954,11 @@ static void handle_clz(DisasContext *s, unsigned int sf,
|
||||
tcg_rn = cpu_reg(s, rn);
|
||||
|
||||
if (sf) {
|
||||
gen_helper_clz64(tcg_rd, tcg_rn);
|
||||
tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
|
||||
} else {
|
||||
TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
|
||||
tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
|
||||
gen_helper_clz(tcg_tmp32, tcg_tmp32);
|
||||
tcg_gen_clzi_i32(tcg_tmp32, tcg_tmp32, 32);
|
||||
tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
|
||||
tcg_temp_free_i32(tcg_tmp32);
|
||||
}
|
||||
@@ -3995,11 +3972,11 @@ static void handle_cls(DisasContext *s, unsigned int sf,
|
||||
tcg_rn = cpu_reg(s, rn);
|
||||
|
||||
if (sf) {
|
||||
gen_helper_cls64(tcg_rd, tcg_rn);
|
||||
tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
|
||||
} else {
|
||||
TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
|
||||
tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
|
||||
gen_helper_cls32(tcg_tmp32, tcg_tmp32);
|
||||
tcg_gen_clrsb_i32(tcg_tmp32, tcg_tmp32);
|
||||
tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
|
||||
tcg_temp_free_i32(tcg_tmp32);
|
||||
}
|
||||
@@ -7614,9 +7591,9 @@ static void handle_2misc_64(DisasContext *s, int opcode, bool u,
|
||||
switch (opcode) {
|
||||
case 0x4: /* CLS, CLZ */
|
||||
if (u) {
|
||||
gen_helper_clz64(tcg_rd, tcg_rn);
|
||||
tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
|
||||
} else {
|
||||
gen_helper_cls64(tcg_rd, tcg_rn);
|
||||
tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
|
||||
}
|
||||
break;
|
||||
case 0x5: /* NOT */
|
||||
@@ -10284,9 +10261,9 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
|
||||
goto do_cmop;
|
||||
case 0x4: /* CLS */
|
||||
if (u) {
|
||||
gen_helper_clz32(tcg_res, tcg_op);
|
||||
tcg_gen_clzi_i32(tcg_res, tcg_op, 32);
|
||||
} else {
|
||||
gen_helper_cls32(tcg_res, tcg_op);
|
||||
tcg_gen_clrsb_i32(tcg_res, tcg_op);
|
||||
}
|
||||
break;
|
||||
case 0x7: /* SQABS, SQNEG */
|
||||
|
||||
+11
-32
@@ -288,29 +288,6 @@ static void gen_revsh(TCGv_i32 var)
|
||||
tcg_gen_ext16s_i32(var, var);
|
||||
}
|
||||
|
||||
/* Unsigned bitfield extract. */
|
||||
static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
|
||||
{
|
||||
if (shift)
|
||||
tcg_gen_shri_i32(var, var, shift);
|
||||
tcg_gen_andi_i32(var, var, mask);
|
||||
}
|
||||
|
||||
/* Signed bitfield extract. */
|
||||
static void gen_sbfx(TCGv_i32 var, int shift, int width)
|
||||
{
|
||||
uint32_t signbit;
|
||||
|
||||
if (shift)
|
||||
tcg_gen_sari_i32(var, var, shift);
|
||||
if (shift + width < 32) {
|
||||
signbit = 1u << (width - 1);
|
||||
tcg_gen_andi_i32(var, var, (1u << width) - 1);
|
||||
tcg_gen_xori_i32(var, var, signbit);
|
||||
tcg_gen_subi_i32(var, var, signbit);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return (b << 32) + a. Mark inputs as dead */
|
||||
static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
|
||||
{
|
||||
@@ -7060,7 +7037,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
||||
switch (size) {
|
||||
case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
|
||||
case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
|
||||
case 2: gen_helper_clz(tmp, tmp); break;
|
||||
case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
|
||||
default: abort();
|
||||
}
|
||||
break;
|
||||
@@ -8242,7 +8219,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
|
||||
ARCH(5);
|
||||
rd = (insn >> 12) & 0xf;
|
||||
tmp = load_reg(s, rm);
|
||||
gen_helper_clz(tmp, tmp);
|
||||
tcg_gen_clzi_i32(tmp, tmp, 32);
|
||||
store_reg(s, rd, tmp);
|
||||
} else {
|
||||
goto illegal_op;
|
||||
@@ -9178,9 +9155,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
|
||||
goto illegal_op;
|
||||
if (i < 32) {
|
||||
if (op1 & 0x20) {
|
||||
gen_ubfx(tmp, shift, (1u << i) - 1);
|
||||
tcg_gen_extract_i32(tmp, tmp, shift, i);
|
||||
} else {
|
||||
gen_sbfx(tmp, shift, i);
|
||||
tcg_gen_sextract_i32(tmp, tmp, shift, i);
|
||||
}
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
@@ -10015,7 +9992,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
||||
tcg_temp_free_i32(tmp2);
|
||||
break;
|
||||
case 0x18: /* clz */
|
||||
gen_helper_clz(tmp, tmp);
|
||||
tcg_gen_clzi_i32(tmp, tmp, 32);
|
||||
break;
|
||||
case 0x20:
|
||||
case 0x21:
|
||||
@@ -10497,15 +10474,17 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
||||
imm++;
|
||||
if (shift + imm > 32)
|
||||
goto illegal_op;
|
||||
if (imm < 32)
|
||||
gen_sbfx(tmp, shift, imm);
|
||||
if (imm < 32) {
|
||||
tcg_gen_sextract_i32(tmp, tmp, shift, imm);
|
||||
}
|
||||
break;
|
||||
case 6: /* Unsigned bitfield extract. */
|
||||
imm++;
|
||||
if (shift + imm > 32)
|
||||
goto illegal_op;
|
||||
if (imm < 32)
|
||||
gen_ubfx(tmp, shift, (1u << imm) - 1);
|
||||
if (imm < 32) {
|
||||
tcg_gen_extract_i32(tmp, tmp, shift, imm);
|
||||
}
|
||||
break;
|
||||
case 3: /* Bitfield insert/clear. */
|
||||
if (imm < shift)
|
||||
|
||||
@@ -7,7 +7,6 @@ DEF_HELPER_1(rfn, void, env)
|
||||
DEF_HELPER_3(movl_sreg_reg, void, env, i32, i32)
|
||||
DEF_HELPER_3(movl_reg_sreg, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_1(lz, TCG_CALL_NO_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_4(btst, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_NO_SE, i32, env, i32, i32, i32)
|
||||
|
||||
@@ -230,11 +230,6 @@ void helper_rfn(CPUCRISState *env)
|
||||
env->pregs[PR_CCS] |= M_FLAG_V32;
|
||||
}
|
||||
|
||||
uint32_t helper_lz(uint32_t t0)
|
||||
{
|
||||
return clz32(t0);
|
||||
}
|
||||
|
||||
uint32_t helper_btst(CPUCRISState *env, uint32_t t0, uint32_t t1, uint32_t ccs)
|
||||
{
|
||||
/* FIXME: clean this up. */
|
||||
|
||||
@@ -767,7 +767,7 @@ static void cris_alu_op_exec(DisasContext *dc, int op,
|
||||
t_gen_subx_carry(dc, dst);
|
||||
break;
|
||||
case CC_OP_LZ:
|
||||
gen_helper_lz(dst, b);
|
||||
tcg_gen_clzi_tl(dst, b, TARGET_LONG_BITS);
|
||||
break;
|
||||
case CC_OP_MULS:
|
||||
tcg_gen_muls2_tl(dst, cpu_PR[PR_MOF], a, b);
|
||||
|
||||
@@ -105,6 +105,8 @@ target_ulong helper_cc_compute_all(target_ulong dst, target_ulong src1,
|
||||
return src1;
|
||||
case CC_OP_CLR:
|
||||
return CC_Z | CC_P;
|
||||
case CC_OP_POPCNT:
|
||||
return src1 ? 0 : CC_Z;
|
||||
|
||||
case CC_OP_MULB:
|
||||
return compute_all_mulb(dst, src1);
|
||||
@@ -232,6 +234,7 @@ target_ulong helper_cc_compute_c(target_ulong dst, target_ulong src1,
|
||||
case CC_OP_LOGICL:
|
||||
case CC_OP_LOGICQ:
|
||||
case CC_OP_CLR:
|
||||
case CC_OP_POPCNT:
|
||||
return 0;
|
||||
|
||||
case CC_OP_EFLAGS:
|
||||
|
||||
@@ -777,6 +777,7 @@ typedef enum {
|
||||
CC_OP_ADCOX, /* CC_DST = C, CC_SRC2 = O, CC_SRC = rest. */
|
||||
|
||||
CC_OP_CLR, /* Z set, all other flags clear. */
|
||||
CC_OP_POPCNT, /* Z via CC_SRC, all other flags clear. */
|
||||
|
||||
CC_OP_NB,
|
||||
} CCOp;
|
||||
|
||||
@@ -202,8 +202,6 @@ DEF_HELPER_FLAGS_3(xsetbv, TCG_CALL_NO_WG, void, env, i32, i64)
|
||||
DEF_HELPER_FLAGS_2(rdpkru, TCG_CALL_NO_WG, i64, env, i32)
|
||||
DEF_HELPER_FLAGS_3(wrpkru, TCG_CALL_NO_WG, void, env, i32, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(ctz, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(pdep, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
DEF_HELPER_FLAGS_2(pext, TCG_CALL_NO_RWG_SE, tl, tl, tl)
|
||||
|
||||
|
||||
@@ -417,17 +417,6 @@ void helper_idivq_EAX(CPUX86State *env, target_ulong t0)
|
||||
# define clztl clz64
|
||||
#endif
|
||||
|
||||
/* bit operations */
|
||||
target_ulong helper_ctz(target_ulong t0)
|
||||
{
|
||||
return ctztl(t0);
|
||||
}
|
||||
|
||||
target_ulong helper_clz(target_ulong t0)
|
||||
{
|
||||
return clztl(t0);
|
||||
}
|
||||
|
||||
target_ulong helper_pdep(target_ulong src, target_ulong mask)
|
||||
{
|
||||
target_ulong dest = 0;
|
||||
|
||||
@@ -2157,32 +2157,6 @@ target_ulong helper_crc32(uint32_t crc1, target_ulong msg, uint32_t len)
|
||||
return crc;
|
||||
}
|
||||
|
||||
#define POPMASK(i) ((target_ulong) -1 / ((1LL << (1 << i)) + 1))
|
||||
#define POPCOUNT(n, i) ((n & POPMASK(i)) + ((n >> (1 << i)) & POPMASK(i)))
|
||||
target_ulong helper_popcnt(CPUX86State *env, target_ulong n, uint32_t type)
|
||||
{
|
||||
CC_SRC = n ? 0 : CC_Z;
|
||||
|
||||
n = POPCOUNT(n, 0);
|
||||
n = POPCOUNT(n, 1);
|
||||
n = POPCOUNT(n, 2);
|
||||
n = POPCOUNT(n, 3);
|
||||
if (type == 1) {
|
||||
return n & 0xff;
|
||||
}
|
||||
|
||||
n = POPCOUNT(n, 4);
|
||||
#ifndef TARGET_X86_64
|
||||
return n;
|
||||
#else
|
||||
if (type == 2) {
|
||||
return n & 0xff;
|
||||
}
|
||||
|
||||
return POPCOUNT(n, 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
|
||||
uint32_t ctrl)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user