* [Qemu-devel] [PATCH 000/126] Rewrite s390x translator
@ 2012-09-09 21:04 Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 001/126] tcg: Add TCGV_IS_UNUSED_* Richard Henderson
` (101 more replies)
0 siblings, 102 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
As promised the other week. I've cleaned up the patch set and
re-based it on Blueswirl's areg0 patch set. For reference, the
entire patch set is available at
git://repo.or.cz/qemu/rth.git rth/s390-reorg-3
Testing has mostly been on the gcc testsuite, where the execute
test failures are reduced to
FAIL: gcc.dg/attr-ifunc-1.c execution test
FAIL: gcc.dg/attr-ifunc-3.c execution test
FAIL: gcc.dg/attr-ifunc-4.c execution test
FAIL: gcc.dg/attr-ifunc-5.c execution test
FAIL: gcc.dg/cdce1.c execution test
FAIL: gcc.dg/cleanup-11.c execution test
FAIL: gcc.dg/cleanup-9.c execution test
FAIL: gcc.dg/torture/pr41094.c -O0 execution test
FAIL: gcc.dg/torture/tls/tls-test.c * execution test
I'll probably start trying out the glibc testsuite next, as
that's quite likely to flush out remaining problems with the
fp support (both cdce1 and pr41094 are both failures in pow).
I've also done some testing with -march={z10,z196}, but I
don't have those results handy atm.
r~
Richard Henderson (126):
tcg: Add TCGV_IS_UNUSED_*
tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS
target-s390: Disassemble more z10 and z196 opcodes
target-s390: Fix disassembly of cpsdr
target-s390: Fix gdbstub
target-s390: Add missing temp_free in gen_op_calc_cc
target-s390: Use TCG registers for FPR
target-s390: Add format based disassassmbly infrastructure
target-s390: Split out disas_jcc
target-s390: Reorg exception handling
target-s390: Convert ADD HALFWORD
target-s390: Implement SUBTRACT HALFWORD
target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE
target-s390: Convert MULTIPLY
target-s390: Convert AND, OR, XOR
target-s390: Convert COMPARE, COMPARE LOGICAL
target-s390: Convert LOAD, LOAD LOGICAL
target-s390: Convert LOAD ADDRESS
target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD
target-s390: Convert LOAD AND TEST
target-s390: Convert LOAD LOGICAL IMMEDIATE
target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE
target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE
target-s390: Convert STORE
target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW
target-s390: Convert BRANCH AND SAVE
target-s390: Convert BRANCH ON CONDITION
target-s390: Convert BRANCH ON COUNT
target-s390: Convert DIVIDE
target-s390: Send signals for divide
target-s390: Convert TEST UNDER MASK
target-s390: Convert SET ADDRESSING MODE
target-s390: Convert SUPERVISOR CALL
target-s390: Convert MOVE LONG
target-s390: Convert FP LOAD
target-s390: Convert INSERT CHARACTER
target-s390: Cleanup cc computation helpers
target-s390: Convert INSERT CHARACTERS UNDER MASK
target-s390: Convert EXECUTE
target-s390: Convert FP STORE
target-s390: Convert CONVERT TO DECIMAL
target-s390: Convert SET SYSTEM MASK
target-s390: Convert LOAD PSW
target-s390: Convert DIAGNOSE
target-s390: Convert SHIFT, ROTATE SINGLE
target-s390: Convert SHIFT DOUBLE
target-s390: Convert LOAD, STORE MULTIPLE
target-s390: Convert MOVE
target-s390: Convert NI, XI, OI
target-s390: Convert STNSM, STOSM
target-s390: Convert LAM, STAM
target-s390: Convert CLCLE, MVCLE
target-s390: Convert MVC
target-s390: Convert NC, XC, OC, TR, UNPK
target-s390: Convert CLC
target-s390: Convert MVCP, MVCS
target-s390: Convert LRA
target-s390: Convert SIGP
target-s390: Convert EFPC, STFPC
target-s390: Convert LCTL, STCTL
target-s390: Convert COMPARE AND SWAP
target-s390: Convert CLM
target-s390: Convert STCM
target-s390: Convert TPROT
target-s390: Convert LOAD CONTROL, part 2
target-s390: Convert LOAD REVERSED
target-s390: Convert STORE REVERSED
target-s390: Convert LLGT
target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED
target-s390: Convert FP SUBTRACT
target-s390: Convert FP DIVIDE
target-s390: Convert FP MULTIPLY
target-s390: Convert MULTIPLY AND ADD, SUBTRACT
target-s390: Convert TEST DATA CLASS
target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE
target-s390: Convert FP SQUARE ROOT
target-s390: Convert LOAD ZERO
target-s390: Convert CONVERT TO FIXED
target-s390: Convert CONVERT FROM FIXED
target-s390: Convert FLOGR
target-s390: Convert LFPC, SFPC
target-s390: Convert IPM
target-s390: Convert CKSM
target-s390: Convert EAR, SAR
target-s390: Convert MVPG
target-s390: Convert CLST, MVST
target-s390: Convert SRST
target-s390: Convert STIDP
target-s390: Convert SCK
target-s390: Convert STCK
target-s390: Convert SCKC, STCKC
target-s390: Convert SPT, STPT
target-s390: Convert SPKA
target-s390: Convert PTLB
target-s390: Convert SPX, STPX
target-s390: Convert STAP
target-s390: Convert IPTE
target-s390: Convert ISKE
target-s390: Convert SSKE
target-s390: Convert RRBE
target-s390: Convert subchannel instructions
target-s390: Convert STURA
target-s390: Convert CSP
target-s390: Convert STCKE
target-s390: Convert SACF
target-s390: Convert STSI
target-s390: Convert STFL
target-s390: Convert LPSWE
target-s390: Convert SERVC
target-s390: Delete dead code from old translator
target-s390: Implement BRANCH ON INDEX
target-s390: Tidy s->op_cc handling
target-s390: Implement COMPARE AND BRANCH
target-s390: Implement RISBG
target-s390: Implement LDGR, LGDR
target-s390: Implement R[NOX]SBG
target-s390: Implement PREFETCH
target-s390: Implement COMPARE RELATIVE LONG
target-s390: Implement COMPARE AND TRAP
target-s390: Implement LOAD ON CONDITION
target-s390: Implement STORE ON CONDITION
target-s390: Implement CONVERT TO LOGICAL
target-s390: Implement CONVERT FROM LOGICAL
target-s390: Implement POPCNT
target-s390: Implement CPSDR
target-s390: Check insn operand specifications
gdbstub.c | 78 +-
linux-user/main.c | 133 +-
s390-dis.c | 173 +-
target-s390x/cc_helper.c | 335 +-
target-s390x/cpu.h | 127 +-
target-s390x/fpu_helper.c | 941 ++---
target-s390x/helper.h | 168 +-
target-s390x/insn-data.def | 800 ++++
target-s390x/insn-format.def | 55 +
target-s390x/int_helper.c | 176 +-
target-s390x/mem_helper.c | 326 +-
target-s390x/misc_helper.c | 98 +-
target-s390x/translate.c | 8314 +++++++++++++++++++-----------------------
tcg/arm/tcg-target.c | 2 +-
tcg/hppa/tcg-target.c | 2 +-
tcg/i386/tcg-target.c | 2 +-
tcg/ppc/tcg-target.c | 2 +-
tcg/ppc64/tcg-target.c | 2 +-
tcg/s390/tcg-target.c | 6 +-
tcg/sparc/tcg-target.c | 2 +-
tcg/tcg-op.h | 82 +-
tcg/tcg.c | 2 +
tcg/tcg.h | 43 +-
23 files changed, 5992 insertions(+), 5877 deletions(-)
create mode 100644 target-s390x/insn-data.def
create mode 100644 target-s390x/insn-format.def
--
1.7.11.4
^ permalink raw reply [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 001/126] tcg: Add TCGV_IS_UNUSED_*
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-10 14:16 ` Aurelien Jarno
2012-09-09 21:04 ` [Qemu-devel] [PATCH 002/126] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS Richard Henderson
` (100 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf, Aurelien Jarno
Signed-off-by: Richard Henderson <rth@twiddle.net>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
tcg/tcg.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index d710694..a9367fe 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -251,6 +251,9 @@ typedef int TCGv_i64;
#define TCGV_UNUSED_I32(x) x = MAKE_TCGV_I32(-1)
#define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1)
+#define TCGV_IS_UNUSED_I32(x) (GET_TCGV_I32(x) == -1)
+#define TCGV_IS_UNUSED_I64(x) (GET_TCGV_I64(x) == -1)
+
/* call flags */
/* A pure function only reads its arguments and TCG global variables
and cannot raise exceptions. Hence a call to a pure function can be
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 002/126] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 001/126] tcg: Add TCGV_IS_UNUSED_* Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-10 14:17 ` Aurelien Jarno
2012-09-09 21:04 ` [Qemu-devel] [PATCH 003/126] target-s390: Disassemble more z10 and z196 opcodes Richard Henderson
` (99 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf, Aurelien Jarno
There are several cases that can be handled easier inside both
translators and code generators if we have out-of-band values
for conditions. It's easy enough to handle ALWAYS and NEVER in
the natural way inside the tcg middle-end.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
tcg/arm/tcg-target.c | 2 +-
tcg/hppa/tcg-target.c | 2 +-
tcg/i386/tcg-target.c | 2 +-
tcg/ppc/tcg-target.c | 2 +-
tcg/ppc64/tcg-target.c | 2 +-
tcg/s390/tcg-target.c | 6 ++--
tcg/sparc/tcg-target.c | 2 +-
tcg/tcg-op.h | 82 ++++++++++++++++++++++++++++++++++++++------------
tcg/tcg.c | 2 ++
tcg/tcg.h | 40 ++++++++++++++++--------
10 files changed, 101 insertions(+), 41 deletions(-)
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index cf0ca3d..bb9516c 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -342,7 +342,7 @@ enum arm_cond_code_e {
COND_AL = 0xe,
};
-static const uint8_t tcg_cond_to_arm_cond[10] = {
+static const uint8_t tcg_cond_to_arm_cond[] = {
[TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_LT,
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 2885212..9cd97d5 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -738,7 +738,7 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul)
}
}
-static const uint8_t tcg_cond_to_cmp_cond[10] =
+static const uint8_t tcg_cond_to_cmp_cond[] =
{
[TCG_COND_EQ] = COND_EQ,
[TCG_COND_NE] = COND_EQ | COND_FALSE,
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index da17bba..5dfa113 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define JCC_JLE 0xe
#define JCC_JG 0xf
-static const uint8_t tcg_cond_to_jcc[10] = {
+static const uint8_t tcg_cond_to_jcc[] = {
[TCG_COND_EQ] = JCC_JE,
[TCG_COND_NE] = JCC_JNE,
[TCG_COND_LT] = JCC_JL,
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 0cff181..4c70fba 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -456,7 +456,7 @@ enum {
CR_SO
};
-static const uint32_t tcg_to_bc[10] = {
+static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 27a0ae8..62dff6a 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -428,7 +428,7 @@ enum {
CR_SO
};
-static const uint32_t tcg_to_bc[10] = {
+static const uint32_t tcg_to_bc[] = {
[TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 04662c1..2bffdb2 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = {
#define S390_CC_ALWAYS 15
/* Condition codes that result from a COMPARE and COMPARE LOGICAL. */
-static const uint8_t tcg_cond_to_s390_cond[10] = {
+static const uint8_t tcg_cond_to_s390_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT,
@@ -284,7 +284,7 @@ static const uint8_t tcg_cond_to_s390_cond[10] = {
/* Condition codes that result from a LOAD AND TEST. Here, we have no
unsigned instruction variation, however since the test is vs zero we
can re-map the outcomes appropriately. */
-static const uint8_t tcg_cond_to_ltr_cond[10] = {
+static const uint8_t tcg_cond_to_ltr_cond[] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT,
@@ -1138,7 +1138,7 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val)
static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
TCGArg c2, int c2const)
{
- bool is_unsigned = (c > TCG_COND_GT);
+ bool is_unsigned = is_unsigned_cond(c);
if (c2const) {
if (c2 == 0) {
if (type == TCG_TYPE_I32) {
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 247a278..0a25065 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -510,7 +510,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
}
#endif
-static const uint8_t tcg_cond_to_bcond[10] = {
+static const uint8_t tcg_cond_to_bcond[] = {
[TCG_COND_EQ] = COND_E,
[TCG_COND_NE] = COND_NE,
[TCG_COND_LT] = COND_L,
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 169d3b2..96a30de 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -627,29 +627,49 @@ static inline void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
static inline void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1,
TCGv_i32 arg2, int label_index)
{
- tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
+ }
}
static inline void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1,
int32_t arg2, int label_index)
{
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_brcond_i32(cond, arg1, t0, label_index);
- tcg_temp_free_i32(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ TCGv_i32 t0 = tcg_const_i32(arg2);
+ tcg_gen_brcond_i32(cond, arg1, t0, label_index);
+ tcg_temp_free_i32(t0);
+ }
}
static inline void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(ret, 0);
+ } else {
+ tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
+ }
}
static inline void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
TCGv_i32 arg1, int32_t arg2)
{
- TCGv_i32 t0 = tcg_const_i32(arg2);
- tcg_gen_setcond_i32(cond, ret, arg1, t0);
- tcg_temp_free_i32(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(ret, 0);
+ } else {
+ TCGv_i32 t0 = tcg_const_i32(arg2);
+ tcg_gen_setcond_i32(cond, ret, arg1, t0);
+ tcg_temp_free_i32(t0);
+ }
}
static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
@@ -945,17 +965,27 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index)
{
- tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
- TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
- TCGV_HIGH(arg2), cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
+ TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
+ TCGV_HIGH(arg2), cond, label_index);
+ }
}
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
- TCGV_LOW(arg1), TCGV_HIGH(arg1),
- TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i32(TCGV_LOW(ret), 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i32(TCGV_LOW(ret), 0);
+ } else {
+ 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_movi_i32(TCGV_HIGH(ret), 0);
}
@@ -1210,13 +1240,23 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
TCGv_i64 arg2, int label_index)
{
- tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
+ }
}
static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_movi_i64(ret, 1);
+ } else if (cond == TCG_COND_NEVER) {
+ tcg_gen_movi_i64(ret, 0);
+ } else {
+ tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
+ }
}
static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
@@ -1334,9 +1374,13 @@ static inline void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
static inline void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1,
int64_t arg2, int label_index)
{
- TCGv_i64 t0 = tcg_const_i64(arg2);
- tcg_gen_brcond_i64(cond, arg1, t0, label_index);
- tcg_temp_free_i64(t0);
+ if (cond == TCG_COND_ALWAYS) {
+ tcg_gen_br(label_index);
+ } else if (cond != TCG_COND_NEVER) {
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_brcond_i64(cond, arg1, t0, label_index);
+ tcg_temp_free_i64(t0);
+ }
}
static inline void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 8386b70..42c3b40 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -861,6 +861,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
static const char * const cond_name[] =
{
+ [TCG_COND_NEVER] = "never",
+ [TCG_COND_ALWAYS] = "always",
[TCG_COND_EQ] = "eq",
[TCG_COND_NE] = "ne",
[TCG_COND_LT] = "lt",
diff --git a/tcg/tcg.h b/tcg/tcg.h
index a9367fe..6c37f15 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -268,18 +268,28 @@ typedef int TCGv_i64;
#define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
#define TCG_CALL_DUMMY_ARG ((TCGArg)(-1))
+/* Conditions. Note that these are layed out for easy manipulation by
+ the the functions below:
+ bit 0 is used for inverting;
+ bit 1 is signed,
+ bit 2 is unsigned,
+ bit 3 is used with bit 0 for swapping signed/unsigned. */
typedef enum {
- TCG_COND_EQ,
- TCG_COND_NE,
- TCG_COND_LT,
- TCG_COND_GE,
- TCG_COND_LE,
- TCG_COND_GT,
+ /* non-signed */
+ TCG_COND_NEVER = 0 | 0 | 0 | 0,
+ TCG_COND_ALWAYS = 0 | 0 | 0 | 1,
+ TCG_COND_EQ = 8 | 0 | 0 | 0,
+ TCG_COND_NE = 8 | 0 | 0 | 1,
+ /* signed */
+ TCG_COND_LT = 0 | 0 | 2 | 0,
+ TCG_COND_GE = 0 | 0 | 2 | 1,
+ TCG_COND_LE = 8 | 0 | 2 | 0,
+ TCG_COND_GT = 8 | 0 | 2 | 1,
/* unsigned */
- TCG_COND_LTU,
- TCG_COND_GEU,
- TCG_COND_LEU,
- TCG_COND_GTU,
+ TCG_COND_LTU = 0 | 4 | 0 | 0,
+ TCG_COND_GEU = 0 | 4 | 0 | 1,
+ TCG_COND_LEU = 8 | 4 | 0 | 0,
+ TCG_COND_GTU = 8 | 4 | 0 | 1,
} TCGCond;
/* Invert the sense of the comparison. */
@@ -291,13 +301,17 @@ static inline TCGCond tcg_invert_cond(TCGCond c)
/* Swap the operands in a comparison. */
static inline TCGCond tcg_swap_cond(TCGCond c)
{
- int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15);
- return (TCGCond)(c ^ mask);
+ return c & 6 ? (TCGCond)(c ^ 9) : c;
}
static inline TCGCond tcg_unsigned_cond(TCGCond c)
{
- return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c);
+ return c & 2 ? (TCGCond)(c ^ 6) : c;
+}
+
+static inline bool is_unsigned_cond(TCGCond c)
+{
+ return (c & 4) != 0;
}
#define TEMP_VAL_DEAD 0
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 003/126] target-s390: Disassemble more z10 and z196 opcodes
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 001/126] tcg: Add TCGV_IS_UNUSED_* Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 002/126] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 004/126] target-s390: Fix disassembly of cpsdr Richard Henderson
` (98 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Also fix disassembly for COMPARE AND BRANCH. The table must be
sorted by primary opcode, and several were out of place.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
s390-dis.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 151 insertions(+), 18 deletions(-)
diff --git a/s390-dis.c b/s390-dis.c
index 8abcdf0..bbdd239 100644
--- a/s390-dis.c
+++ b/s390-dis.c
@@ -589,6 +589,16 @@ static const struct s390_operand s390_operands[] =
{ 4, 32, S390_OPERAND_CCODE },
#define I8_32 46 /* 8 bit signed value starting at 32 */
{ 8, 32, S390_OPERAND_SIGNED },
+#define U8_24 47 /* 8 bit unsigned value starting at 24 */
+ { 8, 24, 0 },
+#define U8_32 48 /* 8 bit unsigned value starting at 32 */
+ { 8, 32, 0 },
+#define I16_32 49
+ { 16, 32, S390_OPERAND_SIGNED },
+#define M4_16 50 /* 4-bit condition-code starting at 12 */
+ { 4, 16, S390_OPERAND_CCODE },
+#define I8_16 51
+ { 8, 16, S390_OPERAND_SIGNED },
/* QEMU-END */
};
@@ -801,11 +811,35 @@ static const struct s390_operand s390_operands[] =
#define MASK_SSF_RRDRD { 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00 }
/* QEMU-ADD: */
-#define INSTR_RIE_MRRP 6, { M4_32,R_8,R_12,J16_16,0,0 } /* e.g. crj */
+#define INSTR_RIE_MRRP 6, { M4_32, R_8, R_12, J16_16, 0, 0 } /* e.g. crj */
#define MASK_RIE_MRRP { 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff }
-#define INSTR_RIE_MRIP 6, { M4_12,R_8,I8_32,J16_16,0,0 } /* e.g. cij */
+#define INSTR_RIE_MRIP 6, { M4_12, R_8, I8_32, J16_16, 0, 0 } /* e.g. cij */
#define MASK_RIE_MRIP { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_RIE_RRIII 6, { R_8, R_12, U8_16, U8_24, U8_32, 0 } /* risbg */
+#define MASK_RIE_RRIII { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+#define INSTR_RIE_MRI 6, { M4_32, R_8, I16_16, 0, 0, 0 } /* e.g. cit */
+#define MASK_RIE_MRI { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+#define INSTR_RIE_MRU 6, { M4_32, R_8, U16_16, 0, 0, 0 } /* e.g. clfit */
+#define MASK_RIE_MRU { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+#define INSTR_RIE_RRI 6, { R_8, R_12, I16_16, 0, 0, 0 }
+#define MASK_RIE_RRI { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_RXY_URRD 6, { U8_8, D20_20, X_12, B_16, 0, 0 }
+#define MASK_RXY_URRD { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_SIL_DRI 6, { D_20, B_16, I16_32, 0, 0, 0 }
+#define MASK_SIL_DRI { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
+
+#define INSTR_RSY_MRRD 6, { M4_12, R_8, D20_20, B_16, 0, 0 }
+#define MASK_SRY_MRRD { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_RRF_MRR 6, { M4_16, R_24, R_28, 0, 0, 0 }
+#define MASK_RRF_MRR { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
+
+#define INSTR_SIY_DRI 6, { D20_20, B_16, I8_16, 0, 0, 0 }
+#define MASK_SIY_DRI { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
/* QEMU-END */
/* The opcode formats table (blueprints for .insn pseudo mnemonic). */
@@ -926,6 +960,30 @@ static const struct s390_opcode s390_opcodes[] =
{ "ldeb", OP48(0xed0000000004LL), MASK_RXE_FRRD, INSTR_RXE_FRRD, 3, 0},
{ "brxlg", OP48(0xec0000000045LL), MASK_RIE_RRP, INSTR_RIE_RRP, 2, 2},
{ "brxhg", OP48(0xec0000000044LL), MASK_RIE_RRP, INSTR_RIE_RRP, 2, 2},
+/* QEMU-ADD: */
+ { "crj", OP48(0xec0000000076LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+ { "cgrj", OP48(0xec0000000064LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+ { "clrj", OP48(0xec0000000077LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+ { "clgrj", OP48(0xec0000000065LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+ { "cij", OP48(0xec000000007eLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+ { "cgij", OP48(0xec000000007cLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+ { "clij", OP48(0xec000000007fLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+ { "clgij", OP48(0xec000000007dLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+ { "risbg", OP48(0xec0000000055LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+ { "risbhg", OP48(0xec000000005dLL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+ { "risblg", OP48(0xec0000000051LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+ { "rnsbg", OP48(0xec0000000054LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+ { "rosbg", OP48(0xec0000000056LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+ { "rxsbg", OP48(0xec0000000057LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+ { "cit", OP48(0xec0000000072LL), MASK_RIE_MRI, INSTR_RIE_MRI, 3, 6},
+ { "cgit", OP48(0xec0000000070LL), MASK_RIE_MRI, INSTR_RIE_MRI, 3, 6},
+ { "clfit", OP48(0xec0000000073LL), MASK_RIE_MRU, INSTR_RIE_MRU, 3, 6},
+ { "clgit", OP48(0xec0000000071LL), MASK_RIE_MRU, INSTR_RIE_MRU, 3, 6},
+ { "ahik", OP48(0xec00000000d8LL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+ { "aghik", OP48(0xec00000000d9LL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+ { "alhsik", OP48(0xec00000000daLL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+ { "alghsik", OP48(0xec00000000dbLL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+/* QEMU-END */
{ "tp", OP48(0xeb00000000c0LL), MASK_RSL_R0RD, INSTR_RSL_R0RD, 3, 0},
{ "stamy", OP48(0xeb000000009bLL), MASK_RSY_AARD, INSTR_RSY_AARD, 2, 3},
{ "lamy", OP48(0xeb000000009aLL), MASK_RSY_AARD, INSTR_RSY_AARD, 2, 3},
@@ -985,6 +1043,20 @@ static const struct s390_opcode s390_opcodes[] =
{ "srag", OP48(0xeb000000000aLL), MASK_RSE_RRRD, INSTR_RSE_RRRD, 2, 2},
{ "lmg", OP48(0xeb0000000004LL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 2, 3},
{ "lmg", OP48(0xeb0000000004LL), MASK_RSE_RRRD, INSTR_RSE_RRRD, 2, 2},
+/* QEMU-ADD: */
+ { "loc", OP48(0xeb00000000f2LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+ { "locg", OP48(0xeb00000000e2LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+ { "stoc", OP48(0xeb00000000f3LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+ { "stocg", OP48(0xeb00000000e3LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+ { "srak", OP48(0xeb00000000dcLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+ { "slak", OP48(0xeb00000000ddLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+ { "srlk", OP48(0xeb00000000deLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+ { "sllk", OP48(0xeb00000000dfLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+ { "asi", OP48(0xeb000000006aLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+ { "alsi", OP48(0xeb000000006eLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+ { "agsi", OP48(0xeb000000007aLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+ { "algsi", OP48(0xeb000000007eLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+/* QEMU-END */
{ "unpka", OP8(0xeaLL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
{ "pka", OP8(0xe9LL), MASK_SS_L2RDRD, INSTR_SS_L2RDRD, 3, 0},
{ "mvcin", OP8(0xe8LL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
@@ -993,6 +1065,17 @@ static const struct s390_opcode s390_opcodes[] =
{ "tprot", OP16(0xe501LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 3, 0},
{ "strag", OP48(0xe50000000002LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 2, 2},
{ "lasp", OP16(0xe500LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 3, 0},
+/* QEMU-ADD: */
+ { "mvhhi", OP16(0xe544LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "mvghi", OP16(0xe548LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "mvhi", OP16(0xe54cLL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "chhsi", OP16(0xe554LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "clhhsi", OP16(0xe555LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "cghsi", OP16(0xe558LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "clghsi", OP16(0xe559LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "chsi", OP16(0xe55cLL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+ { "clfhsi", OP16(0xe55dLL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+/* QEMU-END */
{ "slb", OP48(0xe30000000099LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 3, 3},
{ "slb", OP48(0xe30000000099LL), MASK_RXE_RRRD, INSTR_RXE_RRRD, 3, 2},
{ "alc", OP48(0xe30000000098LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 3, 3},
@@ -1116,6 +1199,9 @@ static const struct s390_opcode s390_opcodes[] =
{ "lrag", OP48(0xe30000000003LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 2, 3},
{ "lrag", OP48(0xe30000000003LL), MASK_RXE_RRRD, INSTR_RXE_RRRD, 2, 2},
{ "ltg", OP48(0xe30000000002LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 2, 4},
+/* QEMU-ADD: */
+ { "pfd", OP48(0xe30000000036LL), MASK_RXY_URRD, INSTR_RXY_URRD, 3, 6},
+/* QEMU-END */
{ "unpku", OP8(0xe2LL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
{ "pku", OP8(0xe1LL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
{ "edmk", OP8(0xdfLL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
@@ -1135,6 +1221,32 @@ static const struct s390_opcode s390_opcodes[] =
{ "csst", OP16(0xc802LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 2, 5},
{ "ectg", OP16(0xc801LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 2, 5},
{ "mvcos", OP16(0xc800LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 2, 4},
+/* QEMU-ADD: */
+ { "exrl", OP16(0xc600ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "pfdrl", OP16(0xc602ll), MASK_RIL_UP, INSTR_RIL_UP, 3, 6},
+ { "cghrl", OP16(0xc604ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "chrl", OP16(0xc605ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "clghrl", OP16(0xc606ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "clhrl", OP16(0xc607ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "cgrl", OP16(0xc608ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "clgrl", OP16(0xc60all), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "cgfrl", OP16(0xc60cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "crl", OP16(0xc60dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "clgfrl", OP16(0xc60ell), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "clrl", OP16(0xc60fll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+
+ { "llhrl", OP16(0xc400ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "lghrl", OP16(0xc404ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "lhrl", OP16(0xc405ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "llghrl", OP16(0xc406ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "sthrl", OP16(0xc407ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "lgrl", OP16(0xc408ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "stgrl", OP16(0xc40bll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "lgfrl", OP16(0xc40cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "lrl", OP16(0xc40dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "llgfrl", OP16(0xc40ell), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "strl", OP16(0xc40fll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+/* QEMU-END */
{ "clfi", OP16(0xc20fLL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
{ "clgfi", OP16(0xc20eLL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
{ "cfi", OP16(0xc20dLL), MASK_RIL_RI, INSTR_RIL_RI, 2, 4},
@@ -1265,6 +1377,29 @@ static const struct s390_opcode s390_opcodes[] =
{ "ltgr", OP16(0xb902LL), MASK_RRE_RR, INSTR_RRE_RR, 2, 2},
{ "lngr", OP16(0xb901LL), MASK_RRE_RR, INSTR_RRE_RR, 2, 2},
{ "lpgr", OP16(0xb900LL), MASK_RRE_RR, INSTR_RRE_RR, 2, 2},
+/* QEMU-ADD: */
+ { "crt", OP16(0xb972LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+ { "cgrt", OP16(0xb960LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+ { "clrt", OP16(0xb973LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+ { "clgrt", OP16(0xb961LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+ { "locr", OP16(0xb9f2LL), MASK_RRF_MRR, INSTR_RRF_MRR, 3, 6},
+ { "locgr", OP16(0xb9e2LL), MASK_RRF_MRR, INSTR_RRF_MRR, 3, 6},
+ { "popcnt", OP16(0xb9e1LL), MASK_RRE_RR, INSTR_RRE_RR, 3, 6},
+ { "ngrk", OP16(0xb9e4LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "ogrk", OP16(0xb9e6LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "xgrk", OP16(0xb9e7LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "agrk", OP16(0xb9e8LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "sgrk", OP16(0xb9e9LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "algrk", OP16(0xb9eaLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "slgrk", OP16(0xb9ebLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "nrk", OP16(0xb9f4LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "ork", OP16(0xb9f6LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "xrk", OP16(0xb9f7LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "ark", OP16(0xb9f8LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "srk", OP16(0xb9f9LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "alrk", OP16(0xb9faLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+ { "slrk", OP16(0xb9fbLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+/* QEMU-END */
{ "lctl", OP8(0xb7LL), MASK_RS_CCRD, INSTR_RS_CCRD, 3, 0},
{ "stctl", OP8(0xb6LL), MASK_RS_CCRD, INSTR_RS_CCRD, 3, 0},
{ "rrxtr", OP16(0xb3ffLL), MASK_RRF_FFFU, INSTR_RRF_FFFU, 2, 5},
@@ -1426,6 +1561,20 @@ static const struct s390_opcode s390_opcodes[] =
{ "ltebr", OP16(0xb302LL), MASK_RRE_FF, INSTR_RRE_FF, 3, 0},
{ "lnebr", OP16(0xb301LL), MASK_RRE_FF, INSTR_RRE_FF, 3, 0},
{ "lpebr", OP16(0xb300LL), MASK_RRE_FF, INSTR_RRE_FF, 3, 0},
+/* QEMU-ADD: */
+ { "clfebr", OP16(0xb39cLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "clfdbr", OP16(0xb39dLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "clfxbr", OP16(0xb39eLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "clgebr", OP16(0xb3acLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "clgdbr", OP16(0xb3adLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "clgxbr", OP16(0xb3aeLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "celfbr", OP16(0xb390LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "cdlfbr", OP16(0xb391LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "cxlfbr", OP16(0xb392LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "celgbr", OP16(0xb3a0LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "cdlgbr", OP16(0xb3a1LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+ { "cxlgbr", OP16(0xb3a2LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+/* QEMU-END */
{ "trap4", OP16(0xb2ffLL), MASK_S_RD, INSTR_S_RD, 3, 0},
{ "lfas", OP16(0xb2bdLL), MASK_S_RD, INSTR_S_RD, 2, 5},
{ "srnmt", OP16(0xb2b9LL), MASK_S_RD, INSTR_S_RD, 2, 5},
@@ -1774,22 +1923,6 @@ static const struct s390_opcode s390_opcodes[] =
{ "sckpf", OP16(0x0107LL), MASK_E, INSTR_E, 3, 0},
{ "upt", OP16(0x0102LL), MASK_E, INSTR_E, 3, 0},
{ "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0},
-
-/* QEMU-ADD: */
- { "crj", OP48(0xec0000000076LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
- { "cgrj", OP48(0xec0000000064LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
- { "clrj", OP48(0xec0000000077LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
- { "clgrj", OP48(0xec0000000065LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
-
- { "cij", OP48(0xec000000007eLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
- { "cgij", OP48(0xec000000007cLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
- { "clij", OP48(0xec000000007fLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
- { "clgij", OP48(0xec000000007dLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
-
- { "lrl", OP16(0xc40dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
- { "lgrl", OP16(0xc408ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
- { "lgfrl", OP16(0xc40cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
-/* QEMU-END */
};
static const int s390_num_opcodes =
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 004/126] target-s390: Fix disassembly of cpsdr
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (2 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 003/126] target-s390: Disassemble more z10 and z196 opcodes Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub Richard Henderson
` (97 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
s390-dis.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/s390-dis.c b/s390-dis.c
index bbdd239..3759164 100644
--- a/s390-dis.c
+++ b/s390-dis.c
@@ -673,7 +673,9 @@ static const struct s390_operand s390_operands[] =
This is just a workaround for existing code e.g. glibc. */
#define INSTR_RRE_RR_OPT 4, { R_24,RO_28,0,0,0,0 } /* efpc, sfpc */
#define INSTR_RRF_F0FF 4, { F_16,F_24,F_28,0,0,0 } /* e.g. madbr */
-#define INSTR_RRF_F0FF2 4, { F_24,F_16,F_28,0,0,0 } /* e.g. cpsdr */
+/* QEMU-MOD */
+#define INSTR_RRF_F0FF2 4, { F_24,F_28,F_16,0,0,0 } /* e.g. cpsdr */
+/* QEMU-END */
#define INSTR_RRF_F0FR 4, { F_24,F_16,R_28,0,0,0 } /* e.g. iedtr */
#define INSTR_RRF_FUFF 4, { F_24,F_16,F_28,U4_20,0,0 } /* e.g. didbr */
#define INSTR_RRF_RURR 4, { R_24,R_28,R_16,U4_20,0,0 } /* e.g. .insn */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (3 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 004/126] target-s390: Fix disassembly of cpsdr Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-12 13:25 ` Alexander Graf
2012-09-09 21:04 ` [Qemu-devel] [PATCH 006/126] target-s390: Add missing temp_free in gen_op_calc_cc Richard Henderson
` (96 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
The real gdb protocol doesn't split out pc or cc as real registers.
Those are pseudos that are extracted as needed from the PSW. Don't
modify env->cc_op during read -- that way lies heisenbugs.
Fill in the XXX for the fp registers.
Remove duplicated defines in cpu.h.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
gdbstub.c | 78 +++++++++++++++++++++++++++++++++---------------------
target-s390x/cpu.h | 73 --------------------------------------------------
2 files changed, 48 insertions(+), 103 deletions(-)
diff --git a/gdbstub.c b/gdbstub.c
index 5d37dd9..6aed0b4 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1499,27 +1499,35 @@ static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
}
#elif defined (TARGET_S390X)
-#define NUM_CORE_REGS S390_NUM_TOTAL_REGS
+#define NUM_CORE_REGS S390_NUM_REGS
static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
{
+ uint64_t val;
+ int cc_op;
+
switch (n) {
- case S390_PSWM_REGNUM: GET_REGL(env->psw.mask); break;
- case S390_PSWA_REGNUM: GET_REGL(env->psw.addr); break;
- case S390_R0_REGNUM ... S390_R15_REGNUM:
- GET_REGL(env->regs[n-S390_R0_REGNUM]); break;
- case S390_A0_REGNUM ... S390_A15_REGNUM:
- GET_REG32(env->aregs[n-S390_A0_REGNUM]); break;
- case S390_FPC_REGNUM: GET_REG32(env->fpc); break;
- case S390_F0_REGNUM ... S390_F15_REGNUM:
- /* XXX */
- break;
- case S390_PC_REGNUM: GET_REGL(env->psw.addr); break;
- case S390_CC_REGNUM:
- env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
- env->cc_vr);
- GET_REG32(env->cc_op);
- break;
+ case S390_PSWM_REGNUM:
+ val = env->psw.mask & ~(3ull << 13);
+ cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
+ val |= cc_op << 13;
+ GET_REGL(val);
+ break;
+ case S390_PSWA_REGNUM:
+ GET_REGL(env->psw.addr);
+ break;
+ case S390_R0_REGNUM ... S390_R15_REGNUM:
+ GET_REGL(env->regs[n-S390_R0_REGNUM]);
+ break;
+ case S390_A0_REGNUM ... S390_A15_REGNUM:
+ GET_REG32(env->aregs[n-S390_A0_REGNUM]);
+ break;
+ case S390_FPC_REGNUM:
+ GET_REG32(env->fpc);
+ break;
+ case S390_F0_REGNUM ... S390_F15_REGNUM:
+ GET_REG64(env->fregs[n-S390_F0_REGNUM].ll);
+ break;
}
return 0;
@@ -1534,20 +1542,30 @@ static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n)
tmp32 = ldl_p(mem_buf);
switch (n) {
- case S390_PSWM_REGNUM: env->psw.mask = tmpl; break;
- case S390_PSWA_REGNUM: env->psw.addr = tmpl; break;
- case S390_R0_REGNUM ... S390_R15_REGNUM:
- env->regs[n-S390_R0_REGNUM] = tmpl; break;
- case S390_A0_REGNUM ... S390_A15_REGNUM:
- env->aregs[n-S390_A0_REGNUM] = tmp32; r=4; break;
- case S390_FPC_REGNUM: env->fpc = tmp32; r=4; break;
- case S390_F0_REGNUM ... S390_F15_REGNUM:
- /* XXX */
- break;
- case S390_PC_REGNUM: env->psw.addr = tmpl; break;
- case S390_CC_REGNUM: env->cc_op = tmp32; r=4; break;
+ case S390_PSWM_REGNUM:
+ env->psw.mask = tmpl;
+ env->cc_op = (tmpl >> 13) & 3;
+ break;
+ case S390_PSWA_REGNUM:
+ env->psw.addr = tmpl;
+ break;
+ case S390_R0_REGNUM ... S390_R15_REGNUM:
+ env->regs[n-S390_R0_REGNUM] = tmpl;
+ break;
+ case S390_A0_REGNUM ... S390_A15_REGNUM:
+ env->aregs[n-S390_A0_REGNUM] = tmp32;
+ r = 4;
+ break;
+ case S390_FPC_REGNUM:
+ env->fpc = tmp32;
+ r = 4;
+ break;
+ case S390_F0_REGNUM ... S390_F15_REGNUM:
+ env->fregs[n-S390_F0_REGNUM].ll = tmpl;
+ break;
+ default:
+ return 0;
}
-
return r;
}
#elif defined (TARGET_LM32)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index ed81af3..471fb91 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -430,79 +430,6 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
/* Total. */
#define S390_NUM_REGS 51
-/* Pseudo registers -- PC and condition code. */
-#define S390_PC_REGNUM S390_NUM_REGS
-#define S390_CC_REGNUM (S390_NUM_REGS+1)
-#define S390_NUM_PSEUDO_REGS 2
-#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
-
-
-
-/* Program Status Word. */
-#define S390_PSWM_REGNUM 0
-#define S390_PSWA_REGNUM 1
-/* General Purpose Registers. */
-#define S390_R0_REGNUM 2
-#define S390_R1_REGNUM 3
-#define S390_R2_REGNUM 4
-#define S390_R3_REGNUM 5
-#define S390_R4_REGNUM 6
-#define S390_R5_REGNUM 7
-#define S390_R6_REGNUM 8
-#define S390_R7_REGNUM 9
-#define S390_R8_REGNUM 10
-#define S390_R9_REGNUM 11
-#define S390_R10_REGNUM 12
-#define S390_R11_REGNUM 13
-#define S390_R12_REGNUM 14
-#define S390_R13_REGNUM 15
-#define S390_R14_REGNUM 16
-#define S390_R15_REGNUM 17
-/* Access Registers. */
-#define S390_A0_REGNUM 18
-#define S390_A1_REGNUM 19
-#define S390_A2_REGNUM 20
-#define S390_A3_REGNUM 21
-#define S390_A4_REGNUM 22
-#define S390_A5_REGNUM 23
-#define S390_A6_REGNUM 24
-#define S390_A7_REGNUM 25
-#define S390_A8_REGNUM 26
-#define S390_A9_REGNUM 27
-#define S390_A10_REGNUM 28
-#define S390_A11_REGNUM 29
-#define S390_A12_REGNUM 30
-#define S390_A13_REGNUM 31
-#define S390_A14_REGNUM 32
-#define S390_A15_REGNUM 33
-/* Floating Point Control Word. */
-#define S390_FPC_REGNUM 34
-/* Floating Point Registers. */
-#define S390_F0_REGNUM 35
-#define S390_F1_REGNUM 36
-#define S390_F2_REGNUM 37
-#define S390_F3_REGNUM 38
-#define S390_F4_REGNUM 39
-#define S390_F5_REGNUM 40
-#define S390_F6_REGNUM 41
-#define S390_F7_REGNUM 42
-#define S390_F8_REGNUM 43
-#define S390_F9_REGNUM 44
-#define S390_F10_REGNUM 45
-#define S390_F11_REGNUM 46
-#define S390_F12_REGNUM 47
-#define S390_F13_REGNUM 48
-#define S390_F14_REGNUM 49
-#define S390_F15_REGNUM 50
-/* Total. */
-#define S390_NUM_REGS 51
-
-/* Pseudo registers -- PC and condition code. */
-#define S390_PC_REGNUM S390_NUM_REGS
-#define S390_CC_REGNUM (S390_NUM_REGS+1)
-#define S390_NUM_PSEUDO_REGS 2
-#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
-
/* CC optimization */
enum cc_op {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 006/126] target-s390: Add missing temp_free in gen_op_calc_cc
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (4 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR Richard Henderson
` (95 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 66119cd..3080cef 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -757,6 +757,7 @@ static void gen_op_calc_cc(DisasContext *s)
}
tcg_temp_free_i32(local_cc_op);
+ tcg_temp_free_i64(dummy);
/* We now have cc in cc_op as constant */
set_cc_static(s);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (5 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 006/126] target-s390: Add missing temp_free in gen_op_calc_cc Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-10 14:34 ` Aurelien Jarno
2012-09-09 21:04 ` [Qemu-devel] [PATCH 008/126] target-s390: Add format based disassassmbly infrastructure Richard Henderson
` (94 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
At the same time, tidy other usages of tcg_gen_deposit_i64.
In some cases we can "type cast" rather than extend, and in
others we can allow tcg_gen_deposit_i64 itself to optimize
the HOST_LONG_BITS==32 case.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 68 ++++++++++++++++++++++++++++--------------------
1 file changed, 40 insertions(+), 28 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3080cef..bf35a65 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -89,7 +89,7 @@ void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf,
}
for (i = 0; i < 16; i++) {
- cpu_fprintf(f, "F%02d=%016" PRIx64, i, *(uint64_t *)&env->fregs[i]);
+ cpu_fprintf(f, "F%02d=%016" PRIx64, i, env->fregs[i].ll);
if ((i % 4) == 3) {
cpu_fprintf(f, "\n");
} else {
@@ -136,21 +136,22 @@ static TCGv_i64 cc_src;
static TCGv_i64 cc_dst;
static TCGv_i64 cc_vr;
-static char cpu_reg_names[10*3 + 6*4];
+static char cpu_reg_names[32][4];
static TCGv_i64 regs[16];
+static TCGv_i64 fregs[16];
static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
void s390x_translate_init(void)
{
int i;
- size_t cpu_reg_names_size = sizeof(cpu_reg_names);
- char *p;
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
- psw_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.addr),
+ psw_addr = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUS390XState, psw.addr),
"psw_addr");
- psw_mask = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.mask),
+ psw_mask = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUS390XState, psw.mask),
"psw_mask");
cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
@@ -162,13 +163,18 @@ void s390x_translate_init(void)
cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
"cc_vr");
- p = cpu_reg_names;
for (i = 0; i < 16; i++) {
- snprintf(p, cpu_reg_names_size, "r%d", i);
+ snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i);
regs[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUS390XState, regs[i]), p);
- p += (i < 10) ? 3 : 4;
- cpu_reg_names_size -= (i < 10) ? 3 : 4;
+ offsetof(CPUS390XState, regs[i]),
+ cpu_reg_names[i]);
+ }
+
+ for (i = 0; i < 16; i++) {
+ snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
+ fregs[i] = tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUS390XState, fregs[i].d),
+ cpu_reg_names[i + 16]);
}
}
@@ -182,14 +188,18 @@ static inline TCGv_i64 load_reg(int reg)
static inline TCGv_i64 load_freg(int reg)
{
TCGv_i64 r = tcg_temp_new_i64();
- tcg_gen_ld_i64(r, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
+ tcg_gen_mov_i64(r, fregs[reg]);
return r;
}
static inline TCGv_i32 load_freg32(int reg)
{
TCGv_i32 r = tcg_temp_new_i32();
- tcg_gen_ld_i32(r, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
+#if HOST_LONG_BITS == 32
+ tcg_gen_mov_i32(r, TCGV_HIGH(fregs[reg]));
+#else
+ tcg_gen_shri_i64(MAKE_TCGV_I64(GET_TCGV_I32(r)), fregs[reg], 32);
+#endif
return r;
}
@@ -214,39 +224,35 @@ static inline void store_reg(int reg, TCGv_i64 v)
static inline void store_freg(int reg, TCGv_i64 v)
{
- tcg_gen_st_i64(v, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
+ tcg_gen_mov_i64(fregs[reg], v);
}
static inline void store_reg32(int reg, TCGv_i32 v)
{
+ /* 32 bit register writes keep the upper half */
#if HOST_LONG_BITS == 32
tcg_gen_mov_i32(TCGV_LOW(regs[reg]), v);
#else
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(tmp, v);
- /* 32 bit register writes keep the upper half */
- tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 32);
- tcg_temp_free_i64(tmp);
+ tcg_gen_deposit_i64(regs[reg], regs[reg],
+ MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 32);
#endif
}
static inline void store_reg32_i64(int reg, TCGv_i64 v)
{
/* 32 bit register writes keep the upper half */
-#if HOST_LONG_BITS == 32
- tcg_gen_mov_i32(TCGV_LOW(regs[reg]), TCGV_LOW(v));
-#else
tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
-#endif
}
static inline void store_reg16(int reg, TCGv_i32 v)
{
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(tmp, v);
/* 16 bit register writes keep the upper bytes */
- tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 16);
- tcg_temp_free_i64(tmp);
+#if HOST_LONG_BITS == 32
+ tcg_gen_deposit_i32(TCGV_LOW(regs[reg]), TCGV_LOW(regs[reg]), v, 0, 16);
+#else
+ tcg_gen_deposit_i64(regs[reg], regs[reg],
+ MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 16);
+#endif
}
static inline void store_reg8(int reg, TCGv_i64 v)
@@ -257,7 +263,13 @@ static inline void store_reg8(int reg, TCGv_i64 v)
static inline void store_freg32(int reg, TCGv_i32 v)
{
- tcg_gen_st_i32(v, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
+ /* 32 bit register writes keep the lower half */
+#if HOST_LONG_BITS == 32
+ tcg_gen_mov_i32(TCGV_HIGH(fregs[reg]), v);
+#else
+ tcg_gen_deposit_i64(fregs[reg], fregs[reg],
+ MAKE_TCGV_I64(GET_TCGV_I32(v)), 32, 32);
+#endif
}
static inline void update_psw_addr(DisasContext *s)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 008/126] target-s390: Add format based disassassmbly infrastructure
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (6 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 009/126] target-s390: Split out disas_jcc Richard Henderson
` (93 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 54 ++
target-s390x/insn-format.def | 55 +++
target-s390x/translate.c | 1119 ++++++++++++++++++++++++++++--------------
3 files changed, 861 insertions(+), 367 deletions(-)
create mode 100644 target-s390x/insn-data.def
create mode 100644 target-s390x/insn-format.def
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
new file mode 100644
index 0000000..7d81928
--- /dev/null
+++ b/target-s390x/insn-data.def
@@ -0,0 +1,54 @@
+/* ADD */
+ C(0x1a00, AR, RR_a, Z, r1, r2, new, r1_32, add, adds32)
+ C(0xb9f8, ARK, RRF_a, DO, r2, r3, new, r1_32, add, adds32)
+ C(0x5a00, A, RX_a, Z, r1, m2_32s, new, r1_32, add, adds32)
+ C(0xe35a, AY, RXY_a, LD, r1, m2_32s, new, r1_32, add, adds32)
+ C(0xb908, AGR, RRE, Z, r1, r2, r1, 0, add, adds64)
+ C(0xb918, AGFR, RRE, Z, r1, r2_32s, r1, 0, add, adds64)
+ C(0xb9e8, AGRK, RRF_a, DO, r2, r3, r1, 0, add, adds64)
+ C(0xe308, AG, RXY_a, Z, r1, m2_64, r1, 0, add, adds64)
+ C(0xe318, AGF, RXY_a, Z, r1, m2_32s, r1, 0, add, adds64)
+/* ADD IMMEDIATE */
+ C(0xc209, AFI, RIL_a, EI, r1, i2, new, r1_32, add, adds32)
+ C(0xeb6a, ASI, SIY, GIE, m1_32s, i2, new, m1_32, add, adds32)
+ C(0xecd8, AHIK, RIE_d, DO, r3, i2, new, r1_32, add, adds32)
+ C(0xc208, AGFI, RIL_a, EI, r1, i2, r1, 0, add, adds64)
+ C(0xeb7a, AGSI, SIY, GIE, m1_64, i2, new, m1_64, add, adds64)
+ C(0xecd9, AGHIK, RIE_d, DO, r3, i2, r1, 0, add, adds64)
+/* ADD LOGICAL */
+ C(0x1e00, ALR, RR_a, Z, r1, r2, new, r1_32, add, addu32)
+ C(0xb9fa, ALRK, RRF_a, DO, r2, r3, new, r1_32, add, addu32)
+ C(0x5e00, AL, RX_a, Z, r1, m2_32u, new, r1_32, add, addu32)
+ C(0xe35e, ALY, RXY_a, LD, r1, m2_32u, new, r1_32, add, addu32)
+ C(0xb90a, ALGR, RRE, Z, r1, r2, r1, 0, add, addu64)
+ C(0xb91a, ALGFR, RRE, Z, r1, r2_32u, r1, 0, add, addu64)
+ C(0xb9ea, ALGRK, RRF_a, DO, r2, r3, r1, 0, add, addu64)
+ C(0xe30a, ALG, RXY_a, Z, r1, m2_64, r1, 0, add, addu64)
+ C(0xe31a, ALGF, RXY_a, Z, r1, m2_32u, r1, 0, add, addu64)
+/* ADD LOGICAL IMMEDIATE */
+ C(0xc20b, ALFI, RIL_a, EI, r1, i2_32u, new, r1_32, add, addu32)
+ C(0xc20a, ALGFI, RIL_a, EI, r1, i2_32u, r1, 0, add, addu64)
+
+/* SUBTRACT */
+ C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
+ C(0xb9f9, SRK, RRF_a, DO, r2, r3, new, r1_32, sub, subs32)
+ C(0x5b00, S, RX_a, Z, r1, m2_32s, new, r1_32, sub, subs32)
+ C(0xe35b, SY, RXY_a, LD, r1, m2_32s, new, r1_32, sub, subs32)
+ C(0xb909, SGR, RRE, Z, r1, r2, r1, 0, sub, subs64)
+ C(0xb919, SGFR, RRE, Z, r1, r2_32s, r1, 0, sub, subs64)
+ C(0xb9e9, SGRK, RRF_a, DO, r2, r3, r1, 0, sub, subs64)
+ C(0xe309, SG, RXY_a, Z, r1, m2_64, r1, 0, sub, subs64)
+ C(0xe319, SGF, RXY_a, Z, r1, m2_32s, r1, 0, sub, subs64)
+/* SUBTRACT LOGICAL */
+ C(0x1f00, SLR, RR_a, Z, r1, r2, new, r1_32, sub, subu32)
+ C(0xb9fb, SLRK, RRF_a, DO, r2, r3, new, r1_32, sub, subu32)
+ C(0x5f00, SL, RX_a, Z, r1, m2_32u, new, r1_32, sub, subu32)
+ C(0xe35f, SLY, RXY_a, LD, r1, m2_32u, new, r1_32, sub, subu32)
+ C(0xb90b, SLGR, RRE, Z, r1, r2, r1, 0, sub, subu64)
+ C(0xb91b, SLGFR, RRE, Z, r1, r2_32u, r1, 0, sub, subu64)
+ C(0xb9eb, SLGRK, RRF_a, DO, r2, r3, r1, 0, sub, subu64)
+ C(0xe30b, SLG, RXY_a, Z, r1, m2_64, r1, 0, sub, subu64)
+ C(0xe31b, SLGF, RXY_a, Z, r1, m2_32u, r1, 0, sub, subu64)
+/* SUBTRACT LOGICAL IMMEDIATE */
+ C(0xc205, SLFI, RIL_a, EI, r1, i2_32u, new, r1_32, sub, subu32)
+ C(0xc204, SLGFI, RIL_a, EI, r1, i2_32u, r1, 0, sub, subu64)
diff --git a/target-s390x/insn-format.def b/target-s390x/insn-format.def
new file mode 100644
index 0000000..0e898b9
--- /dev/null
+++ b/target-s390x/insn-format.def
@@ -0,0 +1,55 @@
+/* Description of s390 insn formats. */
+/* NAME F1, F2... */
+F0(E)
+F1(I, I(1, 8, 8))
+F2(RI_a, R(1, 8), I(2,16,16))
+F2(RI_b, R(1, 8), I(2,16,16))
+F2(RI_c, M(1, 8), I(2,16,16))
+F3(RIE_a, R(1, 8), I(2,16,16), M(3,32))
+F4(RIE_b, R(1, 8), R(2,12), M(3,32), I(4,16,16))
+F4(RIE_c, R(1, 8), I(2,32, 8), M(3,12), I(4,16,16))
+F3(RIE_d, R(1, 8), I(2,16,16), R(3,12))
+F3(RIE_e, R(1, 8), I(2,16,16), R(3,12))
+F5(RIE_f, R(1, 8), R(2,12), I(3,16,8), I(4,24,8), I(5,32,8))
+F2(RIL_a, R(1, 8), I(2,16,32))
+F2(RIL_b, R(1, 8), I(2,16,32))
+F2(RIL_c, M(1, 8), I(2,16,32))
+F4(RIS, R(1, 8), I(2,32, 8), M(3,12), BD(4,16,20))
+/* ??? The PoO does not call out subtypes _a and _b for RR, as it does
+ for e.g. RX. Our checking requires this for e.g. BCR. */
+F2(RR_a, R(1, 8), R(2,12))
+F2(RR_b, M(1, 8), R(2,12))
+F2(RRE, R(1,24), R(2,28))
+F3(RRD, R(1,16), R(2,28), R(3,24))
+F4(RRF_a, R(1,24), R(2,28), R(3,16), M(4,20))
+F4(RRF_b, R(1,24), R(2,28), R(3,16), M(4,20))
+F4(RRF_c, R(1,24), R(2,28), M(3,16), M(4,20))
+F4(RRF_d, R(1,24), R(2,28), M(3,16), M(4,20))
+F4(RRF_e, R(1,24), R(2,28), M(3,16), M(4,20))
+F4(RRS, R(1, 8), R(2,12), M(3,32), BD(4,16,20))
+F3(RS_a, R(1, 8), BD(2,16,20), R(3,12))
+F3(RS_b, R(1, 8), BD(2,16,20), M(3,12))
+F3(RSI, R(1, 8), I(2,16,16), R(3,12))
+F2(RSL, L(1, 8, 4), BD(1,16,20))
+F3(RSY_a, R(1, 8), BDL(2), R(3,12))
+F3(RSY_b, R(1, 8), BDL(2), M(3,12))
+F2(RX_a, R(1, 8), BXD(2))
+F2(RX_b, M(1, 8), BXD(2))
+F2(RXE, R(1, 8), BXD(2))
+F3(RXF, R(1,32), BXD(2), R(3, 8))
+F2(RXY_a, R(1, 8), BXDL(2))
+F2(RXY_b, M(1, 8), BXDL(2))
+F1(S, BD(2,16,20))
+F2(SI, BD(1,16,20), I(2,8,8))
+F2(SIL, BD(1,16,20), I(2,32,16))
+F2(SIY, BDL(1), I(2, 8, 8))
+F3(SS_a, L(1, 8, 8), BD(1,16,20), BD(2,32,36))
+F4(SS_b, L(1, 8, 4), BD(1,16,20), L(2,12,4), BD(2,32,36))
+F4(SS_c, L(1, 8, 4), BD(1,16,20), BD(2,32,36), I(3,12, 4))
+/* ??? Odd man out. The L1 field here is really a register, but the
+ easy way to compress the fields has R1 and B1 overlap. */
+F4(SS_d, L(1, 8, 4), BD(1,16,20), BD(2,32,36), R(3,12))
+F4(SS_e, R(1, 8), BD(2,16,20), R(3,12), BD(4,32,36))
+F3(SS_f, BD(1,16,20), L(2,8,8), BD(2,32,36))
+F2(SSE, BD(1,16,20), BD(2,32,36))
+F3(SSF, BD(1,16,20), BD(2,32,36), R(3,8))
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index bf35a65..ecd6099 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -42,12 +42,20 @@ static TCGv_ptr cpu_env;
#define GEN_HELPER 1
#include "helper.h"
+
+/* Information that (most) every instruction needs to manipulate. */
typedef struct DisasContext DisasContext;
+typedef struct DisasInsn DisasInsn;
+typedef struct DisasFields DisasFields;
+
struct DisasContext {
- uint64_t pc;
- int is_jmp;
- enum cc_op cc_op;
struct TranslationBlock *tb;
+ const DisasInsn *insn;
+ DisasFields *fields;
+ uint64_t pc, next_pc;
+ enum cc_op cc_op;
+ bool singlestep_enabled;
+ int is_jmp;
};
#define DISAS_EXCP 4
@@ -293,15 +301,12 @@ static inline uint64_t ld_code2(uint64_t pc)
static inline uint64_t ld_code4(uint64_t pc)
{
- return (uint64_t)cpu_ldl_code(cpu_single_env, pc);
+ return (uint64_t)(uint32_t)cpu_ldl_code(cpu_single_env, pc);
}
static inline uint64_t ld_code6(uint64_t pc)
{
- uint64_t opc;
- opc = (uint64_t)cpu_lduw_code(cpu_single_env, pc) << 32;
- opc |= (uint64_t)(uint32_t)cpu_ldl_code(cpu_single_env, pc + 2);
- return opc;
+ return (ld_code2(pc) << 32) | ld_code4(pc + 2);
}
static inline int get_mem_index(DisasContext *s)
@@ -603,17 +608,6 @@ static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
gen_op_update3_cc_i64(s, CC_OP_ADDU_64, v1, v2, vr);
}
-static void set_cc_sub64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2, TCGv_i64 vr)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUB_64, v1, v2, vr);
-}
-
-static void set_cc_subu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
- TCGv_i64 vr)
-{
- gen_op_update3_cc_i64(s, CC_OP_SUBU_64, v1, v2, vr);
-}
-
static void set_cc_abs64(DisasContext *s, TCGv_i64 v1)
{
gen_op_update1_cc_i64(s, CC_OP_ABS_64, v1);
@@ -640,12 +634,6 @@ static void set_cc_sub32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
gen_op_update3_cc_i32(s, CC_OP_SUB_32, v1, v2, vr);
}
-static void set_cc_subu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
- TCGv_i32 vr)
-{
- gen_op_update3_cc_i32(s, CC_OP_SUBU_32, v1, v2, vr);
-}
-
static void set_cc_abs32(DisasContext *s, TCGv_i32 v1)
{
gen_op_update1_cc_i32(s, CC_OP_ABS_32, v1);
@@ -1528,72 +1516,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_temp_free_i64(tmp3);
tcg_temp_free_i64(tmp4);
break;
- case 0x8: /* AG R1,D2(X2,B2) [RXY] */
- case 0xa: /* ALG R1,D2(X2,B2) [RXY] */
- case 0x18: /* AGF R1,D2(X2,B2) [RXY] */
- case 0x1a: /* ALGF R1,D2(X2,B2) [RXY] */
- if (op == 0x1a) {
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- } else if (op == 0x18) {
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
- } else {
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- }
- tmp4 = load_reg(r1);
- tmp3 = tcg_temp_new_i64();
- tcg_gen_add_i64(tmp3, tmp4, tmp2);
- store_reg(r1, tmp3);
- switch (op) {
- case 0x8:
- case 0x18:
- set_cc_add64(s, tmp4, tmp2, tmp3);
- break;
- case 0xa:
- case 0x1a:
- set_cc_addu64(s, tmp4, tmp2, tmp3);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- tcg_temp_free_i64(tmp4);
- break;
- case 0x9: /* SG R1,D2(X2,B2) [RXY] */
- case 0xb: /* SLG R1,D2(X2,B2) [RXY] */
- case 0x19: /* SGF R1,D2(X2,B2) [RXY] */
- case 0x1b: /* SLGF R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- if (op == 0x19) {
- tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
- } else if (op == 0x1b) {
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- } else {
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- }
- tmp4 = load_reg(r1);
- tmp3 = tcg_temp_new_i64();
- tcg_gen_sub_i64(tmp3, tmp4, tmp2);
- store_reg(r1, tmp3);
- switch (op) {
- case 0x9:
- case 0x19:
- set_cc_sub64(s, tmp4, tmp2, tmp3);
- break;
- case 0xb:
- case 0x1b:
- set_cc_subu64(s, tmp4, tmp2, tmp3);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- tcg_temp_free_i64(tmp4);
- break;
case 0xf: /* LRVG R1,D2(X2,B2) [RXE] */
tmp2 = tcg_temp_new_i64();
tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
@@ -1716,40 +1638,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg32_i64(r1, tmp3);
tcg_temp_free_i64(tmp3);
break;
- case 0x5a: /* AY R1,D2(X2,B2) [RXY] */
- case 0x5b: /* SY R1,D2(X2,B2) [RXY] */
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp32_3 = tcg_temp_new_i32();
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- tcg_temp_free_i64(tmp2);
- switch (op) {
- case 0x5a:
- tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
- break;
- case 0x5b:
- tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
- break;
- default:
- tcg_abort();
- }
- store_reg32(r1, tmp32_3);
- switch (op) {
- case 0x5a:
- set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x5b:
- set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0x71: /* LAY R1,D2(X2,B2) [RXY] */
store_reg(r1, addr);
break;
@@ -3337,68 +3225,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
store_reg(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0x8: /* AGR R1,R2 [RRE] */
- case 0xa: /* ALGR R1,R2 [RRE] */
- tmp = load_reg(r1);
- tmp2 = load_reg(r2);
- tmp3 = tcg_temp_new_i64();
- tcg_gen_add_i64(tmp3, tmp, tmp2);
- store_reg(r1, tmp3);
- switch (op) {
- case 0x8:
- set_cc_add64(s, tmp, tmp2, tmp3);
- break;
- case 0xa:
- set_cc_addu64(s, tmp, tmp2, tmp3);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
- case 0x9: /* SGR R1,R2 [RRE] */
- case 0xb: /* SLGR R1,R2 [RRE] */
- case 0x1b: /* SLGFR R1,R2 [RRE] */
- case 0x19: /* SGFR R1,R2 [RRE] */
- tmp = load_reg(r1);
- switch (op) {
- case 0x1b:
- tmp32_1 = load_reg32(r2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(tmp2, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x19:
- tmp32_1 = load_reg32(r2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_ext_i32_i64(tmp2, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- default:
- tmp2 = load_reg(r2);
- break;
- }
- tmp3 = tcg_temp_new_i64();
- tcg_gen_sub_i64(tmp3, tmp, tmp2);
- store_reg(r1, tmp3);
- switch (op) {
- case 0x9:
- case 0x19:
- set_cc_sub64(s, tmp, tmp2, tmp3);
- break;
- case 0xb:
- case 0x1b:
- set_cc_subu64(s, tmp, tmp2, tmp3);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0xc: /* MSGR R1,R2 [RRE] */
case 0x1c: /* MSGFR R1,R2 [RRE] */
tmp = load_reg(r1);
@@ -3456,29 +3282,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
break;
- case 0x18: /* AGFR R1,R2 [RRE] */
- case 0x1a: /* ALGFR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tmp2 = tcg_temp_new_i64();
- if (op == 0x18) {
- tcg_gen_ext_i32_i64(tmp2, tmp32_1);
- } else {
- tcg_gen_extu_i32_i64(tmp2, tmp32_1);
- }
- tcg_temp_free_i32(tmp32_1);
- tmp = load_reg(r1);
- tmp3 = tcg_temp_new_i64();
- tcg_gen_add_i64(tmp3, tmp, tmp2);
- store_reg(r1, tmp3);
- if (op == 0x18) {
- set_cc_add64(s, tmp, tmp2, tmp3);
- } else {
- set_cc_addu64(s, tmp, tmp2, tmp3);
- }
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x0f: /* LRVGR R1,R2 [RRE] */
tcg_gen_bswap64_i64(regs[r1], regs[r2]);
break;
@@ -3775,54 +3578,10 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
static void disas_c2(DisasContext *s, int op, int r1, int i2)
{
- TCGv_i64 tmp, tmp2, tmp3;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+ TCGv_i64 tmp;
+ TCGv_i32 tmp32_1;
switch (op) {
- case 0x4: /* SLGFI R1,I2 [RIL] */
- case 0xa: /* ALGFI R1,I2 [RIL] */
- tmp = load_reg(r1);
- tmp2 = tcg_const_i64((uint64_t)(uint32_t)i2);
- tmp3 = tcg_temp_new_i64();
- switch (op) {
- case 0x4:
- tcg_gen_sub_i64(tmp3, tmp, tmp2);
- set_cc_subu64(s, tmp, tmp2, tmp3);
- break;
- case 0xa:
- tcg_gen_add_i64(tmp3, tmp, tmp2);
- set_cc_addu64(s, tmp, tmp2, tmp3);
- break;
- default:
- tcg_abort();
- }
- store_reg(r1, tmp3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
- case 0x5: /* SLFI R1,I2 [RIL] */
- case 0xb: /* ALFI R1,I2 [RIL] */
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_const_i32(i2);
- tmp32_3 = tcg_temp_new_i32();
- switch (op) {
- case 0x5:
- tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
- set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0xb:
- tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
- set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- default:
- tcg_abort();
- }
- store_reg32(r1, tmp32_3);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0xc: /* CGFI R1,I2 [RIL] */
tmp = load_reg(r1);
cmp_s64c(s, tmp, (int64_t)i2);
@@ -4040,42 +3799,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x1a: /* AR R1,R2 [RR] */
- case 0x1e: /* ALR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r2);
- tmp32_3 = tcg_temp_new_i32();
- tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
- store_reg32(r1, tmp32_3);
- if (opc == 0x1a) {
- set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
- } else {
- set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
- }
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0x1b: /* SR R1,R2 [RR] */
- case 0x1f: /* SLR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r2);
- tmp32_3 = tcg_temp_new_i32();
- tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
- store_reg32(r1, tmp32_3);
- if (opc == 0x1b) {
- set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
- } else {
- set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
- }
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0x1c: /* MR R1,R2 [RR] */
/* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
insn = ld_code2(s->pc);
@@ -4361,51 +4084,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x5a: /* A R1,D2(X2,B2) [RX] */
- case 0x5b: /* S R1,D2(X2,B2) [RX] */
- case 0x5e: /* AL R1,D2(X2,B2) [RX] */
- case 0x5f: /* SL R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp32_3 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32s(tmp, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp);
- switch (opc) {
- case 0x5a:
- case 0x5e:
- tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
- break;
- case 0x5b:
- case 0x5f:
- tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
- break;
- default:
- tcg_abort();
- }
- store_reg32(r1, tmp32_3);
- switch (opc) {
- case 0x5a:
- set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x5e:
- set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x5b:
- set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x5f:
- set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0x5c: /* M R1,D2(X2,B2) [RX] */
/* reg(r1, r1+1) = reg(r1+1) * *(s32*)addr */
insn = ld_code4(s->pc);
@@ -5110,9 +4788,698 @@ static void disas_s390_insn(DisasContext *s)
gen_illegal_opcode(s, ilc);
break;
}
+}
+
+/* ====================================================================== */
+/* Define the insn format enumeration. */
+#define F0(N) FMT_##N,
+#define F1(N, X1) F0(N)
+#define F2(N, X1, X2) F0(N)
+#define F3(N, X1, X2, X3) F0(N)
+#define F4(N, X1, X2, X3, X4) F0(N)
+#define F5(N, X1, X2, X3, X4, X5) F0(N)
+
+typedef enum {
+#include "insn-format.def"
+} DisasFormat;
+
+#undef F0
+#undef F1
+#undef F2
+#undef F3
+#undef F4
+#undef F5
+
+/* Define a structure to hold the decoded fields. We'll store each inside
+ an array indexed by an enum. In order to conserve memory, we'll arrange
+ for fields that do not exist at the same time to overlap, thus the "C"
+ for compact. For checking purposes there is an "O" for original index
+ as well that will be applied to availability bitmaps. */
+
+enum DisasFieldIndexO {
+ FLD_O_r1,
+ FLD_O_r2,
+ FLD_O_r3,
+ FLD_O_m1,
+ FLD_O_m3,
+ FLD_O_m4,
+ FLD_O_b1,
+ FLD_O_b2,
+ FLD_O_b4,
+ FLD_O_d1,
+ FLD_O_d2,
+ FLD_O_d4,
+ FLD_O_x2,
+ FLD_O_l1,
+ FLD_O_l2,
+ FLD_O_i1,
+ FLD_O_i2,
+ FLD_O_i3,
+ FLD_O_i4,
+ FLD_O_i5
+};
+
+enum DisasFieldIndexC {
+ FLD_C_r1 = 0,
+ FLD_C_m1 = 0,
+ FLD_C_b1 = 0,
+ FLD_C_i1 = 0,
+
+ FLD_C_r2 = 1,
+ FLD_C_b2 = 1,
+ FLD_C_i2 = 1,
+
+ FLD_C_r3 = 2,
+ FLD_C_m3 = 2,
+ FLD_C_i3 = 2,
+
+ FLD_C_m4 = 3,
+ FLD_C_b4 = 3,
+ FLD_C_i4 = 3,
+ FLD_C_l1 = 3,
+
+ FLD_C_i5 = 4,
+ FLD_C_d1 = 4,
+
+ FLD_C_d2 = 5,
+
+ FLD_C_d4 = 6,
+ FLD_C_x2 = 6,
+ FLD_C_l2 = 6,
+
+ NUM_C_FIELD = 7
+};
+
+struct DisasFields {
+ unsigned op:8;
+ unsigned op2:8;
+ unsigned presentC:16;
+ unsigned int presentO;
+ int c[NUM_C_FIELD];
+};
+
+/* This is the way fields are to be accessed out of DisasFields. */
+#define have_field(S, F) have_field1((S), FLD_O_##F)
+#define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F)
+
+static bool have_field1(const DisasFields *f, enum DisasFieldIndexO c)
+{
+ return (f->presentO >> c) & 1;
+}
+
+static int get_field1(const DisasFields *f, enum DisasFieldIndexO o,
+ enum DisasFieldIndexC c)
+{
+ assert(have_field1(f, o));
+ return f->c[c];
+}
+
+/* Describe the layout of each field in each format. */
+typedef struct DisasField {
+ unsigned int beg:8;
+ unsigned int size:8;
+ unsigned int type:2;
+ unsigned int indexC:6;
+ enum DisasFieldIndexO indexO:8;
+} DisasField;
+
+typedef struct DisasFormatInfo {
+ DisasField op[NUM_C_FIELD];
+} DisasFormatInfo;
+
+#define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N }
+#define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N }
+#define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
+ { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
+#define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
+ { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
+ { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
+#define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
+ { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
+#define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
+ { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
+ { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
+#define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N }
+#define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N }
+
+#define F0(N) { { } },
+#define F1(N, X1) { { X1 } },
+#define F2(N, X1, X2) { { X1, X2 } },
+#define F3(N, X1, X2, X3) { { X1, X2, X3 } },
+#define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } },
+#define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
+
+static const DisasFormatInfo format_info[] = {
+#include "insn-format.def"
+};
+
+#undef F0
+#undef F1
+#undef F2
+#undef F3
+#undef F4
+#undef F5
+#undef R
+#undef M
+#undef BD
+#undef BXD
+#undef BDL
+#undef BXDL
+#undef I
+#undef L
+
+/* Generally, we'll extract operands into this structures, operate upon
+ them, and store them back. See the "in1", "in2", "prep", "wout" sets
+ of routines below for more details. */
+typedef struct {
+ bool g_out, g_out2, g_in1, g_in2;
+ TCGv_i64 out, out2, in1, in2;
+ TCGv_i64 addr1;
+} DisasOps;
+
+/* Return values from translate_one, indicating the state of the TB. */
+typedef enum {
+ /* Continue the TB. */
+ NO_EXIT,
+ /* We have emitted one or more goto_tb. No fixup required. */
+ EXIT_GOTO_TB,
+ /* We are not using a goto_tb (for whatever reason), but have updated
+ the PC (for whatever reason), so there's no need to do it again on
+ exiting the TB. */
+ EXIT_PC_UPDATED,
+ /* We are exiting the TB, but have neither emitted a goto_tb, nor
+ updated the PC for the next instruction to be executed. */
+ EXIT_PC_STALE,
+ /* We are ending the TB with a noreturn function call, e.g. longjmp.
+ No following code will be executed. */
+ EXIT_NORETURN,
+} ExitStatus;
+
+typedef enum DisasFacility {
+ FAC_Z, /* zarch (default) */
+ FAC_CASS, /* compare and swap and store */
+ FAC_CASS2, /* compare and swap and store 2*/
+ FAC_DFP, /* decimal floating point */
+ FAC_DFPR, /* decimal floating point rounding */
+ FAC_DO, /* distinct operands */
+ FAC_EE, /* execute extensions */
+ FAC_EI, /* extended immediate */
+ FAC_FPE, /* floating point extension */
+ FAC_FPSSH, /* floating point support sign handling */
+ FAC_FPRGR, /* FPR-GR transfer */
+ FAC_GIE, /* general instructions extension */
+ FAC_HFP_MA, /* HFP multiply-and-add/subtract */
+ FAC_HW, /* high-word */
+ FAC_IEEEE_SIM, /* IEEE exception sumilation */
+ FAC_LOC, /* load/store on condition */
+ FAC_LD, /* long displacement */
+ FAC_PC, /* population count */
+ FAC_SCF, /* store clock fast */
+ FAC_SFLE, /* store facility list extended */
+} DisasFacility;
+
+struct DisasInsn {
+ unsigned opc:16;
+ DisasFormat fmt:6;
+ DisasFacility fac:6;
+
+ const char *name;
+
+ void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
+ void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
+ void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
+ void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
+ void (*help_cout)(DisasContext *, DisasOps *);
+ ExitStatus (*help_op)(DisasContext *, DisasOps *);
+
+ uint64_t data;
+};
+
+/* ====================================================================== */
+/* The operations. These perform the bulk of the work for any insn,
+ usually after the operands have been loaded and output initialized. */
+
+static ExitStatus op_add(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_add_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sub(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_sub_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+/* ====================================================================== */
+/* The "Cc OUTput" generators. Given the generated output (and in some cases
+ the original inputs), update the various cc data structures in order to
+ be able to compute the new condition code. */
+
+static void cout_adds32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
+}
+
+static void cout_adds64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
+}
+
+static void cout_addu32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
+}
+
+static void cout_addu64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
+}
+
+static void cout_subs32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
+}
+
+static void cout_subs64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
+}
+
+static void cout_subu32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
+}
+
+static void cout_subu64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
+}
+
+/* ====================================================================== */
+/* The "PREPeration" generators. These initialize the DisasOps.OUT fields
+ with the TCG register to which we will write. Used in combination with
+ the "wout" generators, in some cases we need a new temporary, and in
+ some cases we can write to a TCG global. */
+
+static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->out = tcg_temp_new_i64();
+}
+
+static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->out = regs[get_field(f, r1)];
+ o->g_out = true;
+}
+
+/* ====================================================================== */
+/* The "Write OUTput" generators. These generally perform some non-trivial
+ copy of data to TCG globals, or to main memory. The trivial cases are
+ generally handled by having a "prep" generator install the TCG global
+ as the destination of the operation. */
+
+static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ store_reg32_i64(get_field(f, r1), o->out);
+}
+
+static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
+}
+
+static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
+}
+
+/* ====================================================================== */
+/* The "INput 1" generators. These load the first operand to an insn. */
+
+static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = load_reg(get_field(f, r1));
+}
+
+static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = load_reg(get_field(f, r2));
+}
+
+static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = load_reg(get_field(f, r3));
+}
+
+static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
+}
+
+static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in1_la1(s, f, o);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
+}
+
+static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in1_la1(s, f, o);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
+}
+
+/* ====================================================================== */
+/* The "INput 2" generators. These load the second operand to an insn. */
+
+static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = load_reg(get_field(f, r2));
+}
+
+static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = load_reg(get_field(f, r3));
+}
+
+static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
+ o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
+}
+
+static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_a2(s, f, o);
+ tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_a2(s, f, o);
+ tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_a2(s, f, o);
+ tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_const_i64(get_field(f, i2));
+}
+
+static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
+}
+
+/* ====================================================================== */
+
+/* Find opc within the table of insns. This is formulated as a switch
+ statement so that (1) we get compile-time notice of cut-paste errors
+ for duplicated opcodes, and (2) the compiler generates the binary
+ search tree, rather than us having to post-process the table. */
+
+#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
+ D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
+
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
+
+enum DisasInsnEnum {
+#include "insn-data.def"
+};
+
+#undef D
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
+ .opc = OPC, \
+ .fmt = FMT_##FT, \
+ .fac = FAC_##FC, \
+ .name = #NM, \
+ .help_in1 = in1_##I1, \
+ .help_in2 = in2_##I2, \
+ .help_prep = prep_##P, \
+ .help_wout = wout_##W, \
+ .help_cout = cout_##CC, \
+ .help_op = op_##OP, \
+ .data = D \
+ },
+
+/* Allow 0 to be used for NULL in the table below. */
+#define in1_0 NULL
+#define in2_0 NULL
+#define prep_0 NULL
+#define wout_0 NULL
+#define cout_0 NULL
+#define op_0 NULL
+
+static const DisasInsn insn_info[] = {
+#include "insn-data.def"
+};
+
+#undef D
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
+ case OPC: return &insn_info[insn_ ## NM];
+
+static const DisasInsn *lookup_opc(uint16_t opc)
+{
+ switch (opc) {
+#include "insn-data.def"
+ default:
+ return NULL;
+ }
+}
+
+#undef D
+#undef C
+
+/* Extract a field from the insn. The INSN should be left-aligned in
+ the uint64_t so that we can more easily utilize the big-bit-endian
+ definitions we extract from the Principals of Operation. */
+
+static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
+{
+ uint32_t r, m;
+
+ if (f->size == 0) {
+ return;
+ }
+
+ /* Zero extract the field from the insn. */
+ r = (insn << f->beg) >> (64 - f->size);
+
+ /* Sign-extend, or un-swap the field as necessary. */
+ switch (f->type) {
+ case 0: /* unsigned */
+ break;
+ case 1: /* signed */
+ assert(f->size <= 32);
+ m = 1u << (f->size - 1);
+ r = (r ^ m) - m;
+ break;
+ case 2: /* dl+dh split, signed 20 bit. */
+ r = ((int8_t)r << 12) | (r >> 8);
+ break;
+ default:
+ abort();
+ }
+
+ /* Validate that the "compressed" encoding we selected above is valid.
+ I.e. we havn't make two different original fields overlap. */
+ assert(((o->presentC >> f->indexC) & 1) == 0);
+ o->presentC |= 1 << f->indexC;
+ o->presentO |= 1 << f->indexO;
+
+ o->c[f->indexC] = r;
+}
+
+/* Lookup the insn at the current PC, extracting the operands into O and
+ returning the info struct for the insn. Returns NULL for invalid insn. */
+
+static const DisasInsn *extract_insn(DisasContext *s, DisasFields *f)
+{
+ uint64_t insn, pc = s->pc;
+ int op, op2;
+ const DisasInsn *info;
+
+ insn = ld_code2(pc);
+ op = (insn >> 8) & 0xff;
+ switch (get_ilc(op)) {
+ case 1:
+ insn = insn << 48;
+ break;
+ case 2:
+ insn = ld_code4(pc) << 32;
+ break;
+ case 3:
+ insn = (insn << 48) | (ld_code4(pc + 2) << 16);
+ break;
+ default:
+ abort();
+ }
+
+ /* We can't actually determine the insn format until we've looked up
+ the full insn opcode. Which we can't do without locating the
+ secondary opcode. Assume by default that OP2 is at bit 40; for
+ those smaller insns that don't actually have a secondary opcode
+ this will correctly result in OP2 = 0. */
+ switch (op) {
+ case 0x01: /* E */
+ case 0x80: /* S */
+ case 0x82: /* S */
+ case 0x93: /* S */
+ case 0xb2: /* S, RRF, RRE */
+ case 0xb3: /* RRE, RRD, RRF */
+ case 0xb9: /* RRE, RRF */
+ case 0xe5: /* SSE, SIL */
+ op2 = (insn << 8) >> 56;
+ break;
+ case 0xa5: /* RI */
+ case 0xa7: /* RI */
+ case 0xc0: /* RIL */
+ case 0xc2: /* RIL */
+ case 0xc4: /* RIL */
+ case 0xc6: /* RIL */
+ case 0xc8: /* SSF */
+ case 0xcc: /* RIL */
+ op2 = (insn << 12) >> 60;
+ break;
+ case 0xd0 ... 0xdf: /* SS */
+ case 0xe1: /* SS */
+ case 0xe2: /* SS */
+ case 0xe8: /* SS */
+ case 0xe9: /* SS */
+ case 0xea: /* SS */
+ case 0xee ... 0xf3: /* SS */
+ case 0xf8 ... 0xfd: /* SS */
+ op2 = 0;
+ break;
+ default:
+ op2 = (insn << 40) >> 56;
+ break;
+ }
+
+ memset(f, 0, sizeof(*f));
+ f->op = op;
+ f->op2 = op2;
+
+ /* Lookup the instruction. */
+ info = lookup_opc(op << 8 | op2);
+
+ /* If we found it, extract the operands. */
+ if (info != NULL) {
+ DisasFormat fmt = info->fmt;
+ int i;
+
+ for (i = 0; i < NUM_C_FIELD; ++i) {
+ extract_field(f, &format_info[fmt].op[i], insn);
+ }
+ }
+ return info;
+}
+
+static ExitStatus translate_one(DisasContext *s)
+{
+ const DisasInsn *insn;
+ ExitStatus ret = NO_EXIT;
+ DisasFields f;
+ DisasOps o;
+
+ insn = extract_insn(s, &f);
/* Instruction length is encoded in the opcode */
- s->pc += (ilc * 2);
+ s->next_pc = s->pc + get_ilc(f.op) * 2;
+
+ /* If not found, try the old interpreter. This includes ILLOPC. */
+ if (insn == NULL) {
+ disas_s390_insn(s);
+ switch (s->is_jmp) {
+ case DISAS_NEXT:
+ ret = NO_EXIT;
+ break;
+ case DISAS_TB_JUMP:
+ ret = EXIT_GOTO_TB;
+ break;
+ case DISAS_JUMP:
+ ret = EXIT_PC_UPDATED;
+ break;
+ case DISAS_EXCP:
+ ret = EXIT_NORETURN;
+ break;
+ default:
+ abort();
+ }
+
+ s->pc = s->next_pc;
+ return ret;
+ }
+
+ /* Set up the strutures we use to communicate with the helpers. */
+ s->insn = insn;
+ s->fields = &f;
+ o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
+ TCGV_UNUSED_I64(o.out);
+ TCGV_UNUSED_I64(o.out2);
+ TCGV_UNUSED_I64(o.in1);
+ TCGV_UNUSED_I64(o.in2);
+ TCGV_UNUSED_I64(o.addr1);
+
+ /* Implement the instruction. */
+ if (insn->help_in1) {
+ insn->help_in1(s, &f, &o);
+ }
+ if (insn->help_in2) {
+ insn->help_in2(s, &f, &o);
+ }
+ if (insn->help_prep) {
+ insn->help_prep(s, &f, &o);
+ }
+ if (insn->help_op) {
+ ret = insn->help_op(s, &o);
+ }
+ if (insn->help_wout) {
+ insn->help_wout(s, &f, &o);
+ }
+ if (insn->help_cout) {
+ insn->help_cout(s, &o);
+ }
+
+ /* Free any temporaries created by the helpers. */
+ if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
+ tcg_temp_free_i64(o.out);
+ }
+ if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
+ tcg_temp_free_i64(o.out2);
+ }
+ if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
+ tcg_temp_free_i64(o.in1);
+ }
+ if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
+ tcg_temp_free_i64(o.in2);
+ }
+ if (!TCGV_IS_UNUSED_I64(o.addr1)) {
+ tcg_temp_free_i64(o.addr1);
+ }
+
+ /* Advance to the next instruction. */
+ s->pc = s->next_pc;
+ return ret;
}
static inline void gen_intermediate_code_internal(CPUS390XState *env,
@@ -5126,6 +5493,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
int j, lj = -1;
int num_insns, max_insns;
CPUBreakpoint *bp;
+ ExitStatus status;
pc_start = tb->pc;
@@ -5134,10 +5502,11 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
pc_start &= 0x7fffffff;
}
- dc.pc = pc_start;
- dc.is_jmp = DISAS_NEXT;
dc.tb = tb;
+ dc.pc = pc_start;
dc.cc_op = CC_OP_DYNAMIC;
+ dc.singlestep_enabled = env->singlestep_enabled;
+ dc.is_jmp = DISAS_NEXT;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
@@ -5173,42 +5542,58 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
gen_opc_instr_start[lj] = 1;
gen_opc_icount[lj] = num_insns;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
-#if defined(S390X_DEBUG_DISAS_VERBOSE)
- LOG_DISAS("pc " TARGET_FMT_lx "\n",
- dc.pc);
-#endif
- disas_s390_insn(&dc);
- num_insns++;
- if (env->singlestep_enabled) {
- gen_debug(&dc);
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
+ tcg_gen_debug_insn_start(dc.pc);
}
- } while (!dc.is_jmp && gen_opc_ptr < gen_opc_end && dc.pc < next_page_start
- && num_insns < max_insns && !env->singlestep_enabled
- && !singlestep);
-
- if (!dc.is_jmp) {
- update_psw_addr(&dc);
- }
- if (singlestep && dc.cc_op != CC_OP_DYNAMIC) {
- gen_op_calc_cc(&dc);
- } else {
- /* next TB starts off with CC_OP_DYNAMIC, so make sure the cc op type
- is in env */
- gen_op_set_cc_op(&dc);
- }
+ status = translate_one(&dc);
+
+ /* If we reach a page boundary, are single stepping,
+ or exhaust instruction count, stop generation. */
+ if (status == NO_EXIT
+ && (dc.pc >= next_page_start
+ || gen_opc_ptr >= gen_opc_end
+ || num_insns >= max_insns
+ || singlestep
+ || env->singlestep_enabled)) {
+ status = EXIT_PC_STALE;
+ }
+ } while (status == NO_EXIT);
if (tb->cflags & CF_LAST_IO) {
gen_io_end();
}
- /* Generate the return instruction */
- if (dc.is_jmp != DISAS_TB_JUMP) {
- tcg_gen_exit_tb(0);
+
+ switch (status) {
+ case EXIT_GOTO_TB:
+ case EXIT_NORETURN:
+ break;
+ case EXIT_PC_STALE:
+ update_psw_addr(&dc);
+ /* FALLTHRU */
+ case EXIT_PC_UPDATED:
+ if (singlestep && dc.cc_op != CC_OP_DYNAMIC) {
+ gen_op_calc_cc(&dc);
+ } else {
+ /* Next TB starts off with CC_OP_DYNAMIC,
+ so make sure the cc op type is in env */
+ gen_op_set_cc_op(&dc);
+ }
+ if (env->singlestep_enabled) {
+ gen_debug(&dc);
+ } else {
+ /* Generate the return instruction */
+ tcg_gen_exit_tb(0);
+ }
+ break;
+ default:
+ abort();
}
+
gen_icount_end(tb, num_insns);
*gen_opc_ptr = INDEX_op_end;
if (search_pc) {
@@ -5221,8 +5606,8 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
tb->size = dc.pc - pc_start;
tb->icount = num_insns;
}
+
#if defined(S390X_DEBUG_DISAS)
- log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(pc_start, dc.pc - pc_start, 1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 009/126] target-s390: Split out disas_jcc
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (7 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 008/126] target-s390: Add format based disassassmbly infrastructure Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling Richard Henderson
` (92 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Lots of duplicated code replaced with a couple of tables. We no longer
attempt to manually invert the logic operation: the comments now match
the code. In the fully general test, constant propagate (1 << (3 - cc))
into (8 >> cc).
The new function will be usable by non-branch insns as well.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 494 +++++++++++++++++++++--------------------------
1 file changed, 215 insertions(+), 279 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ecd6099..996d786 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -58,6 +58,18 @@ struct DisasContext {
int is_jmp;
};
+/* Information carried about a condition to be evaluated. */
+typedef struct {
+ TCGCond cond:8;
+ bool is_64;
+ bool g1;
+ bool g2;
+ union {
+ struct { TCGv_i64 a, b; } s64;
+ struct { TCGv_i32 a, b; } s32;
+ } u;
+} DisasCompare;
+
#define DISAS_EXCP 4
static void gen_op_calc_cc(DisasContext *s);
@@ -836,357 +848,281 @@ static inline void account_noninline_branch(DisasContext *s, int cc_op)
#endif
}
-static inline void account_inline_branch(DisasContext *s)
+static inline void account_inline_branch(DisasContext *s, int cc_op)
{
#ifdef DEBUG_INLINE_BRANCHES
- inline_branch_hit[s->cc_op]++;
+ inline_branch_hit[cc_op]++;
#endif
}
-static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
+/* Table of mask values to comparison codes, given a comparison as input.
+ For a true comparison CC=3 will never be set, but we treat this
+ conservatively for possible use when CC=3 indicates overflow. */
+static const TCGCond ltgt_cond[16] = {
+ TCG_COND_NEVER, TCG_COND_NEVER, /* | | | x */
+ TCG_COND_GT, TCG_COND_NEVER, /* | | GT | x */
+ TCG_COND_LT, TCG_COND_NEVER, /* | LT | | x */
+ TCG_COND_NE, TCG_COND_NEVER, /* | LT | GT | x */
+ TCG_COND_EQ, TCG_COND_NEVER, /* EQ | | | x */
+ TCG_COND_GE, TCG_COND_NEVER, /* EQ | | GT | x */
+ TCG_COND_LE, TCG_COND_NEVER, /* EQ | LT | | x */
+ TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | LT | GT | x */
+};
+
+/* Table of mask values to comparison codes, given a logic op as input.
+ For such, only CC=0 and CC=1 should be possible. */
+static const TCGCond nz_cond[16] = {
+ /* | | x | x */
+ TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER,
+ /* | NE | x | x */
+ TCG_COND_NE, TCG_COND_NE, TCG_COND_NE, TCG_COND_NE,
+ /* EQ | | x | x */
+ TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ,
+ /* EQ | NE | x | x */
+ TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS,
+};
+
+/* Interpret MASK in terms of S->CC_OP, and fill in C with all the
+ details required to generate a TCG comparison. */
+static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
{
- TCGv_i32 tmp, tmp2, r;
- TCGv_i64 tmp64;
- int old_cc_op;
+ TCGCond cond;
+ enum cc_op old_cc_op = s->cc_op;
- switch (s->cc_op) {
+ if (mask == 15 || mask == 0) {
+ c->cond = (mask ? TCG_COND_ALWAYS : TCG_COND_NEVER);
+ c->u.s32.a = cc_op;
+ c->u.s32.b = cc_op;
+ c->g1 = c->g2 = true;
+ c->is_64 = false;
+ return;
+ }
+
+ /* Find the TCG condition for the mask + cc op. */
+ switch (old_cc_op) {
case CC_OP_LTGT0_32:
- tmp = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp, cc_dst);
- switch (mask) {
- case 0x8 | 0x4: /* dst <= 0 */
- tcg_gen_brcondi_i32(TCG_COND_GT, tmp, 0, skip);
- break;
- case 0x8 | 0x2: /* dst >= 0 */
- tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, skip);
- break;
- case 0x8: /* dst == 0 */
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
- break;
- case 0x7: /* dst != 0 */
- case 0x6: /* dst != 0 */
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
- break;
- case 0x4: /* dst < 0 */
- tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, skip);
- break;
- case 0x2: /* dst > 0 */
- tcg_gen_brcondi_i32(TCG_COND_LE, tmp, 0, skip);
- break;
- default:
- tcg_temp_free_i32(tmp);
- goto do_dynamic;
- }
- account_inline_branch(s);
- tcg_temp_free_i32(tmp);
- break;
case CC_OP_LTGT0_64:
- switch (mask) {
- case 0x8 | 0x4: /* dst <= 0 */
- tcg_gen_brcondi_i64(TCG_COND_GT, cc_dst, 0, skip);
- break;
- case 0x8 | 0x2: /* dst >= 0 */
- tcg_gen_brcondi_i64(TCG_COND_LT, cc_dst, 0, skip);
- break;
- case 0x8: /* dst == 0 */
- tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
- break;
- case 0x7: /* dst != 0 */
- case 0x6: /* dst != 0 */
- tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
- break;
- case 0x4: /* dst < 0 */
- tcg_gen_brcondi_i64(TCG_COND_GE, cc_dst, 0, skip);
- break;
- case 0x2: /* dst > 0 */
- tcg_gen_brcondi_i64(TCG_COND_LE, cc_dst, 0, skip);
- break;
- default:
- goto do_dynamic;
- }
- account_inline_branch(s);
- break;
case CC_OP_LTGT_32:
- tmp = tcg_temp_new_i32();
- tmp2 = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp, cc_src);
- tcg_gen_trunc_i64_i32(tmp2, cc_dst);
- switch (mask) {
- case 0x8 | 0x4: /* src <= dst */
- tcg_gen_brcond_i32(TCG_COND_GT, tmp, tmp2, skip);
- break;
- case 0x8 | 0x2: /* src >= dst */
- tcg_gen_brcond_i32(TCG_COND_LT, tmp, tmp2, skip);
- break;
- case 0x8: /* src == dst */
- tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, skip);
- break;
- case 0x7: /* src != dst */
- case 0x6: /* src != dst */
- tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, skip);
- break;
- case 0x4: /* src < dst */
- tcg_gen_brcond_i32(TCG_COND_GE, tmp, tmp2, skip);
- break;
- case 0x2: /* src > dst */
- tcg_gen_brcond_i32(TCG_COND_LE, tmp, tmp2, skip);
- break;
- default:
- tcg_temp_free_i32(tmp);
- tcg_temp_free_i32(tmp2);
- goto do_dynamic;
- }
- account_inline_branch(s);
- tcg_temp_free_i32(tmp);
- tcg_temp_free_i32(tmp2);
- break;
case CC_OP_LTGT_64:
- switch (mask) {
- case 0x8 | 0x4: /* src <= dst */
- tcg_gen_brcond_i64(TCG_COND_GT, cc_src, cc_dst, skip);
- break;
- case 0x8 | 0x2: /* src >= dst */
- tcg_gen_brcond_i64(TCG_COND_LT, cc_src, cc_dst, skip);
- break;
- case 0x8: /* src == dst */
- tcg_gen_brcond_i64(TCG_COND_NE, cc_src, cc_dst, skip);
- break;
- case 0x7: /* src != dst */
- case 0x6: /* src != dst */
- tcg_gen_brcond_i64(TCG_COND_EQ, cc_src, cc_dst, skip);
- break;
- case 0x4: /* src < dst */
- tcg_gen_brcond_i64(TCG_COND_GE, cc_src, cc_dst, skip);
- break;
- case 0x2: /* src > dst */
- tcg_gen_brcond_i64(TCG_COND_LE, cc_src, cc_dst, skip);
- break;
- default:
+ cond = ltgt_cond[mask];
+ if (cond == TCG_COND_NEVER) {
goto do_dynamic;
}
- account_inline_branch(s);
+ account_inline_branch(s, old_cc_op);
break;
+
case CC_OP_LTUGTU_32:
- tmp = tcg_temp_new_i32();
- tmp2 = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp, cc_src);
- tcg_gen_trunc_i64_i32(tmp2, cc_dst);
- switch (mask) {
- case 0x8 | 0x4: /* src <= dst */
- tcg_gen_brcond_i32(TCG_COND_GTU, tmp, tmp2, skip);
- break;
- case 0x8 | 0x2: /* src >= dst */
- tcg_gen_brcond_i32(TCG_COND_LTU, tmp, tmp2, skip);
- break;
- case 0x8: /* src == dst */
- tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, skip);
- break;
- case 0x7: /* src != dst */
- case 0x6: /* src != dst */
- tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, skip);
- break;
- case 0x4: /* src < dst */
- tcg_gen_brcond_i32(TCG_COND_GEU, tmp, tmp2, skip);
- break;
- case 0x2: /* src > dst */
- tcg_gen_brcond_i32(TCG_COND_LEU, tmp, tmp2, skip);
- break;
- default:
- tcg_temp_free_i32(tmp);
- tcg_temp_free_i32(tmp2);
- goto do_dynamic;
- }
- account_inline_branch(s);
- tcg_temp_free_i32(tmp);
- tcg_temp_free_i32(tmp2);
- break;
case CC_OP_LTUGTU_64:
- switch (mask) {
- case 0x8 | 0x4: /* src <= dst */
- tcg_gen_brcond_i64(TCG_COND_GTU, cc_src, cc_dst, skip);
- break;
- case 0x8 | 0x2: /* src >= dst */
- tcg_gen_brcond_i64(TCG_COND_LTU, cc_src, cc_dst, skip);
- break;
- case 0x8: /* src == dst */
- tcg_gen_brcond_i64(TCG_COND_NE, cc_src, cc_dst, skip);
- break;
- case 0x7: /* src != dst */
- case 0x6: /* src != dst */
- tcg_gen_brcond_i64(TCG_COND_EQ, cc_src, cc_dst, skip);
- break;
- case 0x4: /* src < dst */
- tcg_gen_brcond_i64(TCG_COND_GEU, cc_src, cc_dst, skip);
- break;
- case 0x2: /* src > dst */
- tcg_gen_brcond_i64(TCG_COND_LEU, cc_src, cc_dst, skip);
- break;
- default:
+ cond = tcg_unsigned_cond(ltgt_cond[mask]);
+ if (cond == TCG_COND_NEVER) {
goto do_dynamic;
}
- account_inline_branch(s);
+ account_inline_branch(s, old_cc_op);
break;
+
case CC_OP_NZ:
- switch (mask) {
- /* dst == 0 || dst != 0 */
- case 0x8 | 0x4:
- case 0x8 | 0x4 | 0x2:
- case 0x8 | 0x4 | 0x2 | 0x1:
- case 0x8 | 0x4 | 0x1:
- break;
- /* dst == 0 */
- case 0x8:
- case 0x8 | 0x2:
- case 0x8 | 0x2 | 0x1:
- case 0x8 | 0x1:
- tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
- break;
- /* dst != 0 */
- case 0x4:
- case 0x4 | 0x2:
- case 0x4 | 0x2 | 0x1:
- case 0x4 | 0x1:
- tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
- break;
- default:
+ cond = nz_cond[mask];
+ if (cond == TCG_COND_NEVER) {
goto do_dynamic;
}
- account_inline_branch(s);
+ account_inline_branch(s, old_cc_op);
break;
- case CC_OP_TM_32:
- tmp = tcg_temp_new_i32();
- tmp2 = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp, cc_src);
- tcg_gen_trunc_i64_i32(tmp2, cc_dst);
- tcg_gen_and_i32(tmp, tmp, tmp2);
- switch (mask) {
- case 0x8: /* val & mask == 0 */
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
- break;
- case 0x4 | 0x2 | 0x1: /* val & mask != 0 */
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
- break;
- default:
- tcg_temp_free_i32(tmp);
- tcg_temp_free_i32(tmp2);
- goto do_dynamic;
- }
- tcg_temp_free_i32(tmp);
- tcg_temp_free_i32(tmp2);
- account_inline_branch(s);
- break;
+ case CC_OP_TM_32:
case CC_OP_TM_64:
- tmp64 = tcg_temp_new_i64();
-
- tcg_gen_and_i64(tmp64, cc_src, cc_dst);
switch (mask) {
- case 0x8: /* val & mask == 0 */
- tcg_gen_brcondi_i64(TCG_COND_NE, tmp64, 0, skip);
+ case 8:
+ cond = TCG_COND_EQ;
break;
- case 0x4 | 0x2 | 0x1: /* val & mask != 0 */
- tcg_gen_brcondi_i64(TCG_COND_EQ, tmp64, 0, skip);
+ case 4 | 2 | 1:
+ cond = TCG_COND_NE;
break;
default:
- tcg_temp_free_i64(tmp64);
goto do_dynamic;
}
- tcg_temp_free_i64(tmp64);
- account_inline_branch(s);
+ account_inline_branch(s, old_cc_op);
break;
+
case CC_OP_ICM:
switch (mask) {
- case 0x8: /* val == 0 */
- tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
+ case 8:
+ cond = TCG_COND_EQ;
break;
- case 0x4 | 0x2 | 0x1: /* val != 0 */
- case 0x4 | 0x2: /* val != 0 */
- tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
+ case 4 | 2 | 1:
+ case 4 | 2:
+ cond = TCG_COND_NE;
break;
default:
goto do_dynamic;
}
- account_inline_branch(s);
+ account_inline_branch(s, old_cc_op);
break;
- case CC_OP_STATIC:
- old_cc_op = s->cc_op;
- goto do_dynamic_nocccalc;
- case CC_OP_DYNAMIC:
+
default:
-do_dynamic:
- old_cc_op = s->cc_op;
- /* calculate cc value */
+ do_dynamic:
+ /* Calculate cc value. */
gen_op_calc_cc(s);
+ /* FALLTHRU */
-do_dynamic_nocccalc:
- /* jump based on cc */
+ case CC_OP_STATIC:
+ /* Jump based on CC. We'll load up the real cond below;
+ the assignment here merely avoids a compiler warning. */
account_noninline_branch(s, old_cc_op);
+ old_cc_op = CC_OP_STATIC;
+ cond = TCG_COND_NEVER;
+ break;
+ }
+
+ /* Load up the arguments of the comparison. */
+ c->is_64 = true;
+ c->g1 = c->g2 = false;
+ switch (old_cc_op) {
+ case CC_OP_LTGT0_32:
+ c->is_64 = false;
+ c->u.s32.a = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(c->u.s32.a, cc_dst);
+ c->u.s32.b = tcg_const_i32(0);
+ break;
+ case CC_OP_LTGT_32:
+ case CC_OP_LTUGTU_32:
+ c->is_64 = false;
+ c->u.s32.a = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src);
+ c->u.s32.b = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(c->u.s32.b, cc_dst);
+ break;
+
+ case CC_OP_LTGT0_64:
+ case CC_OP_NZ:
+ case CC_OP_ICM:
+ c->u.s64.a = cc_dst;
+ c->u.s64.b = tcg_const_i64(0);
+ c->g1 = true;
+ break;
+ case CC_OP_LTGT_64:
+ case CC_OP_LTUGTU_64:
+ c->u.s64.a = cc_src;
+ c->u.s64.b = cc_dst;
+ c->g1 = c->g2 = true;
+ break;
+
+ case CC_OP_TM_32:
+ case CC_OP_TM_64:
+ c->u.s64.a = tcg_temp_new_i64();
+ c->u.s64.b = tcg_const_i64(0);
+ tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
+ break;
+ case CC_OP_STATIC:
+ c->is_64 = false;
+ c->u.s32.a = cc_op;
+ c->g1 = true;
switch (mask) {
- case 0x8 | 0x4 | 0x2 | 0x1:
- /* always true */
- break;
case 0x8 | 0x4 | 0x2: /* cc != 3 */
- tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 3, skip);
+ cond = TCG_COND_NE;
+ c->u.s32.b = tcg_const_i32(3);
break;
case 0x8 | 0x4 | 0x1: /* cc != 2 */
- tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 2, skip);
+ cond = TCG_COND_NE;
+ c->u.s32.b = tcg_const_i32(2);
break;
case 0x8 | 0x2 | 0x1: /* cc != 1 */
- tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 1, skip);
+ cond = TCG_COND_NE;
+ c->u.s32.b = tcg_const_i32(1);
break;
- case 0x8 | 0x2: /* cc == 0 || cc == 2 */
- tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cc_op, 1);
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
- tcg_temp_free_i32(tmp);
+ case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */
+ cond = TCG_COND_EQ;
+ c->g1 = false;
+ c->u.s32.a = tcg_temp_new_i32();
+ c->u.s32.b = tcg_const_i32(0);
+ tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
break;
case 0x8 | 0x4: /* cc < 2 */
- tcg_gen_brcondi_i32(TCG_COND_GEU, cc_op, 2, skip);
+ cond = TCG_COND_LTU;
+ c->u.s32.b = tcg_const_i32(2);
break;
case 0x8: /* cc == 0 */
- tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 0, skip);
+ cond = TCG_COND_EQ;
+ c->u.s32.b = tcg_const_i32(0);
break;
case 0x4 | 0x2 | 0x1: /* cc != 0 */
- tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 0, skip);
+ cond = TCG_COND_NE;
+ c->u.s32.b = tcg_const_i32(0);
break;
- case 0x4 | 0x1: /* cc == 1 || cc == 3 */
- tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cc_op, 1);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
- tcg_temp_free_i32(tmp);
+ case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */
+ cond = TCG_COND_NE;
+ c->g1 = false;
+ c->u.s32.a = tcg_temp_new_i32();
+ c->u.s32.b = tcg_const_i32(0);
+ tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
break;
case 0x4: /* cc == 1 */
- tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 1, skip);
+ cond = TCG_COND_EQ;
+ c->u.s32.b = tcg_const_i32(1);
break;
case 0x2 | 0x1: /* cc > 1 */
- tcg_gen_brcondi_i32(TCG_COND_LEU, cc_op, 1, skip);
+ cond = TCG_COND_GTU;
+ c->u.s32.b = tcg_const_i32(1);
break;
case 0x2: /* cc == 2 */
- tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 2, skip);
+ cond = TCG_COND_EQ;
+ c->u.s32.b = tcg_const_i32(2);
break;
case 0x1: /* cc == 3 */
- tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 3, skip);
+ cond = TCG_COND_EQ;
+ c->u.s32.b = tcg_const_i32(3);
break;
- default: /* cc is masked by something else */
- tmp = tcg_const_i32(3);
- /* 3 - cc */
- tcg_gen_sub_i32(tmp, tmp, cc_op);
- tmp2 = tcg_const_i32(1);
- /* 1 << (3 - cc) */
- tcg_gen_shl_i32(tmp2, tmp2, tmp);
- r = tcg_const_i32(mask);
- /* mask & (1 << (3 - cc)) */
- tcg_gen_and_i32(r, r, tmp2);
- tcg_temp_free_i32(tmp);
- tcg_temp_free_i32(tmp2);
-
- tcg_gen_brcondi_i32(TCG_COND_EQ, r, 0, skip);
- tcg_temp_free_i32(r);
+ default:
+ /* CC is masked by something else: (8 >> cc) & mask. */
+ cond = TCG_COND_NE;
+ c->g1 = false;
+ c->u.s32.a = tcg_const_i32(8);
+ c->u.s32.b = tcg_const_i32(0);
+ tcg_gen_shr_i32(c->u.s32.a, c->u.s32.a, cc_op);
+ tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask);
break;
}
break;
+
+ default:
+ abort();
}
+ c->cond = cond;
+}
+
+static void free_compare(DisasCompare *c)
+{
+ if (!c->g1) {
+ if (c->is_64) {
+ tcg_temp_free_i64(c->u.s64.a);
+ } else {
+ tcg_temp_free_i32(c->u.s32.a);
+ }
+ }
+ if (!c->g2) {
+ if (c->is_64) {
+ tcg_temp_free_i64(c->u.s64.b);
+ } else {
+ tcg_temp_free_i32(c->u.s32.b);
+ }
+ }
+}
+
+static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
+{
+ DisasCompare c;
+ TCGCond cond;
+
+ disas_jcc(s, &c, mask);
+ cond = tcg_invert_cond(c.cond);
+
+ if (c.is_64) {
+ tcg_gen_brcond_i64(cond, c.u.s64.a, c.u.s64.b, skip);
+ } else {
+ tcg_gen_brcond_i32(cond, c.u.s32.a, c.u.s32.b, skip);
+ }
+
+ free_compare(&c);
}
static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (8 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 009/126] target-s390: Split out disas_jcc Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-18 20:18 ` Alexander Graf
2012-09-09 21:04 ` [Qemu-devel] [PATCH 011/126] target-s390: Convert ADD HALFWORD Richard Henderson
` (91 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Make the user path more like the system path. Prepare for more kinds
of runtime exceptions. Compute ILC from S->NEXT_PC, rather than
passing it around.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 133 +++++++++++++++++----------
target-s390x/cpu.h | 11 ---
target-s390x/misc_helper.c | 10 ++-
target-s390x/translate.c | 220 +++++++++++++++++----------------------------
4 files changed, 174 insertions(+), 200 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 1a1c661..8f6f39b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2935,71 +2935,108 @@ void cpu_loop(CPUAlphaState *env)
#ifdef TARGET_S390X
void cpu_loop(CPUS390XState *env)
{
- int trapnr;
+ int trapnr, n, sig;
target_siginfo_t info;
+ target_ulong addr;
while (1) {
- trapnr = cpu_s390x_exec (env);
-
+ trapnr = cpu_s390x_exec(env);
switch (trapnr) {
case EXCP_INTERRUPT:
- /* just indicate that signals should be handled asap */
+ /* Just indicate that signals should be handled asap. */
break;
- case EXCP_DEBUG:
- {
- int sig;
- sig = gdb_handlesig (env, TARGET_SIGTRAP);
- if (sig) {
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, &info);
- }
+ case EXCP_SVC:
+ n = env->int_svc_code;
+ if (!n) {
+ /* syscalls > 255 */
+ n = env->regs[1];
}
+ env->psw.addr += env->int_svc_ilc;
+ env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
+ env->regs[4], env->regs[5],
+ env->regs[6], env->regs[7], 0, 0);
break;
- case EXCP_SVC:
- {
- int n = env->int_svc_code;
- if (!n) {
- /* syscalls > 255 */
- n = env->regs[1];
- }
- env->psw.addr += env->int_svc_ilc;
- env->regs[2] = do_syscall(env, n,
- env->regs[2],
- env->regs[3],
- env->regs[4],
- env->regs[5],
- env->regs[6],
- env->regs[7],
- 0, 0);
+
+ case EXCP_DEBUG:
+ sig = gdb_handlesig(env, TARGET_SIGTRAP);
+ if (sig) {
+ n = TARGET_TRAP_BRKPT;
+ goto do_signal_pc;
}
break;
- case EXCP_ADDR:
- {
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
+ case EXCP_PGM:
+ n = env->int_pgm_code;
+ switch (n) {
+ case PGM_OPERATION:
+ case PGM_PRIVILEGED:
+ sig = SIGILL;
+ n = TARGET_ILL_ILLOPC;
+ goto do_signal_pc;
+ case PGM_PROTECTION:
+ case PGM_ADDRESSING:
+ sig = SIGSEGV;
/* XXX: check env->error_code */
- info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = env->__excp_addr;
- queue_signal(env, info.si_signo, &info);
+ n = TARGET_SEGV_MAPERR;
+ addr = env->__excp_addr;
+ goto do_signal;
+ case PGM_EXECUTE:
+ case PGM_SPECIFICATION:
+ case PGM_DATA:
+ case PGM_SPECIAL_OP:
+ case PGM_OPERAND:
+ sig = SIGILL;
+ n = TARGET_ILL_ILLOPN;
+ goto do_signal_pc;
+ case PGM_FIXPT_OVERFLOW:
+ sig = SIGFPE;
+ n = TARGET_FPE_INTOVF;
+ goto do_signal_pc;
+ case PGM_FIXPT_DIVIDE:
+ sig = SIGFPE;
+ n = TARGET_FPE_INTDIV;
+ goto do_signal_pc;
+ case PGM_HFP_EXP_OVERFLOW:
+ sig = SIGFPE;
+ n = TARGET_FPE_FLTOVF;
+ goto do_signal_pc;
+ case PGM_HFP_EXP_UNDERFLOW:
+ sig = SIGFPE;
+ n = TARGET_FPE_FLTUND;
+ goto do_signal_pc;
+ case PGM_HFP_SIGNIFICANCE:
+ sig = SIGFPE;
+ n = TARGET_FPE_FLTRES;
+ goto do_signal_pc;
+ case PGM_HFP_DIVIDE:
+ sig = SIGFPE;
+ n = TARGET_FPE_FLTDIV;
+ goto do_signal_pc;
+ case PGM_HFP_SQRT:
+ sig = SIGFPE;
+ n = TARGET_FPE_FLTINV;
+ goto do_signal_pc;
+ default:
+ fprintf(stderr, "Unhandled program exception: %#x\n", n);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ exit(1);
}
break;
- case EXCP_SPEC:
- {
- fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4));
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPC;
- info._sifields._sigfault._addr = env->__excp_addr;
- queue_signal(env, info.si_signo, &info);
- }
+
+ do_signal_pc:
+ addr = env->psw.addr;
+ do_signal:
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = n;
+ info._sifields._sigfault._addr = addr;
+ queue_signal(env, info.si_signo, &info);
break;
+
default:
- printf ("Unhandled trap: 0x%x\n", trapnr);
+ fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
- exit (1);
+ exit(1);
}
process_pending_signals (env);
}
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 471fb91..17829b5 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -352,21 +352,10 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
#include "exec-all.h"
-#ifdef CONFIG_USER_ONLY
-
-#define EXCP_OPEX 1 /* operation exception (sigill) */
-#define EXCP_SVC 2 /* supervisor call (syscall) */
-#define EXCP_ADDR 5 /* addressing exception */
-#define EXCP_SPEC 6 /* specification exception */
-
-#else
-
#define EXCP_EXT 1 /* external interrupt */
#define EXCP_SVC 2 /* supervisor call (syscall) */
#define EXCP_PGM 3 /* program interruption */
-#endif /* CONFIG_USER_ONLY */
-
#define INTERRUPT_EXT (1 << 0)
#define INTERRUPT_TOD (1 << 1)
#define INTERRUPT_CPUTIMER (1 << 2)
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index f405b97..1502f15 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -86,10 +86,12 @@ void do_interrupt(CPUS390XState *env)
int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address,
int rw, int mmu_idx)
{
- /* fprintf(stderr, "%s: address 0x%lx rw %d mmu_idx %d\n",
- __func__, address, rw, mmu_idx); */
- env->exception_index = EXCP_ADDR;
- /* FIXME: find out how this works on a real machine */
+ env->exception_index = EXCP_PGM;
+ env->int_pgm_code = PGM_PROTECTION;
+ /* A real machine puts the address in LowCore, which the kernel
+ helpfully interprets for us. Since we've nothing similar
+ within the userland address space, invent something for use
+ within cpu_loop. */
env->__excp_addr = address;
return 1;
}
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 996d786..70e5d87 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -18,7 +18,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-/* #define DEBUG_ILLEGAL_INSTRUCTIONS */
/* #define DEBUG_INLINE_BRANCHES */
#define S390X_DEBUG_DISAS
/* #define S390X_DEBUG_DISAS_VERBOSE */
@@ -336,103 +335,52 @@ static inline int get_mem_index(DisasContext *s)
}
}
-static inline void gen_debug(DisasContext *s)
+static void gen_exception(int excp)
{
- TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
- update_psw_addr(s);
- gen_op_calc_cc(s);
- gen_helper_exception(cpu_env, tmp);
- tcg_temp_free_i32(tmp);
- s->is_jmp = DISAS_EXCP;
-}
-
-#ifdef CONFIG_USER_ONLY
-
-static void gen_illegal_opcode(DisasContext *s, int ilc)
-{
- TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC);
- update_psw_addr(s);
- gen_op_calc_cc(s);
+ TCGv_i32 tmp = tcg_const_i32(excp);
gen_helper_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
- s->is_jmp = DISAS_EXCP;
}
-#else /* CONFIG_USER_ONLY */
-
-static void debug_print_inst(DisasContext *s, int ilc)
-{
-#ifdef DEBUG_ILLEGAL_INSTRUCTIONS
- uint64_t inst = 0;
-
- switch (ilc & 3) {
- case 1:
- inst = ld_code2(s->pc);
- break;
- case 2:
- inst = ld_code4(s->pc);
- break;
- case 3:
- inst = ld_code6(s->pc);
- break;
- }
-
- fprintf(stderr, "Illegal instruction [%d at %016" PRIx64 "]: 0x%016"
- PRIx64 "\n", ilc, s->pc, inst);
-#endif
-}
-
-static void gen_program_exception(DisasContext *s, int ilc, int code)
+static void gen_program_exception(DisasContext *s, int code)
{
TCGv_i32 tmp;
- debug_print_inst(s, ilc);
-
- /* remember what pgm exeption this was */
+ /* Remember what pgm exeption this was. */
tmp = tcg_const_i32(code);
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
tcg_temp_free_i32(tmp);
- tmp = tcg_const_i32(ilc);
+ tmp = tcg_const_i32(s->next_pc - s->pc);
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc));
tcg_temp_free_i32(tmp);
- /* advance past instruction */
- s->pc += (ilc * 2);
+ /* Advance past instruction. */
+ s->pc = s->next_pc;
update_psw_addr(s);
- /* save off cc */
+ /* Save off cc. */
gen_op_calc_cc(s);
- /* trigger exception */
- tmp = tcg_const_i32(EXCP_PGM);
- gen_helper_exception(cpu_env, tmp);
- tcg_temp_free_i32(tmp);
+ /* Trigger exception. */
+ gen_exception(EXCP_PGM);
- /* end TB here */
+ /* End TB here. */
s->is_jmp = DISAS_EXCP;
}
-
-static void gen_illegal_opcode(DisasContext *s, int ilc)
-{
- gen_program_exception(s, ilc, PGM_SPECIFICATION);
-}
-
-static void gen_privileged_exception(DisasContext *s, int ilc)
+static inline void gen_illegal_opcode(DisasContext *s)
{
- gen_program_exception(s, ilc, PGM_PRIVILEGED);
+ gen_program_exception(s, PGM_SPECIFICATION);
}
-static void check_privileged(DisasContext *s, int ilc)
+static inline void check_privileged(DisasContext *s)
{
if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
- gen_privileged_exception(s, ilc);
+ gen_program_exception(s, PGM_PRIVILEGED);
}
}
-#endif /* CONFIG_USER_ONLY */
-
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
{
TCGv_i64 tmp;
@@ -1762,7 +1710,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
break;
default:
LOG_DISAS("illegal e3 operation 0x%x\n", op);
- gen_illegal_opcode(s, 3);
+ gen_illegal_opcode(s);
break;
}
tcg_temp_free_i64(addr);
@@ -1787,7 +1735,7 @@ static void disas_e5(DisasContext* s, uint64_t insn)
break;
default:
LOG_DISAS("illegal e5 operation 0x%x\n", op);
- gen_illegal_opcode(s, 3);
+ gen_illegal_opcode(s);
break;
}
@@ -1801,7 +1749,6 @@ static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
TCGv_i64 tmp, tmp2, tmp3, tmp4;
TCGv_i32 tmp32_1, tmp32_2;
int i, stm_len;
- int ilc = 3;
LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
op, r1, r3, b2, d2);
@@ -1939,7 +1886,7 @@ do_mh:
#ifndef CONFIG_USER_ONLY
case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
/* Load Control */
- check_privileged(s, ilc);
+ check_privileged(s);
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
tmp32_2 = tcg_const_i32(r3);
@@ -1951,7 +1898,7 @@ do_mh:
break;
case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
/* Store Control */
- check_privileged(s, ilc);
+ check_privileged(s);
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
tmp32_2 = tcg_const_i32(r3);
@@ -2028,7 +1975,7 @@ do_mh:
break;
default:
LOG_DISAS("illegal eb operation 0x%x\n", op);
- gen_illegal_opcode(s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
@@ -2148,7 +2095,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
break;
default:
LOG_DISAS("illegal ed operation 0x%x\n", op);
- gen_illegal_opcode(s, 3);
+ gen_illegal_opcode(s);
return;
}
tcg_temp_free_i32(tmp_r1);
@@ -2304,7 +2251,7 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2)
break;
default:
LOG_DISAS("illegal a5 operation 0x%x\n", op);
- gen_illegal_opcode(s, 2);
+ gen_illegal_opcode(s);
return;
}
}
@@ -2441,7 +2388,7 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
break;
default:
LOG_DISAS("illegal a7 operation 0x%x\n", op);
- gen_illegal_opcode(s, 2);
+ gen_illegal_opcode(s);
return;
}
}
@@ -2451,7 +2398,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
TCGv_i64 tmp, tmp2, tmp3;
TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
int r1, r2;
- int ilc = 2;
#ifndef CONFIG_USER_ONLY
int r3, d2, b2;
#endif
@@ -2545,7 +2491,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
#ifndef CONFIG_USER_ONLY
case 0x02: /* STIDP D2(B2) [S] */
/* Store CPU ID */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2554,7 +2500,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x04: /* SCK D2(B2) [S] */
/* Set Clock */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2573,7 +2519,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x06: /* SCKC D2(B2) [S] */
/* Set Clock Comparator */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2582,7 +2528,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x07: /* STCKC D2(B2) [S] */
/* Store Clock Comparator */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2591,7 +2537,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x08: /* SPT D2(B2) [S] */
/* Set CPU Timer */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2600,7 +2546,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x09: /* STPT D2(B2) [S] */
/* Store CPU Timer */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2609,7 +2555,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x0a: /* SPKA D2(B2) [S] */
/* Set PSW Key from Address */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
tmp2 = tcg_temp_new_i64();
@@ -2621,12 +2567,12 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x0d: /* PTLB [S] */
/* Purge TLB */
- check_privileged(s, ilc);
+ check_privileged(s);
gen_helper_ptlb(cpu_env);
break;
case 0x10: /* SPX D2(B2) [S] */
/* Set Prefix Register */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2635,7 +2581,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x11: /* STPX D2(B2) [S] */
/* Store Prefix */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
tmp2 = tcg_temp_new_i64();
@@ -2646,7 +2592,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x12: /* STAP D2(B2) [S] */
/* Store CPU Address */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
tmp2 = tcg_temp_new_i64();
@@ -2660,7 +2606,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x21: /* IPTE R1,R2 [RRE] */
/* Invalidate PTE */
- check_privileged(s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp = load_reg(r1);
@@ -2671,7 +2617,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x29: /* ISKE R1,R2 [RRE] */
/* Insert Storage Key Extended */
- check_privileged(s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp = load_reg(r2);
@@ -2683,7 +2629,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x2a: /* RRBE R1,R2 [RRE] */
/* Set Storage Key Extended */
- check_privileged(s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
@@ -2695,7 +2641,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x2b: /* SSKE R1,R2 [RRE] */
/* Set Storage Key Extended */
- check_privileged(s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
@@ -2706,12 +2652,12 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x34: /* STCH ? */
/* Store Subchannel */
- check_privileged(s, ilc);
+ check_privileged(s);
gen_op_movi_cc(s, 3);
break;
case 0x46: /* STURA R1,R2 [RRE] */
/* Store Using Real Address */
- check_privileged(s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
@@ -2723,7 +2669,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x50: /* CSP R1,R2 [RRE] */
/* Compare And Swap And Purge */
- check_privileged(s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = tcg_const_i32(r1);
@@ -2735,7 +2681,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x5f: /* CHSC ? */
/* Channel Subsystem Call */
- check_privileged(s, ilc);
+ check_privileged(s);
gen_op_movi_cc(s, 3);
break;
case 0x78: /* STCKE D2(B2) [S] */
@@ -2749,19 +2695,19 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x79: /* SACF D2(B2) [S] */
/* Store Clock Extended */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
gen_helper_sacf(cpu_env, tmp);
tcg_temp_free_i64(tmp);
/* addressing mode has changed, so end the block */
- s->pc += ilc * 2;
+ s->pc = s->next_pc;
update_psw_addr(s);
s->is_jmp = DISAS_EXCP;
break;
case 0x7d: /* STSI D2,(B2) [S] */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
tmp32_1 = load_reg32(0);
@@ -2787,7 +2733,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0xb1: /* STFL D2(B2) [S] */
/* Store Facility List (CPU features) at 200 */
- check_privileged(s, ilc);
+ check_privileged(s);
tmp2 = tcg_const_i64(0xc0000000);
tmp = tcg_const_i64(200);
tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
@@ -2796,7 +2742,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0xb2: /* LPSWE D2(B2) [S] */
/* Load PSW Extended */
- check_privileged(s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
tmp2 = tcg_temp_new_i64();
@@ -2813,7 +2759,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
break;
case 0x20: /* SERVC R1,R2 [RRE] */
/* SCLP Service call (PV hypercall) */
- check_privileged(s, ilc);
+ check_privileged(s);
potential_page_fault(s);
tmp32_1 = load_reg32(r2);
tmp = load_reg(r1);
@@ -2825,7 +2771,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
#endif
default:
LOG_DISAS("illegal b2 operation 0x%x\n", op);
- gen_illegal_opcode(s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3100,7 +3046,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
break;
default:
LOG_DISAS("illegal b3 operation 0x%x\n", op);
- gen_illegal_opcode(s, 2);
+ gen_illegal_opcode(s);
break;
}
@@ -3406,7 +3352,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
break;
default:
LOG_DISAS("illegal b9 operation 0x%x\n", op);
- gen_illegal_opcode(s, 2);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3507,7 +3453,7 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
break;
default:
LOG_DISAS("illegal c0 operation 0x%x\n", op);
- gen_illegal_opcode(s, 3);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3540,7 +3486,7 @@ static void disas_c2(DisasContext *s, int op, int r1, int i2)
break;
default:
LOG_DISAS("illegal c2 operation 0x%x\n", op);
- gen_illegal_opcode(s, 3);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3570,14 +3516,11 @@ static void disas_s390_insn(DisasContext *s)
uint64_t insn;
int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
TCGv_i32 vl;
- int ilc;
int l1;
opc = cpu_ldub_code(cpu_single_env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
- ilc = get_ilc(opc);
-
switch (opc) {
#ifndef CONFIG_USER_ONLY
case 0x01: /* SAM */
@@ -3630,15 +3573,13 @@ static void disas_s390_insn(DisasContext *s)
update_psw_addr(s);
gen_op_calc_cc(s);
tmp32_1 = tcg_const_i32(i);
- tmp32_2 = tcg_const_i32(ilc * 2);
- tmp32_3 = tcg_const_i32(EXCP_SVC);
+ tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
- gen_helper_exception(cpu_env, tmp32_3);
+ gen_exception(EXCP_SVC);
s->is_jmp = DISAS_EXCP;
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
break;
case 0xd: /* BASR R1,R2 [RR] */
insn = ld_code2(s->pc);
@@ -4129,7 +4070,7 @@ static void disas_s390_insn(DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0x80: /* SSM D2(B2) [S] */
/* Set System Mask */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4145,7 +4086,7 @@ static void disas_s390_insn(DisasContext *s)
break;
case 0x82: /* LPSW D2(B2) [S] */
/* Load PSW */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4163,7 +4104,7 @@ static void disas_s390_insn(DisasContext *s)
break;
case 0x83: /* DIAG R1,R3,D2 [RS] */
/* Diagnose call (KVM hypercall) */
- check_privileged(s, ilc);
+ check_privileged(s);
potential_page_fault(s);
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -4381,7 +4322,7 @@ static void disas_s390_insn(DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0xac: /* STNSM D1(B1),I2 [SI] */
case 0xad: /* STOSM D1(B1),I2 [SI] */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code4(s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1);
tmp2 = tcg_temp_new_i64();
@@ -4397,7 +4338,7 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
break;
case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4411,7 +4352,7 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
break;
case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
tmp32_1 = tcg_const_i32(r1);
@@ -4455,7 +4396,7 @@ static void disas_s390_insn(DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
/* Store Control */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4469,7 +4410,7 @@ static void disas_s390_insn(DisasContext *s)
break;
case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
/* Load Control */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4653,7 +4594,7 @@ static void disas_s390_insn(DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */
case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */
- check_privileged(s, ilc);
+ check_privileged(s);
potential_page_fault(s);
insn = ld_code6(s->pc);
r1 = (insn >> 36) & 0xf;
@@ -4691,7 +4632,7 @@ static void disas_s390_insn(DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0xe5:
/* Test Protection */
- check_privileged(s, ilc);
+ check_privileged(s);
insn = ld_code6(s->pc);
debug_insn(insn);
disas_e5(s, insn);
@@ -4721,7 +4662,7 @@ static void disas_s390_insn(DisasContext *s)
break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
- gen_illegal_opcode(s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
@@ -5430,6 +5371,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
int num_insns, max_insns;
CPUBreakpoint *bp;
ExitStatus status;
+ bool do_debug;
pc_start = tb->pc;
@@ -5441,7 +5383,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
dc.tb = tb;
dc.pc = pc_start;
dc.cc_op = CC_OP_DYNAMIC;
- dc.singlestep_enabled = env->singlestep_enabled;
+ do_debug = dc.singlestep_enabled = env->singlestep_enabled;
dc.is_jmp = DISAS_NEXT;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
@@ -5457,14 +5399,6 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
gen_icount_start();
do {
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
- if (bp->pc == dc.pc) {
- gen_debug(&dc);
- break;
- }
- }
- }
if (search_pc) {
j = gen_opc_ptr - gen_opc_buf;
if (lj < j) {
@@ -5486,7 +5420,19 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
tcg_gen_debug_insn_start(dc.pc);
}
- status = translate_one(&dc);
+ status = NO_EXIT;
+ if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+ QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (bp->pc == dc.pc) {
+ status = EXIT_PC_STALE;
+ do_debug = true;
+ break;
+ }
+ }
+ }
+ if (status == NO_EXIT) {
+ status = translate_one(&dc);
+ }
/* If we reach a page boundary, are single stepping,
or exhaust instruction count, stop generation. */
@@ -5519,8 +5465,8 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
so make sure the cc op type is in env */
gen_op_set_cc_op(&dc);
}
- if (env->singlestep_enabled) {
- gen_debug(&dc);
+ if (do_debug) {
+ gen_exception(EXCP_DEBUG);
} else {
/* Generate the return instruction */
tcg_gen_exit_tb(0);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 011/126] target-s390: Convert ADD HALFWORD
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (9 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 012/126] target-s390: Implement SUBTRACT HALFWORD Richard Henderson
` (90 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 7 +++++++
target-s390x/translate.c | 43 +++++++------------------------------------
2 files changed, 14 insertions(+), 36 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7d81928..2acc8f0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -15,6 +15,13 @@
C(0xc208, AGFI, RIL_a, EI, r1, i2, r1, 0, add, adds64)
C(0xeb7a, AGSI, SIY, GIE, m1_64, i2, new, m1_64, add, adds64)
C(0xecd9, AGHIK, RIE_d, DO, r3, i2, r1, 0, add, adds64)
+/* ADD HALFWORD */
+ C(0x4a00, AH, RX_a, Z, r1, m2_16s, new, r1_32, add, adds32)
+ C(0xe37a, AHY, RXY_a, LD, r1, m2_16s, new, r1_32, add, adds32)
+/* ADD HALFWORD IMMEDIATE */
+ C(0xa70a, AHI, RI_a, Z, r1, i2, new, r1_32, add, adds32)
+ C(0xa70b, AGHI, RI_a, Z, r1, i2, r1, 0, add, adds64)
+
/* ADD LOGICAL */
C(0x1e00, ALR, RR_a, Z, r1, r2, new, r1_32, add, addu32)
C(0xb9fa, ALRK, RRF_a, DO, r2, r3, new, r1_32, add, addu32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 70e5d87..5850b23 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -557,11 +557,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
}
-static void set_cc_add64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2, TCGv_i64 vr)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADD_64, v1, v2, vr);
-}
-
static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
TCGv_i64 vr)
{
@@ -2259,7 +2254,7 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2)
static void disas_a7(DisasContext *s, int op, int r1, int i2)
{
TCGv_i64 tmp, tmp2;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+ TCGv_i32 tmp32_1;
int l1;
LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
@@ -2334,36 +2329,6 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
store_reg(r1, tmp);
tcg_temp_free_i64(tmp);
break;
- case 0xa: /* AHI R1,I2 [RI] */
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp32_3 = tcg_const_i32(i2);
-
- if (i2 < 0) {
- tcg_gen_subi_i32(tmp32_2, tmp32_1, -i2);
- } else {
- tcg_gen_add_i32(tmp32_2, tmp32_1, tmp32_3);
- }
-
- store_reg32(r1, tmp32_2);
- set_cc_add32(s, tmp32_1, tmp32_3, tmp32_2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0xb: /* aghi r1, i2 */
- tmp = load_reg(r1);
- tmp2 = tcg_const_i64(i2);
-
- if (i2 < 0) {
- tcg_gen_subi_i64(regs[r1], tmp, -i2);
- } else {
- tcg_gen_add_i64(regs[r1], tmp, tmp2);
- }
- set_cc_add64(s, tmp, tmp2, regs[r1]);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0xc: /* MHI R1,I2 [RI] */
tmp32_1 = load_reg32(r1);
tcg_gen_muli_i32(tmp32_1, tmp32_1, i2);
@@ -5059,6 +5024,12 @@ static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
}
+static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_a2(s, f, o);
+ tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
+}
+
static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
{
in2_a2(s, f, o);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 012/126] target-s390: Implement SUBTRACT HALFWORD
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (10 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 011/126] target-s390: Convert ADD HALFWORD Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 013/126] target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE Richard Henderson
` (89 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 3 +++
1 file changed, 3 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2acc8f0..44e1ca7 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -46,6 +46,9 @@
C(0xb9e9, SGRK, RRF_a, DO, r2, r3, r1, 0, sub, subs64)
C(0xe309, SG, RXY_a, Z, r1, m2_64, r1, 0, sub, subs64)
C(0xe319, SGF, RXY_a, Z, r1, m2_32s, r1, 0, sub, subs64)
+/* SUBTRACT HALFWORD */
+ C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32)
+ C(0xe37b, SHY, RXY_a, LD, r1, m2_16s, new, r1_32, sub, subs32)
/* SUBTRACT LOGICAL */
C(0x1f00, SLR, RR_a, Z, r1, r2, new, r1_32, sub, subu32)
C(0xb9fb, SLRK, RRF_a, DO, r2, r3, new, r1_32, sub, subu32)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 013/126] target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (11 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 012/126] target-s390: Implement SUBTRACT HALFWORD Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 014/126] target-s390: Convert MULTIPLY Richard Henderson
` (88 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 5 +++++
target-s390x/translate.c | 7 +++++++
2 files changed, 12 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 44e1ca7..acde181 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -35,6 +35,11 @@
/* ADD LOGICAL IMMEDIATE */
C(0xc20b, ALFI, RIL_a, EI, r1, i2_32u, new, r1_32, add, addu32)
C(0xc20a, ALGFI, RIL_a, EI, r1, i2_32u, r1, 0, add, addu64)
+/* ADD LOGICAL WITH SIGNED IMMEDIATE */
+ C(0xeb6e, ALSI, SIY, GIE, m1_32u, i2, new, m1_32, add, addu32)
+ C(0xecda, ALHSIK, RIE_d, DO, r3, i2, new, r1_32, add, addu32)
+ C(0xeb7e, ALGSI, SIY, GIE, m1_64, i2, new, m1_64, add, addu64)
+ C(0xecdb, ALGHSIK, RIE_d, DO, r3, i2, r1, 0, add, addu64)
/* SUBTRACT */
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5850b23..143b744 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -4986,6 +4986,13 @@ static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
}
+static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in1_la1(s, f, o);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
+}
+
static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
{
in1_la1(s, f, o);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 014/126] target-s390: Convert MULTIPLY
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (12 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 013/126] target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 015/126] target-s390: Convert AND, OR, XOR Richard Henderson
` (87 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cpu.h | 15 +--
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 27 +++++
target-s390x/int_helper.c | 15 +--
target-s390x/translate.c | 239 ++++++++++++++-------------------------------
5 files changed, 112 insertions(+), 186 deletions(-)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 17829b5..7486e4c 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -60,17 +60,20 @@ typedef struct ExtQueue {
} ExtQueue;
typedef struct CPUS390XState {
- uint64_t regs[16]; /* GP registers */
+ uint64_t regs[16]; /* GP registers */
+ CPU_DoubleU fregs[16]; /* FP registers */
+ uint32_t aregs[16]; /* access registers */
- uint32_t aregs[16]; /* access registers */
+ uint32_t fpc; /* floating-point control register */
+ uint32_t cc_op;
- uint32_t fpc; /* floating-point control register */
- CPU_DoubleU fregs[16]; /* FP registers */
float_status fpu_status; /* passed to softfloat lib */
+ /* The low part of a 128-bit return, or remainder of a divide. */
+ uint64_t retxl;
+
PSW psw;
- uint32_t cc_op;
uint64_t cc_src;
uint64_t cc_dst;
uint64_t cc_vr;
@@ -86,8 +89,8 @@ typedef struct CPUS390XState {
uint64_t cregs[16]; /* control registers */
- int pending_int;
ExtQueue ext_queue[MAX_EXT_QUEUE];
+ int pending_int;
int ext_index;
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 5419f37..0ebdd53 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -12,7 +12,7 @@ DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
DEF_HELPER_4(clm, i32, env, i32, i32, i64)
DEF_HELPER_4(stcm, void, env, i32, i32, i64)
-DEF_HELPER_3(mlg, void, env, i32, i64)
+DEF_HELPER_FLAGS_3(mul128, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64, i64)
DEF_HELPER_3(dlg, void, env, i32, i64)
DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index acde181..f93aba0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -41,6 +41,33 @@
C(0xeb7e, ALGSI, SIY, GIE, m1_64, i2, new, m1_64, add, addu64)
C(0xecdb, ALGHSIK, RIE_d, DO, r3, i2, r1, 0, add, addu64)
+/* MULTIPLY */
+ C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
+ C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
+ C(0xe35c, MFY, RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
+/* MULTIPLY HALFWORD */
+ C(0x4c00, MH, RX_a, Z, r1, m2_16s, new, r1_32, mul, 0)
+ C(0xe37c, MHY, RXY_a, GIE, r1, m2_16s, new, r1_32, mul, 0)
+/* MULTIPLY HALFWORD IMMEDIATE */
+ C(0xa70c, MHI, RI_a, Z, r1, i2, new, r1_32, mul, 0)
+ C(0xa70d, MGHI, RI_a, Z, r1_o, i2, r1, 0, mul, 0)
+/* MULTIPLY LOGICAL */
+ C(0xb996, MLR, RRE, Z, r1p1_32u, r2_32u, new, r1_D32, mul, 0)
+ C(0xe396, ML, RXY_a, Z, r1p1_32u, m2_32u, new, r1_D32, mul, 0)
+ C(0xb986, MLGR, RRE, Z, r1p1, r2_o, r1_P, 0, mul128, 0)
+ C(0xe386, MLG, RXY_a, Z, r1p1, m2_64, r1_P, 0, mul128, 0)
+/* MULTIPLY SINGLE */
+ C(0xb252, MSR, RRE, Z, r1_o, r2_o, new, r1_32, mul, 0)
+ C(0x7100, MS, RX_a, Z, r1_o, m2_32s, new, r1_32, mul, 0)
+ C(0xe351, MSY, RXY_a, LD, r1_o, m2_32s, new, r1_32, mul, 0)
+ C(0xb90c, MSGR, RRE, Z, r1_o, r2_o, r1, 0, mul, 0)
+ C(0xb91c, MSGFR, RRE, Z, r1_o, r2_32s, r1, 0, mul, 0)
+ C(0xe30c, MSG, RXY_a, Z, r1_o, m2_64, r1, 0, mul, 0)
+ C(0xe31c, MSGF, RXY_a, Z, r1_o, m2_32s, r1, 0, mul, 0)
+/* MULTIPLY SINGLE IMMEDIATE */
+ C(0xc201, MSFI, RIL_a, GIE, r1, i2, new, r1_32, mul, 0)
+ C(0xc200, MSGFI, RIL_a, GIE, r1, i2, r1, 0, mul, 0)
+
/* SUBTRACT */
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
C(0xb9f9, SRK, RRF_a, DO, r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index f202a7e..e54faea 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -30,18 +30,11 @@
#endif
/* 64/64 -> 128 unsigned multiplication */
-void HELPER(mlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
+uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
{
-#if HOST_LONG_BITS == 64 && defined(__GNUC__)
- /* assuming 64-bit hosts have __uint128_t */
- __uint128_t res = (__uint128_t)env->regs[r1 + 1];
-
- res *= (__uint128_t)v2;
- env->regs[r1] = (uint64_t)(res >> 64);
- env->regs[r1 + 1] = (uint64_t)res;
-#else
- mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
-#endif
+ uint64_t reth;
+ mulu64(&env->retxl, &reth, v1, v2);
+ return reth;
}
/* 128 -> 64/64 unsigned division */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 143b744..f308cf4 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -291,6 +291,11 @@ static inline void store_freg32(int reg, TCGv_i32 v)
#endif
}
+static inline void return_low128(TCGv_i64 dest)
+{
+ tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
+}
+
static inline void update_psw_addr(DisasContext *s)
{
/* psw.addr */
@@ -573,22 +578,12 @@ static void set_cc_nabs64(DisasContext *s, TCGv_i64 v1)
gen_op_update1_cc_i64(s, CC_OP_NABS_64, v1);
}
-static void set_cc_add32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
-{
- gen_op_update3_cc_i32(s, CC_OP_ADD_32, v1, v2, vr);
-}
-
static void set_cc_addu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
TCGv_i32 vr)
{
gen_op_update3_cc_i32(s, CC_OP_ADDU_32, v1, v2, vr);
}
-static void set_cc_sub32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
-{
- gen_op_update3_cc_i32(s, CC_OP_SUB_32, v1, v2, vr);
-}
-
static void set_cc_abs32(DisasContext *s, TCGv_i32 v1)
{
gen_op_update1_cc_i32(s, CC_OP_ABS_32, v1);
@@ -1366,17 +1361,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0xc: /* MSG R1,D2(X2,B2) [RXY] */
- case 0x1c: /* MSGF R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- if (op == 0xc) {
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- } else {
- tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
- }
- tcg_gen_mul_i64(regs[r1], regs[r1], tmp2);
- tcg_temp_free_i64(tmp2);
- break;
case 0xd: /* DSG R1,D2(X2,B2) [RXY] */
case 0x1d: /* DSGF R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
@@ -1579,14 +1563,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
set_cc_nz_u64(s, regs[r1]);
tcg_temp_free_i64(tmp3);
break;
- case 0x86: /* MLG R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_const_i32(r1);
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- gen_helper_mlg(cpu_env, tmp32_1, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x87: /* DLG R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
tmp32_1 = tcg_const_i32(r1);
@@ -1640,18 +1616,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg32_i64(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0x96: /* ML R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp3 = load_reg((r1 + 1) & 15);
- tcg_gen_ext32u_i64(tmp3, tmp3);
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- tcg_gen_mul_i64(tmp2, tmp2, tmp3);
- store_reg32_i64((r1 + 1) & 15, tmp2);
- tcg_gen_shri_i64(tmp2, tmp2, 32);
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x97: /* DL R1,D2(X2,B2) [RXY] */
/* reg(r1) = reg(r1, r1+1) % ld32(addr) */
/* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
@@ -2329,18 +2293,6 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
store_reg(r1, tmp);
tcg_temp_free_i64(tmp);
break;
- case 0xc: /* MHI R1,I2 [RI] */
- tmp32_1 = load_reg32(r1);
- tcg_gen_muli_i32(tmp32_1, tmp32_1, i2);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0xd: /* MGHI R1,I2 [RI] */
- tmp = load_reg(r1);
- tcg_gen_muli_i64(tmp, tmp, i2);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0xe: /* CHI R1,I2 [RI] */
tmp32_1 = load_reg32(r1);
cmp_s32c(s, tmp32_1, i2);
@@ -2399,14 +2351,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x52: /* MSR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r2);
- tcg_gen_mul_i32(tmp32_1, tmp32_1, tmp32_2);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x54: /* MVPG R1,R2 [RRE] */
tmp = load_reg(0);
tmp2 = load_reg(r1);
@@ -3072,18 +3016,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
store_reg(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0xc: /* MSGR R1,R2 [RRE] */
- case 0x1c: /* MSGFR R1,R2 [RRE] */
- tmp = load_reg(r1);
- tmp2 = load_reg(r2);
- if (op == 0x1c) {
- tcg_gen_ext32s_i64(tmp2, tmp2);
- }
- tcg_gen_mul_i64(tmp, tmp, tmp2);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0xd: /* DSGR R1,R2 [RRE] */
case 0x1d: /* DSGFR R1,R2 [RRE] */
tmp = load_reg(r1 + 1);
@@ -3261,19 +3193,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x96: /* MLR R1,R2 [RRE] */
- /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
- tmp2 = load_reg(r2);
- tmp3 = load_reg((r1 + 1) & 15);
- tcg_gen_ext32u_i64(tmp2, tmp2);
- tcg_gen_ext32u_i64(tmp3, tmp3);
- tcg_gen_mul_i64(tmp2, tmp2, tmp3);
- store_reg32_i64((r1 + 1) & 15, tmp2);
- tcg_gen_shri_i64(tmp2, tmp2, 32);
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x97: /* DLR R1,R2 [RRE] */
/* reg(r1) = reg(r1, r1+1) % reg(r2) */
/* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
@@ -3641,21 +3560,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x1c: /* MR R1,R2 [RR] */
- /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp2 = load_reg(r2);
- tmp3 = load_reg((r1 + 1) & 15);
- tcg_gen_ext32s_i64(tmp2, tmp2);
- tcg_gen_ext32s_i64(tmp3, tmp3);
- tcg_gen_mul_i64(tmp2, tmp2, tmp3);
- store_reg32_i64((r1 + 1) & 15, tmp2);
- tcg_gen_shri_i64(tmp2, tmp2, 32);
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x1d: /* DR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3803,41 +3707,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x4a: /* AH R1,D2(X2,B2) [RX] */
- case 0x4b: /* SH R1,D2(X2,B2) [RX] */
- case 0x4c: /* MH R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp32_3 = tcg_temp_new_i32();
-
- tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- switch (opc) {
- case 0x4a:
- tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
- set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x4b:
- tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
- set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x4c:
- tcg_gen_mul_i32(tmp32_3, tmp32_1, tmp32_2);
- break;
- default:
- tcg_abort();
- }
- store_reg32(r1, tmp32_3);
-
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x4d: /* BAS R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3926,23 +3795,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x5c: /* M R1,D2(X2,B2) [RX] */
- /* reg(r1, r1+1) = reg(r1+1) * *(s32*)addr */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
- tmp3 = load_reg((r1 + 1) & 15);
- tcg_gen_ext32s_i64(tmp2, tmp2);
- tcg_gen_ext32s_i64(tmp3, tmp3);
- tcg_gen_mul_i64(tmp2, tmp2, tmp3);
- store_reg32_i64((r1 + 1) & 15, tmp2);
- tcg_gen_shri_i64(tmp2, tmp2, 32);
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x5d: /* D R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4005,21 +3857,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x71: /* MS R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- tcg_gen_mul_i32(tmp32_1, tmp32_1, tmp32_2);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x78: /* LE R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4867,6 +4704,19 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_mul(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_mul_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
+{
+ gen_helper_mul128(o->out, cpu_env, o->in1, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_sub(DisasContext *s, DisasOps *o)
{
tcg_gen_sub_i64(o->out, o->in1, o->in2);
@@ -4935,6 +4785,15 @@ static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_out = true;
}
+static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be even. */
+ int r1 = get_field(f, r1);
+ o->out = regs[r1];
+ o->out2 = regs[(r1 + 1) & 15];
+ o->g_out = o->g_out2 = true;
+}
+
/* ====================================================================== */
/* The "Write OUTput" generators. These generally perform some non-trivial
copy of data to TCG globals, or to main memory. The trivial cases are
@@ -4946,6 +4805,15 @@ static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
store_reg32_i64(get_field(f, r1), o->out);
}
+static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be even. */
+ int r1 = get_field(f, r1);
+ store_reg32_i64((r1 + 1) & 15, o->out);
+ tcg_gen_shli_i64(o->out, o->out, 32);
+ store_reg32_i64(r1, o->out);
+}
+
static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
@@ -4964,6 +4832,35 @@ static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = load_reg(get_field(f, r1));
}
+static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = regs[get_field(f, r1)];
+ o->g_in1 = true;
+}
+
+static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be even. */
+ int r1 = get_field(f, r1);
+ o->in1 = load_reg((r1 + 1) & 15);
+}
+
+static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be even. */
+ int r1 = get_field(f, r1);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_ext32s_i64(o->in1, regs[(r1 + 1) & 15]);
+}
+
+static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be even. */
+ int r1 = get_field(f, r1);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_ext32u_i64(o->in1, regs[(r1 + 1) & 15]);
+}
+
static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_reg(get_field(f, r2));
@@ -5008,6 +4905,12 @@ static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = load_reg(get_field(f, r2));
}
+static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = regs[get_field(f, r2)];
+ o->g_in2 = true;
+}
+
static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_reg(get_field(f, r3));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 015/126] target-s390: Convert AND, OR, XOR
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (13 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 014/126] target-s390: Convert MULTIPLY Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 016/126] target-s390: Convert COMPARE, COMPARE LOGICAL Richard Henderson
` (86 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 27 +++++++++
target-s390x/translate.c | 134 ++++++++++-----------------------------------
2 files changed, 56 insertions(+), 105 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f93aba0..2d30c95 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -41,6 +41,24 @@
C(0xeb7e, ALGSI, SIY, GIE, m1_64, i2, new, m1_64, add, addu64)
C(0xecdb, ALGHSIK, RIE_d, DO, r3, i2, r1, 0, add, addu64)
+/* AND */
+ C(0x1400, NR, RR_a, Z, r1, r2, new, r1_32, and, nz32)
+ C(0xb9f4, NRK, RRF_a, DO, r2, r3, new, r1_32, and, nz32)
+ C(0x5400, N, RX_a, Z, r1, m2_32s, new, r1_32, and, nz32)
+ C(0xe354, NY, RXY_a, LD, r1, m2_32s, new, r1_32, and, nz32)
+ C(0xb980, NGR, RRE, Z, r1, r2, r1, 0, and, nz64)
+ C(0xb9e4, NGRK, RRF_a, DO, r2, r3, r1, 0, and, nz64)
+ C(0xe380, NG, RXY_a, Z, r1, m2_64, r1, 0, and, nz64)
+
+/* EXCLUSIVE OR */
+ C(0x1700, XR, RR_a, Z, r1, r2, new, r1_32, xor, nz32)
+ C(0xb9f7, XRK, RRF_a, DO, r2, r3, new, r1_32, xor, nz32)
+ C(0x5700, X, RX_a, Z, r1, m2_32s, new, r1_32, xor, nz32)
+ C(0xe357, XY, RXY_a, LD, r1, m2_32s, new, r1_32, xor, nz32)
+ C(0xb982, XGR, RRE, Z, r1, r2, r1, 0, xor, nz64)
+ C(0xb9e7, XGRK, RRF_a, DO, r2, r3, r1, 0, xor, nz64)
+ C(0xe382, XG, RXY_a, Z, r1, m2_64, r1, 0, xor, nz64)
+
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
@@ -68,6 +86,15 @@
C(0xc201, MSFI, RIL_a, GIE, r1, i2, new, r1_32, mul, 0)
C(0xc200, MSGFI, RIL_a, GIE, r1, i2, r1, 0, mul, 0)
+/* OR */
+ C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32)
+ C(0xb9f6, ORK, RRF_a, DO, r2, r3, new, r1_32, or, nz32)
+ C(0x5600, O, RX_a, Z, r1, m2_32s, new, r1_32, or, nz32)
+ C(0xe356, OY, RXY_a, LD, r1, m2_32s, new, r1_32, or, nz32)
+ C(0xb981, OGR, RRE, Z, r1, r2, r1, 0, or, nz64)
+ C(0xb9e6, OGRK, RRF_a, DO, r2, r3, r1, 0, or, nz64)
+ C(0xe381, OG, RXY_a, Z, r1, m2_64, r1, 0, or, nz64)
+
/* SUBTRACT */
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
C(0xb9f9, SRK, RRF_a, DO, r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f308cf4..3fc8c45 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1482,19 +1482,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
tcg_temp_free_i64(tmp2);
break;
- case 0x57: /* XY R1,D2(X2,B2) [RXY] */
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_gen_xor_i32(tmp32_2, tmp32_1, tmp32_2);
- store_reg32(r1, tmp32_2);
- set_cc_nz_u32(s, tmp32_2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x58: /* LY R1,D2(X2,B2) [RXY] */
tmp3 = tcg_temp_new_i64();
tcg_gen_qemu_ld32u(tmp3, addr, get_mem_index(s));
@@ -1542,27 +1529,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg32_i64(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0x80: /* NG R1,D2(X2,B2) [RXY] */
- case 0x81: /* OG R1,D2(X2,B2) [RXY] */
- case 0x82: /* XG R1,D2(X2,B2) [RXY] */
- tmp3 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(tmp3, addr, get_mem_index(s));
- switch (op) {
- case 0x80:
- tcg_gen_and_i64(regs[r1], regs[r1], tmp3);
- break;
- case 0x81:
- tcg_gen_or_i64(regs[r1], regs[r1], tmp3);
- break;
- case 0x82:
- tcg_gen_xor_i64(regs[r1], regs[r1], tmp3);
- break;
- default:
- tcg_abort();
- }
- set_cc_nz_u64(s, regs[r1]);
- tcg_temp_free_i64(tmp3);
- break;
case 0x87: /* DLG R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
tmp32_1 = tcg_const_i32(r1);
@@ -3104,29 +3070,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x80: /* NGR R1,R2 [RRE] */
- case 0x81: /* OGR R1,R2 [RRE] */
- case 0x82: /* XGR R1,R2 [RRE] */
- tmp = load_reg(r1);
- tmp2 = load_reg(r2);
- switch (op) {
- case 0x80:
- tcg_gen_and_i64(tmp, tmp, tmp2);
- break;
- case 0x81:
- tcg_gen_or_i64(tmp, tmp, tmp2);
- break;
- case 0x82:
- tcg_gen_xor_i64(tmp, tmp, tmp2);
- break;
- default:
- tcg_abort();
- }
- store_reg(r1, tmp);
- set_cc_nz_u64(s, tmp);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x83: /* FLOGR R1,R2 [RRE] */
tmp = load_reg(r2);
tmp32_1 = tcg_const_i32(r1);
@@ -3375,23 +3318,6 @@ static void disas_c2(DisasContext *s, int op, int r1, int i2)
}
}
-static void gen_and_or_xor_i32(int opc, TCGv_i32 tmp, TCGv_i32 tmp2)
-{
- switch (opc & 0xf) {
- case 0x4:
- tcg_gen_and_i32(tmp, tmp, tmp2);
- break;
- case 0x6:
- tcg_gen_or_i32(tmp, tmp, tmp2);
- break;
- case 0x7:
- tcg_gen_xor_i32(tmp, tmp, tmp2);
- break;
- default:
- tcg_abort();
- }
-}
-
static void disas_s390_insn(DisasContext *s)
{
TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -3526,19 +3452,6 @@ static void disas_s390_insn(DisasContext *s)
set_cc_comp32(s, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x14: /* NR R1,R2 [RR] */
- case 0x16: /* OR R1,R2 [RR] */
- case 0x17: /* XR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_2 = load_reg32(r2);
- tmp32_1 = load_reg32(r1);
- gen_and_or_xor_i32(opc, tmp32_1, tmp32_2);
- store_reg32(r1, tmp32_1);
- set_cc_nz_u32(s, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x18: /* LR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3751,24 +3664,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x54: /* N R1,D2(X2,B2) [RX] */
- case 0x56: /* O R1,D2(X2,B2) [RX] */
- case 0x57: /* X R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- gen_and_or_xor_i32(opc, tmp32_1, tmp32_2);
- store_reg32(r1, tmp32_1);
- set_cc_nz_u32(s, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x58: /* l r1, d2(x2, b2) */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4704,6 +4599,12 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_and(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_and_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
{
tcg_gen_mul_i64(o->out, o->in1, o->in2);
@@ -4717,12 +4618,24 @@ static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_or(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_or_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_sub(DisasContext *s, DisasOps *o)
{
tcg_gen_sub_i64(o->out, o->in1, o->in2);
return NO_EXIT;
}
+static ExitStatus op_xor(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_xor_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
/* ====================================================================== */
/* The "Cc OUTput" generators. Given the generated output (and in some cases
the original inputs), update the various cc data structures in order to
@@ -4748,6 +4661,17 @@ static void cout_addu64(DisasContext *s, DisasOps *o)
gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
}
+static void cout_nz32(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_ext32u_i64(cc_dst, o->out);
+ gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
+}
+
+static void cout_nz64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
+}
+
static void cout_subs32(DisasContext *s, DisasOps *o)
{
gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 016/126] target-s390: Convert COMPARE, COMPARE LOGICAL
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (14 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 015/126] target-s390: Convert AND, OR, XOR Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 017/126] target-s390: Convert LOAD, LOAD LOGICAL Richard Henderson
` (85 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 48 +++++++++
target-s390x/translate.c | 258 ++++++++++++++-------------------------------
2 files changed, 128 insertions(+), 178 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2d30c95..45c3913 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -50,6 +50,54 @@
C(0xb9e4, NGRK, RRF_a, DO, r2, r3, r1, 0, and, nz64)
C(0xe380, NG, RXY_a, Z, r1, m2_64, r1, 0, and, nz64)
+/* COMPARE */
+ C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
+ C(0x5900, C, RX_a, Z, r1_o, m2_32s, 0, 0, 0, cmps32)
+ C(0xe359, CY, RXY_a, LD, r1_o, m2_32s, 0, 0, 0, cmps32)
+ C(0xb920, CGR, RRE, Z, r1_o, r2_o, 0, 0, 0, cmps64)
+ C(0xb930, CGFR, RRE, Z, r1_o, r2_32s, 0, 0, 0, cmps64)
+ C(0xe320, CG, RXY_a, Z, r1_o, m2_64, 0, 0, 0, cmps64)
+ C(0xe330, CGF, RXY_a, Z, r1_o, m2_32s, 0, 0, 0, cmps64)
+/* COMPARE IMMEDIATE */
+ C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32)
+ C(0xc20c, CGFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps64)
+/* COMPARE HALFWORD */
+ C(0x4900, CH, RX_a, Z, r1_o, m2_16s, 0, 0, 0, cmps32)
+ C(0xe379, CHY, RXY_a, LD, r1_o, m2_16s, 0, 0, 0, cmps32)
+ C(0xe334, CGH, RXY_a, GIE, r1_o, m2_16s, 0, 0, 0, cmps64)
+/* COMPARE HALFWORD IMMEDIATE */
+ C(0xa70e, CHI, RI_a, Z, r1_o, i2, 0, 0, 0, cmps32)
+ C(0xa70f, CGHI, RI_a, Z, r1_o, i2, 0, 0, 0, cmps64)
+ C(0xe554, CHHSI, SIL, GIE, m1_16s, i2, 0, 0, 0, cmps64)
+ C(0xe55c, CHSI, SIL, GIE, m1_32s, i2, 0, 0, 0, cmps64)
+ C(0xe558, CGHSI, SIL, GIE, m1_64, i2, 0, 0, 0, cmps64)
+/* COMPARE HALFWORD RELATIVE LONG */
+ C(0xc605, CHRL, RIL_a, GIE, r1_o, mri2_32s, 0, 0, 0, cmps32)
+ C(0xc604, CGHRL, RIL_a, GIE, r1_o, mri2_64, 0, 0, 0, cmps64)
+
+/* COMPARE LOGICAL */
+ C(0x1500, CLR, RR_a, Z, r1, r2, 0, 0, 0, cmpu32)
+ C(0x5500, CL, RX_a, Z, r1, m2_32s, 0, 0, 0, cmpu32)
+ C(0xe355, CLY, RXY_a, LD, r1, m2_32s, 0, 0, 0, cmpu32)
+ C(0xb921, CLGR, RRE, Z, r1, r2, 0, 0, 0, cmpu64)
+ C(0xb931, CLGFR, RRE, Z, r1, r2_32u, 0, 0, 0, cmpu64)
+ C(0xe321, CLG, RXY_a, Z, r1, m2_64, 0, 0, 0, cmpu64)
+ C(0xe331, CLGF, RXY_a, Z, r1, m2_32u, 0, 0, 0, cmpu64)
+/* COMPARE LOGICAL IMMEDIATE */
+ C(0xc20f, CLFI, RIL_a, EI, r1, i2, 0, 0, 0, cmpu32)
+ C(0xc20e, CLGFI, RIL_a, EI, r1, i2_32u, 0, 0, 0, cmpu64)
+ C(0x9500, CLI, SI, Z, m1_8u, i2_8u, 0, 0, 0, cmpu64)
+ C(0xeb55, CLIY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, cmpu64)
+ C(0xe555, CLHHSI, SIL, GIE, m1_16u, i2_16u, 0, 0, 0, cmpu64)
+ C(0xe55d, CLFHSI, SIL, GIE, m1_32u, i2_16u, 0, 0, 0, cmpu64)
+ C(0xe559, CLGHSI, SIL, GIE, m1_64, i2_16u, 0, 0, 0, cmpu64)
+/* COMPARE LOGICAL RELATIVE LONG */
+ C(0xc60f, CLRL, RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu32)
+ C(0xc60a, CLGRL, RIL_b, GIE, r1_o, mri2_64, 0, 0, 0, cmpu64)
+ C(0xc60e, CLGFRL, RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu64)
+ C(0xc607, CLHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
+ C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
+
/* EXCLUSIVE OR */
C(0x1700, XR, RR_a, Z, r1, r2, new, r1_32, xor, nz32)
C(0xb9f7, XRK, RRF_a, DO, r2, r3, new, r1_32, xor, nz32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3fc8c45..01beb24 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1429,39 +1429,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg16(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x20: /* CG R1,D2(X2,B2) [RXY] */
- case 0x21: /* CLG R1,D2(X2,B2) */
- case 0x30: /* CGF R1,D2(X2,B2) [RXY] */
- case 0x31: /* CLGF R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- switch (op) {
- case 0x20:
- case 0x21:
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- break;
- case 0x30:
- tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
- break;
- case 0x31:
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- break;
- default:
- tcg_abort();
- }
- switch (op) {
- case 0x20:
- case 0x30:
- cmp_s64(s, regs[r1], tmp2);
- break;
- case 0x21:
- case 0x31:
- cmp_u64(s, regs[r1], tmp2);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i64(tmp2);
- break;
case 0x24: /* stg r1, d2(x2,b2) */
tcg_gen_qemu_st64(regs[r1], addr, get_mem_index(s));
break;
@@ -1875,17 +1842,6 @@ do_mh:
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x55: /* CLIY D1(B1),I2 [SIY] */
- tmp3 = get_address(s, 0, b2, d2); /* SIY -> this is the 1st operand */
- tmp = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_qemu_ld8u(tmp, tmp3, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp);
- cmp_u32c(s, tmp32_1, (r1 << 4) | r3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp3);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x80: /* ICMH R1,M3,D2(B2) [RSY] */
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
@@ -2259,16 +2215,6 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
store_reg(r1, tmp);
tcg_temp_free_i64(tmp);
break;
- case 0xe: /* CHI R1,I2 [RI] */
- tmp32_1 = load_reg32(r1);
- cmp_s32c(s, tmp32_1, i2);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0xf: /* CGHI R1,I2 [RI] */
- tmp = load_reg(r1);
- cmp_s64c(s, tmp, i2);
- tcg_temp_free_i64(tmp);
- break;
default:
LOG_DISAS("illegal a7 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -3036,28 +2982,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x20: /* CGR R1,R2 [RRE] */
- case 0x30: /* CGFR R1,R2 [RRE] */
- tmp2 = load_reg(r2);
- if (op == 0x30) {
- tcg_gen_ext32s_i64(tmp2, tmp2);
- }
- tmp = load_reg(r1);
- cmp_s64(s, tmp, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- case 0x21: /* CLGR R1,R2 [RRE] */
- case 0x31: /* CLGFR R1,R2 [RRE] */
- tmp2 = load_reg(r2);
- if (op == 0x31) {
- tcg_gen_ext32u_i64(tmp2, tmp2);
- }
- tmp = load_reg(r1);
- cmp_u64(s, tmp, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x26: /* LBR R1,R2 [RRE] */
tmp32_1 = load_reg32(r2);
tcg_gen_ext8s_i32(tmp32_1, tmp32_1);
@@ -3285,39 +3209,6 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
}
}
-static void disas_c2(DisasContext *s, int op, int r1, int i2)
-{
- TCGv_i64 tmp;
- TCGv_i32 tmp32_1;
-
- switch (op) {
- case 0xc: /* CGFI R1,I2 [RIL] */
- tmp = load_reg(r1);
- cmp_s64c(s, tmp, (int64_t)i2);
- tcg_temp_free_i64(tmp);
- break;
- case 0xe: /* CLGFI R1,I2 [RIL] */
- tmp = load_reg(r1);
- cmp_u64c(s, tmp, (uint64_t)(uint32_t)i2);
- tcg_temp_free_i64(tmp);
- break;
- case 0xd: /* CFI R1,I2 [RIL] */
- tmp32_1 = load_reg32(r1);
- cmp_s32c(s, tmp32_1, i2);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0xf: /* CLFI R1,I2 [RIL] */
- tmp32_1 = load_reg32(r1);
- cmp_u32c(s, tmp32_1, i2);
- tcg_temp_free_i32(tmp32_1);
- break;
- default:
- LOG_DISAS("illegal c2 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- break;
- }
-}
-
static void disas_s390_insn(DisasContext *s)
{
TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -3459,20 +3350,6 @@ static void disas_s390_insn(DisasContext *s)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x15: /* CLR R1,R2 [RR] */
- case 0x19: /* CR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r2);
- if (opc == 0x15) {
- cmp_u32(s, tmp32_1, tmp32_2);
- } else {
- cmp_s32(s, tmp32_1, tmp32_2);
- }
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x1d: /* DR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3606,20 +3483,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x49: /* CH R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- cmp_s32(s, tmp32_1, tmp32_2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x4d: /* BAS R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3650,20 +3513,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x55: /* CL R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tmp32_2 = load_reg32(r1);
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- cmp_u32(s, tmp32_2, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x58: /* l r1, d2(x2, b2) */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3676,20 +3525,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x59: /* C R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tmp32_2 = load_reg32(r1);
- tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- cmp_s32(s, tmp32_2, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x5d: /* D R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3943,15 +3778,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x95: /* CLI D1(B1),I2 [SI] */
- insn = ld_code4(s->pc);
- tmp = decode_si(s, insn, &i2, &b1, &d1);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
- cmp_u64c(s, tmp2, i2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x9a: /* LAM R1,R3,D2(B2) [RS] */
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -4220,7 +4046,6 @@ static void disas_s390_insn(DisasContext *s)
}
break;
case 0xc0:
- case 0xc2:
insn = ld_code6(s->pc);
r1 = (insn >> 36) & 0xf;
op = (insn >> 32) & 0xf;
@@ -4229,9 +4054,6 @@ static void disas_s390_insn(DisasContext *s)
case 0xc0:
disas_c0(s, op, r1, i2);
break;
- case 0xc2:
- disas_c2(s, op, r1, i2);
- break;
default:
tcg_abort();
}
@@ -4661,6 +4483,26 @@ static void cout_addu64(DisasContext *s, DisasOps *o)
gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
}
+static void cout_cmps32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
+}
+
+static void cout_cmps64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
+}
+
+static void cout_cmpu32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
+}
+
+static void cout_cmpu64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
+}
+
static void cout_nz32(DisasContext *s, DisasOps *o)
{
tcg_gen_ext32u_i64(cc_dst, o->out);
@@ -4800,6 +4642,27 @@ static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
}
+static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in1_la1(s, f, o);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
+}
+
+static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in1_la1(s, f, o);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
+}
+
+static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in1_la1(s, f, o);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
+}
+
static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
{
in1_la1(s, f, o);
@@ -4858,6 +4721,11 @@ static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
}
+static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
+}
+
static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
{
in2_a2(s, f, o);
@@ -4882,11 +4750,45 @@ static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
}
+static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_ri2(s, f, o);
+ tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_ri2(s, f, o);
+ tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_ri2(s, f, o);
+ tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_ri2(s, f, o);
+ tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
+}
+
static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_const_i64(get_field(f, i2));
}
+static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
+}
+
+static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
+}
+
static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 017/126] target-s390: Convert LOAD, LOAD LOGICAL
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (15 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 016/126] target-s390: Convert COMPARE, COMPARE LOGICAL Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 018/126] target-s390: Convert LOAD ADDRESS Richard Henderson
` (84 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 20 +++++++++
target-s390x/translate.c | 100 ++++++++++++++++++---------------------------
2 files changed, 60 insertions(+), 60 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 45c3913..2590f83 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -107,6 +107,26 @@
C(0xb9e7, XGRK, RRF_a, DO, r2, r3, r1, 0, xor, nz64)
C(0xe382, XG, RXY_a, Z, r1, m2_64, r1, 0, xor, nz64)
+/* LOAD */
+ C(0x1800, LR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, 0)
+ C(0x5800, L, RX_a, Z, 0, a2, new, r1_32, ld32s, 0)
+ C(0xe358, LY, RXY_a, Z, 0, a2, new, r1_32, ld32s, 0)
+ C(0xb904, LGR, RRE, Z, 0, r2_o, 0, r1, mov2, 0)
+ C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0)
+ C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0)
+ C(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0)
+/* LOAD IMMEDIATE */
+ C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
+/* LOAD RELATIVE LONG */
+ C(0xc40d, LRL, RIL_b, GIE, 0, ri2, new, r1_32, ld32s, 0)
+ C(0xc408, LGRL, RIL_b, GIE, 0, ri2, r1, 0, ld64, 0)
+ C(0xc40c, LGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32s, 0)
+/* LOAD LOGICAL */
+ C(0xb916, LLGFR, RRE, Z, 0, r2_32u, 0, r1, mov2, 0)
+ C(0xe316, LLGF, RXY_a, Z, 0, a2, r1, 0, ld32u, 0)
+/* LOAD LOGICAL RELATIVE LONG */
+ C(0xc40e, LLGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0)
+
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 01beb24..82dda8b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1345,7 +1345,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
addr = get_address(s, x2, b2, d2);
switch (op) {
case 0x2: /* LTG R1,D2(X2,B2) [RXY] */
- case 0x4: /* lg r1,d2(x2,b2) */
+ case 0x4: /* LG r1,d2(x2,b2) */
tcg_gen_qemu_ld64(regs[r1], addr, get_mem_index(s));
if (op == 0x2) {
set_cc_s64(s, regs[r1]);
@@ -1386,16 +1386,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0x14: /* LGF R1,D2(X2,B2) [RXY] */
- case 0x16: /* LLGF R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- if (op == 0x14) {
- tcg_gen_ext32s_i64(tmp2, tmp2);
- }
- store_reg(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
case 0x15: /* LGH R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
@@ -1449,12 +1439,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
tcg_temp_free_i64(tmp2);
break;
- case 0x58: /* LY R1,D2(X2,B2) [RXY] */
- tmp3 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(tmp3, addr, get_mem_index(s));
- store_reg32_i64(r1, tmp3);
- tcg_temp_free_i64(tmp3);
- break;
case 0x71: /* LAY R1,D2(X2,B2) [RXY] */
store_reg(r1, addr);
break;
@@ -2919,9 +2903,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
}
tcg_temp_free_i64(tmp);
break;
- case 0x4: /* LGR R1,R2 [RRE] */
- store_reg(r1, regs[r2]);
- break;
case 0x6: /* LGBR R1,R2 [RRE] */
tmp2 = load_reg(r2);
tcg_gen_ext8s_i64(tmp2, tmp2);
@@ -2948,22 +2929,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i64(tmp3);
break;
- case 0x14: /* LGFR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tmp = tcg_temp_new_i64();
- tcg_gen_ext_i32_i64(tmp, tmp32_1);
- store_reg(r1, tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
- case 0x16: /* LLGFR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tmp = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(tmp, tmp32_1);
- store_reg(r1, tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
case 0x17: /* LLGTR R1,R2 [RRE] */
tmp32_1 = load_reg32(r2);
tmp = tcg_temp_new_i64();
@@ -3123,11 +3088,6 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
store_reg(r1, tmp);
tcg_temp_free_i64(tmp);
break;
- case 0x1: /* LGFI R1,I2 [RIL] */
- tmp = tcg_const_i64((int64_t)i2);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0x4: /* BRCL M1,I2 [RIL] */
/* m1 & (1 << (3 - cc)) */
tmp32_1 = tcg_const_i32(3);
@@ -3343,13 +3303,6 @@ static void disas_s390_insn(DisasContext *s)
set_cc_comp32(s, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x18: /* LR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r2);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x1d: /* DR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3513,18 +3466,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x58: /* l r1, d2(x2, b2) */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x5d: /* D R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4427,6 +4368,33 @@ static ExitStatus op_and(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
+{
+ o->out = o->in2;
+ o->g_out = o->g_in2;
+ TCGV_UNUSED_I64(o->in2);
+ o->g_in2 = false;
+ return NO_EXIT;
+}
+
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
{
tcg_gen_mul_i64(o->out, o->in1, o->in2);
@@ -4566,6 +4534,11 @@ static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
generally handled by having a "prep" generator install the TCG global
as the destination of the operation. */
+static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ store_reg(get_field(f, r1), o->out);
+}
+
static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_reg32_i64(get_field(f, r1), o->out);
@@ -4580,6 +4553,13 @@ static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
store_reg32_i64(r1, o->out);
}
+static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ if (get_field(f, r1) != get_field(f, r2)) {
+ store_reg32_i64(get_field(f, r1), o->out);
+ }
+}
+
static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 018/126] target-s390: Convert LOAD ADDRESS
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (16 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 017/126] target-s390: Convert LOAD, LOAD LOGICAL Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 019/126] target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD Richard Henderson
` (83 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 5 +++++
target-s390x/translate.c | 14 --------------
2 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2590f83..0829368 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -121,6 +121,11 @@
C(0xc40d, LRL, RIL_b, GIE, 0, ri2, new, r1_32, ld32s, 0)
C(0xc408, LGRL, RIL_b, GIE, 0, ri2, r1, 0, ld64, 0)
C(0xc40c, LGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32s, 0)
+/* LOAD ADDRESS */
+ C(0x4100, LA, RX_a, Z, 0, a2, 0, r1, mov2, 0)
+ C(0xe371, LAY, RXY_a, LD, 0, a2, 0, r1, mov2, 0)
+/* LOAD ADDRESS RELATIVE LONG */
+ C(0xc000, LARL, RIL_b, Z, 0, ri2, 0, r1, mov2, 0)
/* LOAD LOGICAL */
C(0xb916, LLGFR, RRE, Z, 0, r2_32u, 0, r1, mov2, 0)
C(0xe316, LLGF, RXY_a, Z, 0, a2, r1, 0, ld32u, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 82dda8b..8fafcff 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1439,9 +1439,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
tcg_temp_free_i64(tmp2);
break;
- case 0x71: /* LAY R1,D2(X2,B2) [RXY] */
- store_reg(r1, addr);
- break;
case 0x72: /* STCY R1,D2(X2,B2) [RXY] */
tmp32_1 = load_reg32(r1);
tmp2 = tcg_temp_new_i64();
@@ -3083,11 +3080,6 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
LOG_DISAS("disas_c0: op 0x%x r1 %d i2 %d\n", op, r1, i2);
switch (op) {
- case 0: /* larl r1, i2 */
- tmp = tcg_const_i64(target);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0x4: /* BRCL M1,I2 [RIL] */
/* m1 & (1 << (3 - cc)) */
tmp32_1 = tcg_const_i32(3);
@@ -3360,12 +3352,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x41: /* la */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- store_reg(r1, tmp); /* FIXME: 31/24-bit addressing */
- tcg_temp_free_i64(tmp);
- break;
case 0x42: /* STC R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 019/126] target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (17 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 018/126] target-s390: Convert LOAD ADDRESS Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 020/126] target-s390: Convert LOAD AND TEST Richard Henderson
` (82 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 30 +++++++++
target-s390x/translate.c | 157 ++++++++++++++-------------------------------
2 files changed, 78 insertions(+), 109 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 0829368..6b08340 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -126,11 +126,41 @@
C(0xe371, LAY, RXY_a, LD, 0, a2, 0, r1, mov2, 0)
/* LOAD ADDRESS RELATIVE LONG */
C(0xc000, LARL, RIL_b, Z, 0, ri2, 0, r1, mov2, 0)
+/* LOAD BYTE */
+ C(0xb926, LBR, RRE, EI, 0, r2_8s, 0, r1_32, mov2, 0)
+ C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0)
+ C(0xe376, LB, RXY_a, LD, 0, a2, new, r1_32, ld8s, 0)
+ C(0xe377, LGB, RXY_a, LD, 0, a2, r1, 0, ld8s, 0)
+/* LOAD HALFWORD */
+ C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
+ C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
+ C(0x4800, LH, RX_a, Z, 0, a2, new, r1_32, ld16s, 0)
+ C(0xe378, LHY, RXY_a, LD, 0, a2, new, r1_32, ld16s, 0)
+ C(0xe315, LGH, RXY_a, Z, 0, a2, r1, 0, ld16s, 0)
+/* LOAD HALFWORD IMMEDIATE */
+ C(0xa708, LHI, RI_a, Z, 0, i2, 0, r1_32, mov2, 0)
+ C(0xa709, LGHI, RI_a, Z, 0, i2, 0, r1, mov2, 0)
+/* LOAD HALFWORD RELATIVE LONG */
+ C(0xc405, LHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16s, 0)
+ C(0xc404, LGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16s, 0)
/* LOAD LOGICAL */
C(0xb916, LLGFR, RRE, Z, 0, r2_32u, 0, r1, mov2, 0)
C(0xe316, LLGF, RXY_a, Z, 0, a2, r1, 0, ld32u, 0)
/* LOAD LOGICAL RELATIVE LONG */
C(0xc40e, LLGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0)
+/* LOAD LOGICAL CHARACTER */
+ C(0xb994, LLCR, RRE, EI, 0, r2_8u, 0, r1_32, mov2, 0)
+ C(0xb984, LLGCR, RRE, EI, 0, r2_8u, 0, r1, mov2, 0)
+ C(0xe394, LLC, RXY_a, EI, 0, a2, new, r1_32, ld8u, 0)
+ C(0xe390, LLGC, RXY_a, Z, 0, a2, r1, 0, ld8u, 0)
+/* LOAD LOGICAL HALFWORD */
+ C(0xb995, LLHR, RRE, EI, 0, r2_16u, 0, r1_32, mov2, 0)
+ C(0xb985, LLGHR, RRE, EI, 0, r2_16u, 0, r1, mov2, 0)
+ C(0xe395, LLH, RXY_a, EI, 0, a2, new, r1_32, ld16u, 0)
+ C(0xe391, LLGH, RXY_a, Z, 0, a2, r1, 0, ld16u, 0)
+/* LOAD LOGICAL HALFWORD RELATIVE LONG */
+ C(0xc402, LLHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16u, 0)
+ C(0xc406, LLGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16u, 0)
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8fafcff..e9c9f34 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1386,12 +1386,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0x15: /* LGH R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
- store_reg(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
case 0x17: /* LLGT R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
@@ -1453,30 +1447,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg8(r1, tmp3);
tcg_temp_free_i64(tmp3);
break;
- case 0x76: /* LB R1,D2(X2,B2) [RXY] */
- case 0x77: /* LGB R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld8s(tmp2, addr, get_mem_index(s));
- switch (op) {
- case 0x76:
- tcg_gen_ext8s_i64(tmp2, tmp2);
- store_reg32_i64(r1, tmp2);
- break;
- case 0x77:
- tcg_gen_ext8s_i64(tmp2, tmp2);
- store_reg(r1, tmp2);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i64(tmp2);
- break;
- case 0x78: /* LHY R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
case 0x87: /* DLG R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
tmp32_1 = tcg_const_i32(r1);
@@ -1512,24 +1482,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x90: /* LLGC R1,D2(X2,B2) [RXY] */
- tcg_gen_qemu_ld8u(regs[r1], addr, get_mem_index(s));
- break;
- case 0x91: /* LLGH R1,D2(X2,B2) [RXY] */
- tcg_gen_qemu_ld16u(regs[r1], addr, get_mem_index(s));
- break;
- case 0x94: /* LLC R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld8u(tmp2, addr, get_mem_index(s));
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
- case 0x95: /* LLH R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
case 0x97: /* DL R1,D2(X2,B2) [RXY] */
/* reg(r1) = reg(r1, r1+1) % ld32(addr) */
/* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
@@ -2186,16 +2138,6 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
s->is_jmp = DISAS_TB_JUMP;
tcg_temp_free_i64(tmp);
break;
- case 0x8: /* lhi r1, i2 */
- tmp32_1 = tcg_const_i32(i2);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x9: /* lghi r1, i2 */
- tmp = tcg_const_i64(i2);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
default:
LOG_DISAS("illegal a7 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2900,12 +2842,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
}
tcg_temp_free_i64(tmp);
break;
- case 0x6: /* LGBR R1,R2 [RRE] */
- tmp2 = load_reg(r2);
- tcg_gen_ext8s_i64(tmp2, tmp2);
- store_reg(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
case 0xd: /* DSGR R1,R2 [RRE] */
case 0x1d: /* DSGFR R1,R2 [RRE] */
tmp = load_reg(r1 + 1);
@@ -2944,18 +2880,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x26: /* LBR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tcg_gen_ext8s_i32(tmp32_1, tmp32_1);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x27: /* LHR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tcg_gen_ext16s_i32(tmp32_1, tmp32_1);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x83: /* FLOGR R1,R2 [RRE] */
tmp = load_reg(r2);
tmp32_1 = tcg_const_i32(r1);
@@ -2964,18 +2888,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x84: /* LLGCR R1,R2 [RRE] */
- tmp = load_reg(r2);
- tcg_gen_andi_i64(tmp, tmp, 0xff);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0x85: /* LLGHR R1,R2 [RRE] */
- tmp = load_reg(r2);
- tcg_gen_andi_i64(tmp, tmp, 0xffff);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0x87: /* DLGR R1,R2 [RRE] */
tmp32_1 = tcg_const_i32(r1);
tmp = load_reg(r2);
@@ -3010,18 +2922,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x94: /* LLCR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tcg_gen_andi_i32(tmp32_1, tmp32_1, 0xff);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x95: /* LLHR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tcg_gen_andi_i32(tmp32_1, tmp32_1, 0xffff);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x97: /* DLR R1,R2 [RRE] */
/* reg(r1) = reg(r1, r1+1) % reg(r2) */
/* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
@@ -3413,15 +3313,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
s->is_jmp = DISAS_TB_JUMP;
break;
- case 0x48: /* LH R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
- store_reg32_i64(r1, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x4d: /* BAS R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4354,6 +4245,30 @@ static ExitStatus op_and(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
{
tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
@@ -4664,6 +4579,30 @@ static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_in2 = true;
}
+static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
+}
+
static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_reg(get_field(f, r3));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 020/126] target-s390: Convert LOAD AND TEST
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (18 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 019/126] target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 021/126] target-s390: Convert LOAD LOGICAL IMMEDIATE Richard Henderson
` (81 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 7 +++++++
target-s390x/translate.c | 37 ++++++++++---------------------------
2 files changed, 17 insertions(+), 27 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6b08340..06d0ad8 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -126,6 +126,13 @@
C(0xe371, LAY, RXY_a, LD, 0, a2, 0, r1, mov2, 0)
/* LOAD ADDRESS RELATIVE LONG */
C(0xc000, LARL, RIL_b, Z, 0, ri2, 0, r1, mov2, 0)
+/* LOAD AND TEST */
+ C(0x1200, LTR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, s32)
+ C(0xb902, LTGR, RRE, Z, 0, r2_o, 0, r1, mov2, s64)
+ C(0xb912, LTGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, s64)
+ C(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64)
+ C(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64)
+ C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64)
/* LOAD BYTE */
C(0xb926, LBR, RRE, EI, 0, r2_8s, 0, r1_32, mov2, 0)
C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e9c9f34..1c83009 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1344,23 +1344,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
op, r1, x2, b2, d2);
addr = get_address(s, x2, b2, d2);
switch (op) {
- case 0x2: /* LTG R1,D2(X2,B2) [RXY] */
- case 0x4: /* LG r1,d2(x2,b2) */
- tcg_gen_qemu_ld64(regs[r1], addr, get_mem_index(s));
- if (op == 0x2) {
- set_cc_s64(s, regs[r1]);
- }
- break;
- case 0x12: /* LT R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- store_reg32(r1, tmp32_1);
- set_cc_s32(s, tmp32_1);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0xd: /* DSG R1,D2(X2,B2) [RXY] */
case 0x1d: /* DSGF R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
@@ -3176,16 +3159,6 @@ static void disas_s390_insn(DisasContext *s)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x12: /* LTR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r2);
- if (r1 != r2) {
- store_reg32(r1, tmp32_1);
- }
- set_cc_s32(s, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x13: /* LCR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -4383,6 +4356,16 @@ static void cout_nz64(DisasContext *s, DisasOps *o)
gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
}
+static void cout_s32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
+}
+
+static void cout_s64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
+}
+
static void cout_subs32(DisasContext *s, DisasOps *o)
{
gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 021/126] target-s390: Convert LOAD LOGICAL IMMEDIATE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (19 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 020/126] target-s390: Convert LOAD AND TEST Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 022/126] target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE Richard Henderson
` (80 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 7 +++++++
target-s390x/translate.c | 42 ++++++++++++------------------------------
2 files changed, 19 insertions(+), 30 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 06d0ad8..9433d3d 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -168,6 +168,13 @@
/* LOAD LOGICAL HALFWORD RELATIVE LONG */
C(0xc402, LLHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16u, 0)
C(0xc406, LLGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16u, 0)
+/* LOAD LOGICAL IMMEDATE */
+ D(0xc00e, LLIHF, RIL_a, EI, 0, i2_32u_shl, 0, r1, mov2, 0, 32)
+ D(0xc00f, LLILF, RIL_a, EI, 0, i2_32u_shl, 0, r1, mov2, 0, 0)
+ D(0xa50c, LLIHH, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 48)
+ D(0xa50d, LLIHL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 32)
+ D(0xa50e, LLILH, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 16)
+ D(0xa50f, LLILL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 0)
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1c83009..8233bed 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2026,26 +2026,6 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2)
tcg_temp_free_i32(tmp32);
tcg_temp_free_i64(tmp);
break;
- case 0xc: /* LLIHH R1,I2 [RI] */
- tmp = tcg_const_i64( ((uint64_t)i2) << 48 );
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0xd: /* LLIHL R1,I2 [RI] */
- tmp = tcg_const_i64( ((uint64_t)i2) << 32 );
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0xe: /* LLILH R1,I2 [RI] */
- tmp = tcg_const_i64( ((uint64_t)i2) << 16 );
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0xf: /* LLILL R1,I2 [RI] */
- tmp = tcg_const_i64(i2);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
default:
LOG_DISAS("illegal a5 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -3027,16 +3007,6 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32_1);
break;
- case 0xe: /* LLIHF R1,I2 [RIL] */
- tmp = tcg_const_i64(((uint64_t)(uint32_t)i2) << 32);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0xf: /* LLILF R1,I2 [RIL] */
- tmp = tcg_const_i64((uint32_t)i2);
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
default:
LOG_DISAS("illegal c0 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -4682,6 +4652,18 @@ static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
}
+static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ uint64_t i2 = (uint16_t)get_field(f, i2);
+ o->in2 = tcg_const_i64(i2 << s->insn->data);
+}
+
+static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ uint64_t i2 = (uint32_t)get_field(f, i2);
+ o->in2 = tcg_const_i64(i2 << s->insn->data);
+}
+
/* ====================================================================== */
/* Find opc within the table of insns. This is formulated as a switch
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 022/126] target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (20 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 021/126] target-s390: Convert LOAD LOGICAL IMMEDIATE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 023/126] target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE Richard Henderson
` (79 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 12 ++++
target-s390x/translate.c | 142 +++++++++++++++------------------------------
2 files changed, 60 insertions(+), 94 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9433d3d..29919e4 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -138,6 +138,10 @@
C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0)
C(0xe376, LB, RXY_a, LD, 0, a2, new, r1_32, ld8s, 0)
C(0xe377, LGB, RXY_a, LD, 0, a2, r1, 0, ld8s, 0)
+/* LOAD COMPLEMENT */
+ C(0x1300, LCR, RR_a, Z, 0, r2, new, r1_32, neg, neg32)
+ C(0xb903, LCGR, RRE, Z, 0, r2, r1, 0, neg, neg64)
+ C(0xb913, LCGFR, RRE, Z, 0, r2_32s, r1, 0, neg, neg64)
/* LOAD HALFWORD */
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
@@ -175,6 +179,14 @@
D(0xa50d, LLIHL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 32)
D(0xa50e, LLILH, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 16)
D(0xa50f, LLILL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 0)
+/* LOAD NEGATIVE */
+ C(0x1100, LNR, RR_a, Z, 0, r2_32s, new, r1_32, nabs, nabs32)
+ C(0xb901, LNGR, RRE, Z, 0, r2, r1, 0, nabs, nabs64)
+ C(0xb911, LNGFR, RRE, Z, 0, r2_32s, r1, 0, nabs, nabs64)
+/* LOAD POSITIVE */
+ C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32)
+ C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
+ C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8233bed..865b5fc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -568,42 +568,12 @@ static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
gen_op_update3_cc_i64(s, CC_OP_ADDU_64, v1, v2, vr);
}
-static void set_cc_abs64(DisasContext *s, TCGv_i64 v1)
-{
- gen_op_update1_cc_i64(s, CC_OP_ABS_64, v1);
-}
-
-static void set_cc_nabs64(DisasContext *s, TCGv_i64 v1)
-{
- gen_op_update1_cc_i64(s, CC_OP_NABS_64, v1);
-}
-
static void set_cc_addu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
TCGv_i32 vr)
{
gen_op_update3_cc_i32(s, CC_OP_ADDU_32, v1, v2, vr);
}
-static void set_cc_abs32(DisasContext *s, TCGv_i32 v1)
-{
- gen_op_update1_cc_i32(s, CC_OP_ABS_32, v1);
-}
-
-static void set_cc_nabs32(DisasContext *s, TCGv_i32 v1)
-{
- gen_op_update1_cc_i32(s, CC_OP_NABS_32, v1);
-}
-
-static void set_cc_comp32(DisasContext *s, TCGv_i32 v1)
-{
- gen_op_update1_cc_i32(s, CC_OP_COMP_32, v1);
-}
-
-static void set_cc_comp64(DisasContext *s, TCGv_i64 v1)
-{
- gen_op_update1_cc_i64(s, CC_OP_COMP_64, v1);
-}
-
static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
{
gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
@@ -2768,43 +2738,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x0: /* LPGR R1,R2 [RRE] */
- case 0x1: /* LNGR R1,R2 [RRE] */
- case 0x2: /* LTGR R1,R2 [RRE] */
- case 0x3: /* LCGR R1,R2 [RRE] */
- case 0x10: /* LPGFR R1,R2 [RRE] */
- case 0x11: /* LNFGR R1,R2 [RRE] */
- case 0x12: /* LTGFR R1,R2 [RRE] */
- case 0x13: /* LCGFR R1,R2 [RRE] */
- if (op & 0x10) {
- tmp = load_reg32_i64(r2);
- } else {
- tmp = load_reg(r2);
- }
- switch (op & 0xf) {
- case 0x0: /* LP?GR */
- set_cc_abs64(s, tmp);
- gen_helper_abs_i64(tmp, tmp);
- store_reg(r1, tmp);
- break;
- case 0x1: /* LN?GR */
- set_cc_nabs64(s, tmp);
- gen_helper_nabs_i64(tmp, tmp);
- store_reg(r1, tmp);
- break;
- case 0x2: /* LT?GR */
- if (r1 != r2) {
- store_reg(r1, tmp);
- }
- set_cc_s64(s, tmp);
- break;
- case 0x3: /* LC?GR */
- tcg_gen_neg_i64(regs[r1], tmp);
- set_cc_comp64(s, regs[r1]);
- break;
- }
- tcg_temp_free_i64(tmp);
- break;
case 0xd: /* DSGR R1,R2 [RRE] */
case 0x1d: /* DSGFR R1,R2 [RRE] */
tmp = load_reg(r1 + 1);
@@ -3111,33 +3044,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x10: /* LPR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r2);
- set_cc_abs32(s, tmp32_1);
- gen_helper_abs_i32(tmp32_1, tmp32_1);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x11: /* LNR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r2);
- set_cc_nabs32(s, tmp32_1);
- gen_helper_nabs_i32(tmp32_1, tmp32_1);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x13: /* LCR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r2);
- tcg_gen_neg_i32(tmp32_1, tmp32_1);
- store_reg32(r1, tmp32_1);
- set_cc_comp32(s, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x1d: /* DR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -4176,6 +4082,12 @@ struct DisasInsn {
/* The operations. These perform the bulk of the work for any insn,
usually after the operands have been loaded and output initialized. */
+static ExitStatus op_abs(DisasContext *s, DisasOps *o)
+{
+ gen_helper_abs_i64(o->out, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_add(DisasContext *s, DisasOps *o)
{
tcg_gen_add_i64(o->out, o->in1, o->in2);
@@ -4252,6 +4164,18 @@ static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
+{
+ gen_helper_nabs_i64(o->out, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_neg(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_neg_i64(o->out, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_or(DisasContext *s, DisasOps *o)
{
tcg_gen_or_i64(o->out, o->in1, o->in2);
@@ -4275,6 +4199,16 @@ static ExitStatus op_xor(DisasContext *s, DisasOps *o)
the original inputs), update the various cc data structures in order to
be able to compute the new condition code. */
+static void cout_abs32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
+}
+
+static void cout_abs64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
+}
+
static void cout_adds32(DisasContext *s, DisasOps *o)
{
gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
@@ -4315,6 +4249,26 @@ static void cout_cmpu64(DisasContext *s, DisasOps *o)
gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
}
+static void cout_nabs32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
+}
+
+static void cout_nabs64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
+}
+
+static void cout_neg32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
+}
+
+static void cout_neg64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
+}
+
static void cout_nz32(DisasContext *s, DisasOps *o)
{
tcg_gen_ext32u_i64(cc_dst, o->out);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 023/126] target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (21 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 022/126] target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 024/126] target-s390: Convert STORE Richard Henderson
` (78 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 25 +++++
target-s390x/translate.c | 236 +++++++++++----------------------------------
2 files changed, 82 insertions(+), 179 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 29919e4..8e348b2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -49,6 +49,13 @@
C(0xb980, NGR, RRE, Z, r1, r2, r1, 0, and, nz64)
C(0xb9e4, NGRK, RRF_a, DO, r2, r3, r1, 0, and, nz64)
C(0xe380, NG, RXY_a, Z, r1, m2_64, r1, 0, and, nz64)
+/* AND IMMEDIATE */
+ D(0xc00a, NIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, andi, 0, 0x2020)
+ D(0xc00b, NILF, RIL_a, EI, r1_o, i2_32u, r1, 0, andi, 0, 0x2000)
+ D(0xa504, NIHH, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1030)
+ D(0xa505, NIHL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1020)
+ D(0xa506, NILH, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1010)
+ D(0xa507, NILL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
/* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
@@ -106,6 +113,17 @@
C(0xb982, XGR, RRE, Z, r1, r2, r1, 0, xor, nz64)
C(0xb9e7, XGRK, RRF_a, DO, r2, r3, r1, 0, xor, nz64)
C(0xe382, XG, RXY_a, Z, r1, m2_64, r1, 0, xor, nz64)
+/* EXCLUSIVE OR IMMEDIATE */
+ D(0xc006, XIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
+ D(0xc007, XILF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
+
+/* INSERT IMMEDIATE */
+ D(0xc008, IIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
+ D(0xc009, IILF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
+ D(0xa500, IIHH, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1030)
+ D(0xa501, IIHL, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1020)
+ D(0xa502, IILH, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1010)
+ D(0xa503, IILL, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1000)
/* LOAD */
C(0x1800, LR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, 0)
@@ -223,6 +241,13 @@
C(0xb981, OGR, RRE, Z, r1, r2, r1, 0, or, nz64)
C(0xb9e6, OGRK, RRF_a, DO, r2, r3, r1, 0, or, nz64)
C(0xe381, OG, RXY_a, Z, r1, m2_64, r1, 0, or, nz64)
+/* OR IMMEDIATE */
+ D(0xc00c, OIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, ori, 0, 0x2020)
+ D(0xc00d, OILF, RIL_a, EI, r1_o, i2_32u, r1, 0, ori, 0, 0x2000)
+ D(0xa508, OIHH, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1030)
+ D(0xa509, OIHL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1020)
+ D(0xa50a, OILH, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
+ D(0xa50b, OILL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
/* SUBTRACT */
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 865b5fc..ab8bcf9 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1869,140 +1869,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
tcg_temp_free_i64(addr);
}
-static void disas_a5(DisasContext *s, int op, int r1, int i2)
-{
- TCGv_i64 tmp, tmp2;
- TCGv_i32 tmp32;
- LOG_DISAS("disas_a5: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
- switch (op) {
- case 0x0: /* IIHH R1,I2 [RI] */
- tmp = tcg_const_i64(i2);
- tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 48, 16);
- tcg_temp_free_i64(tmp);
- break;
- case 0x1: /* IIHL R1,I2 [RI] */
- tmp = tcg_const_i64(i2);
- tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 32, 16);
- tcg_temp_free_i64(tmp);
- break;
- case 0x2: /* IILH R1,I2 [RI] */
- tmp = tcg_const_i64(i2);
- tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 16, 16);
- tcg_temp_free_i64(tmp);
- break;
- case 0x3: /* IILL R1,I2 [RI] */
- tmp = tcg_const_i64(i2);
- tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 0, 16);
- tcg_temp_free_i64(tmp);
- break;
- case 0x4: /* NIHH R1,I2 [RI] */
- case 0x8: /* OIHH R1,I2 [RI] */
- tmp = load_reg(r1);
- tmp32 = tcg_temp_new_i32();
- switch (op) {
- case 0x4:
- tmp2 = tcg_const_i64((((uint64_t)i2) << 48)
- | 0x0000ffffffffffffULL);
- tcg_gen_and_i64(tmp, tmp, tmp2);
- break;
- case 0x8:
- tmp2 = tcg_const_i64(((uint64_t)i2) << 48);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- break;
- default:
- tcg_abort();
- }
- store_reg(r1, tmp);
- tcg_gen_shri_i64(tmp2, tmp, 48);
- tcg_gen_trunc_i64_i32(tmp32, tmp2);
- set_cc_nz_u32(s, tmp32);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32);
- tcg_temp_free_i64(tmp);
- break;
- case 0x5: /* NIHL R1,I2 [RI] */
- case 0x9: /* OIHL R1,I2 [RI] */
- tmp = load_reg(r1);
- tmp32 = tcg_temp_new_i32();
- switch (op) {
- case 0x5:
- tmp2 = tcg_const_i64((((uint64_t)i2) << 32)
- | 0xffff0000ffffffffULL);
- tcg_gen_and_i64(tmp, tmp, tmp2);
- break;
- case 0x9:
- tmp2 = tcg_const_i64(((uint64_t)i2) << 32);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- break;
- default:
- tcg_abort();
- }
- store_reg(r1, tmp);
- tcg_gen_shri_i64(tmp2, tmp, 32);
- tcg_gen_trunc_i64_i32(tmp32, tmp2);
- tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
- set_cc_nz_u32(s, tmp32);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32);
- tcg_temp_free_i64(tmp);
- break;
- case 0x6: /* NILH R1,I2 [RI] */
- case 0xa: /* OILH R1,I2 [RI] */
- tmp = load_reg(r1);
- tmp32 = tcg_temp_new_i32();
- switch (op) {
- case 0x6:
- tmp2 = tcg_const_i64((((uint64_t)i2) << 16)
- | 0xffffffff0000ffffULL);
- tcg_gen_and_i64(tmp, tmp, tmp2);
- break;
- case 0xa:
- tmp2 = tcg_const_i64(((uint64_t)i2) << 16);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- break;
- default:
- tcg_abort();
- }
- store_reg(r1, tmp);
- tcg_gen_shri_i64(tmp, tmp, 16);
- tcg_gen_trunc_i64_i32(tmp32, tmp);
- tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
- set_cc_nz_u32(s, tmp32);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32);
- tcg_temp_free_i64(tmp);
- break;
- case 0x7: /* NILL R1,I2 [RI] */
- case 0xb: /* OILL R1,I2 [RI] */
- tmp = load_reg(r1);
- tmp32 = tcg_temp_new_i32();
- switch (op) {
- case 0x7:
- tmp2 = tcg_const_i64(i2 | 0xffffffffffff0000ULL);
- tcg_gen_and_i64(tmp, tmp, tmp2);
- break;
- case 0xb:
- tmp2 = tcg_const_i64(i2);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- break;
- default:
- tcg_abort();
- }
- store_reg(r1, tmp);
- tcg_gen_trunc_i64_i32(tmp32, tmp);
- tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
- set_cc_nz_u32(s, tmp32); /* signedness should not matter here */
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32);
- tcg_temp_free_i64(tmp);
- break;
- default:
- LOG_DISAS("illegal a5 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- return;
- }
-}
-
static void disas_a7(DisasContext *s, int op, int r1, int i2)
{
TCGv_i64 tmp, tmp2;
@@ -2902,44 +2768,6 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
gen_goto_tb(s, 0, target);
s->is_jmp = DISAS_TB_JUMP;
break;
- case 0x7: /* XILF R1,I2 [RIL] */
- case 0xb: /* NILF R1,I2 [RIL] */
- case 0xd: /* OILF R1,I2 [RIL] */
- tmp32_1 = load_reg32(r1);
- switch (op) {
- case 0x7:
- tcg_gen_xori_i32(tmp32_1, tmp32_1, (uint32_t)i2);
- break;
- case 0xb:
- tcg_gen_andi_i32(tmp32_1, tmp32_1, (uint32_t)i2);
- break;
- case 0xd:
- tcg_gen_ori_i32(tmp32_1, tmp32_1, (uint32_t)i2);
- break;
- default:
- tcg_abort();
- }
- store_reg32(r1, tmp32_1);
- set_cc_nz_u32(s, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x9: /* IILF R1,I2 [RIL] */
- tmp32_1 = tcg_const_i32((uint32_t)i2);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0xa: /* NIHF R1,I2 [RIL] */
- tmp = load_reg(r1);
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_andi_i64(tmp, tmp, (((uint64_t)((uint32_t)i2)) << 32)
- | 0xffffffffULL);
- store_reg(r1, tmp);
- tcg_gen_shri_i64(tmp, tmp, 32);
- tcg_gen_trunc_i64_i32(tmp32_1, tmp);
- set_cc_nz_u32(s, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- break;
default:
LOG_DISAS("illegal c0 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -3469,13 +3297,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xa5:
- insn = ld_code4(s->pc);
- r1 = (insn >> 20) & 0xf;
- op = (insn >> 16) & 0xf;
- i2 = insn & 0xffff;
- disas_a5(s, op, r1, i2);
- break;
case 0xa7:
insn = ld_code4(s->pc);
r1 = (insn >> 20) & 0xf;
@@ -4100,6 +3921,31 @@ static ExitStatus op_and(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_andi(DisasContext *s, DisasOps *o)
+{
+ int shift = s->insn->data & 0xff;
+ int size = s->insn->data >> 8;
+ uint64_t mask = ((1ull << size) - 1) << shift;
+
+ assert(!o->g_in2);
+ tcg_gen_shli_i64(o->in2, o->in2, shift);
+ tcg_gen_ori_i64(o->in2, o->in2, ~mask);
+ tcg_gen_and_i64(o->out, o->in1, o->in2);
+
+ /* Produce the CC from only the bits manipulated. */
+ tcg_gen_andi_i64(cc_dst, o->out, mask);
+ set_cc_nz_u64(s, cc_dst);
+ return NO_EXIT;
+}
+
+static ExitStatus op_insi(DisasContext *s, DisasOps *o)
+{
+ int shift = s->insn->data & 0xff;
+ int size = s->insn->data >> 8;
+ tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
+ return NO_EXIT;
+}
+
static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
{
tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
@@ -4182,6 +4028,22 @@ static ExitStatus op_or(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ori(DisasContext *s, DisasOps *o)
+{
+ int shift = s->insn->data & 0xff;
+ int size = s->insn->data >> 8;
+ uint64_t mask = ((1ull << size) - 1) << shift;
+
+ assert(!o->g_in2);
+ tcg_gen_shli_i64(o->in2, o->in2, shift);
+ tcg_gen_or_i64(o->out, o->in1, o->in2);
+
+ /* Produce the CC from only the bits manipulated. */
+ tcg_gen_andi_i64(cc_dst, o->out, mask);
+ set_cc_nz_u64(s, cc_dst);
+ return NO_EXIT;
+}
+
static ExitStatus op_sub(DisasContext *s, DisasOps *o)
{
tcg_gen_sub_i64(o->out, o->in1, o->in2);
@@ -4194,6 +4056,22 @@ static ExitStatus op_xor(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_xori(DisasContext *s, DisasOps *o)
+{
+ int shift = s->insn->data & 0xff;
+ int size = s->insn->data >> 8;
+ uint64_t mask = ((1ull << size) - 1) << shift;
+
+ assert(!o->g_in2);
+ tcg_gen_shli_i64(o->in2, o->in2, shift);
+ tcg_gen_xor_i64(o->out, o->in1, o->in2);
+
+ /* Produce the CC from only the bits manipulated. */
+ tcg_gen_andi_i64(cc_dst, o->out, mask);
+ set_cc_nz_u64(s, cc_dst);
+ return NO_EXIT;
+}
+
/* ====================================================================== */
/* The "Cc OUTput" generators. Given the generated output (and in some cases
the original inputs), update the various cc data structures in order to
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 024/126] target-s390: Convert STORE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (22 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 023/126] target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 025/126] target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW Richard Henderson
` (77 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 16 +++++++++++
target-s390x/translate.c | 67 +++++++++++++++++-----------------------------
2 files changed, 40 insertions(+), 43 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8e348b2..692795f 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -249,6 +249,22 @@
D(0xa50a, OILH, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
D(0xa50b, OILL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
+/* STORE */
+ C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0)
+ C(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0)
+ C(0xe324, STG, RXY_a, Z, r1_o, a2, 0, 0, st64, 0)
+/* STORE RELATIVE LONG */
+ C(0xc40f, STRL, RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0)
+ C(0xc40b, STGRL, RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0)
+/* STORE CHARACTER */
+ C(0x4200, STC, RX_a, Z, r1_o, a2, 0, 0, st8, 0)
+ C(0xe372, STCY, RXY_a, LD, r1_o, a2, 0, 0, st8, 0)
+/* STORE HALFWORD */
+ C(0x4000, STH, RX_a, Z, r1_o, a2, 0, 0, st16, 0)
+ C(0xe370, STHY, RXY_a, LD, r1_o, a2, 0, 0, st16, 0)
+/* STORE HALFWORD RELATIVE LONG */
+ C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
+
/* SUBTRACT */
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
C(0xb9f9, SRK, RRF_a, DO, r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ab8bcf9..cb82fdd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1366,9 +1366,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg16(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x24: /* stg r1, d2(x2,b2) */
- tcg_gen_qemu_st64(regs[r1], addr, get_mem_index(s));
- break;
case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
tmp32_1 = load_reg32(r1);
tmp2 = tcg_temp_new_i64();
@@ -1378,22 +1375,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
tcg_temp_free_i64(tmp2);
break;
- case 0x50: /* STY R1,D2(X2,B2) [RXY] */
- tmp32_1 = load_reg32(r1);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(tmp2, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
- tcg_temp_free_i64(tmp2);
- break;
- case 0x72: /* STCY R1,D2(X2,B2) [RXY] */
- tmp32_1 = load_reg32(r1);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_ext_i32_i64(tmp2, tmp32_1);
- tcg_gen_qemu_st8(tmp2, addr, get_mem_index(s));
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp2);
- break;
case 0x73: /* ICY R1,D2(X2,B2) [RXY] */
tmp3 = tcg_temp_new_i64();
tcg_gen_qemu_ld8u(tmp3, addr, get_mem_index(s));
@@ -2921,22 +2902,6 @@ static void disas_s390_insn(DisasContext *s)
store_freg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x40: /* STH R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = load_reg(r1);
- tcg_gen_qemu_st16(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- case 0x42: /* STC R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = load_reg(r1);
- tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x43: /* IC R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3012,14 +2977,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x50: /* st r1, d2(x2, b2) */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = load_reg(r1);
- tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x5d: /* D R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4044,6 +4001,30 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_st8(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_st16(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_st32(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
+static ExitStatus op_st64(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
+ return NO_EXIT;
+}
+
static ExitStatus op_sub(DisasContext *s, DisasOps *o)
{
tcg_gen_sub_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 025/126] target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (23 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 024/126] target-s390: Convert STORE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 026/126] target-s390: Convert BRANCH AND SAVE Richard Henderson
` (76 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
I'm resonably certain that the carry/borrow-out condition for both
helpers was incorrect, failing to take into account the carry-in.
Adding the new CC_OP codes also allows removing the awkward interface
we used for the slb helpers.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 108 ++++++++++++++++++-------
target-s390x/cpu.h | 8 ++
target-s390x/helper.h | 4 -
target-s390x/insn-data.def | 10 +++
target-s390x/int_helper.c | 43 ----------
target-s390x/translate.c | 191 +++++++++++++++------------------------------
6 files changed, 157 insertions(+), 207 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 19ef145..880e3b2 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -146,22 +146,21 @@ static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
}
}
-static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
- uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
+ uint64_t a2, uint64_t ar)
{
- if (ar == 0) {
- if (a1) {
- return 2;
- } else {
- return 0;
- }
- } else {
- if (ar < a1 || ar < a2) {
- return 3;
- } else {
- return 1;
- }
- }
+ return (ar != 0) + 2 * (ar < a1);
+}
+
+static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
+ uint64_t a2, uint64_t ar)
+{
+ /* Recover a2 + carry_in. */
+ uint64_t a2c = ar - a1;
+ /* Check for a2+carry_in overflow, then a1+a2c overflow. */
+ int carry_out = (a2c < a2) || (ar < a1);
+
+ return (ar != 0) + 2 * carry_out;
}
static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
@@ -194,6 +193,25 @@ static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
}
}
+static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
+ uint64_t a2, uint64_t ar)
+{
+ /* We had borrow-in if normal subtraction isn't equal. */
+ int borrow_in = ar - (a1 - a2);
+ int borrow_out;
+
+ /* If a2 was ULONG_MAX, and borrow_in, then a2 is logically 65 bits,
+ and we must have had borrow out. */
+ if (borrow_in && a2 == (uint64_t)-1) {
+ borrow_out = 1;
+ } else {
+ a2 += borrow_in;
+ borrow_out = (a2 > a1);
+ }
+
+ return (ar != 0) + 2 * !borrow_out;
+}
+
static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
{
if ((uint64_t)dst == 0x8000000000000000ULL) {
@@ -240,22 +258,21 @@ static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
}
}
-static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
- uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
+ uint32_t a2, uint32_t ar)
{
- if (ar == 0) {
- if (a1) {
- return 2;
- } else {
- return 0;
- }
- } else {
- if (ar < a1 || ar < a2) {
- return 3;
- } else {
- return 1;
- }
- }
+ return (ar != 0) + 2 * (ar < a1);
+}
+
+static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
+ uint32_t a2, uint32_t ar)
+{
+ /* Recover a2 + carry_in. */
+ uint32_t a2c = ar - a1;
+ /* Check for a2+carry_in overflow, then a1+a2c overflow. */
+ int carry_out = (a2c < a2) || (ar < a1);
+
+ return (ar != 0) + 2 * carry_out;
}
static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
@@ -288,6 +305,25 @@ static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
}
}
+static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
+ uint32_t a2, uint32_t ar)
+{
+ /* We had borrow-in if normal subtraction isn't equal. */
+ int borrow_in = ar - (a1 - a2);
+ int borrow_out;
+
+ /* If a2 was UINT_MAX, and borrow_in, then a2 is logically 65 bits,
+ and we must have had borrow out. */
+ if (borrow_in && a2 == (uint32_t)-1) {
+ borrow_out = 1;
+ } else {
+ a2 += borrow_in;
+ borrow_out = (a2 > a1);
+ }
+
+ return (ar != 0) + 2 * !borrow_out;
+}
+
static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
{
if ((uint32_t)dst == 0x80000000UL) {
@@ -426,12 +462,18 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_ADDU_64:
r = cc_calc_addu_64(env, src, dst, vr);
break;
+ case CC_OP_ADDC_64:
+ r = cc_calc_addc_64(env, src, dst, vr);
+ break;
case CC_OP_SUB_64:
r = cc_calc_sub_64(env, src, dst, vr);
break;
case CC_OP_SUBU_64:
r = cc_calc_subu_64(env, src, dst, vr);
break;
+ case CC_OP_SUBB_64:
+ r = cc_calc_subb_64(env, src, dst, vr);
+ break;
case CC_OP_ABS_64:
r = cc_calc_abs_64(env, dst);
break;
@@ -448,12 +490,18 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_ADDU_32:
r = cc_calc_addu_32(env, src, dst, vr);
break;
+ case CC_OP_ADDC_32:
+ r = cc_calc_addc_32(env, src, dst, vr);
+ break;
case CC_OP_SUB_32:
r = cc_calc_sub_32(env, src, dst, vr);
break;
case CC_OP_SUBU_32:
r = cc_calc_subu_32(env, src, dst, vr);
break;
+ case CC_OP_SUBB_32:
+ r = cc_calc_subb_32(env, src, dst, vr);
+ break;
case CC_OP_ABS_32:
r = cc_calc_abs_64(env, dst);
break;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 7486e4c..52ab5ea 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -443,15 +443,19 @@ enum cc_op {
CC_OP_ADD_64, /* overflow on add (64bit) */
CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
+ CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
CC_OP_SUB_64, /* overflow on subtraction (64bit) */
CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
+ CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
CC_OP_ABS_64, /* sign eval on abs (64bit) */
CC_OP_NABS_64, /* sign eval on nabs (64bit) */
CC_OP_ADD_32, /* overflow on add (32bit) */
CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
+ CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
CC_OP_SUB_32, /* overflow on subtraction (32bit) */
CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
+ CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
CC_OP_ABS_32, /* sign eval on abs (64bit) */
CC_OP_NABS_32, /* sign eval on nabs (64bit) */
@@ -488,14 +492,18 @@ static const char *cc_names[] = {
[CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
[CC_OP_ADD_64] = "CC_OP_ADD_64",
[CC_OP_ADDU_64] = "CC_OP_ADDU_64",
+ [CC_OP_ADDC_64] = "CC_OP_ADDC_64",
[CC_OP_SUB_64] = "CC_OP_SUB_64",
[CC_OP_SUBU_64] = "CC_OP_SUBU_64",
+ [CC_OP_SUBB_64] = "CC_OP_SUBB_64",
[CC_OP_ABS_64] = "CC_OP_ABS_64",
[CC_OP_NABS_64] = "CC_OP_NABS_64",
[CC_OP_ADD_32] = "CC_OP_ADD_32",
[CC_OP_ADDU_32] = "CC_OP_ADDU_32",
+ [CC_OP_ADDC_32] = "CC_OP_ADDC_32",
[CC_OP_SUB_32] = "CC_OP_SUB_32",
[CC_OP_SUBU_32] = "CC_OP_SUBU_32",
+ [CC_OP_SUBB_32] = "CC_OP_SUBB_32",
[CC_OP_ABS_32] = "CC_OP_ABS_32",
[CC_OP_NABS_32] = "CC_OP_NABS_32",
[CC_OP_COMP_32] = "CC_OP_COMP_32",
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 0ebdd53..a3ca204 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -37,14 +37,10 @@ DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
DEF_HELPER_4(icmh, i32, env, i32, i64, i32)
DEF_HELPER_3(ipm, void, env, i32, i32)
-DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
DEF_HELPER_4(stam, void, env, i32, i64, i32)
DEF_HELPER_4(lam, void, env, i32, i64, i32)
DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
-DEF_HELPER_4(slb, i32, env, i32, i32, i32)
-DEF_HELPER_5(slbg, i32, env, i32, i32, i64, i64)
DEF_HELPER_3(cefbr, void, env, i32, s32)
DEF_HELPER_3(cdfbr, void, env, i32, s32)
DEF_HELPER_3(cxfbr, void, env, i32, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 692795f..3389e28 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -40,6 +40,11 @@
C(0xecda, ALHSIK, RIE_d, DO, r3, i2, new, r1_32, add, addu32)
C(0xeb7e, ALGSI, SIY, GIE, m1_64, i2, new, m1_64, add, addu64)
C(0xecdb, ALGHSIK, RIE_d, DO, r3, i2, r1, 0, add, addu64)
+/* ADD LOGICAL WITH CARRY */
+ C(0xb998, ALCR, RRE, Z, r1, r2, new, r1_32, addc, addc32)
+ C(0xb988, ALCGR, RRE, Z, r1, r2, r1, 0, addc, addc64)
+ C(0xe398, ALC, RXY_a, Z, r1, m2_32u, new, r1_32, addc, addc32)
+ C(0xe388, ALCG, RXY_a, Z, r1, m2_64, r1, 0, addc, addc64)
/* AND */
C(0x1400, NR, RR_a, Z, r1, r2, new, r1_32, and, nz32)
@@ -291,3 +296,8 @@
/* SUBTRACT LOGICAL IMMEDIATE */
C(0xc205, SLFI, RIL_a, EI, r1, i2_32u, new, r1_32, sub, subu32)
C(0xc204, SLGFI, RIL_a, EI, r1, i2_32u, r1, 0, sub, subu64)
+/* SUBTRACT LOGICAL WITH BORROW */
+ C(0xb999, SLBR, RRE, Z, r1, r2, new, r1_32, subb, subb32)
+ C(0xb989, SLBGR, RRE, Z, r1, r2, r1, 0, subb, subb64)
+ C(0xe399, SLB, RXY_a, Z, r1, m2_32u, new, r1_32, subb, subb32)
+ C(0xe389, SLBG, RXY_a, Z, r1, m2_64, r1, 0, subb, subb64)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index e54faea..b870932 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -107,49 +107,6 @@ int64_t HELPER(nabs_i64)(int64_t val)
}
}
-/* add with carry 32-bit unsigned */
-uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
-{
- uint32_t res;
-
- res = v1 + v2;
- if (cc & 2) {
- res++;
- }
-
- return res;
-}
-
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slb)(CPUS390XState *env, uint32_t cc, uint32_t r1, uint32_t v2)
-{
- uint32_t v1 = env->regs[r1];
- uint32_t res = v1 + (~v2) + (cc >> 1);
-
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
- if (cc & 2) {
- /* borrow */
- return v1 ? 1 : 0;
- } else {
- return v1 ? 3 : 2;
- }
-}
-
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slbg)(CPUS390XState *env, uint32_t cc, uint32_t r1,
- uint64_t v1, uint64_t v2)
-{
- uint64_t res = v1 + (~v2) + (cc >> 1);
-
- env->regs[r1] = res;
- if (cc & 2) {
- /* borrow */
- return v1 ? 1 : 0;
- } else {
- return v1 ? 3 : 2;
- }
-}
-
/* find leftmost one */
uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2)
{
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index cb82fdd..6b8bf42 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -472,15 +472,6 @@ static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
s->cc_op = op;
}
-static void gen_op_update3_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
- TCGv_i32 dst, TCGv_i32 vr)
-{
- tcg_gen_extu_i32_i64(cc_src, src);
- tcg_gen_extu_i32_i64(cc_dst, dst);
- tcg_gen_extu_i32_i64(cc_vr, vr);
- s->cc_op = op;
-}
-
static inline void set_cc_nz_u32(DisasContext *s, TCGv_i32 val)
{
gen_op_update1_cc_i32(s, CC_OP_NZ, val);
@@ -562,18 +553,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
}
-static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
- TCGv_i64 vr)
-{
- gen_op_update3_cc_i64(s, CC_OP_ADDU_64, v1, v2, vr);
-}
-
-static void set_cc_addu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
- TCGv_i32 vr)
-{
- gen_op_update3_cc_i32(s, CC_OP_ADDU_32, v1, v2, vr);
-}
-
static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
{
gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
@@ -659,12 +638,16 @@ static void gen_op_calc_cc(DisasContext *s)
break;
case CC_OP_ADD_64:
case CC_OP_ADDU_64:
+ case CC_OP_ADDC_64:
case CC_OP_SUB_64:
case CC_OP_SUBU_64:
+ case CC_OP_SUBB_64:
case CC_OP_ADD_32:
case CC_OP_ADDU_32:
+ case CC_OP_ADDC_32:
case CC_OP_SUB_32:
case CC_OP_SUBU_32:
+ case CC_OP_SUBB_32:
/* 3 arguments */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
break;
@@ -1308,7 +1291,7 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
{
TCGv_i64 addr, tmp, tmp2, tmp3, tmp4;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+ TCGv_i32 tmp32_1;
LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
op, r1, x2, b2, d2);
@@ -1389,33 +1372,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x88: /* ALCG R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp3 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- /* XXX possible optimization point */
- gen_op_calc_cc(s);
- tcg_gen_extu_i32_i64(tmp3, cc_op);
- tcg_gen_shri_i64(tmp3, tmp3, 1);
- tcg_gen_andi_i64(tmp3, tmp3, 1);
- tcg_gen_add_i64(tmp3, tmp2, tmp3);
- tcg_gen_add_i64(tmp3, regs[r1], tmp3);
- store_reg(r1, tmp3);
- set_cc_addu64(s, regs[r1], tmp2, tmp3);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
- case 0x89: /* SLBG R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_const_i32(r1);
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- /* XXX possible optimization point */
- gen_op_calc_cc(s);
- gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, regs[r1], tmp2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x97: /* DL R1,D2(X2,B2) [RXY] */
/* reg(r1) = reg(r1, r1+1) % ld32(addr) */
/* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
@@ -1436,37 +1392,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i64(tmp3);
break;
- case 0x98: /* ALC R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp32_3 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- /* XXX possible optimization point */
- gen_op_calc_cc(s);
- gen_helper_addc_u32(tmp32_3, cc_op, tmp32_1, tmp32_2);
- set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
- store_reg32(r1, tmp32_3);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0x99: /* SLB R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- /* XXX possible optimization point */
- gen_op_calc_cc(s);
- gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_1, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
default:
LOG_DISAS("illegal e3 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2581,7 +2506,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
static void disas_b9(DisasContext *s, int op, int r1, int r2)
{
TCGv_i64 tmp, tmp2, tmp3;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+ TCGv_i32 tmp32_1;
LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
@@ -2638,33 +2563,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x88: /* ALCGR R1,R2 [RRE] */
- tmp = load_reg(r1);
- tmp2 = load_reg(r2);
- tmp3 = tcg_temp_new_i64();
- gen_op_calc_cc(s);
- tcg_gen_extu_i32_i64(tmp3, cc_op);
- tcg_gen_shri_i64(tmp3, tmp3, 1);
- tcg_gen_andi_i64(tmp3, tmp3, 1);
- tcg_gen_add_i64(tmp3, tmp2, tmp3);
- tcg_gen_add_i64(tmp3, tmp, tmp3);
- store_reg(r1, tmp3);
- set_cc_addu64(s, tmp, tmp2, tmp3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
- case 0x89: /* SLBGR R1,R2 [RRE] */
- tmp = load_reg(r1);
- tmp2 = load_reg(r2);
- tmp32_1 = tcg_const_i32(r1);
- gen_op_calc_cc(s);
- gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, tmp, tmp2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x97: /* DLR R1,R2 [RRE] */
/* reg(r1) = reg(r1, r1+1) % reg(r2) */
/* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
@@ -2684,28 +2582,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i64(tmp3);
break;
- case 0x98: /* ALCR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r2);
- tmp32_3 = tcg_temp_new_i32();
- /* XXX possible optimization point */
- gen_op_calc_cc(s);
- gen_helper_addc_u32(tmp32_3, cc_op, tmp32_1, tmp32_2);
- set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
- store_reg32(r1, tmp32_3);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0x99: /* SLBR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tmp32_2 = tcg_const_i32(r1);
- gen_op_calc_cc(s);
- gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_2, tmp32_1);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
default:
LOG_DISAS("illegal b9 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -3872,6 +3748,23 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_addc(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 cc;
+
+ tcg_gen_add_i64(o->out, o->in1, o->in2);
+
+ /* XXX possible optimization point */
+ gen_op_calc_cc(s);
+ cc = tcg_temp_new_i64();
+ tcg_gen_extu_i32_i64(cc, cc_op);
+ tcg_gen_shri_i64(cc, cc, 1);
+
+ tcg_gen_add_i64(o->out, o->out, cc);
+ tcg_temp_free_i64(cc);
+ return NO_EXIT;
+}
+
static ExitStatus op_and(DisasContext *s, DisasOps *o)
{
tcg_gen_and_i64(o->out, o->in1, o->in2);
@@ -4031,6 +3924,24 @@ static ExitStatus op_sub(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_subb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 cc;
+
+ assert(!o->g_in2);
+ tcg_gen_not_i64(o->in2, o->in2);
+ tcg_gen_add_i64(o->out, o->in1, o->in2);
+
+ /* XXX possible optimization point */
+ gen_op_calc_cc(s);
+ cc = tcg_temp_new_i64();
+ tcg_gen_extu_i32_i64(cc, cc_op);
+ tcg_gen_shri_i64(cc, cc, 1);
+ tcg_gen_add_i64(o->out, o->out, cc);
+ tcg_temp_free_i64(cc);
+ return NO_EXIT;
+}
+
static ExitStatus op_xor(DisasContext *s, DisasOps *o)
{
tcg_gen_xor_i64(o->out, o->in1, o->in2);
@@ -4088,6 +3999,16 @@ static void cout_addu64(DisasContext *s, DisasOps *o)
gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
}
+static void cout_addc32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
+}
+
+static void cout_addc64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
+}
+
static void cout_cmps32(DisasContext *s, DisasOps *o)
{
gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
@@ -4169,6 +4090,16 @@ static void cout_subu64(DisasContext *s, DisasOps *o)
gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
}
+static void cout_subb32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
+}
+
+static void cout_subb64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
+}
+
/* ====================================================================== */
/* The "PREPeration" generators. These initialize the DisasOps.OUT fields
with the TCG register to which we will write. Used in combination with
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 026/126] target-s390: Convert BRANCH AND SAVE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (24 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 025/126] target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 027/126] target-s390: Convert BRANCH ON CONDITION Richard Henderson
` (75 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 7 ++++
target-s390x/translate.c | 102 +++++++++++++++++++++++++--------------------
2 files changed, 63 insertions(+), 46 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 3389e28..00b06a3 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -62,6 +62,13 @@
D(0xa506, NILH, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1010)
D(0xa507, NILL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
+/* BRANCH AND SAVE */
+ C(0x0d00, BASR, RR_a, Z, 0, r2_nz, r1, 0, bas, 0)
+ C(0x4d00, BAS, RX_a, Z, 0, a2, r1, 0, bas, 0)
+/* BRANCH RELATIVE AND SAVE */
+ C(0xa705, BRAS, RI_b, Z, 0, 0, r1, 0, basi, 0)
+ C(0xc005, BRASL, RIL_b, Z, 0, 0, r1, 0, basi, 0)
+
/* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
C(0x5900, C, RX_a, Z, r1_o, m2_32s, 0, 0, 0, cmps32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6b8bf42..407edd2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -711,20 +711,23 @@ static inline TCGv_i64 decode_si(DisasContext *s, uint64_t insn, int *i2,
return get_address(s, 0, *b1, *d1);
}
-static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
+static int use_goto_tb(DisasContext *s, uint64_t dest)
{
- TranslationBlock *tb;
+ /* NOTE: we handle the case where the TB spans two pages here */
+ return (((dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK)
+ || (dest & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))
+ && !s->singlestep_enabled
+ && !(s->tb->cflags & CF_LAST_IO));
+}
+static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
+{
gen_update_cc_op(s);
- tb = s->tb;
- /* NOTE: we handle the case where the TB spans two pages here */
- if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
- (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
- /* jump to same page: we can use a direct jump */
+ if (use_goto_tb(s, pc)) {
tcg_gen_goto_tb(tb_num);
tcg_gen_movi_i64(psw_addr, pc);
- tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
+ tcg_gen_exit_tb((tcg_target_long)s->tb + tb_num);
} else {
/* jump to another page: currently not optimized */
tcg_gen_movi_i64(psw_addr, pc);
@@ -1810,13 +1813,6 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
case 0x4: /* brc m1, i2 */
gen_brc(r1, s, i2 * 2LL);
return;
- case 0x5: /* BRAS R1,I2 [RI] */
- tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 4));
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- gen_goto_tb(s, 0, s->pc + i2 * 2LL);
- s->is_jmp = DISAS_TB_JUMP;
- break;
case 0x6: /* BRCT R1,I2 [RI] */
tmp32_1 = load_reg32(r1);
tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
@@ -2591,7 +2587,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
static void disas_c0(DisasContext *s, int op, int r1, int i2)
{
- TCGv_i64 tmp;
TCGv_i32 tmp32_1, tmp32_2;
uint64_t target = s->pc + i2 * 2LL;
int l1;
@@ -2618,13 +2613,6 @@ static void disas_c0(DisasContext *s, int op, int r1, int i2)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x5: /* brasl r1, i2 */
- tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 6));
- store_reg(r1, tmp);
- tcg_temp_free_i64(tmp);
- gen_goto_tb(s, 0, target);
- s->is_jmp = DISAS_TB_JUMP;
- break;
default:
LOG_DISAS("illegal c0 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2705,19 +2693,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xd: /* BASR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 2));
- store_reg(r1, tmp);
- if (r2) {
- tmp2 = load_reg(r2);
- tcg_gen_mov_i64(psw_addr, tmp2);
- tcg_temp_free_i64(tmp2);
- s->is_jmp = DISAS_JUMP;
- }
- tcg_temp_free_i64(tmp);
- break;
case 0xe: /* MVCL R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -2831,16 +2806,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
s->is_jmp = DISAS_TB_JUMP;
break;
- case 0x4d: /* BAS R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_const_i64(pc_to_link_info(s, s->pc + 4));
- store_reg(r1, tmp2);
- tcg_gen_mov_i64(psw_addr, tmp);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- s->is_jmp = DISAS_JUMP;
- break;
case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3733,6 +3698,26 @@ struct DisasInsn {
};
/* ====================================================================== */
+/* Miscelaneous helpers, used by several operations. */
+
+static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
+{
+ if (dest == s->next_pc) {
+ return NO_EXIT;
+ }
+ if (use_goto_tb(s, dest)) {
+ gen_update_cc_op(s);
+ tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(psw_addr, dest);
+ tcg_gen_exit_tb((tcg_target_long)s->tb);
+ return EXIT_GOTO_TB;
+ } else {
+ tcg_gen_movi_i64(psw_addr, dest);
+ return EXIT_PC_UPDATED;
+ }
+}
+
+/* ====================================================================== */
/* The operations. These perform the bulk of the work for any insn,
usually after the operands have been loaded and output initialized. */
@@ -3788,6 +3773,23 @@ static ExitStatus op_andi(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_bas(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
+ if (!TCGV_IS_UNUSED_I64(o->in2)) {
+ tcg_gen_mov_i64(psw_addr, o->in2);
+ return EXIT_PC_UPDATED;
+ } else {
+ return NO_EXIT;
+ }
+}
+
+static ExitStatus op_basi(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
+ return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
+}
+
static ExitStatus op_insi(DisasContext *s, DisasOps *o)
{
int shift = s->insn->data & 0xff;
@@ -4276,6 +4278,14 @@ static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_in2 = true;
}
+static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int r2 = get_field(f, r2);
+ if (r2 != 0) {
+ o->in2 = load_reg(r2);
+ }
+}
+
static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_temp_new_i64();
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 027/126] target-s390: Convert BRANCH ON CONDITION
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (25 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 026/126] target-s390: Convert BRANCH AND SAVE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 028/126] target-s390: Convert BRANCH ON COUNT Richard Henderson
` (74 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 6 ++
target-s390x/translate.c | 186 ++++++++++++++++++++++-----------------------
2 files changed, 98 insertions(+), 94 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 00b06a3..5c3587b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -68,6 +68,12 @@
/* BRANCH RELATIVE AND SAVE */
C(0xa705, BRAS, RI_b, Z, 0, 0, r1, 0, basi, 0)
C(0xc005, BRASL, RIL_b, Z, 0, 0, r1, 0, basi, 0)
+/* BRANCH ON CONDITION */
+ C(0x0700, BCR, RR_b, Z, 0, r2_nz, 0, 0, bc, 0)
+ C(0x4700, BC, RX_b, Z, 0, a2, 0, 0, bc, 0)
+/* BRANCH RELATIVE ON CONDITION */
+ C(0xa704, BRC, RI_c, Z, 0, 0, 0, 0, bc, 0)
+ C(0xc004, BRCL, RIL_c, Z, 0, 0, 0, 0, bc, 0)
/* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 407edd2..3974b82 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1019,33 +1019,6 @@ static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
free_compare(&c);
}
-static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
- uint64_t offset)
-{
- int skip;
-
- if (mask == 0xf) {
- /* unconditional */
- tcg_gen_mov_i64(psw_addr, target);
- tcg_gen_exit_tb(0);
- } else if (mask == 0) {
- /* ignore cc and never match */
- gen_goto_tb(s, 0, offset + 2);
- } else {
- TCGv_i64 new_addr = tcg_temp_local_new_i64();
-
- tcg_gen_mov_i64(new_addr, target);
- skip = gen_new_label();
- gen_jcc(s, mask, skip);
- tcg_gen_mov_i64(psw_addr, new_addr);
- tcg_temp_free_i64(new_addr);
- tcg_gen_exit_tb(0);
- gen_set_label(skip);
- tcg_temp_free_i64(new_addr);
- gen_goto_tb(s, 1, offset + 2);
- }
-}
-
static void gen_brc(uint32_t mask, DisasContext *s, int32_t offset)
{
int skip;
@@ -2585,41 +2558,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
}
}
-static void disas_c0(DisasContext *s, int op, int r1, int i2)
-{
- TCGv_i32 tmp32_1, tmp32_2;
- uint64_t target = s->pc + i2 * 2LL;
- int l1;
-
- LOG_DISAS("disas_c0: op 0x%x r1 %d i2 %d\n", op, r1, i2);
-
- switch (op) {
- case 0x4: /* BRCL M1,I2 [RIL] */
- /* m1 & (1 << (3 - cc)) */
- tmp32_1 = tcg_const_i32(3);
- tmp32_2 = tcg_const_i32(1);
- gen_op_calc_cc(s);
- tcg_gen_sub_i32(tmp32_1, tmp32_1, cc_op);
- tcg_gen_shl_i32(tmp32_2, tmp32_2, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- tmp32_1 = tcg_const_i32(r1); /* m1 == r1 */
- tcg_gen_and_i32(tmp32_1, tmp32_1, tmp32_2);
- l1 = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp32_1, 0, l1);
- gen_goto_tb(s, 0, target);
- gen_set_label(l1);
- gen_goto_tb(s, 1, s->pc + 6);
- s->is_jmp = DISAS_TB_JUMP;
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
- default:
- LOG_DISAS("illegal c0 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- break;
- }
-}
-
static void disas_s390_insn(DisasContext *s)
{
TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -2666,18 +2604,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
}
break;
- case 0x7: /* BCR M1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- if (r2) {
- tmp = load_reg(r2);
- gen_bcr(s, r1, tmp, s->pc);
- tcg_temp_free_i64(tmp);
- s->is_jmp = DISAS_TB_JUMP;
- } else {
- /* XXX: "serialization and checkpoint-synchronization function"? */
- }
- break;
case 0xa: /* SVC I [RR] */
insn = ld_code2(s->pc);
debug_insn(insn);
@@ -2799,13 +2725,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
break;
- case 0x47: /* BC M1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- gen_bcr(s, r1, tmp, s->pc + 4);
- tcg_temp_free_i64(tmp);
- s->is_jmp = DISAS_TB_JUMP;
- break;
case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3331,19 +3250,6 @@ static void disas_s390_insn(DisasContext *s)
gen_op_movi_cc(s, 0);
}
break;
- case 0xc0:
- insn = ld_code6(s->pc);
- r1 = (insn >> 36) & 0xf;
- op = (insn >> 32) & 0xf;
- i2 = (int)insn;
- switch (opc) {
- case 0xc0:
- disas_c0(s, op, r1, i2);
- break;
- default:
- tcg_abort();
- }
- break;
case 0xd2: /* MVC D1(L,B1),D2(B2) [SS] */
case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
@@ -3717,6 +3623,87 @@ static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
}
}
+static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
+ bool is_imm, int imm, TCGv_i64 cdest)
+{
+ ExitStatus ret;
+ int lab;
+
+ if (c->cond == TCG_COND_NEVER) {
+ ret = NO_EXIT;
+ goto egress;
+ }
+ if (is_imm) {
+ uint64_t dest = s->pc + 2 * imm;
+
+ if (dest == s->next_pc) {
+ /* Branch to next. */
+ ret = NO_EXIT;
+ goto egress;
+ }
+ if (c->cond == TCG_COND_ALWAYS) {
+ ret = help_goto_direct(s, dest);
+ goto egress;
+ }
+ if (use_goto_tb(s, dest) && use_goto_tb(s, s->next_pc)) {
+ gen_update_cc_op(s);
+
+ lab = gen_new_label();
+ if (c->is_64) {
+ tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
+ } else {
+ tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
+ }
+
+ /* Branch not taken. */
+ tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(psw_addr, s->next_pc);
+ tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
+
+ /* Branch taken. */
+ gen_set_label(lab);
+ tcg_gen_goto_tb(1);
+ tcg_gen_movi_i64(psw_addr, dest);
+ tcg_gen_exit_tb((tcg_target_long)s->tb + 1);
+
+ ret = EXIT_GOTO_TB;
+ goto egress;
+ }
+ /* See below wrt assuming branch taken. */
+ tcg_gen_movi_i64(psw_addr, dest);
+ } else {
+ if (TCGV_IS_UNUSED_I64(cdest)) {
+ /* E.g. bcr %r0 -> no branch. */
+ ret = NO_EXIT;
+ goto egress;
+ }
+ /* Prepare by assuming branch taken. This avoids needing to allocate
+ a new local temp to hold the value we may have computed across the
+ tcg branch here. */
+ tcg_gen_mov_i64(psw_addr, cdest);
+ if (c->cond == TCG_COND_ALWAYS) {
+ ret = EXIT_PC_UPDATED;
+ goto egress;
+ }
+ }
+
+ lab = gen_new_label();
+ if (c->is_64) {
+ tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
+ } else {
+ tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
+ }
+
+ /* Branch not taken. Reset the PSW.ADDR to the next insn. */
+ tcg_gen_movi_i64(psw_addr, s->next_pc);
+
+ gen_set_label(lab);
+ ret = EXIT_PC_UPDATED;
+ egress:
+ free_compare(c);
+ return ret;
+}
+
/* ====================================================================== */
/* The operations. These perform the bulk of the work for any insn,
usually after the operands have been loaded and output initialized. */
@@ -3790,6 +3777,17 @@ static ExitStatus op_basi(DisasContext *s, DisasOps *o)
return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
}
+static ExitStatus op_bc(DisasContext *s, DisasOps *o)
+{
+ int m1 = get_field(s->fields, m1);
+ bool is_imm = have_field(s->fields, i2);
+ int imm = is_imm ? get_field(s->fields, i2) : 0;
+ DisasCompare c;
+
+ disas_jcc(s, &c, m1);
+ return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
static ExitStatus op_insi(DisasContext *s, DisasOps *o)
{
int shift = s->insn->data & 0xff;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 028/126] target-s390: Convert BRANCH ON COUNT
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (26 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 027/126] target-s390: Convert BRANCH ON CONDITION Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 029/126] target-s390: Convert DIVIDE Richard Henderson
` (73 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 8 +++
target-s390x/translate.c | 162 ++++++++++++---------------------------------
2 files changed, 51 insertions(+), 119 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 5c3587b..63fff63 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -74,6 +74,14 @@
/* BRANCH RELATIVE ON CONDITION */
C(0xa704, BRC, RI_c, Z, 0, 0, 0, 0, bc, 0)
C(0xc004, BRCL, RIL_c, Z, 0, 0, 0, 0, bc, 0)
+/* BRANCH ON COUNT */
+ C(0x0600, BCTR, RR_a, Z, 0, r2_nz, 0, 0, bct32, 0)
+ C(0xb946, BCTGR, RRE, Z, 0, r2_nz, 0, 0, bct64, 0)
+ C(0x4600, BCT, RX_a, Z, 0, a2, 0, 0, bct32, 0)
+ C(0xe346, BCTG, RXY_a, Z, 0, a2, 0, 0, bct64, 0)
+/* BRANCH RELATIVE ON COUNT */
+ C(0xa706, BRCT, RI_b, Z, 0, 0, 0, 0, bct32, 0)
+ C(0xa707, BRCTG, RI_b, Z, 0, 0, 0, 0, bct64, 0)
/* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3974b82..e2128e5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1002,43 +1002,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
-{
- DisasCompare c;
- TCGCond cond;
-
- disas_jcc(s, &c, mask);
- cond = tcg_invert_cond(c.cond);
-
- if (c.is_64) {
- tcg_gen_brcond_i64(cond, c.u.s64.a, c.u.s64.b, skip);
- } else {
- tcg_gen_brcond_i32(cond, c.u.s32.a, c.u.s32.b, skip);
- }
-
- free_compare(&c);
-}
-
-static void gen_brc(uint32_t mask, DisasContext *s, int32_t offset)
-{
- int skip;
-
- if (mask == 0xf) {
- /* unconditional */
- gen_goto_tb(s, 0, s->pc + offset);
- } else if (mask == 0) {
- /* ignore cc and never match */
- gen_goto_tb(s, 0, s->pc + 4);
- } else {
- skip = gen_new_label();
- gen_jcc(s, mask, skip);
- gen_goto_tb(s, 0, s->pc + offset);
- gen_set_label(skip);
- gen_goto_tb(s, 1, s->pc + 4);
- }
- s->is_jmp = DISAS_TB_JUMP;
-}
-
static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
{
TCGv_i64 tmp, tmp2;
@@ -1754,8 +1717,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
static void disas_a7(DisasContext *s, int op, int r1, int i2)
{
TCGv_i64 tmp, tmp2;
- TCGv_i32 tmp32_1;
- int l1;
LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
switch (op) {
@@ -1783,35 +1744,6 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x4: /* brc m1, i2 */
- gen_brc(r1, s, i2 * 2LL);
- return;
- case 0x6: /* BRCT R1,I2 [RI] */
- tmp32_1 = load_reg32(r1);
- tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
- store_reg32(r1, tmp32_1);
- gen_update_cc_op(s);
- l1 = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp32_1, 0, l1);
- gen_goto_tb(s, 0, s->pc + (i2 * 2LL));
- gen_set_label(l1);
- gen_goto_tb(s, 1, s->pc + 4);
- s->is_jmp = DISAS_TB_JUMP;
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x7: /* BRCTG R1,I2 [RI] */
- tmp = load_reg(r1);
- tcg_gen_subi_i64(tmp, tmp, 1);
- store_reg(r1, tmp);
- gen_update_cc_op(s);
- l1 = gen_new_label();
- tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, l1);
- gen_goto_tb(s, 0, s->pc + (i2 * 2LL));
- gen_set_label(l1);
- gen_goto_tb(s, 1, s->pc + 4);
- s->is_jmp = DISAS_TB_JUMP;
- tcg_temp_free_i64(tmp);
- break;
default:
LOG_DISAS("illegal a7 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2566,7 +2498,6 @@ static void disas_s390_insn(DisasContext *s)
uint64_t insn;
int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
TCGv_i32 vl;
- int l1;
opc = cpu_ldub_code(cpu_single_env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -2578,32 +2509,6 @@ static void disas_s390_insn(DisasContext *s)
/* set addressing mode, but we only do 64bit anyways */
break;
#endif
- case 0x6: /* BCTR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r1);
- tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
- store_reg32(r1, tmp32_1);
-
- if (r2) {
- gen_update_cc_op(s);
- l1 = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp32_1, 0, l1);
-
- /* not taking the branch, jump to after the instruction */
- gen_goto_tb(s, 0, s->pc + 2);
- gen_set_label(l1);
-
- /* take the branch, move R2 into psw.addr */
- tmp32_1 = load_reg32(r2);
- tmp = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(tmp, tmp32_1);
- tcg_gen_mov_i64(psw_addr, tmp);
- s->is_jmp = DISAS_JUMP;
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- }
- break;
case 0xa: /* SVC I [RR] */
insn = ld_code2(s->pc);
debug_insn(insn);
@@ -2701,30 +2606,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i64(tmp3);
break;
- case 0x46: /* BCT R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tcg_temp_free_i64(tmp);
-
- tmp32_1 = load_reg32(r1);
- tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
- store_reg32(r1, tmp32_1);
-
- gen_update_cc_op(s);
- l1 = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp32_1, 0, l1);
-
- /* not taking the branch, jump to after the instruction */
- gen_goto_tb(s, 0, s->pc + 4);
- gen_set_label(l1);
-
- /* take the branch, move R2 into psw.addr */
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tcg_gen_mov_i64(psw_addr, tmp);
- s->is_jmp = DISAS_JUMP;
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3788,6 +3669,49 @@ static ExitStatus op_bc(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_bct32(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ bool is_imm = have_field(s->fields, i2);
+ int imm = is_imm ? get_field(s->fields, i2) : 0;
+ DisasCompare c;
+ TCGv_i64 t;
+
+ c.cond = TCG_COND_NE;
+ c.is_64 = false;
+ c.g1 = false;
+ c.g2 = false;
+
+ t = tcg_temp_new_i64();
+ tcg_gen_subi_i64(t, regs[r1], 1);
+ store_reg32_i64(r1, t);
+ c.u.s32.a = tcg_temp_new_i32();
+ c.u.s32.b = tcg_const_i32(0);
+ tcg_gen_trunc_i64_i32(c.u.s32.a, t);
+ tcg_temp_free_i64(t);
+
+ return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
+static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ bool is_imm = have_field(s->fields, i2);
+ int imm = is_imm ? get_field(s->fields, i2) : 0;
+ DisasCompare c;
+
+ c.cond = TCG_COND_NE;
+ c.is_64 = true;
+ c.g1 = true;
+ c.g2 = false;
+
+ tcg_gen_subi_i64(regs[r1], regs[r1], 1);
+ c.u.s64.a = regs[r1];
+ c.u.s64.b = tcg_const_i64(0);
+
+ return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
static ExitStatus op_insi(DisasContext *s, DisasOps *o)
{
int shift = s->insn->data & 0xff;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 029/126] target-s390: Convert DIVIDE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (27 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 028/126] target-s390: Convert BRANCH ON COUNT Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 030/126] target-s390: Send signals for divide Richard Henderson
` (72 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 5 +-
target-s390x/insn-data.def | 14 +++
target-s390x/int_helper.c | 47 +++++++---
target-s390x/translate.c | 215 +++++++++++----------------------------------
4 files changed, 103 insertions(+), 178 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index a3ca204..56e1b60 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -13,7 +13,10 @@ DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
DEF_HELPER_4(clm, i32, env, i32, i32, i64)
DEF_HELPER_4(stcm, void, env, i32, i32, i64)
DEF_HELPER_FLAGS_3(mul128, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64, i64)
-DEF_HELPER_3(dlg, void, env, i32, i64)
+DEF_HELPER_3(divs32, s64, env, s64, s64)
+DEF_HELPER_3(divu32, i64, env, i64, i64)
+DEF_HELPER_3(divs64, s64, env, s64, s64)
+DEF_HELPER_4(divu64, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 63fff63..6785bc2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -131,6 +131,20 @@
C(0xc607, CLHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
+/* DIVIDE */
+ C(0x1d00, DR, RR_a, Z, r1_P32, r2_32s, new_P, r1_P32, divs32, 0)
+ C(0x5d00, D, RX_a, Z, r1_P32, m2_32s, new_P, r1_P32, divs32, 0)
+/* DIVIDE LOGICAL */
+ C(0xb997, DLR, RRE, Z, r1_P32, r2_32u, new_P, r1_P32, divu32, 0)
+ C(0xe397, DL, RXY_a, Z, r1_P32, m2_32u, new_P, r1_P32, divu32, 0)
+ C(0xb987, DLGR, RRE, Z, 0, r2_o, r1_P, 0, divu64, 0)
+ C(0xe387, DLG, RXY_a, Z, 0, m2_64, r1_P, 0, divu64, 0)
+/* DIVIDE SINGLE */
+ C(0xb90d, DSGR, RRE, Z, r1p1, r2, r1_P, 0, divs64, 0)
+ C(0xb91d, DSGFR, RRE, Z, r1p1, r2_32s, r1_P, 0, divs64, 0)
+ C(0xe30d, DSG, RXY_a, Z, r1p1, m2_64, r1_P, 0, divs64, 0)
+ C(0xe31d, DSGF, RXY_a, Z, r1p1, m2_32s, r1_P, 0, divs64, 0)
+
/* EXCLUSIVE OR */
C(0x1700, XR, RR_a, Z, r1, r2, new, r1_32, xor, nz32)
C(0xb9f7, XRK, RRF_a, DO, r2, r3, new, r1_32, xor, nz32)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index b870932..fe1cb87 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -37,32 +37,51 @@ uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
return reth;
}
-/* 128 -> 64/64 unsigned division */
-void HELPER(dlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
+/* 64/32 -> 32 signed division */
+int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b)
+{
+ env->retxl = a % (int32_t)b;
+ return a / (int32_t)b;
+}
+
+/* 64/32 -> 32 unsigned division */
+uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b)
{
- uint64_t divisor = v2;
+ env->retxl = a % (uint32_t)b;
+ return a / (uint32_t)b;
+}
- if (!env->regs[r1]) {
+/* 64/64 -> 64 signed division */
+int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b)
+{
+ env->retxl = a % b;
+ return a / b;
+}
+
+/* 128 -> 64/64 unsigned division */
+uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint64_t b)
+{
+ uint64_t ret;
+ if (ah == 0) {
/* 64 -> 64/64 case */
- env->regs[r1] = env->regs[r1 + 1] % divisor;
- env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
- return;
+ env->retxl = al % b;
+ ret = al / b;
} else {
+ /* ??? Move i386 idivq helper to host-utils. */
#if HOST_LONG_BITS == 64 && defined(__GNUC__)
/* assuming 64-bit hosts have __uint128_t */
- __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
- (env->regs[r1 + 1]);
- __uint128_t quotient = dividend / divisor;
- __uint128_t remainder = dividend % divisor;
-
- env->regs[r1 + 1] = quotient;
- env->regs[r1] = remainder;
+ __uint128_t a = ((__uint128_t)ah << 64) | al;
+ __uint128_t q = a / b;
+ env->retxl = a % b;
+ ret = q;
#else
/* 32-bit hosts would need special wrapper functionality - just abort if
we encounter such a case; it's very unlikely anyways. */
cpu_abort(env, "128 -> 64/64 division not implemented\n");
#endif
}
+ return ret;
}
/* absolute value 32-bit */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e2128e5..42f8ce8 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1229,31 +1229,13 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
{
- TCGv_i64 addr, tmp, tmp2, tmp3, tmp4;
+ TCGv_i64 addr, tmp2, tmp3;
TCGv_i32 tmp32_1;
LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
op, r1, x2, b2, d2);
addr = get_address(s, x2, b2, d2);
switch (op) {
- case 0xd: /* DSG R1,D2(X2,B2) [RXY] */
- case 0x1d: /* DSGF R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- if (op == 0x1d) {
- tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
- } else {
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- }
- tmp4 = load_reg(r1 + 1);
- tmp3 = tcg_temp_new_i64();
- tcg_gen_div_i64(tmp3, tmp4, tmp2);
- store_reg(r1 + 1, tmp3);
- tcg_gen_rem_i64(tmp3, tmp4, tmp2);
- store_reg(r1, tmp3);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- tcg_temp_free_i64(tmp4);
- break;
case 0xf: /* LRVG R1,D2(X2,B2) [RXE] */
tmp2 = tcg_temp_new_i64();
tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
@@ -1303,34 +1285,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg8(r1, tmp3);
tcg_temp_free_i64(tmp3);
break;
- case 0x87: /* DLG R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_const_i32(r1);
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- gen_helper_dlg(cpu_env, tmp32_1, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x97: /* DL R1,D2(X2,B2) [RXY] */
- /* reg(r1) = reg(r1, r1+1) % ld32(addr) */
- /* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
- tmp = load_reg(r1);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- tmp3 = load_reg((r1 + 1) & 15);
- tcg_gen_ext32u_i64(tmp2, tmp2);
- tcg_gen_ext32u_i64(tmp3, tmp3);
- tcg_gen_shli_i64(tmp, tmp, 32);
- tcg_gen_or_i64(tmp, tmp, tmp3);
-
- tcg_gen_rem_i64(tmp3, tmp, tmp2);
- tcg_gen_div_i64(tmp, tmp, tmp2);
- store_reg32_i64((r1 + 1) & 15, tmp);
- store_reg32_i64(r1, tmp3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
default:
LOG_DISAS("illegal e3 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2406,31 +2360,11 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
static void disas_b9(DisasContext *s, int op, int r1, int r2)
{
- TCGv_i64 tmp, tmp2, tmp3;
+ TCGv_i64 tmp;
TCGv_i32 tmp32_1;
LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0xd: /* DSGR R1,R2 [RRE] */
- case 0x1d: /* DSGFR R1,R2 [RRE] */
- tmp = load_reg(r1 + 1);
- if (op == 0xd) {
- tmp2 = load_reg(r2);
- } else {
- tmp32_1 = load_reg32(r2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_ext_i32_i64(tmp2, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- }
- tmp3 = tcg_temp_new_i64();
- tcg_gen_div_i64(tmp3, tmp, tmp2);
- store_reg(r1 + 1, tmp3);
- tcg_gen_rem_i64(tmp3, tmp, tmp2);
- store_reg(r1, tmp3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x17: /* LLGTR R1,R2 [RRE] */
tmp32_1 = load_reg32(r2);
tmp = tcg_temp_new_i64();
@@ -2457,32 +2391,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x87: /* DLGR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp = load_reg(r2);
- gen_helper_dlg(cpu_env, tmp32_1, tmp);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x97: /* DLR R1,R2 [RRE] */
- /* reg(r1) = reg(r1, r1+1) % reg(r2) */
- /* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
- tmp = load_reg(r1);
- tmp2 = load_reg(r2);
- tmp3 = load_reg((r1 + 1) & 15);
- tcg_gen_ext32u_i64(tmp2, tmp2);
- tcg_gen_ext32u_i64(tmp3, tmp3);
- tcg_gen_shli_i64(tmp, tmp, 32);
- tcg_gen_or_i64(tmp, tmp, tmp3);
-
- tcg_gen_rem_i64(tmp3, tmp, tmp2);
- tcg_gen_div_i64(tmp, tmp, tmp2);
- store_reg32_i64((r1 + 1) & 15, tmp);
- store_reg32_i64(r1, tmp3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
default:
LOG_DISAS("illegal b9 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2535,41 +2443,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x1d: /* DR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r1 + 1);
- tmp32_3 = load_reg32(r2);
-
- tmp = tcg_temp_new_i64(); /* dividend */
- tmp2 = tcg_temp_new_i64(); /* divisor */
- tmp3 = tcg_temp_new_i64();
-
- /* dividend is r(r1 << 32) | r(r1 + 1) */
- tcg_gen_extu_i32_i64(tmp, tmp32_1);
- tcg_gen_extu_i32_i64(tmp2, tmp32_2);
- tcg_gen_shli_i64(tmp, tmp, 32);
- tcg_gen_or_i64(tmp, tmp, tmp2);
-
- /* divisor is r(r2) */
- tcg_gen_ext_i32_i64(tmp2, tmp32_3);
-
- tcg_gen_div_i64(tmp3, tmp, tmp2);
- tcg_gen_rem_i64(tmp, tmp, tmp2);
-
- tcg_gen_trunc_i64_i32(tmp32_1, tmp);
- tcg_gen_trunc_i64_i32(tmp32_2, tmp3);
-
- store_reg32(r1, tmp32_1); /* remainder */
- store_reg32(r1 + 1, tmp32_2); /* quotient */
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x28: /* LDR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -2618,40 +2491,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x5d: /* D R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r1 + 1);
-
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
-
- /* dividend is r(r1 << 32) | r(r1 + 1) */
- tcg_gen_extu_i32_i64(tmp, tmp32_1);
- tcg_gen_extu_i32_i64(tmp2, tmp32_2);
- tcg_gen_shli_i64(tmp, tmp, 32);
- tcg_gen_or_i64(tmp, tmp, tmp2);
-
- /* divisor is in memory */
- tcg_gen_qemu_ld32s(tmp2, tmp3, get_mem_index(s));
-
- /* XXX divisor == 0 -> FixP divide exception */
-
- tcg_gen_div_i64(tmp3, tmp, tmp2);
- tcg_gen_rem_i64(tmp, tmp, tmp2);
-
- tcg_gen_trunc_i64_i32(tmp32_1, tmp);
- tcg_gen_trunc_i64_i32(tmp32_2, tmp3);
-
- store_reg32(r1, tmp32_1); /* remainder */
- store_reg32(r1 + 1, tmp32_2); /* quotient */
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x60: /* STD R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3712,6 +3551,34 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
+{
+ gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
+ return_low128(o->out);
+ return NO_EXIT;
+}
+
+static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
+{
+ gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
+ return_low128(o->out);
+ return NO_EXIT;
+}
+
+static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
+{
+ gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
+ return_low128(o->out);
+ return NO_EXIT;
+}
+
+static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
+{
+ gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
+ return_low128(o->out);
+ return NO_EXIT;
+}
+
static ExitStatus op_insi(DisasContext *s, DisasOps *o)
{
int shift = s->insn->data & 0xff;
@@ -4035,6 +3902,12 @@ static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
o->out = tcg_temp_new_i64();
}
+static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->out = tcg_temp_new_i64();
+ o->out2 = tcg_temp_new_i64();
+}
+
static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->out = regs[get_field(f, r1)];
@@ -4066,6 +3939,14 @@ static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
store_reg32_i64(get_field(f, r1), o->out);
}
+static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be even. */
+ int r1 = get_field(f, r1);
+ store_reg32_i64(r1, o->out);
+ store_reg32_i64((r1 + 1) & 15, o->out2);
+}
+
static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
{
/* ??? Specification exception: r1 must be even. */
@@ -4129,6 +4010,14 @@ static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_ext32u_i64(o->in1, regs[(r1 + 1) & 15]);
}
+static void in1_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be even. */
+ int r1 = get_field(f, r1);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_deposit_i64(o->in1, regs[(r1 + 1) & 15], regs[r1], 32, 32);
+}
+
static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_reg(get_field(f, r2));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 030/126] target-s390: Send signals for divide
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (28 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 029/126] target-s390: Convert DIVIDE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 031/126] target-s390: Convert TEST UNDER MASK Richard Henderson
` (71 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cpu.h | 2 ++
target-s390x/int_helper.c | 51 ++++++++++++++++++++++++++++++++++++++++------
target-s390x/misc_helper.c | 22 ++++++++++++++++++++
3 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 52ab5ea..7d89a6f 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -934,5 +934,7 @@ uint32_t set_cc_nz_f64(float64 v);
/* misc_helper.c */
void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
+void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
+ uintptr_t retaddr);
#endif
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index fe1cb87..f2f420c 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -38,22 +38,54 @@ uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
}
/* 64/32 -> 32 signed division */
-int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b)
+int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64)
{
- env->retxl = a % (int32_t)b;
- return a / (int32_t)b;
+ int32_t ret, b = b64;
+ int64_t q;
+
+ if (b == 0) {
+ runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+ }
+
+ ret = q = a / b;
+ env->retxl = a % b;
+
+ /* Catch non-representable quotient. */
+ if (ret != q) {
+ runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+ }
+
+ return ret;
}
/* 64/32 -> 32 unsigned division */
-uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64)
{
- env->retxl = a % (uint32_t)b;
- return a / (uint32_t)b;
+ uint32_t ret, b = b64;
+ uint64_t q;
+
+ if (b == 0) {
+ runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+ }
+
+ ret = q = a / b;
+ env->retxl = a % b;
+
+ /* Catch non-representable quotient. */
+ if (ret != q) {
+ runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+ }
+
+ return ret;
}
/* 64/64 -> 64 signed division */
int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b)
{
+ /* Catch divide by zero, and non-representable quotient (MIN / -1). */
+ if (b == 0 || (b == -1 && a == (1ll << 63))) {
+ runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+ }
env->retxl = a % b;
return a / b;
}
@@ -63,6 +95,10 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t b)
{
uint64_t ret;
+ /* Signal divide by zero. */
+ if (b == 0) {
+ runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+ }
if (ah == 0) {
/* 64 -> 64/64 case */
env->retxl = al % b;
@@ -75,6 +111,9 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
__uint128_t q = a / b;
env->retxl = a % b;
ret = q;
+ if (ret != q) {
+ runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+ }
#else
/* 32-bit hosts would need special wrapper functionality - just abort if
we encounter such a case; it's very unlikely anyways. */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 1502f15..32b75f2 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -69,6 +69,28 @@
do { } while (0)
#endif
+void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
+ uintptr_t retaddr)
+{
+ TranslationBlock *tb;
+ int t;
+
+ env->exception_index = EXCP_PGM;
+ env->int_pgm_code = excp;
+
+ /* Use the (ultimate) callers address to find the insn that trapped. */
+ tb = tb_find_pc(retaddr);
+ assert(tb != NULL);
+ cpu_restore_state(tb, env, retaddr);
+
+ /* Advance past the insn. */
+ t = cpu_ldub_code(env, env->psw.addr);
+ env->int_pgm_ilc = t = get_ilc(t);
+ env->psw.addr += 2 * t;
+
+ cpu_loop_exit(env);
+}
+
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
HELPER_LOG("%s: exception %d\n", __func__, excp);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 031/126] target-s390: Convert TEST UNDER MASK
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (29 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 030/126] target-s390: Send signals for divide Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 032/126] target-s390: Convert SET ADDRESSING MODE Richard Henderson
` (70 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 25 ++++++----------
target-s390x/insn-data.def | 8 +++++
target-s390x/translate.c | 73 +++++++---------------------------------------
3 files changed, 27 insertions(+), 79 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 880e3b2..99c7d57 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -20,6 +20,7 @@
#include "cpu.h"
#include "helper.h"
+#include "host-utils.h"
/* #define DEBUG_HELPER */
#ifdef DEBUG_HELPER
@@ -86,13 +87,11 @@ static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
}
}
-static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
- uint32_t mask)
+static uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
{
- uint16_t r = val & mask;
+ uint32_t r = val & mask;
- HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask);
- if (r == 0 || mask == 0) {
+ if (r == 0) {
return 0;
} else if (r == mask) {
return 3;
@@ -101,23 +100,17 @@ static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
}
}
-/* set condition code for test under mask */
-static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
- uint32_t mask)
+static uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint64_t mask)
{
- uint16_t r = val & mask;
+ uint64_t r = val & mask;
- HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r);
- if (r == 0 || mask == 0) {
+ if (r == 0) {
return 0;
} else if (r == mask) {
return 3;
} else {
- while (!(mask & 0x8000)) {
- mask <<= 1;
- val <<= 1;
- }
- if (val & 0x8000) {
+ int top = clz64(mask);
+ if ((int64_t)(val << top) < 0) {
return 2;
} else {
return 1;
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6785bc2..845d22c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -336,3 +336,11 @@
C(0xb989, SLBGR, RRE, Z, r1, r2, r1, 0, subb, subb64)
C(0xe399, SLB, RXY_a, Z, r1, m2_32u, new, r1_32, subb, subb32)
C(0xe389, SLBG, RXY_a, Z, r1, m2_64, r1, 0, subb, subb64)
+
+/* TEST UNDER MASK */
+ C(0x9100, TM, SI, Z, m1_8u, i2_8u, 0, 0, 0, tm32)
+ C(0xeb51, TMY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, tm32)
+ D(0xa702, TMHH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 48)
+ D(0xa703, TMHL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 32)
+ D(0xa700, TMLH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
+ D(0xa701, TMLL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 42f8ce8..34513d5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1510,16 +1510,6 @@ do_mh:
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x51: /* TMY D1(B1),I2 [SIY] */
- tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
- tmp2 = tcg_const_i64((r1 << 4) | r3);
- tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
- /* yes, this is a 32 bit operation with 64 bit tcg registers, because
- that incurs less conversions */
- cmp_64(s, tmp, tmp2, CC_OP_TM_32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x52: /* MVIY D1(B1),I2 [SIY] */
tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
tmp2 = tcg_const_i64((r1 << 4) | r3);
@@ -1668,43 +1658,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
tcg_temp_free_i64(addr);
}
-static void disas_a7(DisasContext *s, int op, int r1, int i2)
-{
- TCGv_i64 tmp, tmp2;
-
- LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
- switch (op) {
- case 0x0: /* TMLH or TMH R1,I2 [RI] */
- case 0x1: /* TMLL or TML R1,I2 [RI] */
- case 0x2: /* TMHH R1,I2 [RI] */
- case 0x3: /* TMHL R1,I2 [RI] */
- tmp = load_reg(r1);
- tmp2 = tcg_const_i64((uint16_t)i2);
- switch (op) {
- case 0x0:
- tcg_gen_shri_i64(tmp, tmp, 16);
- break;
- case 0x1:
- break;
- case 0x2:
- tcg_gen_shri_i64(tmp, tmp, 48);
- break;
- case 0x3:
- tcg_gen_shri_i64(tmp, tmp, 32);
- break;
- }
- tcg_gen_andi_i64(tmp, tmp, 0xffff);
- cmp_64(s, tmp, tmp2, CC_OP_TM_64);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- default:
- LOG_DISAS("illegal a7 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- return;
- }
-}
-
static void disas_b2(DisasContext *s, int op, uint32_t insn)
{
TCGv_i64 tmp, tmp2, tmp3;
@@ -2668,15 +2621,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp3);
tcg_temp_free_i64(tmp4);
break;
- case 0x91: /* TM D1(B1),I2 [SI] */
- insn = ld_code4(s->pc);
- tmp = decode_si(s, insn, &i2, &b1, &d1);
- tmp2 = tcg_const_i64(i2);
- tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
- cmp_64(s, tmp, tmp2, CC_OP_TM_32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x92: /* MVI D1(B1),I2 [SI] */
insn = ld_code4(s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1);
@@ -2734,13 +2678,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xa7:
- insn = ld_code4(s->pc);
- r1 = (insn >> 20) & 0xf;
- op = (insn >> 16) & 0xf;
- i2 = (short)insn;
- disas_a7(s, op, r1, i2);
- break;
case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -3891,6 +3828,16 @@ static void cout_subb64(DisasContext *s, DisasOps *o)
gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
}
+static void cout_tm32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
+}
+
+static void cout_tm64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
+}
+
/* ====================================================================== */
/* The "PREPeration" generators. These initialize the DisasOps.OUT fields
with the TCG register to which we will write. Used in combination with
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 032/126] target-s390: Convert SET ADDRESSING MODE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (30 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 031/126] target-s390: Convert TEST UNDER MASK Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 033/126] target-s390: Convert SUPERVISOR CALL Richard Henderson
` (69 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 7 +++++++
target-s390x/translate.c | 6 ------
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 845d22c..267050f 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -344,3 +344,10 @@
D(0xa703, TMHL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 32)
D(0xa700, TMLH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
D(0xa701, TMLL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
+
+#ifndef CONFIG_USER_ONLY
+/* SET ADDRESSING MODE */
+ /* We only do 64-bit, so accept this as a no-op.
+ Let SAM24 and SAM31 signal illegal instruction. */
+ C(0x010e, SAM64, E, Z, 0, 0, 0, 0, 0, 0)
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 34513d5..ccba739 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2364,12 +2364,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
-#ifndef CONFIG_USER_ONLY
- case 0x01: /* SAM */
- insn = ld_code2(s->pc);
- /* set addressing mode, but we only do 64bit anyways */
- break;
-#endif
case 0xa: /* SVC I [RR] */
insn = ld_code2(s->pc);
debug_insn(insn);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 033/126] target-s390: Convert SUPERVISOR CALL
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (31 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 032/126] target-s390: Convert SET ADDRESSING MODE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 034/126] target-s390: Convert MOVE LONG Richard Henderson
` (68 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 3 +++
target-s390x/translate.c | 34 +++++++++++++++++++---------------
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 267050f..ab014ff 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -337,6 +337,9 @@
C(0xe399, SLB, RXY_a, Z, r1, m2_32u, new, r1_32, subb, subb32)
C(0xe389, SLBG, RXY_a, Z, r1, m2_64, r1, 0, subb, subb64)
+/* SUPERVISOR CALL */
+ C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0)
+
/* TEST UNDER MASK */
C(0x9100, TM, SI, Z, m1_8u, i2_8u, 0, 0, 0, tm32)
C(0xeb51, TMY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, tm32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ccba739..00b6266 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2364,21 +2364,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0xa: /* SVC I [RR] */
- insn = ld_code2(s->pc);
- debug_insn(insn);
- i = insn & 0xff;
- update_psw_addr(s);
- gen_op_calc_cc(s);
- tmp32_1 = tcg_const_i32(i);
- tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
- tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
- tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
- gen_exception(EXCP_SVC);
- s->is_jmp = DISAS_EXCP;
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0xe: /* MVCL R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3664,6 +3649,25 @@ static ExitStatus op_subb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_svc(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 t;
+
+ update_psw_addr(s);
+ gen_op_calc_cc(s);
+
+ t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
+ tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
+ tcg_temp_free_i32(t);
+
+ t = tcg_const_i32(s->next_pc - s->pc);
+ tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
+ tcg_temp_free_i32(t);
+
+ gen_exception(EXCP_SVC);
+ return EXIT_NORETURN;
+}
+
static ExitStatus op_xor(DisasContext *s, DisasOps *o)
{
tcg_gen_xor_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 034/126] target-s390: Convert MOVE LONG
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (32 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 033/126] target-s390: Convert SUPERVISOR CALL Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 035/126] target-s390: Convert FP LOAD Richard Henderson
` (67 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 3 +++
target-s390x/translate.c | 23 ++++++++++++-----------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ab014ff..3c3a8f7 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -246,6 +246,9 @@
C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
+/* MOVE LONG */
+ C(0x0e00, MVCL, RR_a, Z, 0, 0, 0, 0, mvcl, 0)
+
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 00b6266..0752c67 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2364,17 +2364,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0xe: /* MVCL R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- potential_page_fault(s);
- gen_helper_mvcl(cc_op, cpu_env, tmp32_1, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x28: /* LDR R1,R2 [RR] */
insn = ld_code2(s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3554,6 +3543,18 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
+ potential_page_fault(s);
+ gen_helper_mvcl(cc_op, cpu_env, r1, r2);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
{
tcg_gen_mul_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 035/126] target-s390: Convert FP LOAD
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (33 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 034/126] target-s390: Convert MOVE LONG Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 036/126] target-s390: Convert INSERT CHARACTER Richard Henderson
` (66 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 7 ++++
target-s390x/translate.c | 102 +++++++++++++++++++++++++++++----------------
2 files changed, 74 insertions(+), 35 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 3c3a8f7..02e9cc0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -173,6 +173,13 @@
C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0)
C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0)
C(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0)
+ C(0x2800, LDR, RR_a, Z, 0, f2_o, 0, f1, mov2, 0)
+ C(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0)
+ C(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0)
+ C(0x3800, LER, RR_a, Z, 0, e2, 0, cond_e1e2, mov2, 0)
+ C(0x7800, LE, RX_a, Z, 0, m2_32u, 0, e1, mov2, 0)
+ C(0xed64, LEY, RXY_a, LD, 0, m2_32u, 0, e1, mov2, 0)
+ C(0xb365, LXR, RRE, Z, 0, x2_o, 0, x1, movx, 0)
/* LOAD IMMEDIATE */
C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
/* LOAD RELATIVE LONG */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0752c67..c36ad44 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -222,6 +222,13 @@ static inline TCGv_i32 load_freg32(int reg)
return r;
}
+static inline TCGv_i64 load_freg32_i64(int reg)
+{
+ TCGv_i64 r = tcg_temp_new_i64();
+ tcg_gen_shri_i64(r, fregs[reg], 32);
+ return r;
+}
+
static inline TCGv_i32 load_reg32(int reg)
{
TCGv_i32 r = tcg_temp_new_i32();
@@ -291,6 +298,11 @@ static inline void store_freg32(int reg, TCGv_i32 v)
#endif
}
+static inline void store_freg32_i64(int reg, TCGv_i64 v)
+{
+ tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
+}
+
static inline void return_low128(TCGv_i64 dest)
{
tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
@@ -2364,20 +2376,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x28: /* LDR R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp = load_freg(r2);
- store_freg(r1, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0x38: /* LER R1,R2 [RR] */
- insn = ld_code2(s->pc);
- decode_rr(s, insn, &r1, &r2);
- tmp32_1 = load_freg32(r2);
- store_freg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x43: /* IC R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2420,15 +2418,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x68: /* LD R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
- store_freg(r1, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x70: /* STE R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2440,18 +2429,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x78: /* LE R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- store_freg32(r1, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
#ifndef CONFIG_USER_ONLY
case 0x80: /* SSM D2(B2) [S] */
/* Set System Mask */
@@ -3543,6 +3520,18 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_movx(DisasContext *s, DisasOps *o)
+{
+ o->out = o->in1;
+ o->out2 = o->in2;
+ o->g_out = o->g_in1;
+ o->g_out2 = o->g_in2;
+ TCGV_UNUSED_I64(o->in1);
+ TCGV_UNUSED_I64(o->in2);
+ o->g_in1 = o->g_in2 = false;
+ return NO_EXIT;
+}
+
static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
@@ -3902,6 +3891,23 @@ static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
store_reg32_i64(r1, o->out);
}
+static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ store_freg32_i64(get_field(f, r1), o->out);
+}
+
+static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ store_freg(get_field(f, r1), o->out);
+}
+
+static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int f1 = get_field(s->fields, r1);
+ store_freg(f1, o->out);
+ store_freg((f1 + 2) & 15, o->out2);
+}
+
static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
if (get_field(f, r1) != get_field(f, r2)) {
@@ -3909,6 +3915,13 @@ static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
}
}
+static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ if (get_field(f, r1) != get_field(f, r2)) {
+ store_freg32_i64(get_field(f, r1), o->out);
+ }
+}
+
static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
@@ -4084,6 +4097,25 @@ static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
}
+static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = load_freg32_i64(get_field(f, r2));
+}
+
+static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = fregs[get_field(f, r2)];
+ o->g_in2 = true;
+}
+
+static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int f2 = get_field(f, r2);
+ o->in1 = fregs[f2];
+ o->in2 = fregs[(f2 + 2) & 15];
+ o->g_in1 = o->g_in2 = true;
+}
+
static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
{
int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 036/126] target-s390: Convert INSERT CHARACTER
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (34 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 035/126] target-s390: Convert FP LOAD Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 037/126] target-s390: Cleanup cc computation helpers Richard Henderson
` (65 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 3 +++
target-s390x/translate.c | 35 +++++++++++++----------------------
2 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 02e9cc0..7fff688 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -157,6 +157,9 @@
D(0xc006, XIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
D(0xc007, XILF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
+/* INSERT CHARACTER */
+ C(0x4300, IC, RX_a, Z, 0, m2_8u, 0, r1_8, mov2, 0)
+ C(0xe373, ICY, RXY_a, LD, 0, m2_8u, 0, r1_8, mov2, 0)
/* INSERT IMMEDIATE */
D(0xc008, IIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
D(0xc009, IILF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c36ad44..4f7731a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -281,12 +281,6 @@ static inline void store_reg16(int reg, TCGv_i32 v)
#endif
}
-static inline void store_reg8(int reg, TCGv_i64 v)
-{
- /* 8 bit register writes keep the upper bytes */
- tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 8);
-}
-
static inline void store_freg32(int reg, TCGv_i32 v)
{
/* 32 bit register writes keep the lower half */
@@ -1241,7 +1235,7 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
{
- TCGv_i64 addr, tmp2, tmp3;
+ TCGv_i64 addr, tmp2;
TCGv_i32 tmp32_1;
LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
@@ -1291,12 +1285,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
tcg_temp_free_i64(tmp2);
break;
- case 0x73: /* ICY R1,D2(X2,B2) [RXY] */
- tmp3 = tcg_temp_new_i64();
- tcg_gen_qemu_ld8u(tmp3, addr, get_mem_index(s));
- store_reg8(r1, tmp3);
- tcg_temp_free_i64(tmp3);
- break;
default:
LOG_DISAS("illegal e3 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2376,15 +2364,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x43: /* IC R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
- store_reg8(r1, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x44: /* EX R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3869,6 +3848,12 @@ static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
store_reg(get_field(f, r1), o->out);
}
+static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int r1 = get_field(f, r1);
+ tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
+}
+
static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_reg32_i64(get_field(f, r1), o->out);
@@ -4127,6 +4112,12 @@ static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
}
+static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_a2(s, f, o);
+ tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
+}
+
static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
{
in2_a2(s, f, o);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 037/126] target-s390: Cleanup cc computation helpers
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (35 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 036/126] target-s390: Convert INSERT CHARACTER Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 038/126] target-s390: Convert INSERT CHARACTERS UNDER MASK Richard Henderson
` (64 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
The inline markers hid the fact that {n}abs_32 were unused
because of typos in the main do_calc_cc function. Let the
compiler handle auto-inlining here.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 140 +++++++++++++++++++++--------------------------
1 file changed, 61 insertions(+), 79 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 99c7d57..663d0c9 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -29,8 +29,7 @@
#define HELPER_LOG(x...)
#endif
-static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
- int32_t dst)
+static uint32_t cc_calc_ltgt_32(int32_t src, int32_t dst)
{
if (src == dst) {
return 0;
@@ -41,13 +40,12 @@ static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
}
}
-static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_ltgt0_32(int32_t dst)
{
- return cc_calc_ltgt_32(env, dst, 0);
+ return cc_calc_ltgt_32(dst, 0);
}
-static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
- int64_t dst)
+static uint32_t cc_calc_ltgt_64(int64_t src, int64_t dst)
{
if (src == dst) {
return 0;
@@ -58,13 +56,12 @@ static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
}
}
-static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_ltgt0_64(int64_t dst)
{
- return cc_calc_ltgt_64(env, dst, 0);
+ return cc_calc_ltgt_64(dst, 0);
}
-static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
- uint32_t dst)
+static uint32_t cc_calc_ltugtu_32(uint32_t src, uint32_t dst)
{
if (src == dst) {
return 0;
@@ -75,8 +72,7 @@ static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
}
}
-static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
- uint64_t dst)
+static uint32_t cc_calc_ltugtu_64(uint64_t src, uint64_t dst)
{
if (src == dst) {
return 0;
@@ -87,7 +83,7 @@ static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
}
}
-static uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
+static uint32_t cc_calc_tm_32(uint32_t val, uint32_t mask)
{
uint32_t r = val & mask;
@@ -100,7 +96,7 @@ static uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
}
}
-static uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint64_t mask)
+static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask)
{
uint64_t r = val & mask;
@@ -118,13 +114,12 @@ static uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint64_t mask)
}
}
-static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
+static uint32_t cc_calc_nz(uint64_t dst)
{
return !!dst;
}
-static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
- int64_t a2, int64_t ar)
+static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
{
if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
return 3; /* overflow */
@@ -139,14 +134,12 @@ static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
}
}
-static uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
- uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addu_64(uint64_t a1, uint64_t a2, uint64_t ar)
{
return (ar != 0) + 2 * (ar < a1);
}
-static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
- uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addc_64(uint64_t a1, uint64_t a2, uint64_t ar)
{
/* Recover a2 + carry_in. */
uint64_t a2c = ar - a1;
@@ -156,8 +149,7 @@ static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
return (ar != 0) + 2 * carry_out;
}
-static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
- int64_t a2, int64_t ar)
+static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
{
if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
return 3; /* overflow */
@@ -172,8 +164,7 @@ static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
}
}
-static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
- uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_subu_64(uint64_t a1, uint64_t a2, uint64_t ar)
{
if (ar == 0) {
return 2;
@@ -186,8 +177,7 @@ static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
}
}
-static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
- uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_subb_64(uint64_t a1, uint64_t a2, uint64_t ar)
{
/* We had borrow-in if normal subtraction isn't equal. */
int borrow_in = ar - (a1 - a2);
@@ -205,7 +195,7 @@ static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
return (ar != 0) + 2 * !borrow_out;
}
-static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_abs_64(int64_t dst)
{
if ((uint64_t)dst == 0x8000000000000000ULL) {
return 3;
@@ -216,12 +206,12 @@ static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
}
}
-static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_nabs_64(int64_t dst)
{
return !!dst;
}
-static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_comp_64(int64_t dst)
{
if ((uint64_t)dst == 0x8000000000000000ULL) {
return 3;
@@ -235,8 +225,7 @@ static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
}
-static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
- int32_t a2, int32_t ar)
+static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
{
if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
return 3; /* overflow */
@@ -251,14 +240,12 @@ static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
}
}
-static uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
- uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addu_32(uint32_t a1, uint32_t a2, uint32_t ar)
{
return (ar != 0) + 2 * (ar < a1);
}
-static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
- uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addc_32(uint32_t a1, uint32_t a2, uint32_t ar)
{
/* Recover a2 + carry_in. */
uint32_t a2c = ar - a1;
@@ -268,8 +255,7 @@ static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
return (ar != 0) + 2 * carry_out;
}
-static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
- int32_t a2, int32_t ar)
+static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
{
if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
return 3; /* overflow */
@@ -284,8 +270,7 @@ static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
}
}
-static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
- uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_subu_32(uint32_t a1, uint32_t a2, uint32_t ar)
{
if (ar == 0) {
return 2;
@@ -298,8 +283,7 @@ static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
}
}
-static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
- uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_subb_32(uint32_t a1, uint32_t a2, uint32_t ar)
{
/* We had borrow-in if normal subtraction isn't equal. */
int borrow_in = ar - (a1 - a2);
@@ -317,7 +301,7 @@ static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
return (ar != 0) + 2 * !borrow_out;
}
-static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_abs_32(int32_t dst)
{
if ((uint32_t)dst == 0x80000000UL) {
return 3;
@@ -328,12 +312,12 @@ static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
}
}
-static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_nabs_32(int32_t dst)
{
return !!dst;
}
-static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_comp_32(int32_t dst)
{
if ((uint32_t)dst == 0x80000000UL) {
return 3;
@@ -347,8 +331,7 @@ static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
}
/* calculate condition code for insert character under mask insn */
-static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
- uint32_t val)
+static uint32_t cc_calc_icm_32(uint32_t mask, uint32_t val)
{
uint32_t cc;
@@ -379,8 +362,7 @@ static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
return cc;
}
-static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
- uint64_t shift)
+static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
{
uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
uint64_t match, r;
@@ -409,7 +391,7 @@ static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
}
-static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
+static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
{
uint32_t r = 0;
@@ -423,93 +405,93 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
r = cc_op;
break;
case CC_OP_LTGT0_32:
- r = cc_calc_ltgt0_32(env, dst);
+ r = cc_calc_ltgt0_32(dst);
break;
case CC_OP_LTGT0_64:
- r = cc_calc_ltgt0_64(env, dst);
+ r = cc_calc_ltgt0_64(dst);
break;
case CC_OP_LTGT_32:
- r = cc_calc_ltgt_32(env, src, dst);
+ r = cc_calc_ltgt_32(src, dst);
break;
case CC_OP_LTGT_64:
- r = cc_calc_ltgt_64(env, src, dst);
+ r = cc_calc_ltgt_64(src, dst);
break;
case CC_OP_LTUGTU_32:
- r = cc_calc_ltugtu_32(env, src, dst);
+ r = cc_calc_ltugtu_32(src, dst);
break;
case CC_OP_LTUGTU_64:
- r = cc_calc_ltugtu_64(env, src, dst);
+ r = cc_calc_ltugtu_64(src, dst);
break;
case CC_OP_TM_32:
- r = cc_calc_tm_32(env, src, dst);
+ r = cc_calc_tm_32(src, dst);
break;
case CC_OP_TM_64:
- r = cc_calc_tm_64(env, src, dst);
+ r = cc_calc_tm_64(src, dst);
break;
case CC_OP_NZ:
- r = cc_calc_nz(env, dst);
+ r = cc_calc_nz(dst);
break;
case CC_OP_ADD_64:
- r = cc_calc_add_64(env, src, dst, vr);
+ r = cc_calc_add_64(src, dst, vr);
break;
case CC_OP_ADDU_64:
- r = cc_calc_addu_64(env, src, dst, vr);
+ r = cc_calc_addu_64(src, dst, vr);
break;
case CC_OP_ADDC_64:
- r = cc_calc_addc_64(env, src, dst, vr);
+ r = cc_calc_addc_64(src, dst, vr);
break;
case CC_OP_SUB_64:
- r = cc_calc_sub_64(env, src, dst, vr);
+ r = cc_calc_sub_64(src, dst, vr);
break;
case CC_OP_SUBU_64:
- r = cc_calc_subu_64(env, src, dst, vr);
+ r = cc_calc_subu_64(src, dst, vr);
break;
case CC_OP_SUBB_64:
- r = cc_calc_subb_64(env, src, dst, vr);
+ r = cc_calc_subb_64(src, dst, vr);
break;
case CC_OP_ABS_64:
- r = cc_calc_abs_64(env, dst);
+ r = cc_calc_abs_64(dst);
break;
case CC_OP_NABS_64:
- r = cc_calc_nabs_64(env, dst);
+ r = cc_calc_nabs_64(dst);
break;
case CC_OP_COMP_64:
- r = cc_calc_comp_64(env, dst);
+ r = cc_calc_comp_64(dst);
break;
case CC_OP_ADD_32:
- r = cc_calc_add_32(env, src, dst, vr);
+ r = cc_calc_add_32(src, dst, vr);
break;
case CC_OP_ADDU_32:
- r = cc_calc_addu_32(env, src, dst, vr);
+ r = cc_calc_addu_32(src, dst, vr);
break;
case CC_OP_ADDC_32:
- r = cc_calc_addc_32(env, src, dst, vr);
+ r = cc_calc_addc_32(src, dst, vr);
break;
case CC_OP_SUB_32:
- r = cc_calc_sub_32(env, src, dst, vr);
+ r = cc_calc_sub_32(src, dst, vr);
break;
case CC_OP_SUBU_32:
- r = cc_calc_subu_32(env, src, dst, vr);
+ r = cc_calc_subu_32(src, dst, vr);
break;
case CC_OP_SUBB_32:
- r = cc_calc_subb_32(env, src, dst, vr);
+ r = cc_calc_subb_32(src, dst, vr);
break;
case CC_OP_ABS_32:
- r = cc_calc_abs_64(env, dst);
+ r = cc_calc_abs_32(dst);
break;
case CC_OP_NABS_32:
- r = cc_calc_nabs_64(env, dst);
+ r = cc_calc_nabs_32(dst);
break;
case CC_OP_COMP_32:
- r = cc_calc_comp_32(env, dst);
+ r = cc_calc_comp_32(dst);
break;
case CC_OP_ICM:
- r = cc_calc_icm_32(env, src, dst);
+ r = cc_calc_icm_32(src, dst);
break;
case CC_OP_SLAG:
- r = cc_calc_slag(env, src, dst);
+ r = cc_calc_slag(src, dst);
break;
case CC_OP_LTGT_F32:
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 038/126] target-s390: Convert INSERT CHARACTERS UNDER MASK
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (36 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 037/126] target-s390: Cleanup cc computation helpers Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 039/126] target-s390: Convert EXECUTE Richard Henderson
` (63 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Change the CC handling to be more like TEST UNDER MASK, with val & mask.
This lets us handle ICMH much more like ICM.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 31 +++--------
target-s390x/helper.h | 1 -
target-s390x/insn-data.def | 4 ++
target-s390x/mem_helper.c | 33 -----------
target-s390x/translate.c | 136 +++++++++++++++++++++------------------------
5 files changed, 74 insertions(+), 131 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 663d0c9..d13f241 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -331,35 +331,18 @@ static uint32_t cc_calc_comp_32(int32_t dst)
}
/* calculate condition code for insert character under mask insn */
-static uint32_t cc_calc_icm_32(uint32_t mask, uint32_t val)
+static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
{
- uint32_t cc;
-
- HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val);
- if (mask == 0xf) {
- if (!val) {
- return 0;
- } else if (val & 0x80000000) {
+ if ((val & mask) == 0) {
+ return 0;
+ } else {
+ int top = clz64(mask);
+ if ((int64_t)(val << top) < 0) {
return 1;
} else {
return 2;
}
}
-
- if (!val || !mask) {
- cc = 0;
- } else {
- while (mask != 1) {
- mask >>= 1;
- val >>= 8;
- }
- if (val & 0x80) {
- cc = 1;
- } else {
- cc = 2;
- }
- }
- return cc;
}
static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
@@ -488,7 +471,7 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
break;
case CC_OP_ICM:
- r = cc_calc_icm_32(src, dst);
+ r = cc_calc_icm(src, dst);
break;
case CC_OP_SLAG:
r = cc_calc_slag(src, dst);
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 56e1b60..93931e4 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -38,7 +38,6 @@ DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32)
DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
-DEF_HELPER_4(icmh, i32, env, i32, i64, i32)
DEF_HELPER_3(ipm, void, env, i32, i32)
DEF_HELPER_4(stam, void, env, i32, i64, i32)
DEF_HELPER_4(lam, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7fff688..322fcc1 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -160,6 +160,10 @@
/* INSERT CHARACTER */
C(0x4300, IC, RX_a, Z, 0, m2_8u, 0, r1_8, mov2, 0)
C(0xe373, ICY, RXY_a, LD, 0, m2_8u, 0, r1_8, mov2, 0)
+/* INSERT CHARACTERS UNDER MASK */
+ D(0xbf00, ICM, RS_b, Z, 0, a2, r1, 0, icm, 0, 0)
+ D(0xeb81, ICMY, RSY_b, LD, 0, a2, r1, 0, icm, 0, 0)
+ D(0xeb80, ICMH, RSY_b, Z, 0, a2, r1, 0, icm, 0, 32)
/* INSERT IMMEDIATE */
D(0xc008, IIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
D(0xc009, IILF, RIL_a, EI, r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index b21b37c..b868346 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -635,39 +635,6 @@ void HELPER(stcmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
}
}
-/* insert character under mask high; same as icm, but operates on the
- upper half of r1 */
-uint32_t HELPER(icmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
- uint32_t mask)
-{
- int pos = 56; /* top of the upper half of r1 */
- uint64_t rmask = 0xff00000000000000ULL;
- uint8_t val = 0;
- int ccd = 0;
- uint32_t cc = 0;
-
- while (mask) {
- if (mask & 8) {
- env->regs[r1] &= ~rmask;
- val = cpu_ldub_data(env, address);
- if ((val & 0x80) && !ccd) {
- cc = 1;
- }
- ccd = 1;
- if (val && cc == 0) {
- cc = 2;
- }
- env->regs[r1] |= (uint64_t)val << pos;
- address++;
- }
- mask = (mask << 1) & 0xf;
- pos -= 8;
- rmask >>= 8;
- }
-
- return cc;
-}
-
/* load access registers r1 to r3 from memory at a2 */
void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
{
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4f7731a..e9eae6f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -32,6 +32,7 @@
#include "disas.h"
#include "tcg-op.h"
#include "qemu-log.h"
+#include "host-utils.h"
/* global register indexes */
static TCGv_ptr cpu_env;
@@ -559,11 +560,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
}
-static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
-{
- gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
-}
-
static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
{
tcg_gen_extu_i32_i64(cc_src, v1);
@@ -894,7 +890,6 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
case CC_OP_LTGT0_64:
case CC_OP_NZ:
- case CC_OP_ICM:
c->u.s64.a = cc_dst;
c->u.s64.b = tcg_const_i64(0);
c->g1 = true;
@@ -908,6 +903,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
case CC_OP_TM_32:
case CC_OP_TM_64:
+ case CC_OP_ICM:
c->u.s64.a = tcg_temp_new_i64();
c->u.s64.b = tcg_const_i64(0);
tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
@@ -1517,18 +1513,6 @@ do_mh:
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x80: /* ICMH R1,M3,D2(B2) [RSY] */
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- /* XXX split CC calculation out */
- gen_helper_icmh(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
default:
LOG_DISAS("illegal eb operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2354,7 +2338,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
static void disas_s390_insn(DisasContext *s)
{
TCGv_i64 tmp, tmp2, tmp3, tmp4;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3, tmp32_4;
+ TCGv_i32 tmp32_1, tmp32_2;
unsigned char opc;
uint64_t insn;
int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
@@ -2777,60 +2761,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xbf: /* ICM R1,M3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- if (r3 == 15) {
- /* effectively a 32-bit load */
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_temp_new_i32();
- tmp32_2 = tcg_const_i32(r3);
- tcg_gen_qemu_ld32u(tmp, tmp, get_mem_index(s));
- store_reg32_i64(r1, tmp);
- tcg_gen_trunc_i64_i32(tmp32_1, tmp);
- set_cc_icm(s, tmp32_2, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- } else if (r3) {
- uint32_t mask = 0x00ffffffUL;
- uint32_t shift = 24;
- int m3 = r3;
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tmp32_3 = tcg_const_i32(r3);
- tmp32_4 = tcg_const_i32(0);
- while (m3) {
- if (m3 & 8) {
- tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- if (shift) {
- tcg_gen_shli_i32(tmp32_2, tmp32_2, shift);
- }
- tcg_gen_andi_i32(tmp32_1, tmp32_1, mask);
- tcg_gen_or_i32(tmp32_1, tmp32_1, tmp32_2);
- tcg_gen_or_i32(tmp32_4, tmp32_4, tmp32_2);
- tcg_gen_addi_i64(tmp, tmp, 1);
- }
- m3 = (m3 << 1) & 0xf;
- mask = (mask >> 8) | 0xff000000UL;
- shift -= 8;
- }
- store_reg32(r1, tmp32_1);
- set_cc_icm(s, tmp32_3, tmp32_4);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- tcg_temp_free_i32(tmp32_4);
- } else {
- /* i.e. env->cc = 0 */
- gen_op_movi_cc(s, 0);
- }
- break;
case 0xd2: /* MVC D1(L,B1),D2(B2) [SS] */
case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
@@ -3440,6 +3370,66 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_icm(DisasContext *s, DisasOps *o)
+{
+ int m3 = get_field(s->fields, m3);
+ int pos, len, base = s->insn->data;
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ uint64_t ccm;
+
+ switch (m3) {
+ case 0xf:
+ /* Effectively a 32-bit load. */
+ tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
+ len = 32;
+ goto one_insert;
+
+ case 0xc:
+ case 0x6:
+ case 0x3:
+ /* Effectively a 16-bit load. */
+ tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
+ len = 16;
+ goto one_insert;
+
+ case 0x8:
+ case 0x4:
+ case 0x2:
+ case 0x1:
+ /* Effectively an 8-bit load. */
+ tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
+ len = 8;
+ goto one_insert;
+
+ one_insert:
+ pos = base + ctz32(m3) * 8;
+ tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
+ ccm = ((1ull << len) - 1) << pos;
+ break;
+
+ default:
+ /* This is going to be a sequence of loads and inserts. */
+ pos = base + 32 - 8;
+ ccm = 0;
+ while (m3) {
+ if (m3 & 0x8) {
+ tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
+ tcg_gen_addi_i64(o->in2, o->in2, 1);
+ tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
+ ccm |= 0xff << pos;
+ }
+ m3 = (m3 << 1) & 0xf;
+ pos -= 8;
+ }
+ break;
+ }
+
+ tcg_gen_movi_i64(tmp, ccm);
+ gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
+ tcg_temp_free_i64(tmp);
+ return NO_EXIT;
+}
+
static ExitStatus op_insi(DisasContext *s, DisasOps *o)
{
int shift = s->insn->data & 0xff;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 039/126] target-s390: Convert EXECUTE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (37 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 038/126] target-s390: Convert INSERT CHARACTERS UNDER MASK Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 040/126] target-s390: Convert FP STORE Richard Henderson
` (62 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 5 +++++
target-s390x/translate.c | 39 ++++++++++++++++++++++++++-------------
2 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 322fcc1..6bd4265 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -157,6 +157,11 @@
D(0xc006, XIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
D(0xc007, XILF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
+/* EXECUTE */
+ C(0x4400, EX, RX_a, Z, r1_o, a2, 0, 0, ex, 0)
+/* EXECUTE RELATIVE LONG */
+ C(0xc600, EXRL, RIL_b, EE, r1_o, ri2, 0, 0, ex, 0)
+
/* INSERT CHARACTER */
C(0x4300, IC, RX_a, Z, 0, m2_8u, 0, r1_8, mov2, 0)
C(0xe373, ICY, RXY_a, LD, 0, m2_8u, 0, r1_8, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e9eae6f..c37c567 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2348,19 +2348,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x44: /* EX R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = load_reg(r1);
- tmp3 = tcg_const_i64(s->pc + 4);
- update_psw_addr(s);
- gen_op_calc_cc(s);
- gen_helper_ex(cc_op, cpu_env, cc_op, tmp2, tmp, tmp3);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
insn = ld_code4(s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3370,6 +3357,32 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ex(DisasContext *s, DisasOps *o)
+{
+ /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
+ tb->flags, (ab)use the tb->cs_base field as the address of
+ the template in memory, and grab 8 bits of tb->flags/cflags for
+ the contents of the register. We would then recognize all this
+ in gen_intermediate_code_internal, generating code for exactly
+ one instruction. This new TB then gets executed normally.
+
+ On the other hand, this seems to be mostly used for modifying
+ MVC inside of memcpy, which needs a helper call anyway. So
+ perhaps this doesn't bear thinking about any further. */
+
+ TCGv_i64 tmp;
+
+ update_psw_addr(s);
+ gen_op_calc_cc(s);
+
+ tmp = tcg_const_i64(s->next_pc);
+ gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
+ tcg_temp_free_i64(tmp);
+
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_icm(DisasContext *s, DisasOps *o)
{
int m3 = get_field(s->fields, m3);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 040/126] target-s390: Convert FP STORE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (38 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 039/126] target-s390: Convert EXECUTE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 041/126] target-s390: Convert CONVERT TO DECIMAL Richard Henderson
` (61 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 30 +++++++++++-------------------
2 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6bd4265..68f9711 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -315,6 +315,10 @@
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0)
C(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0)
C(0xe324, STG, RXY_a, Z, r1_o, a2, 0, 0, st64, 0)
+ C(0x6000, STD, RX_a, Z, f1_o, a2, 0, 0, st64, 0)
+ C(0xed67, STDY, RXY_a, LD, f1_o, a2, 0, 0, st64, 0)
+ C(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0)
+ C(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0)
/* STORE RELATIVE LONG */
C(0xc40f, STRL, RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0)
C(0xc40b, STGRL, RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c37c567..621cd20 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2360,25 +2360,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x60: /* STD R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = load_freg(r1);
- tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- case 0x70: /* STE R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = load_freg32(r1);
- tcg_gen_extu_i32_i64(tmp2, tmp32_1);
- tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
#ifndef CONFIG_USER_ONLY
case 0x80: /* SSM D2(B2) [S] */
/* Set System Mask */
@@ -3975,6 +3956,17 @@ static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = load_reg(get_field(f, r3));
}
+static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = load_freg32_i64(get_field(f, r1));
+}
+
+static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = fregs[get_field(f, r1)];
+ o->g_in1 = true;
+}
+
static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 041/126] target-s390: Convert CONVERT TO DECIMAL
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (39 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 040/126] target-s390: Convert FP STORE Richard Henderson
@ 2012-09-09 21:04 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 042/126] target-s390: Convert SET SYSTEM MASK Richard Henderson
` (60 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:04 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 24 ++++++++++++------------
2 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 68f9711..9d26370 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -131,6 +131,10 @@
C(0xc607, CLHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
+/* CONVERT TO DECIMAL */
+ C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
+ C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
+
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_P32, r2_32s, new_P, r1_P32, divs32, 0)
C(0x5d00, D, RX_a, Z, r1_P32, m2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 621cd20..11feffd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2348,18 +2348,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp32_1, regs[r1]);
- gen_helper_cvd(tmp2, tmp32_1);
- tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
#ifndef CONFIG_USER_ONLY
case 0x80: /* SSM D2(B2) [S] */
/* Set System Mask */
@@ -3310,6 +3298,18 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i32 t2 = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(t2, o->in1);
+ gen_helper_cvd(t1, t2);
+ tcg_temp_free_i32(t2);
+ tcg_gen_qemu_st64(t1, o->in2, get_mem_index(s));
+ tcg_temp_free_i64(t1);
+ return NO_EXIT;
+}
+
static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
{
gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 042/126] target-s390: Convert SET SYSTEM MASK
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (40 preceding siblings ...)
2012-09-09 21:04 ` [Qemu-devel] [PATCH 041/126] target-s390: Convert CONVERT TO DECIMAL Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 043/126] target-s390: Convert LOAD PSW Richard Henderson
` (59 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 25 +++++++++----------------
2 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9d26370..7af3ba3 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -383,4 +383,6 @@
/* We only do 64-bit, so accept this as a no-op.
Let SAM24 and SAM31 signal illegal instruction. */
C(0x010e, SAM64, E, Z, 0, 0, 0, 0, 0, 0)
+/* SET SYSTEM MASK */
+ C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
#endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 11feffd..deb5cb9 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2349,22 +2349,6 @@ static void disas_s390_insn(DisasContext *s)
switch (opc) {
#ifndef CONFIG_USER_ONLY
- case 0x80: /* SSM D2(B2) [S] */
- /* Set System Mask */
- check_privileged(s);
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tmp3 = tcg_temp_new_i64();
- tcg_gen_andi_i64(tmp3, psw_mask, ~0xff00000000000000ULL);
- tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
- tcg_gen_shli_i64(tmp2, tmp2, 56);
- tcg_gen_or_i64(psw_mask, tmp3, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x82: /* LPSW D2(B2) [S] */
/* Load PSW */
check_privileged(s);
@@ -3554,6 +3538,15 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_st8(DisasContext *s, DisasOps *o)
{
tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 043/126] target-s390: Convert LOAD PSW
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (41 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 042/126] target-s390: Convert SET SYSTEM MASK Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 044/126] target-s390: Convert DIAGNOSE Richard Henderson
` (58 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 37 +++++++++++++++++++------------------
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7af3ba3..f2ad737 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -379,6 +379,8 @@
D(0xa701, TMLL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
#ifndef CONFIG_USER_ONLY
+/* LOAD PSW */
+ C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
/* SET ADDRESSING MODE */
/* We only do 64-bit, so accept this as a no-op.
Let SAM24 and SAM31 signal illegal instruction. */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index deb5cb9..8d285ee 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2349,24 +2349,6 @@ static void disas_s390_insn(DisasContext *s)
switch (opc) {
#ifndef CONFIG_USER_ONLY
- case 0x82: /* LPSW D2(B2) [S] */
- /* Load PSW */
- check_privileged(s);
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tmp3 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_addi_i64(tmp, tmp, 4);
- tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s));
- gen_helper_load_psw(cpu_env, tmp2, tmp3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- /* we need to keep cc_op intact */
- s->is_jmp = DISAS_JUMP;
- break;
case 0x83: /* DIAG R1,R3,D2 [RS] */
/* Diagnose call (KVM hypercall) */
check_privileged(s);
@@ -3458,6 +3440,25 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 t1, t2;
+
+ check_privileged(s);
+
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
+ tcg_gen_addi_i64(o->in2, o->in2, 4);
+ tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
+ gen_helper_load_psw(cpu_env, t1, t2);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
+ return EXIT_NORETURN;
+}
+#endif
+
static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
{
o->out = o->in2;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 044/126] target-s390: Convert DIAGNOSE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (42 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 043/126] target-s390: Convert LOAD PSW Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 045/126] target-s390: Convert SHIFT, ROTATE SINGLE Richard Henderson
` (57 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 33 ++++++++++++++++-----------------
2 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f2ad737..ba9f094 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -379,6 +379,8 @@
D(0xa701, TMLL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
#ifndef CONFIG_USER_ONLY
+/* DIAGNOSE (KVM hypercall) */
+ C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
/* LOAD PSW */
C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
/* SET ADDRESSING MODE */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8d285ee..d2e7a22 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2348,23 +2348,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
-#ifndef CONFIG_USER_ONLY
- case 0x83: /* DIAG R1,R3,D2 [RS] */
- /* Diagnose call (KVM hypercall) */
- check_privileged(s);
- potential_page_fault(s);
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp32_1 = tcg_const_i32(insn & 0xfff);
- tmp2 = load_reg(2);
- tmp3 = load_reg(1);
- gen_helper_diag(tmp2, cpu_env, tmp32_1, tmp2, tmp3);
- store_reg(2, tmp2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
-#endif
case 0x88: /* SRL R1,D2(B2) [RS] */
case 0x89: /* SLL R1,D2(B2) [RS] */
case 0x8a: /* SRA R1,D2(B2) [RS] */
@@ -3276,6 +3259,22 @@ static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_diag(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 tmp;
+
+ check_privileged(s);
+ potential_page_fault(s);
+
+ /* We pretend the format is RX_a so that D2 is the field we want. */
+ tmp = tcg_const_i32(get_field(s->fields, d2) & 0xfff);
+ gen_helper_diag(regs[2], cpu_env, tmp, regs[2], regs[1]);
+ tcg_temp_free_i32(tmp);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
{
gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 045/126] target-s390: Convert SHIFT, ROTATE SINGLE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (43 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 044/126] target-s390: Convert DIAGNOSE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 046/126] target-s390: Convert SHIFT DOUBLE Richard Henderson
` (56 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Note that we were missing the 32-bit SLA.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 56 +++++++++---
target-s390x/cpu.h | 6 +-
target-s390x/insn-data.def | 21 +++++
target-s390x/translate.c | 207 ++++++++++++++++++++++++---------------------
4 files changed, 176 insertions(+), 114 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index d13f241..bead820 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -345,34 +345,59 @@ static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
}
}
-static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
+static uint32_t cc_calc_sla_32(uint32_t src, int shift)
{
- uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
- uint64_t match, r;
+ uint32_t mask = ((1U << shift) - 1U) << (32 - shift);
+ uint32_t sign = 1U << 31;
+ uint32_t match;
+ int32_t r;
- /* check if the sign bit stays the same */
- if (src & (1ULL << 63)) {
+ /* Check if the sign bit stays the same. */
+ if (src & sign) {
match = mask;
} else {
match = 0;
}
-
if ((src & mask) != match) {
- /* overflow */
+ /* Overflow. */
return 3;
}
- r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
-
- if ((int64_t)r == 0) {
+ r = ((src << shift) & ~sign) | (src & sign);
+ if (r == 0) {
return 0;
- } else if ((int64_t)r < 0) {
+ } else if (r < 0) {
return 1;
}
-
return 2;
}
+static uint32_t cc_calc_sla_64(uint64_t src, int shift)
+{
+ uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
+ uint64_t sign = 1ULL << 63;
+ uint64_t match;
+ int64_t r;
+
+ /* Check if the sign bit stays the same. */
+ if (src & sign) {
+ match = mask;
+ } else {
+ match = 0;
+ }
+ if ((src & mask) != match) {
+ /* Overflow. */
+ return 3;
+ }
+
+ r = ((src << shift) & ~sign) | (src & sign);
+ if (r == 0) {
+ return 0;
+ } else if (r < 0) {
+ return 1;
+ }
+ return 2;
+}
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
@@ -473,8 +498,11 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_ICM:
r = cc_calc_icm(src, dst);
break;
- case CC_OP_SLAG:
- r = cc_calc_slag(src, dst);
+ case CC_OP_SLA_32:
+ r = cc_calc_sla_32(src, dst);
+ break;
+ case CC_OP_SLA_64:
+ r = cc_calc_sla_64(src, dst);
break;
case CC_OP_LTGT_F32:
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 7d89a6f..c33df11 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -472,7 +472,8 @@ enum cc_op {
CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
CC_OP_ICM, /* insert characters under mask */
- CC_OP_SLAG, /* Calculate shift left signed */
+ CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
+ CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
CC_OP_MAX
};
@@ -515,7 +516,8 @@ static const char *cc_names[] = {
[CC_OP_NZ_F32] = "CC_OP_NZ_F32",
[CC_OP_NZ_F64] = "CC_OP_NZ_F64",
[CC_OP_ICM] = "CC_OP_ICM",
- [CC_OP_SLAG] = "CC_OP_SLAG",
+ [CC_OP_SLA_32] = "CC_OP_SLA_32",
+ [CC_OP_SLA_64] = "CC_OP_SLA_64",
};
static inline const char *cc_name(int cc_op)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ba9f094..fd94333 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -315,6 +315,27 @@
D(0xa50a, OILH, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
D(0xa50b, OILL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
+/* ROTATE LEFT SINGLE LOGICAL */
+ C(0xeb1d, RLL, RSY_a, Z, r3_o, sh32, new, r1_32, rll32, 0)
+ C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh64, r1, 0, rll64, 0)
+
+/* SHIFT LEFT SINGLE */
+ D(0x8b00, SLA, RS_a, Z, r1, sh32, new, r1_32, sla, 0, 31)
+ D(0xebdd, SLAK, RSY_a, DO, r3, sh32, new, r1_32, sla, 0, 31)
+ D(0xeb0b, SLAG, RSY_a, Z, r3, sh64, r1, 0, sla, 0, 63)
+/* SHIFT LEFT SINGLE LOGICAL */
+ C(0x8900, SLL, RS_a, Z, r1_o, sh32, new, r1_32, sll, 0)
+ C(0xebdf, SLLK, RSY_a, DO, r3_o, sh32, new, r1_32, sll, 0)
+ C(0xeb0d, SLLG, RSY_a, Z, r3_o, sh64, r1, 0, sll, 0)
+/* SHIFT RIGHT SINGLE */
+ C(0x8a00, SRA, RS_a, Z, r1_32s, sh32, new, r1_32, sra, s32)
+ C(0xebdc, SRAK, RSY_a, DO, r3_32s, sh32, new, r1_32, sra, s32)
+ C(0xeb0a, SRAG, RSY_a, Z, r3_o, sh64, r1, 0, sra, s64)
+/* SHIFT RIGHT SINGLE LOGICAL */
+ C(0x8800, SRL, RS_a, Z, r1_32u, sh32, new, r1_32, srl, 0)
+ C(0xebde, SRLK, RSY_a, DO, r3_32u, sh32, new, r1_32, srl, 0)
+ C(0xeb0c, SRLG, RSY_a, Z, r3_o, sh64, r1, 0, srl, 0)
+
/* STORE */
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0)
C(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d2e7a22..c37c385 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -634,7 +634,8 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_TM_64:
case CC_OP_LTGT_F32:
case CC_OP_LTGT_F64:
- case CC_OP_SLAG:
+ case CC_OP_SLA_32:
+ case CC_OP_SLA_64:
/* 2 arguments */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
break;
@@ -1326,74 +1327,6 @@ static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
op, r1, r3, b2, d2);
switch (op) {
- case 0xc: /* SRLG R1,R3,D2(B2) [RSY] */
- case 0xd: /* SLLG R1,R3,D2(B2) [RSY] */
- case 0xa: /* SRAG R1,R3,D2(B2) [RSY] */
- case 0xb: /* SLAG R1,R3,D2(B2) [RSY] */
- case 0x1c: /* RLLG R1,R3,D2(B2) [RSY] */
- if (b2) {
- tmp = get_address(s, 0, b2, d2);
- tcg_gen_andi_i64(tmp, tmp, 0x3f);
- } else {
- tmp = tcg_const_i64(d2 & 0x3f);
- }
- switch (op) {
- case 0xc:
- tcg_gen_shr_i64(regs[r1], regs[r3], tmp);
- break;
- case 0xd:
- tcg_gen_shl_i64(regs[r1], regs[r3], tmp);
- break;
- case 0xa:
- tcg_gen_sar_i64(regs[r1], regs[r3], tmp);
- break;
- case 0xb:
- tmp2 = tcg_temp_new_i64();
- tmp3 = tcg_temp_new_i64();
- gen_op_update2_cc_i64(s, CC_OP_SLAG, regs[r3], tmp);
- tcg_gen_shl_i64(tmp2, regs[r3], tmp);
- /* override sign bit with source sign */
- tcg_gen_andi_i64(tmp2, tmp2, ~0x8000000000000000ULL);
- tcg_gen_andi_i64(tmp3, regs[r3], 0x8000000000000000ULL);
- tcg_gen_or_i64(regs[r1], tmp2, tmp3);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
- case 0x1c:
- tcg_gen_rotl_i64(regs[r1], regs[r3], tmp);
- break;
- default:
- tcg_abort();
- break;
- }
- if (op == 0xa) {
- set_cc_s64(s, regs[r1]);
- }
- tcg_temp_free_i64(tmp);
- break;
- case 0x1d: /* RLL R1,R3,D2(B2) [RSY] */
- if (b2) {
- tmp = get_address(s, 0, b2, d2);
- tcg_gen_andi_i64(tmp, tmp, 0x3f);
- } else {
- tmp = tcg_const_i64(d2 & 0x3f);
- }
- tmp32_1 = tcg_temp_new_i32();
- tmp32_2 = load_reg32(r3);
- tcg_gen_trunc_i64_i32(tmp32_1, tmp);
- switch (op) {
- case 0x1d:
- tcg_gen_rotl_i32(tmp32_1, tmp32_2, tmp32_1);
- break;
- default:
- tcg_abort();
- break;
- }
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x4: /* LMG R1,R3,D2(B2) [RSE] */
case 0x24: /* STMG R1,R3,D2(B2) [RSE] */
stm_len = 8;
@@ -2348,35 +2281,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x88: /* SRL R1,D2(B2) [RS] */
- case 0x89: /* SLL R1,D2(B2) [RS] */
- case 0x8a: /* SRA R1,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_temp_new_i32();
- tcg_gen_trunc_i64_i32(tmp32_2, tmp);
- tcg_gen_andi_i32(tmp32_2, tmp32_2, 0x3f);
- switch (opc) {
- case 0x88:
- tcg_gen_shr_i32(tmp32_1, tmp32_1, tmp32_2);
- break;
- case 0x89:
- tcg_gen_shl_i32(tmp32_1, tmp32_1, tmp32_2);
- break;
- case 0x8a:
- tcg_gen_sar_i32(tmp32_1, tmp32_1, tmp32_2);
- set_cc_s32(s, tmp32_1);
- break;
- default:
- tcg_abort();
- }
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0x8c: /* SRDL R1,D2(B2) [RS] */
case 0x8d: /* SLDL R1,D2(B2) [RS] */
case 0x8e: /* SRDA R1,D2(B2) [RS] */
@@ -3022,6 +2926,20 @@ struct DisasInsn {
/* ====================================================================== */
/* Miscelaneous helpers, used by several operations. */
+static void help_l2_shift(DisasContext *s, DisasFields *f,
+ DisasOps *o, int mask)
+{
+ int b2 = get_field(f, b2);
+ int d2 = get_field(f, d2);
+
+ if (b2 == 0) {
+ o->in2 = tcg_const_i64(d2 & mask);
+ } else {
+ o->in2 = get_address(s, 0, b2, d2);
+ tcg_gen_andi_i64(o->in2, o->in2, mask);
+ }
+}
+
static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
{
if (dest == s->next_pc) {
@@ -3538,6 +3456,59 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 t1 = tcg_temp_new_i32();
+ TCGv_i32 t2 = tcg_temp_new_i32();
+ TCGv_i32 to = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(t1, o->in1);
+ tcg_gen_trunc_i64_i32(t2, o->in2);
+ tcg_gen_rotl_i32(to, t1, t2);
+ tcg_gen_extu_i32_i64(o->out, to);
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+ tcg_temp_free_i32(to);
+ return NO_EXIT;
+}
+
+static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_rotl_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sla(DisasContext *s, DisasOps *o)
+{
+ uint64_t sign = 1ull << s->insn->data;
+ enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64;
+ gen_op_update2_cc_i64(s, cco, o->in1, o->in2);
+ tcg_gen_shl_i64(o->out, o->in1, o->in2);
+ /* The arithmetic left shift is curious in that it does not affect
+ the sign bit. Copy that over from the source unchanged. */
+ tcg_gen_andi_i64(o->out, o->out, ~sign);
+ tcg_gen_andi_i64(o->in1, o->in1, sign);
+ tcg_gen_or_i64(o->out, o->out, o->in1);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sll(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_shl_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sra(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_sar_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_srl(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_shr_i64(o->out, o->in1, o->in2);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
{
@@ -3908,6 +3879,18 @@ static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_in1 = true;
}
+static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
+}
+
+static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
+}
+
static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
{
/* ??? Specification exception: r1 must be even. */
@@ -3949,6 +3932,24 @@ static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = load_reg(get_field(f, r3));
}
+static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = regs[get_field(f, r3)];
+ o->g_in1 = true;
+}
+
+static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
+}
+
+static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
+}
+
static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_freg32_i64(get_field(f, r1));
@@ -4100,6 +4101,16 @@ static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
}
+static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ help_l2_shift(s, f, o, 31);
+}
+
+static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ help_l2_shift(s, f, o, 63);
+}
+
static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
{
in2_a2(s, f, o);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 046/126] target-s390: Convert SHIFT DOUBLE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (44 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 045/126] target-s390: Convert SHIFT, ROTATE SINGLE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 047/126] target-s390: Convert LOAD, STORE MULTIPLE Richard Henderson
` (55 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 8 ++++++++
target-s390x/translate.c | 30 ------------------------------
2 files changed, 8 insertions(+), 30 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index fd94333..103c1d2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -335,6 +335,14 @@
C(0x8800, SRL, RS_a, Z, r1_32u, sh32, new, r1_32, srl, 0)
C(0xebde, SRLK, RSY_a, DO, r3_32u, sh32, new, r1_32, srl, 0)
C(0xeb0c, SRLG, RSY_a, Z, r3_o, sh64, r1, 0, srl, 0)
+/* SHIFT LEFT DOUBLE */
+ D(0x8f00, SLDA, RS_a, Z, r1_P32, sh64, new, r1_P32, sla, 0, 31)
+/* SHIFT LEFT DOUBLE LOGICAL */
+ C(0x8d00, SLDL, RS_a, Z, r1_P32, sh64, new, r1_P32, sll, 0)
+/* SHIFT RIGHT DOUBLE */
+ C(0x8e00, SRDA, RS_a, Z, r1_P32, sh64, new, r1_P32, sra, s64)
+/* SHIFT RIGHT DOUBLE LOGICAL */
+ C(0x8c00, SRDL, RS_a, Z, r1_P32, sh64, new, r1_P32, srl, 0)
/* STORE */
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c37c385..e78e4bb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2281,36 +2281,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x8c: /* SRDL R1,D2(B2) [RS] */
- case 0x8d: /* SLDL R1,D2(B2) [RS] */
- case 0x8e: /* SRDA R1,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2); /* shift */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = load_reg32(r1);
- tmp32_2 = load_reg32(r1 + 1);
- tcg_gen_concat_i32_i64(tmp2, tmp32_2, tmp32_1); /* operand */
- switch (opc) {
- case 0x8c:
- tcg_gen_shr_i64(tmp2, tmp2, tmp);
- break;
- case 0x8d:
- tcg_gen_shl_i64(tmp2, tmp2, tmp);
- break;
- case 0x8e:
- tcg_gen_sar_i64(tmp2, tmp2, tmp);
- set_cc_s64(s, tmp2);
- break;
- }
- tcg_gen_shri_i64(tmp, tmp2, 32);
- tcg_gen_trunc_i64_i32(tmp32_1, tmp);
- store_reg32(r1, tmp32_1);
- tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
- store_reg32(r1 + 1, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x98: /* LM R1,R3,D2(B2) [RS] */
case 0x90: /* STM R1,R3,D2(B2) [RS] */
insn = ld_code4(s->pc);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 047/126] target-s390: Convert LOAD, STORE MULTIPLE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (45 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 046/126] target-s390: Convert SHIFT DOUBLE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-18 20:49 ` Alexander Graf
2012-09-09 21:05 ` [Qemu-devel] [PATCH 048/126] target-s390: Convert MOVE Richard Henderson
` (54 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 14 ++++
target-s390x/translate.c | 191 ++++++++++++++++++++++++---------------------
2 files changed, 116 insertions(+), 89 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 103c1d2..b1f0448 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -269,6 +269,13 @@
C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
+/* LOAD MULTIPLE */
+ C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
+ C(0xeb98, LMY, RSY_a, LD, 0, a2, 0, 0, lm32, 0)
+ C(0xeb04, LMG, RSY_a, Z, 0, a2, 0, 0, lm64, 0)
+/* LOAD MULTIPLE HIGH */
+ C(0xeb96, LMH, RSY_a, Z, 0, a2, 0, 0, lmh, 0)
+
/* MOVE LONG */
C(0x0e00, MVCL, RR_a, Z, 0, 0, 0, 0, mvcl, 0)
@@ -364,6 +371,13 @@
/* STORE HALFWORD RELATIVE LONG */
C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
+/* STORE MULTIPLE */
+ D(0x9000, STM, RS_a, Z, 0, a2, 0, 0, stm, 0, 4)
+ D(0xeb90, STMY, RSY_a, LD, 0, a2, 0, 0, stm, 0, 4)
+ D(0xeb24, STMG, RSY_a, Z, 0, a2, 0, 0, stm, 0, 8)
+/* STORE MULTIPLE HIGH */
+ C(0xeb26, STMH, RSY_a, Z, 0, a2, 0, 0, stmh, 0)
+
/* SUBTRACT */
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
C(0xb9f9, SRK, RRF_a, DO, r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e78e4bb..4c5540d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -271,6 +271,11 @@ static inline void store_reg32_i64(int reg, TCGv_i64 v)
tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
}
+static inline void store_reg32h_i64(int reg, TCGv_i64 v)
+{
+ tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
+}
+
static inline void store_reg16(int reg, TCGv_i32 v)
{
/* 16 bit register writes keep the upper bytes */
@@ -1320,65 +1325,12 @@ static void disas_e5(DisasContext* s, uint64_t insn)
static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
{
- TCGv_i64 tmp, tmp2, tmp3, tmp4;
+ TCGv_i64 tmp, tmp2;
TCGv_i32 tmp32_1, tmp32_2;
- int i, stm_len;
LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
op, r1, r3, b2, d2);
switch (op) {
- case 0x4: /* LMG R1,R3,D2(B2) [RSE] */
- case 0x24: /* STMG R1,R3,D2(B2) [RSE] */
- stm_len = 8;
- goto do_mh;
- case 0x26: /* STMH R1,R3,D2(B2) [RSE] */
- case 0x96: /* LMH R1,R3,D2(B2) [RSE] */
- stm_len = 4;
-do_mh:
- /* Apparently, unrolling lmg/stmg of any size gains performance -
- even for very long ones... */
- tmp = get_address(s, 0, b2, d2);
- tmp3 = tcg_const_i64(stm_len);
- tmp4 = tcg_const_i64(op == 0x26 ? 32 : 4);
- for (i = r1;; i = (i + 1) % 16) {
- switch (op) {
- case 0x4:
- tcg_gen_qemu_ld64(regs[i], tmp, get_mem_index(s));
- break;
- case 0x96:
- tmp2 = tcg_temp_new_i64();
-#if HOST_LONG_BITS == 32
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(TCGV_HIGH(regs[i]), tmp2);
-#else
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_shl_i64(tmp2, tmp2, tmp4);
- tcg_gen_ext32u_i64(regs[i], regs[i]);
- tcg_gen_or_i64(regs[i], regs[i], tmp2);
-#endif
- tcg_temp_free_i64(tmp2);
- break;
- case 0x24:
- tcg_gen_qemu_st64(regs[i], tmp, get_mem_index(s));
- break;
- case 0x26:
- tmp2 = tcg_temp_new_i64();
- tcg_gen_shr_i64(tmp2, regs[i], tmp4);
- tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp2);
- break;
- default:
- tcg_abort();
- }
- if (i == r3) {
- break;
- }
- tcg_gen_add_i64(tmp, tmp, tmp3);
- }
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp3);
- tcg_temp_free_i64(tmp4);
- break;
case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
@@ -2270,44 +2222,17 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
static void disas_s390_insn(DisasContext *s)
{
- TCGv_i64 tmp, tmp2, tmp3, tmp4;
+ TCGv_i64 tmp, tmp2;
TCGv_i32 tmp32_1, tmp32_2;
unsigned char opc;
uint64_t insn;
- int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
+ int op, r1, r2, r3, d1, d2, x2, b1, b2, i2, r1b;
TCGv_i32 vl;
opc = cpu_ldub_code(cpu_single_env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x98: /* LM R1,R3,D2(B2) [RS] */
- case 0x90: /* STM R1,R3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
-
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tmp3 = tcg_const_i64(4);
- tmp4 = tcg_const_i64(0xffffffff00000000ULL);
- for (i = r1;; i = (i + 1) % 16) {
- if (opc == 0x98) {
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_and_i64(regs[i], regs[i], tmp4);
- tcg_gen_or_i64(regs[i], regs[i], tmp2);
- } else {
- tcg_gen_qemu_st32(regs[i], tmp, get_mem_index(s));
- }
- if (i == r3) {
- break;
- }
- tcg_gen_add_i64(tmp, tmp, tmp3);
- }
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- tcg_temp_free_i64(tmp4);
- break;
case 0x92: /* MVI D1(B1),I2 [SI] */
insn = ld_code4(s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1);
@@ -2604,19 +2529,17 @@ static void disas_s390_insn(DisasContext *s)
d1 = (insn >> 16) & 0xfff;
b2 = (insn >> 12) & 0xf;
d2 = insn & 0xfff;
- tmp = load_reg(r1);
/* XXX key in r3 */
- tmp2 = get_address(s, 0, b1, d1);
- tmp3 = get_address(s, 0, b2, d2);
+ tmp = get_address(s, 0, b1, d1);
+ tmp2 = get_address(s, 0, b2, d2);
if (opc == 0xda) {
- gen_helper_mvcp(cc_op, cpu_env, tmp, tmp2, tmp3);
+ gen_helper_mvcp(cc_op, cpu_env, regs[r1], tmp, tmp2);
} else {
- gen_helper_mvcs(cc_op, cpu_env, tmp, tmp2, tmp3);
+ gen_helper_mvcs(cc_op, cpu_env, regs[r1], tmp, tmp2);
}
set_cc_static(s);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
break;
#endif
case 0xe3:
@@ -3346,6 +3269,57 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
}
#endif
+static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ int r3 = get_field(s->fields, r3);
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ while (1) {
+ tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
+ store_reg32_i64(r1, t);
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_addi_i64(o->in2, o->in2, 4);
+ r1 = (r1 + 1) & 15;
+ }
+ return NO_EXIT;
+}
+
+static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ int r3 = get_field(s->fields, r3);
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ while (1) {
+ tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
+ store_reg32h_i64(r1, t);
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_addi_i64(o->in2, o->in2, 4);
+ r1 = (r1 + 1) & 15;
+ }
+ return NO_EXIT;
+}
+
+static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ int r3 = get_field(s->fields, r3);
+ while (1) {
+ tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_addi_i64(o->in2, o->in2, 8);
+ r1 = (r1 + 1) & 15;
+ }
+ return NO_EXIT;
+}
+
static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
{
o->out = o->in2;
@@ -3512,6 +3486,45 @@ static ExitStatus op_st64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stm(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ int r3 = get_field(s->fields, r3);
+ int size = s->insn->data;
+
+ while (1) {
+ if (size == 8) {
+ tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s));
+ } else {
+ tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s));
+ }
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_addi_i64(o->in2, o->in2, size);
+ r1 = (r1 + 1) & 15;
+ }
+ return NO_EXIT;
+}
+
+static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ int r3 = get_field(s->fields, r3);
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ while (1) {
+ tcg_gen_shli_i64(t, regs[r1], 32);
+ tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_addi_i64(o->in2, o->in2, 4);
+ r1 = (r1 + 1) & 15;
+ }
+ return NO_EXIT;
+}
+
static ExitStatus op_sub(DisasContext *s, DisasOps *o)
{
tcg_gen_sub_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 048/126] target-s390: Convert MOVE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (46 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 047/126] target-s390: Convert LOAD, STORE MULTIPLE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 049/126] target-s390: Convert NI, XI, OI Richard Henderson
` (53 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 6 ++++++
target-s390x/translate.c | 27 +++++++++++----------------
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b1f0448..81f2917 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -276,6 +276,12 @@
/* LOAD MULTIPLE HIGH */
C(0xeb96, LMH, RSY_a, Z, 0, a2, 0, 0, lmh, 0)
+/* MOVE */
+ C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0)
+ C(0xe54c, MVHI, SIL, GIE, la1, i2, 0, m1_32, mov2, 0)
+ C(0xe548, MVGHI, SIL, GIE, la1, i2, 0, m1_64, mov2, 0)
+ C(0x9200, MVI, SI, Z, la1, i2, 0, m1_8, mov2, 0)
+ C(0xeb52, MVIY, SIY, LD, la1, i2, 0, m1_8, mov2, 0)
/* MOVE LONG */
C(0x0e00, MVCL, RR_a, Z, 0, 0, 0, 0, mvcl, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4c5540d..ec7ccd3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1325,7 +1325,7 @@ static void disas_e5(DisasContext* s, uint64_t insn)
static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
{
- TCGv_i64 tmp, tmp2;
+ TCGv_i64 tmp;
TCGv_i32 tmp32_1, tmp32_2;
LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
@@ -1391,13 +1391,6 @@ static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x52: /* MVIY D1(B1),I2 [SIY] */
- tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
- tmp2 = tcg_const_i64((r1 << 4) | r3);
- tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
default:
LOG_DISAS("illegal eb operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2233,14 +2226,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x92: /* MVI D1(B1),I2 [SI] */
- insn = ld_code4(s->pc);
- tmp = decode_si(s, insn, &i2, &b1, &d1);
- tmp2 = tcg_const_i64(i2);
- tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x94: /* NI D1(B1),I2 [SI] */
case 0x96: /* OI D1(B1),I2 [SI] */
case 0x97: /* XI D1(B1),I2 [SI] */
@@ -3838,6 +3823,16 @@ static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
}
}
+static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
+}
+
+static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
+}
+
static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 049/126] target-s390: Convert NI, XI, OI
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (47 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 048/126] target-s390: Convert MOVE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 050/126] target-s390: Convert STNSM, STOSM Richard Henderson
` (52 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 6 ++++++
target-s390x/translate.c | 25 -------------------------
2 files changed, 6 insertions(+), 25 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 81f2917..84ca631 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -61,6 +61,8 @@
D(0xa505, NIHL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1020)
D(0xa506, NILH, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1010)
D(0xa507, NILL, RI_a, Z, r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
+ C(0x9400, NI, SI, Z, m1_8u, i2_8u, new, m1_8, and, nz64)
+ C(0xeb54, NIY, SIY, LD, m1_8u, i2_8u, new, m1_8, and, nz64)
/* BRANCH AND SAVE */
C(0x0d00, BASR, RR_a, Z, 0, r2_nz, r1, 0, bas, 0)
@@ -160,6 +162,8 @@
/* EXCLUSIVE OR IMMEDIATE */
D(0xc006, XIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
D(0xc007, XILF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
+ C(0x9700, XI, SI, Z, m1_8u, i2_8u, new, m1_8, xor, nz64)
+ C(0xeb57, XIY, SIY, LD, m1_8u, i2_8u, new, m1_8, xor, nz64)
/* EXECUTE */
C(0x4400, EX, RX_a, Z, r1_o, a2, 0, 0, ex, 0)
@@ -327,6 +331,8 @@
D(0xa509, OIHL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1020)
D(0xa50a, OILH, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
D(0xa50b, OILL, RI_a, Z, r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
+ C(0x9600, OI, SI, Z, m1_8u, i2_8u, new, m1_8, or, nz64)
+ C(0xeb56, OIY, SIY, LD, m1_8u, i2_8u, new, m1_8, or, nz64)
/* ROTATE LEFT SINGLE LOGICAL */
C(0xeb1d, RLL, RSY_a, Z, r3_o, sh32, new, r1_32, rll32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ec7ccd3..4ddd77f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2226,31 +2226,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x94: /* NI D1(B1),I2 [SI] */
- case 0x96: /* OI D1(B1),I2 [SI] */
- case 0x97: /* XI D1(B1),I2 [SI] */
- insn = ld_code4(s->pc);
- tmp = decode_si(s, insn, &i2, &b1, &d1);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
- switch (opc) {
- case 0x94:
- tcg_gen_andi_i64(tmp2, tmp2, i2);
- break;
- case 0x96:
- tcg_gen_ori_i64(tmp2, tmp2, i2);
- break;
- case 0x97:
- tcg_gen_xori_i64(tmp2, tmp2, i2);
- break;
- default:
- tcg_abort();
- }
- tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
- set_cc_nz_u64(s, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x9a: /* LAM R1,R3,D2(B2) [RS] */
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 050/126] target-s390: Convert STNSM, STOSM
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (48 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 049/126] target-s390: Convert NI, XI, OI Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 051/126] target-s390: Convert LAM, STAM Richard Henderson
` (51 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 37 +++++++++++++++++++------------------
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 84ca631..52f44e0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -444,4 +444,8 @@
C(0x010e, SAM64, E, Z, 0, 0, 0, 0, 0, 0)
/* SET SYSTEM MASK */
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
+/* STORE THEN AND SYSTEM MASK */
+ C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
+/* STORE THEN OR SYSTEM MASK */
+ C(0xad00, STOSM, SI, Z, la1, 0, new, m1_8, stosm, 0)
#endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4ddd77f..295caec 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2219,7 +2219,7 @@ static void disas_s390_insn(DisasContext *s)
TCGv_i32 tmp32_1, tmp32_2;
unsigned char opc;
uint64_t insn;
- int op, r1, r2, r3, d1, d2, x2, b1, b2, i2, r1b;
+ int op, r1, r2, r3, d1, d2, x2, b1, b2, r1b;
TCGv_i32 vl;
opc = cpu_ldub_code(cpu_single_env, s->pc);
@@ -2277,23 +2277,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_2);
break;
#ifndef CONFIG_USER_ONLY
- case 0xac: /* STNSM D1(B1),I2 [SI] */
- case 0xad: /* STOSM D1(B1),I2 [SI] */
- check_privileged(s);
- insn = ld_code4(s->pc);
- tmp = decode_si(s, insn, &i2, &b1, &d1);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_shri_i64(tmp2, psw_mask, 56);
- tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
- if (opc == 0xac) {
- tcg_gen_andi_i64(psw_mask, psw_mask,
- ((uint64_t)i2 << 56) | 0x00ffffffffffffffULL);
- } else {
- tcg_gen_ori_i64(psw_mask, psw_mask, (uint64_t)i2 << 56);
- }
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
check_privileged(s);
insn = ld_code4(s->pc);
@@ -3420,6 +3403,24 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
return NO_EXIT;
}
+
+static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
+{
+ uint64_t i2 = get_field(s->fields, i2);
+ check_privileged(s);
+ tcg_gen_shri_i64(o->out, psw_mask, 56);
+ tcg_gen_andi_i64(psw_mask, psw_mask, (i2 << 56) | 0x00ffffffffffffffull);
+ return NO_EXIT;
+}
+
+static ExitStatus op_stosm(DisasContext *s, DisasOps *o)
+{
+ uint64_t i2 = get_field(s->fields, i2);
+ check_privileged(s);
+ tcg_gen_shri_i64(o->out, psw_mask, 56);
+ tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
+ return NO_EXIT;
+}
#endif
static ExitStatus op_st8(DisasContext *s, DisasOps *o)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 051/126] target-s390: Convert LAM, STAM
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (49 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 050/126] target-s390: Convert STNSM, STOSM Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 052/126] target-s390: Convert CLCLE, MVCLE Richard Henderson
` (50 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 6 ++++++
target-s390x/translate.c | 46 ++++++++++++++++++++++------------------------
2 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 52f44e0..598447e 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -279,6 +279,9 @@
C(0xeb04, LMG, RSY_a, Z, 0, a2, 0, 0, lm64, 0)
/* LOAD MULTIPLE HIGH */
C(0xeb96, LMH, RSY_a, Z, 0, a2, 0, 0, lmh, 0)
+/* LOAD ACCESS MULTIPLE */
+ C(0x9a00, LAM, RS_a, Z, 0, a2, 0, 0, lam, 0)
+ C(0xeb9a, LAMY, RSY_a, LD, 0, a2, 0, 0, lam, 0)
/* MOVE */
C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0)
@@ -389,6 +392,9 @@
D(0xeb24, STMG, RSY_a, Z, 0, a2, 0, 0, stm, 0, 8)
/* STORE MULTIPLE HIGH */
C(0xeb26, STMH, RSY_a, Z, 0, a2, 0, 0, stmh, 0)
+/* STORE ACCESS MULTIPLE */
+ C(0x9b00, STAM, RS_a, Z, 0, a2, 0, 0, stam, 0)
+ C(0xeb9b, STAMY, RSY_a, LD, 0, a2, 0, 0, stam, 0)
/* SUBTRACT */
C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 295caec..43c7ec7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2226,30 +2226,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x9a: /* LAM R1,R3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_lam(cpu_env, tmp32_1, tmp, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
- case 0x9b: /* STAM R1,R3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_stam(cpu_env, tmp32_1, tmp, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -3212,6 +3188,17 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
}
#endif
+static ExitStatus op_lam(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ potential_page_fault(s);
+ gen_helper_lam(cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ return NO_EXIT;
+}
+
static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s->fields, r1);
@@ -3447,6 +3434,17 @@ static ExitStatus op_st64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stam(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ potential_page_fault(s);
+ gen_helper_stam(cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ return NO_EXIT;
+}
+
static ExitStatus op_stm(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s->fields, r1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 052/126] target-s390: Convert CLCLE, MVCLE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (50 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 051/126] target-s390: Convert LAM, STAM Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 053/126] target-s390: Convert MVC Richard Henderson
` (49 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 50 ++++++++++++++++++++++------------------------
2 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 598447e..c1dafea 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -132,6 +132,8 @@
C(0xc60e, CLGFRL, RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu64)
C(0xc607, CLHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
+/* COMPARE LOGICAL LONG EXTENDED */
+ C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0)
/* CONVERT TO DECIMAL */
C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
@@ -291,6 +293,8 @@
C(0xeb52, MVIY, SIY, LD, la1, i2, 0, m1_8, mov2, 0)
/* MOVE LONG */
C(0x0e00, MVCL, RR_a, Z, 0, 0, 0, 0, mvcl, 0)
+/* MOVE LONG EXTENDED */
+ C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0)
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 43c7ec7..0de193a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2226,32 +2226,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_mvcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
- case 0xa9: /* CLCLE R1,R3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_clcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
#ifndef CONFIG_USER_ONLY
case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
check_privileged(s);
@@ -2977,6 +2951,18 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ potential_page_fault(s);
+ gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
{
TCGv_i64 t1 = tcg_temp_new_i64();
@@ -3283,6 +3269,18 @@ static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ potential_page_fault(s);
+ gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
{
tcg_gen_mul_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 053/126] target-s390: Convert MVC
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (51 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 052/126] target-s390: Convert CLCLE, MVCLE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-18 20:52 ` Alexander Graf
2012-09-09 21:05 ` [Qemu-devel] [PATCH 054/126] target-s390: Convert NC, XC, OC, TR, UNPK Richard Henderson
` (48 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
The code that was in gen_op_mvc was a bit confused wrt what lengths
it wanted to handle. I also disbelieve that the inline memset is
worthwhile.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 1 +
target-s390x/translate.c | 177 +++------------------------------------------
2 files changed, 10 insertions(+), 168 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c1dafea..aa70715 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -286,6 +286,7 @@
C(0xeb9a, LAMY, RSY_a, LD, 0, a2, 0, 0, lam, 0)
/* MOVE */
+ C(0xd200, MVC, SS_a, Z, la1, a2, 0, 0, mvc, 0)
C(0xe544, MVHHI, SIL, GIE, la1, i2, 0, m1_16, mov2, 0)
C(0xe54c, MVHI, SIL, GIE, la1, i2, 0, m1_32, mov2, 0)
C(0xe548, MVGHI, SIL, GIE, la1, i2, 0, m1_64, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0de193a..f463525 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1010,170 +1010,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
-{
- TCGv_i64 tmp, tmp2;
- int i;
- int l_memset = gen_new_label();
- int l_out = gen_new_label();
- TCGv_i64 dest = tcg_temp_local_new_i64();
- TCGv_i64 src = tcg_temp_local_new_i64();
- TCGv_i32 vl;
-
- /* Find out if we should use the inline version of mvc */
- switch (l) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 11:
- case 15:
- /* use inline */
- break;
- default:
- /* Fall back to helper */
- vl = tcg_const_i32(l);
- potential_page_fault(s);
- gen_helper_mvc(cpu_env, vl, s1, s2);
- tcg_temp_free_i32(vl);
- return;
- }
-
- tcg_gen_mov_i64(dest, s1);
- tcg_gen_mov_i64(src, s2);
-
- if (!(s->tb->flags & FLAG_MASK_64)) {
- /* XXX what if we overflow while moving? */
- tcg_gen_andi_i64(dest, dest, 0x7fffffffUL);
- tcg_gen_andi_i64(src, src, 0x7fffffffUL);
- }
-
- tmp = tcg_temp_new_i64();
- tcg_gen_addi_i64(tmp, src, 1);
- tcg_gen_brcond_i64(TCG_COND_EQ, dest, tmp, l_memset);
- tcg_temp_free_i64(tmp);
-
- switch (l) {
- case 0:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- case 1:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld16u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st16(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- case 3:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- case 4:
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
- tcg_gen_addi_i64(src, src, 4);
- tcg_gen_qemu_ld8u(tmp2, src, get_mem_index(s));
- tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
- tcg_gen_addi_i64(dest, dest, 4);
- tcg_gen_qemu_st8(tmp2, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- case 7:
- tmp = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
-
- tcg_temp_free_i64(tmp);
- break;
- default:
- /* The inline version can become too big for too uneven numbers, only
- use it on known good lengths */
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_const_i64(8);
- for (i = 0; (i + 7) <= l; i += 8) {
- tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
-
- tcg_gen_add_i64(src, src, tmp2);
- tcg_gen_add_i64(dest, dest, tmp2);
- }
-
- tcg_temp_free_i64(tmp2);
- tmp2 = tcg_const_i64(1);
-
- for (; i <= l; i++) {
- tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
- tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
-
- tcg_gen_add_i64(src, src, tmp2);
- tcg_gen_add_i64(dest, dest, tmp2);
- }
-
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp);
- break;
- }
-
- tcg_gen_br(l_out);
-
- gen_set_label(l_memset);
- /* memset case (dest == (src + 1)) */
-
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
- /* fill tmp with the byte */
- tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
- tcg_gen_shli_i64(tmp2, tmp, 8);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- tcg_gen_shli_i64(tmp2, tmp, 16);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- tcg_gen_shli_i64(tmp2, tmp, 32);
- tcg_gen_or_i64(tmp, tmp, tmp2);
- tcg_temp_free_i64(tmp2);
-
- tmp2 = tcg_const_i64(8);
-
- for (i = 0; (i + 7) <= l; i += 8) {
- tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
- tcg_gen_addi_i64(dest, dest, 8);
- }
-
- tcg_temp_free_i64(tmp2);
- tmp2 = tcg_const_i64(1);
-
- for (; i <= l; i++) {
- tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
- tcg_gen_addi_i64(dest, dest, 1);
- }
-
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp);
-
- gen_set_label(l_out);
-
- tcg_temp_free(dest);
- tcg_temp_free(src);
-}
-
static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
{
TCGv_i64 tmp;
@@ -2358,7 +2194,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xd2: /* MVC D1(L,B1),D2(B2) [SS] */
case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
case 0xd6: /* OC D1(L,B1),D2(B2) [SS] */
@@ -2374,9 +2209,6 @@ static void disas_s390_insn(DisasContext *s)
tmp = get_address(s, 0, b1, d1);
tmp2 = get_address(s, 0, b2, d2);
switch (opc) {
- case 0xd2:
- gen_op_mvc(s, (insn >> 32) & 0xff, tmp, tmp2);
- break;
case 0xd4:
potential_page_fault(s);
gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2);
@@ -3257,6 +3089,15 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ potential_page_fault(s);
+ gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
+ tcg_temp_free_i32(l);
+ return NO_EXIT;
+}
+
static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 054/126] target-s390: Convert NC, XC, OC, TR, UNPK
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (52 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 053/126] target-s390: Convert MVC Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 055/126] target-s390: Convert CLC Richard Henderson
` (47 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 11 ++++++
target-s390x/translate.c | 88 ++++++++++++++++++++++++++--------------------
2 files changed, 61 insertions(+), 38 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index aa70715..f7941d8 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -54,6 +54,7 @@
C(0xb980, NGR, RRE, Z, r1, r2, r1, 0, and, nz64)
C(0xb9e4, NGRK, RRF_a, DO, r2, r3, r1, 0, and, nz64)
C(0xe380, NG, RXY_a, Z, r1, m2_64, r1, 0, and, nz64)
+ C(0xd400, NC, SS_a, Z, la1, a2, 0, 0, nc, 0)
/* AND IMMEDIATE */
D(0xc00a, NIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, andi, 0, 0x2020)
D(0xc00b, NILF, RIL_a, EI, r1_o, i2_32u, r1, 0, andi, 0, 0x2000)
@@ -161,6 +162,7 @@
C(0xb982, XGR, RRE, Z, r1, r2, r1, 0, xor, nz64)
C(0xb9e7, XGRK, RRF_a, DO, r2, r3, r1, 0, xor, nz64)
C(0xe382, XG, RXY_a, Z, r1, m2_64, r1, 0, xor, nz64)
+ C(0xd700, XC, SS_a, Z, la1, a2, 0, 0, xc, 0)
/* EXCLUSIVE OR IMMEDIATE */
D(0xc006, XIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
D(0xc007, XILF, RIL_a, EI, r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
@@ -332,6 +334,7 @@
C(0xb981, OGR, RRE, Z, r1, r2, r1, 0, or, nz64)
C(0xb9e6, OGRK, RRF_a, DO, r2, r3, r1, 0, or, nz64)
C(0xe381, OG, RXY_a, Z, r1, m2_64, r1, 0, or, nz64)
+ C(0xd600, OC, SS_a, Z, la1, a2, 0, 0, oc, 0)
/* OR IMMEDIATE */
D(0xc00c, OIHF, RIL_a, EI, r1_o, i2_32u, r1, 0, ori, 0, 0x2020)
D(0xc00d, OILF, RIL_a, EI, r1_o, i2_32u, r1, 0, ori, 0, 0x2000)
@@ -444,6 +447,14 @@
D(0xa700, TMLH, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
D(0xa701, TMLL, RI_a, Z, r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
+/* TRANSLATE */
+ C(0xdc00, TR, SS_a, Z, la1, a2, 0, 0, tr, 0)
+
+/* UNPACK */
+ /* Really format SS_b, but we pack both lengths into one argument
+ for the helper call, so we might as well leave one 8-bit field. */
+ C(0xf300, UNPK, SS_a, Z, la1, a2, 0, 0, unpk, 0)
+
#ifndef CONFIG_USER_ONLY
/* DIAGNOSE (KVM hypercall) */
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f463525..45b8c3a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2056,7 +2056,6 @@ static void disas_s390_insn(DisasContext *s)
unsigned char opc;
uint64_t insn;
int op, r1, r2, r3, d1, d2, x2, b1, b2, r1b;
- TCGv_i32 vl;
opc = cpu_ldub_code(cpu_single_env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -2194,51 +2193,15 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
- case 0xd6: /* OC D1(L,B1),D2(B2) [SS] */
- case 0xd7: /* XC D1(L,B1),D2(B2) [SS] */
- case 0xdc: /* TR D1(L,B1),D2(B2) [SS] */
- case 0xf3: /* UNPK D1(L1,B1),D2(L2,B2) [SS] */
insn = ld_code6(s->pc);
- vl = tcg_const_i32((insn >> 32) & 0xff);
b1 = (insn >> 28) & 0xf;
b2 = (insn >> 12) & 0xf;
d1 = (insn >> 16) & 0xfff;
d2 = insn & 0xfff;
tmp = get_address(s, 0, b1, d1);
tmp2 = get_address(s, 0, b2, d2);
- switch (opc) {
- case 0xd4:
- potential_page_fault(s);
- gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2);
- set_cc_static(s);
- break;
- case 0xd5:
- gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
- break;
- case 0xd6:
- potential_page_fault(s);
- gen_helper_oc(cc_op, cpu_env, vl, tmp, tmp2);
- set_cc_static(s);
- break;
- case 0xd7:
- potential_page_fault(s);
- gen_helper_xc(cc_op, cpu_env, vl, tmp, tmp2);
- set_cc_static(s);
- break;
- case 0xdc:
- potential_page_fault(s);
- gen_helper_tr(cpu_env, vl, tmp, tmp2);
- set_cc_static(s);
- break;
- case 0xf3:
- potential_page_fault(s);
- gen_helper_unpk(cpu_env, vl, tmp, tmp2);
- break;
- default:
- tcg_abort();
- }
+ gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
@@ -3141,12 +3104,32 @@ static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_nc(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ potential_page_fault(s);
+ gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
+ tcg_temp_free_i32(l);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_neg(DisasContext *s, DisasOps *o)
{
tcg_gen_neg_i64(o->out, o->in2);
return NO_EXIT;
}
+static ExitStatus op_oc(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ potential_page_fault(s);
+ gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
+ tcg_temp_free_i32(l);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_or(DisasContext *s, DisasOps *o)
{
tcg_gen_or_i64(o->out, o->in1, o->in2);
@@ -3366,6 +3349,35 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
return EXIT_NORETURN;
}
+static ExitStatus op_tr(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ potential_page_fault(s);
+ gen_helper_tr(cpu_env, l, o->addr1, o->in2);
+ tcg_temp_free_i32(l);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ potential_page_fault(s);
+ gen_helper_unpk(cpu_env, l, o->addr1, o->in2);
+ tcg_temp_free_i32(l);
+ return NO_EXIT;
+}
+
+static ExitStatus op_xc(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ potential_page_fault(s);
+ gen_helper_xc(cc_op, cpu_env, l, o->addr1, o->in2);
+ tcg_temp_free_i32(l);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_xor(DisasContext *s, DisasOps *o)
{
tcg_gen_xor_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 055/126] target-s390: Convert CLC
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (53 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 054/126] target-s390: Convert NC, XC, OC, TR, UNPK Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 056/126] target-s390: Convert MVCP, MVCS Richard Henderson
` (46 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 1 +
target-s390x/translate.c | 107 ++++++++++++++-------------------------------
2 files changed, 35 insertions(+), 73 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f7941d8..fa0711f 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -119,6 +119,7 @@
C(0xb931, CLGFR, RRE, Z, r1, r2_32u, 0, 0, 0, cmpu64)
C(0xe321, CLG, RXY_a, Z, r1, m2_64, 0, 0, 0, cmpu64)
C(0xe331, CLGF, RXY_a, Z, r1, m2_32u, 0, 0, 0, cmpu64)
+ C(0xd500, CLC, SS_a, Z, la1, a2, 0, 0, clc, 0)
/* COMPARE LOGICAL IMMEDIATE */
C(0xc20f, CLFI, RIL_a, EI, r1, i2, 0, 0, 0, cmpu32)
C(0xc20e, CLGFI, RIL_a, EI, r1, i2_32u, 0, 0, 0, cmpu64)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 45b8c3a..b3f79bd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1010,67 +1010,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
-{
- TCGv_i64 tmp;
- TCGv_i64 tmp2;
- TCGv_i32 vl;
-
- /* check for simple 32bit or 64bit match */
- switch (l) {
- case 0:
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld8u(tmp, s1, get_mem_index(s));
- tcg_gen_qemu_ld8u(tmp2, s2, get_mem_index(s));
- cmp_u64(s, tmp, tmp2);
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- return;
- case 1:
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld16u(tmp, s1, get_mem_index(s));
- tcg_gen_qemu_ld16u(tmp2, s2, get_mem_index(s));
- cmp_u64(s, tmp, tmp2);
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- return;
- case 3:
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld32u(tmp, s1, get_mem_index(s));
- tcg_gen_qemu_ld32u(tmp2, s2, get_mem_index(s));
- cmp_u64(s, tmp, tmp2);
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- return;
- case 7:
- tmp = tcg_temp_new_i64();
- tmp2 = tcg_temp_new_i64();
-
- tcg_gen_qemu_ld64(tmp, s1, get_mem_index(s));
- tcg_gen_qemu_ld64(tmp2, s2, get_mem_index(s));
- cmp_u64(s, tmp, tmp2);
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- return;
- }
-
- potential_page_fault(s);
- vl = tcg_const_i32(l);
- gen_helper_clc(cc_op, cpu_env, vl, s1, s2);
- tcg_temp_free_i32(vl);
- set_cc_static(s);
-}
-
static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
{
TCGv_i64 addr, tmp2;
@@ -2193,18 +2132,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xd5: /* CLC D1(L,B1),D2(B2) [SS] */
- insn = ld_code6(s->pc);
- b1 = (insn >> 28) & 0xf;
- b2 = (insn >> 12) & 0xf;
- d1 = (insn >> 16) & 0xfff;
- d2 = insn & 0xfff;
- tmp = get_address(s, 0, b1, d1);
- tmp2 = get_address(s, 0, b2, d2);
- gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
#ifndef CONFIG_USER_ONLY
case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */
case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */
@@ -2746,6 +2673,40 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_clc(DisasContext *s, DisasOps *o)
+{
+ int l = get_field(s->fields, l1);
+ TCGv_i32 vl;
+
+ switch (l + 1) {
+ case 1:
+ tcg_gen_qemu_ld8u(cc_src, o->addr1, get_mem_index(s));
+ tcg_gen_qemu_ld8u(cc_dst, o->in2, get_mem_index(s));
+ break;
+ case 2:
+ tcg_gen_qemu_ld16u(cc_src, o->addr1, get_mem_index(s));
+ tcg_gen_qemu_ld16u(cc_dst, o->in2, get_mem_index(s));
+ break;
+ case 4:
+ tcg_gen_qemu_ld32u(cc_src, o->addr1, get_mem_index(s));
+ tcg_gen_qemu_ld32u(cc_dst, o->in2, get_mem_index(s));
+ break;
+ case 8:
+ tcg_gen_qemu_ld64(cc_src, o->addr1, get_mem_index(s));
+ tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s));
+ break;
+ default:
+ potential_page_fault(s);
+ vl = tcg_const_i32(l);
+ gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2);
+ tcg_temp_free_i32(vl);
+ set_cc_static(s);
+ return NO_EXIT;
+ }
+ gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst);
+ return NO_EXIT;
+}
+
static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 056/126] target-s390: Convert MVCP, MVCS
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (54 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 055/126] target-s390: Convert CLC Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 057/126] target-s390: Convert LRA Richard Henderson
` (45 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 49 ++++++++++++++++++++++------------------------
2 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index fa0711f..301e509 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -461,6 +461,10 @@
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
/* LOAD PSW */
C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
+/* MOVE TO PRIMARY */
+ C(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0)
+/* MOVE TO SECONDARY */
+ C(0xdb00, MVCS, SS_d, Z, la1, a2, 0, 0, mvcs, 0)
/* SET ADDRESSING MODE */
/* We only do 64-bit, so accept this as a no-op.
Let SAM24 and SAM31 signal illegal instruction. */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b3f79bd..c8ab897 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1994,7 +1994,7 @@ static void disas_s390_insn(DisasContext *s)
TCGv_i32 tmp32_1, tmp32_2;
unsigned char opc;
uint64_t insn;
- int op, r1, r2, r3, d1, d2, x2, b1, b2, r1b;
+ int op, r1, r2, r3, d2, x2, b2, r1b;
opc = cpu_ldub_code(cpu_single_env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -2132,31 +2132,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
-#ifndef CONFIG_USER_ONLY
- case 0xda: /* MVCP D1(R1,B1),D2(B2),R3 [SS] */
- case 0xdb: /* MVCS D1(R1,B1),D2(B2),R3 [SS] */
- check_privileged(s);
- potential_page_fault(s);
- insn = ld_code6(s->pc);
- r1 = (insn >> 36) & 0xf;
- r3 = (insn >> 32) & 0xf;
- b1 = (insn >> 28) & 0xf;
- d1 = (insn >> 16) & 0xfff;
- b2 = (insn >> 12) & 0xf;
- d2 = insn & 0xfff;
- /* XXX key in r3 */
- tmp = get_address(s, 0, b1, d1);
- tmp2 = get_address(s, 0, b2, d2);
- if (opc == 0xda) {
- gen_helper_mvcp(cc_op, cpu_env, regs[r1], tmp, tmp2);
- } else {
- gen_helper_mvcs(cc_op, cpu_env, regs[r1], tmp, tmp2);
- }
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
-#endif
case 0xe3:
insn = ld_code6(s->pc);
debug_insn(insn);
@@ -3046,6 +3021,28 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_mvcp(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, l1);
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, l1);
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
{
tcg_gen_mul_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 057/126] target-s390: Convert LRA
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (55 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 056/126] target-s390: Convert MVCP, MVCS Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 058/126] target-s390: Convert SIGP Richard Henderson
` (44 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Note that truncating the store to r1 based on PSW_MASK_64
is incorrect. We always modify the entire register.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 4 ++++
target-s390x/mem_helper.c | 13 +++----------
target-s390x/translate.c | 20 +++++++++-----------
4 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 93931e4..4a041cb 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -140,7 +140,7 @@ DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
DEF_HELPER_2(sacf, void, env, i64)
DEF_HELPER_FLAGS_3(ipte, TCG_CALL_CONST, void, env, i64, i64)
DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env)
-DEF_HELPER_3(lra, i32, env, i64, i32)
+DEF_HELPER_2(lra, i64, env, i64)
DEF_HELPER_3(stura, void, env, i64, i32)
DEF_HELPER_3(cksm, void, env, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 301e509..a078cc5 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -461,6 +461,10 @@
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
/* LOAD PSW */
C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
+/* LOAD REAL ADDRESS */
+ C(0xb100, LRA, RX_a, Z, 0, a2, r1, 0, lra, 0)
+ C(0xe313, LRAY, RXY_a, LD, 0, a2, r1, 0, lra, 0)
+ C(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0)
/* MOVE TO PRIMARY */
C(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0)
/* MOVE TO SECONDARY */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index b868346..961f748 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -1133,7 +1133,7 @@ void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint32_t v1)
}
/* load real address */
-uint32_t HELPER(lra)(CPUS390XState *env, uint64_t addr, uint32_t r1)
+uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
{
uint32_t cc = 0;
int old_exc = env->exception_index;
@@ -1157,14 +1157,7 @@ uint32_t HELPER(lra)(CPUS390XState *env, uint64_t addr, uint32_t r1)
}
env->exception_index = old_exc;
- if (!(env->psw.mask & PSW_MASK_64)) {
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- (ret & 0xffffffffULL);
- } else {
- env->regs[r1] = ret;
- }
-
- return cc;
+ env->cc_op = cc;
+ return ret;
}
-
#endif
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c8ab897..1829b25 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2015,17 +2015,6 @@ static void disas_s390_insn(DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
- check_privileged(s);
- insn = ld_code4(s->pc);
- tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
- tmp32_1 = tcg_const_i32(r1);
- potential_page_fault(s);
- gen_helper_lra(cc_op, cpu_env, tmp, tmp32_1);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- break;
#endif
case 0xb2:
insn = ld_code4(s->pc);
@@ -2887,6 +2876,15 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
}
#ifndef CONFIG_USER_ONLY
+static ExitStatus op_lra(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_lra(o->out, cpu_env, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
{
TCGv_i64 t1, t2;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 058/126] target-s390: Convert SIGP
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (56 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 057/126] target-s390: Convert LRA Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 059/126] target-s390: Convert EFPC, STFPC Richard Henderson
` (43 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 28 ++++++++++++----------------
2 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a078cc5..95f9987 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -475,6 +475,8 @@
C(0x010e, SAM64, E, Z, 0, 0, 0, 0, 0, 0)
/* SET SYSTEM MASK */
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
+/* SIGNAL PROCESSOR */
+ C(0xae00, SIGP, RS_a, Z, r3_o, a2, 0, 0, sigp, 0)
/* STORE THEN AND SYSTEM MASK */
C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1829b25..698cb99 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2000,22 +2000,6 @@ static void disas_s390_insn(DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
-#ifndef CONFIG_USER_ONLY
- case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
- check_privileged(s);
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp2 = load_reg(r3);
- tmp32_1 = tcg_const_i32(r1);
- potential_page_fault(s);
- gen_helper_sigp(cc_op, cpu_env, tmp, tmp32_1, tmp2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
-#endif
case 0xb2:
insn = ld_code4(s->pc);
op = (insn >> 16) & 0xff;
@@ -3129,6 +3113,18 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_sigp(cc_op, cpu_env, o->in2, r1, o->in1);
+ tcg_temp_free_i32(r1);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_sla(DisasContext *s, DisasOps *o)
{
uint64_t sign = 1ull << s->insn->data;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 059/126] target-s390: Convert EFPC, STFPC
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (57 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 058/126] target-s390: Convert SIGP Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 060/126] target-s390: Convert LCTL, STCTL Richard Henderson
` (42 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 6 ++++++
target-s390x/translate.c | 38 +++++++++++++-------------------------
2 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 95f9987..745d1e6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -175,6 +175,9 @@
/* EXECUTE RELATIVE LONG */
C(0xc600, EXRL, RIL_b, EE, r1_o, ri2, 0, 0, ex, 0)
+/* EXTRACT FPC */
+ C(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0)
+
/* INSERT CHARACTER */
C(0x4300, IC, RX_a, Z, 0, m2_8u, 0, r1_8, mov2, 0)
C(0xe373, ICY, RXY_a, LD, 0, m2_8u, 0, r1_8, mov2, 0)
@@ -395,6 +398,9 @@
/* STORE HALFWORD RELATIVE LONG */
C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
+/* STORE FPC */
+ C(0xb29c, STFPC, S, Z, 0, a2, new, m2_32, efpc, 0)
+
/* STORE MULTIPLE */
D(0x9000, STM, RS_a, Z, 0, a2, 0, 0, stm, 0, 4)
D(0xeb90, STMY, RSY_a, LD, 0, a2, 0, 0, stm, 0, 4)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 698cb99..439a90d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1833,12 +1833,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
tcg_temp_free_i32(tmp32_1);
break;
- case 0x8c: /* EFPC R1 [RRE] */
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x94: /* CEFBR R1,R2 [RRE] */
case 0x95: /* CDFBR R1,R2 [RRE] */
case 0x96: /* CXFBR R1,R2 [RRE] */
@@ -1990,7 +1984,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
static void disas_s390_insn(DisasContext *s)
{
- TCGv_i64 tmp, tmp2;
+ TCGv_i64 tmp;
TCGv_i32 tmp32_1, tmp32_2;
unsigned char opc;
uint64_t insn;
@@ -2003,24 +1997,7 @@ static void disas_s390_insn(DisasContext *s)
case 0xb2:
insn = ld_code4(s->pc);
op = (insn >> 16) & 0xff;
- switch (op) {
- case 0x9c: /* STFPC D2(B2) [S] */
- d2 = insn & 0xfff;
- b2 = (insn >> 12) & 0xf;
- tmp32_1 = tcg_temp_new_i32();
- tmp = tcg_temp_new_i64();
- tmp2 = get_address(s, 0, b2, d2);
- tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
- tcg_gen_extu_i32_i64(tmp, tmp32_1);
- tcg_gen_qemu_st32(tmp, tmp2, get_mem_index(s));
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
- default:
- disas_b2(s, op, insn);
- break;
- }
+ disas_b2(s, op, insn);
break;
case 0xb3:
insn = ld_code4(s->pc);
@@ -2723,6 +2700,12 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
+ return NO_EXIT;
+}
+
static ExitStatus op_ex(DisasContext *s, DisasOps *o)
{
/* ??? Perhaps a better way to implement EXECUTE is to set a bit in
@@ -3620,6 +3603,11 @@ static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
}
+static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
+}
+
/* ====================================================================== */
/* The "INput 1" generators. These load the first operand to an insn. */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 060/126] target-s390: Convert LCTL, STCTL
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (58 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 059/126] target-s390: Convert EFPC, STFPC Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 061/126] target-s390: Convert COMPARE AND SWAP Richard Henderson
` (41 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 54 +++++++++++++++++++++-------------------------
2 files changed, 28 insertions(+), 30 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 745d1e6..522fe12 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -465,6 +465,8 @@
#ifndef CONFIG_USER_ONLY
/* DIAGNOSE (KVM hypercall) */
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
+/* LOAD CONTROL */
+ C(0xb700, LCTL, RS_a, Z, 0, a2, 0, 0, lctl, 0)
/* LOAD PSW */
C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
/* LOAD REAL ADDRESS */
@@ -483,6 +485,8 @@
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
/* SIGNAL PROCESSOR */
C(0xae00, SIGP, RS_a, Z, r3_o, a2, 0, 0, sigp, 0)
+/* STORE CONTROL */
+ C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0)
/* STORE THEN AND SYSTEM MASK */
C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 439a90d..d08b42f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2007,36 +2007,6 @@ static void disas_s390_insn(DisasContext *s)
r2 = insn & 0xf;
disas_b3(s, op, r3, r1, r2);
break;
-#ifndef CONFIG_USER_ONLY
- case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
- /* Store Control */
- check_privileged(s);
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_stctl(cpu_env, tmp32_1, tmp, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
- case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
- /* Load Control */
- check_privileged(s);
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_lctl(cpu_env, tmp32_1, tmp, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
-#endif
case 0xb9:
insn = ld_code4(s->pc);
r1 = (insn >> 4) & 0xf;
@@ -2843,6 +2813,18 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
}
#ifndef CONFIG_USER_ONLY
+static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_lctl(cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ return NO_EXIT;
+}
+
static ExitStatus op_lra(DisasContext *s, DisasOps *o)
{
check_privileged(s);
@@ -3148,6 +3130,18 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_stctl(cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ return NO_EXIT;
+}
+
static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 061/126] target-s390: Convert COMPARE AND SWAP
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (59 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 060/126] target-s390: Convert LCTL, STCTL Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 062/126] target-s390: Convert CLM Richard Henderson
` (40 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 4 +--
target-s390x/insn-data.def | 9 ++++++
target-s390x/mem_helper.c | 33 +++++++++-----------
target-s390x/translate.c | 78 ++++++++++++++++++++++++----------------------
4 files changed, 66 insertions(+), 58 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 4a041cb..38b9aa4 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -29,9 +29,9 @@ DEF_HELPER_4(srst, i32, env, i32, i32, i32)
DEF_HELPER_4(clst, i32, env, i32, i32, i32)
DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
DEF_HELPER_4(mvst, void, env, i32, i32, i32)
-DEF_HELPER_4(csg, i32, env, i32, i64, i32)
+DEF_HELPER_4(csg, i64, env, i64, i64, i64)
DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
-DEF_HELPER_4(cs, i32, env, i32, i64, i32)
+DEF_HELPER_4(cs, i64, env, i64, i64, i64)
DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 522fe12..d2c9671 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -137,6 +137,15 @@
/* COMPARE LOGICAL LONG EXTENDED */
C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0)
+/* COMPARE AND SWAP */
+ C(0xba00, CS, RS_a, Z, r1_o, a2, new, r1_32, cs, 0)
+ C(0xeb14, CSY, RSY_a, LD, r1_o, a2, new, r1_32, cs, 0)
+ C(0xeb30, CSG, RSY_a, Z, r1_o, a2, r1, 0, csg, 0)
+/* COMPARE DOUBLE AND SWAP */
+ C(0xbb00, CDS, RS_a, Z, r1_P32, a2, new, r1_P32, cds, 0)
+ C(0xeb31, CDSY, RSY_a, LD, r1_P32, a2, new, r1_P32, cds, 0)
+ C(0xeb3e, CDSG, RSY_a, Z, 0, a2, 0, 0, cdsg, 0)
+
/* CONVERT TO DECIMAL */
C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 961f748..90d2c39 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -463,20 +463,18 @@ void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
}
/* compare and swap 64-bit */
-uint32_t HELPER(csg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+uint64_t HELPER(csg)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
{
/* FIXME: locking? */
- uint32_t cc;
uint64_t v2 = cpu_ldq_data(env, a2);
-
- if (env->regs[r1] == v2) {
- cc = 0;
- cpu_stq_data(env, a2, env->regs[r3]);
+ if (r1 == v2) {
+ cpu_stq_data(env, a2, r3);
+ env->cc_op = 0;
+ return r1;
} else {
- cc = 1;
- env->regs[r1] = v2;
+ env->cc_op = 1;
+ return v2;
}
- return cc;
}
/* compare double and swap 64-bit */
@@ -503,21 +501,18 @@ uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
}
/* compare and swap 32-bit */
-uint32_t HELPER(cs)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+uint64_t HELPER(cs)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
{
/* FIXME: locking? */
- uint32_t cc;
uint32_t v2 = cpu_ldl_data(env, a2);
-
- HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3);
- if (((uint32_t)env->regs[r1]) == v2) {
- cc = 0;
- cpu_stl_data(env, a2, (uint32_t)env->regs[r3]);
+ if ((uint32_t)r1 == v2) {
+ cpu_stl_data(env, a2, (uint32_t)r3);
+ env->cc_op = 0;
+ return r1;
} else {
- cc = 1;
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
+ env->cc_op = 1;
+ return v2;
}
- return cc;
}
static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address,
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d08b42f..dcb663d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1142,30 +1142,6 @@ static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
tcg_temp_free_i32(tmp32_2);
break;
#endif
- case 0x30: /* CSG R1,R3,D2(B2) [RSY] */
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- /* XXX rewrite in tcg */
- gen_helper_csg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
- case 0x3e: /* CDSG R1,R3,D2(B2) [RSY] */
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- /* XXX rewrite in tcg */
- gen_helper_cdsg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
default:
LOG_DISAS("illegal eb operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2014,19 +1990,6 @@ static void disas_s390_insn(DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(s, op, r1, r2);
break;
- case 0xba: /* CS R1,R3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_cs(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0xbd: /* CLM R1,M3,D2(B2) [RS] */
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2614,6 +2577,47 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_cs(DisasContext *s, DisasOps *o)
+{
+ int r3 = get_field(s->fields, r3);
+ potential_page_fault(s);
+ gen_helper_cs(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_csg(DisasContext *s, DisasOps *o)
+{
+ int r3 = get_field(s->fields, r3);
+ potential_page_fault(s);
+ gen_helper_csg(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cds(DisasContext *s, DisasOps *o)
+{
+ int r3 = get_field(s->fields, r3);
+ TCGv_i64 in3 = tcg_temp_new_i64();
+ tcg_gen_deposit_i64(in3, regs[r3 + 1], regs[r3], 32, 32);
+ potential_page_fault(s);
+ gen_helper_csg(o->out, cpu_env, o->in1, o->in2, in3);
+ tcg_temp_free_i64(in3);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ potential_page_fault(s);
+ /* XXX rewrite in tcg */
+ gen_helper_cdsg(cc_op, cpu_env, r1, o->in2, r3);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
{
TCGv_i64 t1 = tcg_temp_new_i64();
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 062/126] target-s390: Convert CLM
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (60 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 061/126] target-s390: Convert COMPARE AND SWAP Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 063/126] target-s390: Convert STCM Richard Henderson
` (39 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 32 +++++++++++++++++++-------------
2 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index d2c9671..ee2ab46 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -136,6 +136,10 @@
C(0xc606, CLGHRL, RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
/* COMPARE LOGICAL LONG EXTENDED */
C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0)
+/* COMPARE LOGICAL CHARACTERS UNDER MASK */
+ C(0xbd00, CLM, RS_b, Z, r1_o, a2, 0, 0, clm, 0)
+ C(0xeb21, CLMY, RSY_b, LD, r1_o, a2, 0, 0, clm, 0)
+ C(0xeb20, CLMH, RSY_b, Z, r1_sr32, a2, 0, 0, clm, 0)
/* COMPARE AND SWAP */
C(0xba00, CS, RS_a, Z, r1_o, a2, new, r1_32, cs, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index dcb663d..0c3cf73 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1990,19 +1990,6 @@ static void disas_s390_insn(DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(s, op, r1, r2);
break;
- case 0xbd: /* CLM R1,M3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_clm(cc_op, cpu_env, tmp32_1, tmp32_2, tmp);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
insn = ld_code4(s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2577,6 +2564,19 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_clm(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ TCGv_i32 t1 = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(t1, o->in1);
+ potential_page_fault(s);
+ gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2);
+ set_cc_static(s);
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(m3);
+ return NO_EXIT;
+}
+
static ExitStatus op_cs(DisasContext *s, DisasOps *o)
{
int r3 = get_field(s->fields, r3);
@@ -3632,6 +3632,12 @@ static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
}
+static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
+}
+
static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
{
/* ??? Specification exception: r1 must be even. */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 063/126] target-s390: Convert STCM
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (61 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 062/126] target-s390: Convert CLM Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 064/126] target-s390: Convert TPROT Richard Henderson
` (38 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 --
target-s390x/insn-data.def | 4 +++
target-s390x/mem_helper.c | 37 -----------------------
target-s390x/translate.c | 73 +++++++++++++++++++++++++++++++---------------
4 files changed, 53 insertions(+), 63 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 38b9aa4..7aa03c1 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -11,7 +11,6 @@ DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
DEF_HELPER_4(clm, i32, env, i32, i32, i64)
-DEF_HELPER_4(stcm, void, env, i32, i32, i64)
DEF_HELPER_FLAGS_3(mul128, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64, i64)
DEF_HELPER_3(divs32, s64, env, s64, s64)
DEF_HELPER_3(divu32, i64, env, i64, i64)
@@ -37,7 +36,6 @@ DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32)
DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
-DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
DEF_HELPER_3(ipm, void, env, i32, i32)
DEF_HELPER_4(stam, void, env, i32, i64, i32)
DEF_HELPER_4(lam, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ee2ab46..7f50fc7 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -405,6 +405,10 @@
/* STORE CHARACTER */
C(0x4200, STC, RX_a, Z, r1_o, a2, 0, 0, st8, 0)
C(0xe372, STCY, RXY_a, LD, r1_o, a2, 0, 0, st8, 0)
+/* STORE CHARACTERS UNDER MASK */
+ D(0xbe00, STCM, RS_b, Z, r1_o, a2, 0, 0, stcm, 0, 0)
+ D(0xeb2d, STCMY, RSY_b, LD, r1_o, a2, 0, 0, stcm, 0, 0)
+ D(0xeb2c, STCMH, RSY_b, LD, r1_o, a2, 0, 0, stcm, 0, 32)
/* STORE HALFWORD */
C(0x4000, STH, RX_a, Z, r1_o, a2, 0, 0, st16, 0)
C(0xe370, STHY, RXY_a, LD, r1_o, a2, 0, 0, st16, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 90d2c39..dfdb2c7 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -310,27 +310,6 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
return cc;
}
-/* store character under mask */
-void HELPER(stcm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
- uint64_t addr)
-{
- uint8_t r;
-
- HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask,
- addr);
- while (mask) {
- if (mask & 8) {
- r = (r1 & 0xff000000UL) >> 24;
- cpu_stb_data(env, addr, r);
- HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
- addr++;
- }
- mask = (mask << 1) & 0xf;
- r1 <<= 8;
- }
- HELPER_LOG("\n");
-}
-
static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2)
{
uint64_t r = d2;
@@ -614,22 +593,6 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
return cc;
}
-/* store character under mask high operates on the upper half of r1 */
-void HELPER(stcmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
- uint32_t mask)
-{
- int pos = 56; /* top of the upper half of r1 */
-
- while (mask) {
- if (mask & 8) {
- cpu_stb_data(env, address, (env->regs[r1] >> pos) & 0xff);
- address++;
- }
- mask = (mask << 1) & 0xf;
- pos -= 8;
- }
-}
-
/* load access registers r1 to r3 from memory at a2 */
void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
{
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0c3cf73..e545ed4 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1106,16 +1106,6 @@ static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
op, r1, r3, b2, d2);
switch (op) {
- case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_stcmh(cpu_env, tmp32_1, tmp, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
#ifndef CONFIG_USER_ONLY
case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
/* Load Control */
@@ -1960,8 +1950,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
static void disas_s390_insn(DisasContext *s)
{
- TCGv_i64 tmp;
- TCGv_i32 tmp32_1, tmp32_2;
unsigned char opc;
uint64_t insn;
int op, r1, r2, r3, d2, x2, b2, r1b;
@@ -1990,18 +1978,6 @@ static void disas_s390_insn(DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(s, op, r1, r2);
break;
- case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
- insn = ld_code4(s->pc);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = load_reg32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_stcm(cpu_env, tmp32_1, tmp32_2, tmp);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
case 0xe3:
insn = ld_code6(s->pc);
debug_insn(insn);
@@ -3200,6 +3176,55 @@ static ExitStatus op_stam(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
+{
+ int m3 = get_field(s->fields, m3);
+ int pos, base = s->insn->data;
+ TCGv_i64 tmp = tcg_temp_new_i64();
+
+ pos = base + ctz32(m3) * 8;
+ switch (m3) {
+ case 0xf:
+ /* Effectively a 32-bit store. */
+ tcg_gen_shri_i64(tmp, o->in1, pos);
+ tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
+ break;
+
+ case 0xc:
+ case 0x6:
+ case 0x3:
+ /* Effectively a 16-bit store. */
+ tcg_gen_shri_i64(tmp, o->in1, pos);
+ tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
+ break;
+
+ case 0x8:
+ case 0x4:
+ case 0x2:
+ case 0x1:
+ /* Effectively an 8-bit store. */
+ tcg_gen_shri_i64(tmp, o->in1, pos);
+ tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
+ break;
+
+ default:
+ /* This is going to be a sequence of shifts and stores. */
+ pos = base + 32 - 8;
+ while (m3) {
+ if (m3 & 0x8) {
+ tcg_gen_shri_i64(tmp, o->in1, pos);
+ tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
+ tcg_gen_addi_i64(o->in2, o->in2, 1);
+ }
+ m3 = (m3 << 1) & 0xf;
+ pos -= 8;
+ }
+ break;
+ }
+ tcg_temp_free_i64(tmp);
+ return NO_EXIT;
+}
+
static ExitStatus op_stm(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s->fields, r1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 064/126] target-s390: Convert TPROT
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (62 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 063/126] target-s390: Convert STCM Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 065/126] target-s390: Convert LOAD CONTROL, part 2 Richard Henderson
` (37 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 47 ++++++++++------------------------------------
2 files changed, 12 insertions(+), 37 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7f50fc7..92dbf26 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -508,4 +508,6 @@
C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
/* STORE THEN OR SYSTEM MASK */
C(0xad00, STOSM, SI, Z, la1, 0, new, m1_8, stosm, 0)
+/* TEST PROTECTION */
+ C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0)
#endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e545ed4..7a912ca 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1070,34 +1070,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_temp_free_i64(addr);
}
-#ifndef CONFIG_USER_ONLY
-static void disas_e5(DisasContext* s, uint64_t insn)
-{
- TCGv_i64 tmp, tmp2;
- int op = (insn >> 32) & 0xff;
-
- tmp = get_address(s, 0, (insn >> 28) & 0xf, (insn >> 16) & 0xfff);
- tmp2 = get_address(s, 0, (insn >> 12) & 0xf, insn & 0xfff);
-
- LOG_DISAS("disas_e5: insn %" PRIx64 "\n", insn);
- switch (op) {
- case 0x01: /* TPROT D1(B1),D2(B2) [SSE] */
- /* Test Protection */
- potential_page_fault(s);
- gen_helper_tprot(cc_op, tmp, tmp2);
- set_cc_static(s);
- break;
- default:
- LOG_DISAS("illegal e5 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- break;
- }
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
-}
-#endif
-
static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
{
TCGv_i64 tmp;
@@ -1989,15 +1961,6 @@ static void disas_s390_insn(DisasContext *s)
| ((insn << 4) & 0xff000)) << 12)) >> 12;
disas_e3(s, op, r1, x2, b2, d2 );
break;
-#ifndef CONFIG_USER_ONLY
- case 0xe5:
- /* Test Protection */
- check_privileged(s);
- insn = ld_code6(s->pc);
- debug_insn(insn);
- disas_e5(s, insn);
- break;
-#endif
case 0xeb:
insn = ld_code6(s->pc);
debug_insn(insn);
@@ -3307,6 +3270,16 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
return EXIT_NORETURN;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
+{
+ potential_page_fault(s);
+ gen_helper_tprot(cc_op, o->addr1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_tr(DisasContext *s, DisasOps *o)
{
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 065/126] target-s390: Convert LOAD CONTROL, part 2
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (63 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 064/126] target-s390: Convert TPROT Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 066/126] target-s390: Convert LOAD REVERSED Richard Henderson
` (36 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 75 ++++++++++++++--------------------------------
2 files changed, 25 insertions(+), 52 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 92dbf26..ed28d2d 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -484,6 +484,7 @@
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
/* LOAD CONTROL */
C(0xb700, LCTL, RS_a, Z, 0, a2, 0, 0, lctl, 0)
+ C(0xeb2f, LCTLG, RSY_a, Z, 0, a2, 0, 0, lctlg, 0)
/* LOAD PSW */
C(0x8200, LPSW, S, Z, 0, a2, 0, 0, lpsw, 0)
/* LOAD REAL ADDRESS */
@@ -504,6 +505,7 @@
C(0xae00, SIGP, RS_a, Z, r3_o, a2, 0, 0, sigp, 0)
/* STORE CONTROL */
C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0)
+ C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0)
/* STORE THEN AND SYSTEM MASK */
C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 7a912ca..9277081 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1070,47 +1070,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
tcg_temp_free_i64(addr);
}
-static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
-{
- TCGv_i64 tmp;
- TCGv_i32 tmp32_1, tmp32_2;
-
- LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
- op, r1, r3, b2, d2);
- switch (op) {
-#ifndef CONFIG_USER_ONLY
- case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
- /* Load Control */
- check_privileged(s);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_lctlg(cpu_env, tmp32_1, tmp, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
- case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
- /* Store Control */
- check_privileged(s);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r3);
- potential_page_fault(s);
- gen_helper_stctg(cpu_env, tmp32_1, tmp, tmp32_2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
-#endif
- default:
- LOG_DISAS("illegal eb operation 0x%x\n", op);
- gen_illegal_opcode(s);
- break;
- }
-}
-
static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
int r1b)
{
@@ -1961,17 +1920,6 @@ static void disas_s390_insn(DisasContext *s)
| ((insn << 4) & 0xff000)) << 12)) >> 12;
disas_e3(s, op, r1, x2, b2, d2 );
break;
- case 0xeb:
- insn = ld_code6(s->pc);
- debug_insn(insn);
- op = insn & 0xff;
- r1 = (insn >> 36) & 0xf;
- r3 = (insn >> 32) & 0xf;
- b2 = (insn >> 28) & 0xf;
- d2 = ((int)((((insn >> 16) & 0xfff)
- | ((insn << 4) & 0xff000)) << 12)) >> 12;
- disas_eb(s, op, r1, r3, b2, d2);
- break;
case 0xed:
insn = ld_code6(s->pc);
debug_insn(insn);
@@ -2768,6 +2716,17 @@ static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_lctlg(cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ return NO_EXIT;
+}
static ExitStatus op_lra(DisasContext *s, DisasOps *o)
{
check_privileged(s);
@@ -3085,6 +3044,18 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_stctg(cpu_env, r1, o->in2, r3);
+ tcg_temp_free_i32(r1);
+ tcg_temp_free_i32(r3);
+ return NO_EXIT;
+}
+
static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 066/126] target-s390: Convert LOAD REVERSED
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (64 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 065/126] target-s390: Convert LOAD CONTROL, part 2 Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 067/126] target-s390: Convert STORE REVERSED Richard Henderson
` (35 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 6 ++++
target-s390x/translate.c | 77 ++++++++++++++++++----------------------------
2 files changed, 36 insertions(+), 47 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ed28d2d..f02e54c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -293,6 +293,12 @@
C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32)
C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
+/* LOAD REVERSED */
+ C(0xb91f, LRVR, RRE, Z, 0, r2_32u, new, r1_32, rev32, 0)
+ C(0xb90f, LRVGR, RRE, Z, 0, r2_o, r1, 0, rev64, 0)
+ C(0xe31f, LRVH, RXY_a, Z, 0, m2_16u, new, r1_16, rev16, 0)
+ C(0xe31e, LRV, RXY_a, Z, 0, m2_32u, new, r1_32, rev32, 0)
+ C(0xe30f, LRVG, RXY_a, Z, 0, m2_64, r1, 0, rev64, 0)
/* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9277081..44975c0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -276,17 +276,6 @@ static inline void store_reg32h_i64(int reg, TCGv_i64 v)
tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
}
-static inline void store_reg16(int reg, TCGv_i32 v)
-{
- /* 16 bit register writes keep the upper bytes */
-#if HOST_LONG_BITS == 32
- tcg_gen_deposit_i32(TCGV_LOW(regs[reg]), TCGV_LOW(regs[reg]), v, 0, 16);
-#else
- tcg_gen_deposit_i64(regs[reg], regs[reg],
- MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 16);
-#endif
-}
-
static inline void store_freg32(int reg, TCGv_i32 v)
{
/* 32 bit register writes keep the lower half */
@@ -1019,13 +1008,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
op, r1, x2, b2, d2);
addr = get_address(s, x2, b2, d2);
switch (op) {
- case 0xf: /* LRVG R1,D2(X2,B2) [RXE] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
- tcg_gen_bswap64_i64(tmp2, tmp2);
- store_reg(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
case 0x17: /* LLGT R1,D2(X2,B2) [RXY] */
tmp2 = tcg_temp_new_i64();
tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
@@ -1033,26 +1015,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0x1e: /* LRV R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x1f: /* LRVH R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- tcg_temp_free_i64(tmp2);
- tcg_gen_bswap16_i32(tmp32_1, tmp32_1);
- store_reg16(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
tmp32_1 = load_reg32(r1);
tmp2 = tcg_temp_new_i64();
@@ -1855,15 +1817,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
break;
- case 0x0f: /* LRVGR R1,R2 [RRE] */
- tcg_gen_bswap64_i64(regs[r1], regs[r2]);
- break;
- case 0x1f: /* LRVR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x83: /* FLOGR R1,R2 [RRE] */
tmp = load_reg(r2);
tmp32_1 = tcg_const_i32(r1);
@@ -2959,6 +2912,24 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_bswap16_i64(o->out, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_bswap32_i64(o->out, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_bswap64_i64(o->out, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
{
TCGv_i32 t1 = tcg_temp_new_i32();
@@ -3497,6 +3468,12 @@ static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
}
+static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int r1 = get_field(f, r1);
+ tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
+}
+
static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_reg32_i64(get_field(f, r1), o->out);
@@ -3839,6 +3816,12 @@ static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
}
+static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ in2_a2(s, f, o);
+ tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
+}
+
static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
{
in2_a2(s, f, o);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 067/126] target-s390: Convert STORE REVERSED
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (65 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 066/126] target-s390: Convert LOAD REVERSED Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 068/126] target-s390: Convert LLGT Richard Henderson
` (34 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 34 ++++++++++++++++++++++++----------
2 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f02e54c..11903bb 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -420,6 +420,10 @@
C(0xe370, STHY, RXY_a, LD, r1_o, a2, 0, 0, st16, 0)
/* STORE HALFWORD RELATIVE LONG */
C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
+/* STORE REVERSED */
+ C(0xe33f, STRVH, RXY_a, Z, la2, r1_16u, new, m1_16, rev16, 0)
+ C(0xe33e, STRV, RXY_a, Z, la2, r1_32u, new, m1_32, rev32, 0)
+ C(0xe32f, STRVG, RXY_a, Z, la2, r1_o, new, m1_64, rev64, 0)
/* STORE FPC */
C(0xb29c, STFPC, S, Z, 0, a2, new, m2_32, efpc, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 44975c0..92fb4c7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1002,7 +1002,6 @@ static void free_compare(DisasCompare *c)
static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
{
TCGv_i64 addr, tmp2;
- TCGv_i32 tmp32_1;
LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
op, r1, x2, b2, d2);
@@ -1015,15 +1014,6 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
store_reg(r1, tmp2);
tcg_temp_free_i64(tmp2);
break;
- case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
- tmp32_1 = load_reg32(r1);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
- tcg_gen_extu_i32_i64(tmp2, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
- tcg_temp_free_i64(tmp2);
- break;
default:
LOG_DISAS("illegal e3 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -3659,6 +3649,12 @@ static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
}
+static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
+ o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
+}
+
static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
{
in1_la1(s, f, o);
@@ -3704,6 +3700,24 @@ static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
/* ====================================================================== */
/* The "INput 2" generators. These load the second operand to an insn. */
+static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = regs[get_field(f, r1)];
+ o->g_in2 = true;
+}
+
+static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
+}
+
+static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
+}
+
static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_reg(get_field(f, r2));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 068/126] target-s390: Convert LLGT
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (66 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 067/126] target-s390: Convert STORE REVERSED Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 069/126] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED Richard Henderson
` (33 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 3 +++
target-s390x/translate.c | 49 ++++++----------------------------------------
2 files changed, 9 insertions(+), 43 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 11903bb..35a52f5 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -285,6 +285,9 @@
D(0xa50d, LLIHL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 32)
D(0xa50e, LLILH, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 16)
D(0xa50f, LLILL, RI_a, Z, 0, i2_16u_shl, 0, r1, mov2, 0, 0)
+/* LOAD LOGICAL THIRTY ONE BITS */
+ C(0xb917, LLGTR, RRE, Z, 0, r2_o, r1, 0, llgt, 0)
+ C(0xe317, LLGT, RXY_a, Z, 0, m2_32u, r1, 0, llgt, 0)
/* LOAD NEGATIVE */
C(0x1100, LNR, RR_a, Z, 0, r2_32s, new, r1_32, nabs, nabs32)
C(0xb901, LNGR, RRE, Z, 0, r2, r1, 0, nabs, nabs64)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 92fb4c7..0d09fcd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -999,29 +999,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
-{
- TCGv_i64 addr, tmp2;
-
- LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
- op, r1, x2, b2, d2);
- addr = get_address(s, x2, b2, d2);
- switch (op) {
- case 0x17: /* LLGT R1,D2(X2,B2) [RXY] */
- tmp2 = tcg_temp_new_i64();
- tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
- tcg_gen_andi_i64(tmp2, tmp2, 0x7fffffffULL);
- store_reg(r1, tmp2);
- tcg_temp_free_i64(tmp2);
- break;
- default:
- LOG_DISAS("illegal e3 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- break;
- }
- tcg_temp_free_i64(addr);
-}
-
static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
int r1b)
{
@@ -1798,15 +1775,6 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x17: /* LLGTR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tmp = tcg_temp_new_i64();
- tcg_gen_andi_i32(tmp32_1, tmp32_1, 0x7fffffffUL);
- tcg_gen_extu_i32_i64(tmp, tmp32_1);
- store_reg(r1, tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
case 0x83: /* FLOGR R1,R2 [RRE] */
tmp = load_reg(r2);
tmp32_1 = tcg_const_i32(r1);
@@ -1852,17 +1820,6 @@ static void disas_s390_insn(DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(s, op, r1, r2);
break;
- case 0xe3:
- insn = ld_code6(s->pc);
- debug_insn(insn);
- op = insn & 0xff;
- r1 = (insn >> 36) & 0xf;
- x2 = (insn >> 32) & 0xf;
- b2 = (insn >> 28) & 0xf;
- d2 = ((int)((((insn >> 16) & 0xfff)
- | ((insn << 4) & 0xff000)) << 12)) >> 12;
- disas_e3(s, op, r1, x2, b2, d2 );
- break;
case 0xed:
insn = ld_code6(s->pc);
debug_insn(insn);
@@ -2604,6 +2561,12 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
+ return NO_EXIT;
+}
+
static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
{
tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 069/126] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (67 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 068/126] target-s390: Convert LLGT Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 070/126] target-s390: Convert FP SUBTRACT Richard Henderson
` (32 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 9 +-
target-s390x/cpu.h | 10 +-
target-s390x/fpu_helper.c | 299 +++++++++++++++++----------------------------
target-s390x/helper.h | 31 ++---
target-s390x/insn-data.def | 25 ++++
target-s390x/translate.c | 217 ++++++++++++++++++--------------
6 files changed, 279 insertions(+), 312 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index bead820..27aac03 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -505,18 +505,15 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
r = cc_calc_sla_64(src, dst);
break;
- case CC_OP_LTGT_F32:
- r = set_cc_f32(env, src, dst);
- break;
- case CC_OP_LTGT_F64:
- r = set_cc_f64(env, src, dst);
- break;
case CC_OP_NZ_F32:
r = set_cc_nz_f32(dst);
break;
case CC_OP_NZ_F64:
r = set_cc_nz_f64(dst);
break;
+ case CC_OP_NZ_F128:
+ r = set_cc_nz_f128(make_float128(src, dst));
+ break;
default:
cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index c33df11..37a91d3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -465,11 +465,9 @@ enum cc_op {
CC_OP_TM_32, /* test under mask (32bit) */
CC_OP_TM_64, /* test under mask (64bit) */
- CC_OP_LTGT_F32, /* FP compare (32bit) */
- CC_OP_LTGT_F64, /* FP compare (64bit) */
-
CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
+ CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
CC_OP_ICM, /* insert characters under mask */
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
@@ -511,10 +509,9 @@ static const char *cc_names[] = {
[CC_OP_COMP_64] = "CC_OP_COMP_64",
[CC_OP_TM_32] = "CC_OP_TM_32",
[CC_OP_TM_64] = "CC_OP_TM_64",
- [CC_OP_LTGT_F32] = "CC_OP_LTGT_F32",
- [CC_OP_LTGT_F64] = "CC_OP_LTGT_F64",
[CC_OP_NZ_F32] = "CC_OP_NZ_F32",
[CC_OP_NZ_F64] = "CC_OP_NZ_F64",
+ [CC_OP_NZ_F128] = "CC_OP_NZ_F128",
[CC_OP_ICM] = "CC_OP_ICM",
[CC_OP_SLA_32] = "CC_OP_SLA_32",
[CC_OP_SLA_64] = "CC_OP_SLA_64",
@@ -929,10 +926,9 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
}
/* fpu_helper.c */
-uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2);
-uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2);
uint32_t set_cc_nz_f32(float32 v);
uint32_t set_cc_nz_f64(float64 v);
+uint32_t set_cc_nz_f128(float128 v);
/* misc_helper.c */
void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index ee9420d..c632366 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -32,6 +32,53 @@
#define HELPER_LOG(x...)
#endif
+#define RET128(F) (env->retxl = F.low, F.high)
+
+#define convert_bit(mask, to, from) \
+ (to < from \
+ ? (mask / (from / to)) & to \
+ : (mask & from) * (to / from))
+
+/* Should be called after any operation that may raise IEEE exceptions. */
+static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
+{
+ unsigned s390_exc, qemu_exc;
+
+ /* Get the exceptions raised by the current operation. Reset the
+ fpu_status contents so that the next operation has a clean slate. */
+ qemu_exc = env->fpu_status.float_exception_flags;
+ env->fpu_status.float_exception_flags = 0;
+
+ /* Convert softfloat exception bits to s390 exception bits. */
+ s390_exc = 0;
+ s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
+ s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
+ s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
+ s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
+ s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
+
+ /* Install the exceptions that we raised. */
+ env->fpc |= s390_exc << 16;
+
+ /* Send signals for enabled exceptions. */
+ /* ??? It would probably be better to pass DXC codes instead. */
+ if (s390_exc & (env->fpc >> 24)) {
+ int which = 0;
+ if (qemu_exc & float_flag_invalid) {
+ which = PGM_HFP_SQRT; /* Yes, really. */
+ } else if (qemu_exc & float_flag_divbyzero) {
+ which = PGM_HFP_DIVIDE;
+ } else if (qemu_exc & float_flag_overflow) {
+ which = PGM_HFP_EXP_OVERFLOW;
+ } else if (qemu_exc & float_flag_underflow) {
+ which = PGM_HFP_EXP_UNDERFLOW;
+ } else {
+ which = PGM_HFP_SIGNIFICANCE;
+ }
+ runtime_exception(env, which, retaddr);
+ }
+}
+
static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
{
switch (float_compare) {
@@ -48,19 +95,6 @@ static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
}
}
-/* condition codes for binary FP ops */
-uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2)
-{
- return float_comp_to_cc(env, float32_compare_quiet(v1, v2,
- &env->fpu_status));
-}
-
-uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2)
-{
- return float_comp_to_cc(env, float64_compare_quiet(v1, v2,
- &env->fpu_status));
-}
-
/* condition codes for unary FP ops */
uint32_t set_cc_nz_f32(float32 v)
{
@@ -88,7 +122,7 @@ uint32_t set_cc_nz_f64(float64 v)
}
}
-static uint32_t set_cc_nz_f128(float128 v)
+uint32_t set_cc_nz_f128(float128 v)
{
if (float128_is_any_nan(v)) {
return 3;
@@ -152,27 +186,31 @@ void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
env->fregs[f1].l.upper, f1);
}
-/* 32-bit FP addition RR */
-uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP addition */
+uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
- env->fregs[f2].l.upper,
- &env->fpu_status);
- HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
- env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
-
- return set_cc_nz_f32(env->fregs[f1].l.upper);
+ float32 ret = float32_add(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
-/* 64-bit FP addition RR */
-uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP addition */
+uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
- &env->fpu_status);
- HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__,
- env->fregs[f2].d, env->fregs[f1].d, f1);
+ float64 ret = float64_add(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
- return set_cc_nz_f64(env->fregs[f1].d);
+/* 128-bit FP addition */
+uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint64_t bh, uint64_t bl)
+{
+ float128 ret = float128_add(make_float128(ah, al),
+ make_float128(bh, bl),
+ &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
}
/* 32-bit FP subtraction RR */
@@ -246,50 +284,51 @@ void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
}
/* convert 32-bit float to 64-bit float */
-void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2)
+uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
{
- env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
- &env->fpu_status);
+ float64 ret = float32_to_float64(f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 128-bit float to 64-bit float */
-void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
- CPU_QuadU x2;
-
- x2.ll.upper = env->fregs[f2].ll;
- x2.ll.lower = env->fregs[f2 + 2].ll;
- env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
- HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d);
+ float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 64-bit float to 128-bit float */
-void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
{
- CPU_QuadU res;
+ float128 ret = float64_to_float128(f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
+}
- res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
- env->fregs[f1].ll = res.ll.upper;
- env->fregs[f1 + 2].ll = res.ll.lower;
+/* convert 32-bit float to 128-bit float */
+uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
+{
+ float128 ret = float32_to_float128(f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
}
/* convert 64-bit float to 32-bit float */
-void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
{
- float64 d2 = env->fregs[f2].d;
-
- env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
+ float32 ret = float64_to_float32(f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 128-bit float to 32-bit float */
-void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
- CPU_QuadU x2;
-
- x2.ll.upper = env->fregs[f2].ll;
- x2.ll.lower = env->fregs[f2 + 2].ll;
- env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
- HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper);
+ float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* absolute value of 32-bit float */
@@ -328,32 +367,6 @@ uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(v1.q);
}
-/* load and test 64-bit float */
-uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- env->fregs[f1].d = env->fregs[f2].d;
- return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* load and test 32-bit float */
-uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- env->fregs[f1].l.upper = env->fregs[f2].l.upper;
- return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* load and test 128-bit float */
-uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- CPU_QuadU x;
-
- x.ll.upper = env->fregs[f2].ll;
- x.ll.lower = env->fregs[f2 + 2].ll;
- env->fregs[f1].ll = x.ll.upper;
- env->fregs[f1 + 2].ll = x.ll.lower;
- return set_cc_nz_f128(x.q);
-}
-
/* load complement of 32-bit float */
uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
@@ -383,18 +396,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(x1.q);
}
-/* 32-bit FP addition RM */
-void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
- float32 v1 = env->fregs[f1].l.upper;
- CPU_FloatU v2;
-
- v2.l = val;
- HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
- v1, f1, v2.f);
- env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
-}
-
/* 32-bit FP division RM */
void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
{
@@ -419,66 +420,31 @@ void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
}
-/* 32-bit FP compare RR */
-uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP compare */
+uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- float32 v1 = env->fregs[f1].l.upper;
- float32 v2 = env->fregs[f2].l.upper;
-
- HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
- v1, f1, v2);
- return set_cc_f32(env, v1, v2);
+ int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return float_comp_to_cc(env, cmp);
}
-/* 64-bit FP compare RR */
-uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP compare */
+uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- float64 v1 = env->fregs[f1].d;
- float64 v2 = env->fregs[f2].d;
-
- HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
- v1, f1, v2);
- return set_cc_f64(env, v1, v2);
-}
-
-/* 128-bit FP compare RR */
-uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- CPU_QuadU v1;
- CPU_QuadU v2;
-
- v1.ll.upper = env->fregs[f1].ll;
- v1.ll.lower = env->fregs[f1 + 2].ll;
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
-
- return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q,
- &env->fpu_status));
+ int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return float_comp_to_cc(env, cmp);
}
-/* 64-bit FP compare RM */
-uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+/* 128-bit FP compare */
+uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint64_t bh, uint64_t bl)
{
- float64 v1 = env->fregs[f1].d;
- CPU_DoubleU v2;
-
- v2.ll = cpu_ldq_data(env, a2);
- HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
- f1, v2.d);
- return set_cc_f64(env, v1, v2.d);
-}
-
-/* 64-bit FP addition RM */
-uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
- float64 v1 = env->fregs[f1].d;
- CPU_DoubleU v2;
-
- v2.ll = cpu_ldq_data(env, a2);
- HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
- v1, f1, v2.d);
- env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
- return set_cc_nz_f64(v1);
+ int cmp = float128_compare_quiet(make_float128(ah, al),
+ make_float128(bh, bl),
+ &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return float_comp_to_cc(env, cmp);
}
/* 32-bit FP subtraction RM */
@@ -672,23 +638,6 @@ uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(res.q);
}
-/* 128-bit FP addition RR */
-uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- CPU_QuadU v1;
- CPU_QuadU v2;
- CPU_QuadU res;
-
- v1.ll.upper = env->fregs[f1].ll;
- v1.ll.lower = env->fregs[f1 + 2].ll;
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- res.q = float128_add(v1.q, v2.q, &env->fpu_status);
- env->fregs[f1].ll = res.ll.upper;
- env->fregs[f1 + 2].ll = res.ll.lower;
- return set_cc_nz_f128(res.q);
-}
-
/* 32-bit FP multiplication RR */
void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
@@ -747,28 +696,6 @@ void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
&env->fpu_status);
}
-/* convert 32-bit float to 64-bit float */
-void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
- uint32_t v2;
-
- v2 = cpu_ldl_data(env, a2);
- env->fregs[f1].d = float32_to_float64(v2,
- &env->fpu_status);
-}
-
-/* convert 64-bit float to 128-bit float */
-void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
- CPU_DoubleU v2;
- CPU_QuadU v1;
-
- v2.ll = cpu_ldq_data(env, a2);
- v1.q = float64_to_float128(v2.d, &env->fpu_status);
- env->fregs[f1].ll = v1.ll.upper;
- env->fregs[f1 + 2].ll = v1.ll.lower;
-}
-
/* test data class 32-bit */
uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
{
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 7aa03c1..244c6ca 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -47,40 +47,36 @@ DEF_HELPER_3(cxfbr, void, env, i32, s32)
DEF_HELPER_3(cegbr, void, env, i32, s64)
DEF_HELPER_3(cdgbr, void, env, i32, s64)
DEF_HELPER_3(cxgbr, void, env, i32, s64)
-DEF_HELPER_3(adbr, i32, env, i32, i32)
-DEF_HELPER_3(aebr, i32, env, i32, i32)
+DEF_HELPER_3(aeb, i64, env, i64, i64)
+DEF_HELPER_3(adb, i64, env, i64, i64)
+DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
DEF_HELPER_3(sebr, i32, env, i32, i32)
DEF_HELPER_3(sdbr, i32, env, i32, i32)
DEF_HELPER_3(debr, void, env, i32, i32)
DEF_HELPER_3(dxbr, void, env, i32, i32)
DEF_HELPER_3(mdbr, void, env, i32, i32)
DEF_HELPER_3(mxbr, void, env, i32, i32)
-DEF_HELPER_3(ldebr, void, env, i32, i32)
-DEF_HELPER_3(ldxbr, void, env, i32, i32)
-DEF_HELPER_3(lxdbr, void, env, i32, i32)
-DEF_HELPER_3(ledbr, void, env, i32, i32)
-DEF_HELPER_3(lexbr, void, env, i32, i32)
+DEF_HELPER_2(ldeb, i64, env, i64)
+DEF_HELPER_3(ldxb, i64, env, i64, i64)
+DEF_HELPER_2(lxdb, i64, env, i64)
+DEF_HELPER_2(lxeb, i64, env, i64)
+DEF_HELPER_2(ledb, i64, env, i64)
+DEF_HELPER_3(lexb, i64, env, i64, i64)
DEF_HELPER_3(lpebr, i32, env, i32, i32)
DEF_HELPER_3(lpdbr, i32, env, i32, i32)
DEF_HELPER_3(lpxbr, i32, env, i32, i32)
-DEF_HELPER_3(ltebr, i32, env, i32, i32)
-DEF_HELPER_3(ltdbr, i32, env, i32, i32)
-DEF_HELPER_3(ltxbr, i32, env, i32, i32)
DEF_HELPER_3(lcebr, i32, env, i32, i32)
DEF_HELPER_3(lcdbr, i32, env, i32, i32)
DEF_HELPER_3(lcxbr, i32, env, i32, i32)
-DEF_HELPER_3(aeb, void, env, i32, i32)
DEF_HELPER_3(deb, void, env, i32, i32)
DEF_HELPER_3(meeb, void, env, i32, i32)
-DEF_HELPER_3(cdb, i32, env, i32, i64)
-DEF_HELPER_3(adb, i32, env, i32, i64)
DEF_HELPER_3(seb, void, env, i32, i32)
DEF_HELPER_3(sdb, i32, env, i32, i64)
DEF_HELPER_3(mdb, void, env, i32, i64)
DEF_HELPER_3(ddb, void, env, i32, i64)
-DEF_HELPER_FLAGS_3(cebr, TCG_CALL_PURE, i32, env, i32, i32)
-DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_PURE, i32, env, i32, i32)
-DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(ceb, TCG_CALL_PURE, i32, env, i64, i64)
+DEF_HELPER_FLAGS_3(cdb, TCG_CALL_PURE, i32, env, i64, i64)
+DEF_HELPER_FLAGS_5(cxb, TCG_CALL_PURE, i32, env, i64, i64, i64, i64)
DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
@@ -90,7 +86,6 @@ DEF_HELPER_2(lzxr, void, env, i32)
DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_3(axbr, i32, env, i32, i32)
DEF_HELPER_3(sxbr, i32, env, i32, i32)
DEF_HELPER_3(meebr, void, env, i32, i32)
DEF_HELPER_3(ddbr, void, env, i32, i32)
@@ -98,8 +93,6 @@ DEF_HELPER_4(madb, void, env, i32, i64, i32)
DEF_HELPER_4(maebr, void, env, i32, i32, i32)
DEF_HELPER_4(madbr, void, env, i32, i32, i32)
DEF_HELPER_4(msdbr, void, env, i32, i32, i32)
-DEF_HELPER_3(ldeb, void, env, i32, i64)
-DEF_HELPER_3(lxdb, void, env, i32, i64)
DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 35a52f5..1709cbf 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -8,6 +8,11 @@
C(0xb9e8, AGRK, RRF_a, DO, r2, r3, r1, 0, add, adds64)
C(0xe308, AG, RXY_a, Z, r1, m2_64, r1, 0, add, adds64)
C(0xe318, AGF, RXY_a, Z, r1, m2_32s, r1, 0, add, adds64)
+ C(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32)
+ C(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64)
+ C(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128)
+ C(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32)
+ C(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64)
/* ADD IMMEDIATE */
C(0xc209, AFI, RIL_a, EI, r1, i2, new, r1_32, add, adds32)
C(0xeb6a, ASI, SIY, GIE, m1_32s, i2, new, m1_32, add, adds32)
@@ -94,6 +99,11 @@
C(0xb930, CGFR, RRE, Z, r1_o, r2_32s, 0, 0, 0, cmps64)
C(0xe320, CG, RXY_a, Z, r1_o, m2_64, 0, 0, 0, cmps64)
C(0xe330, CGF, RXY_a, Z, r1_o, m2_32s, 0, 0, 0, cmps64)
+ C(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0)
+ C(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0)
+ C(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0)
+ C(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0)
+ C(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0)
/* COMPARE IMMEDIATE */
C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32)
C(0xc20c, CGFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps64)
@@ -239,6 +249,9 @@
C(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64)
C(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64)
C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64)
+ C(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32)
+ C(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64)
+ C(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128)
/* LOAD BYTE */
C(0xb926, LBR, RRE, EI, 0, r2_8s, 0, r1_32, mov2, 0)
C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0)
@@ -303,6 +316,18 @@
C(0xe31e, LRV, RXY_a, Z, 0, m2_32u, new, r1_32, rev32, 0)
C(0xe30f, LRVG, RXY_a, Z, 0, m2_64, r1, 0, rev64, 0)
+/* LOAD LENGTHENED */
+ C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0)
+ C(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0)
+ C(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0)
+ C(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0)
+ C(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0)
+ C(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0)
+/* LOAD ROUNDED */
+ C(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0)
+ C(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0)
+ C(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0)
+
/* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
C(0xeb98, LMY, RSY_a, LD, 0, a2, 0, 0, lm32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0d09fcd..3d5668d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -554,14 +554,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
}
-static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
-{
- tcg_gen_extu_i32_i64(cc_src, v1);
- tcg_gen_mov_i64(cc_dst, v2);
- tcg_gen_discard_i64(cc_vr);
- s->cc_op = CC_OP_LTGT_F32;
-}
-
static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
{
gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
@@ -626,10 +618,9 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_LTUGTU_64:
case CC_OP_TM_32:
case CC_OP_TM_64:
- case CC_OP_LTGT_F32:
- case CC_OP_LTGT_F64:
case CC_OP_SLA_32:
case CC_OP_SLA_64:
+ case CC_OP_NZ_F128:
/* 2 arguments */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
break;
@@ -1007,35 +998,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
addr = get_address(s, x2, b2, d2);
tmp_r1 = tcg_const_i32(r1);
switch (op) {
- case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_ldeb(cpu_env, tmp_r1, addr);
- break;
- case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_lxdb(cpu_env, tmp_r1, addr);
- break;
- case 0x9: /* CEB R1,D2(X2,B2) [RXE] */
- tmp = tcg_temp_new_i64();
- tmp32 = load_freg32(r1);
- tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
- set_cc_cmp_f32_i64(s, tmp32, tmp);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32);
- break;
- case 0xa: /* AEB R1,D2(X2,B2) [RXE] */
- tmp = tcg_temp_new_i64();
- tmp32 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32, tmp);
- gen_helper_aeb(cpu_env, tmp_r1, tmp32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32);
-
- tmp32 = load_freg32(r1);
- gen_set_cc_nz_f32(s, tmp32);
- tcg_temp_free_i32(tmp32);
- break;
case 0xb: /* SEB R1,D2(X2,B2) [RXE] */
tmp = tcg_temp_new_i64();
tmp32 = tcg_temp_new_i32();
@@ -1082,16 +1044,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32);
break;
- case 0x19: /* CDB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr);
- set_cc_static(s);
- break;
- case 0x1a: /* ADB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_adb(cc_op, cpu_env, tmp_r1, addr);
- set_cc_static(s);
- break;
case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
@@ -1520,24 +1472,9 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x0: /* LPEBR R1,R2 [RRE] */
FP_HELPER_CC(lpebr);
break;
- case 0x2: /* LTEBR R1,R2 [RRE] */
- FP_HELPER_CC(ltebr);
- break;
case 0x3: /* LCEBR R1,R2 [RRE] */
FP_HELPER_CC(lcebr);
break;
- case 0x4: /* LDEBR R1,R2 [RRE] */
- FP_HELPER(ldebr);
- break;
- case 0x5: /* LXDBR R1,R2 [RRE] */
- FP_HELPER(lxdbr);
- break;
- case 0x9: /* CEBR R1,R2 [RRE] */
- FP_HELPER_CC(cebr);
- break;
- case 0xa: /* AEBR R1,R2 [RRE] */
- FP_HELPER_CC(aebr);
- break;
case 0xb: /* SEBR R1,R2 [RRE] */
FP_HELPER_CC(sebr);
break;
@@ -1547,9 +1484,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x10: /* LPDBR R1,R2 [RRE] */
FP_HELPER_CC(lpdbr);
break;
- case 0x12: /* LTDBR R1,R2 [RRE] */
- FP_HELPER_CC(ltdbr);
- break;
case 0x13: /* LCDBR R1,R2 [RRE] */
FP_HELPER_CC(lcdbr);
break;
@@ -1559,12 +1493,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x17: /* MEEBR R1,R2 [RRE] */
FP_HELPER(meebr);
break;
- case 0x19: /* CDBR R1,R2 [RRE] */
- FP_HELPER_CC(cdbr);
- break;
- case 0x1a: /* ADBR R1,R2 [RRE] */
- FP_HELPER_CC(adbr);
- break;
case 0x1b: /* SDBR R1,R2 [RRE] */
FP_HELPER_CC(sdbr);
break;
@@ -1601,27 +1529,9 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x40: /* LPXBR R1,R2 [RRE] */
FP_HELPER_CC(lpxbr);
break;
- case 0x42: /* LTXBR R1,R2 [RRE] */
- FP_HELPER_CC(ltxbr);
- break;
case 0x43: /* LCXBR R1,R2 [RRE] */
FP_HELPER_CC(lcxbr);
break;
- case 0x44: /* LEDBR R1,R2 [RRE] */
- FP_HELPER(ledbr);
- break;
- case 0x45: /* LDXBR R1,R2 [RRE] */
- FP_HELPER(ldxbr);
- break;
- case 0x46: /* LEXBR R1,R2 [RRE] */
- FP_HELPER(lexbr);
- break;
- case 0x49: /* CXBR R1,R2 [RRE] */
- FP_HELPER_CC(cxbr);
- break;
- case 0x4a: /* AXBR R1,R2 [RRE] */
- FP_HELPER_CC(axbr);
- break;
case 0x4b: /* SXBR R1,R2 [RRE] */
FP_HELPER_CC(sxbr);
break;
@@ -2211,6 +2121,25 @@ static ExitStatus op_addc(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_aeb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_aeb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_adb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_adb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_axb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_and(DisasContext *s, DisasOps *o)
{
tcg_gen_and_i64(o->out, o->in1, o->in2);
@@ -2305,6 +2234,27 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cdb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
{
int l = get_field(s->fields, l1);
@@ -2561,6 +2511,44 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_ldeb(o->out, cpu_env, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_ledb(o->out, cpu_env, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_lxdb(o->out, cpu_env, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_lxeb(o->out, cpu_env, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
{
tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
@@ -3291,6 +3279,21 @@ static void cout_cmpu64(DisasContext *s, DisasOps *o)
gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
}
+static void cout_f32(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
+}
+
+static void cout_f64(DisasContext *s, DisasOps *o)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
+}
+
+static void cout_f128(DisasContext *s, DisasOps *o)
+{
+ gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
+}
+
static void cout_nabs32(DisasContext *s, DisasOps *o)
{
gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
@@ -3404,6 +3407,21 @@ static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_out = o->g_out2 = true;
}
+static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->out = fregs[get_field(f, r1)];
+ o->g_out = true;
+}
+
+static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be < 14. */
+ int r1 = get_field(f, r1);
+ o->out = fregs[r1];
+ o->out2 = fregs[(r1 + 2) & 15];
+ o->g_out = o->g_out2 = true;
+}
+
/* ====================================================================== */
/* The "Write OUTput" generators. These generally perform some non-trivial
copy of data to TCG globals, or to main memory. The trivial cases are
@@ -3461,6 +3479,7 @@ static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
{
+ /* ??? Specification exception: r1 must be < 14. */
int f1 = get_field(s->fields, r1);
store_freg(f1, o->out);
store_freg((f1 + 2) & 15, o->out2);
@@ -3607,6 +3626,15 @@ static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_in1 = true;
}
+static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ /* ??? Specification exception: r1 must be < 14. */
+ int r1 = get_field(f, r1);
+ o->out = fregs[r1];
+ o->out2 = fregs[(r1 + 2) & 15];
+ o->g_out = o->g_out2 = true;
+}
+
static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
@@ -3754,9 +3782,10 @@ static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
- int f2 = get_field(f, r2);
- o->in1 = fregs[f2];
- o->in2 = fregs[(f2 + 2) & 15];
+ /* ??? Specification exception: r1 must be < 14. */
+ int r2 = get_field(f, r2);
+ o->in1 = fregs[r2];
+ o->in2 = fregs[(r2 + 2) & 15];
o->g_in1 = o->g_in2 = true;
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 070/126] target-s390: Convert FP SUBTRACT
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (68 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 069/126] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 071/126] target-s390: Convert FP DIVIDE Richard Henderson
` (31 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 74 +++++++++++++---------------------------------
target-s390x/helper.h | 8 ++---
target-s390x/insn-data.def | 5 ++++
target-s390x/translate.c | 51 ++++++++++++--------------------
4 files changed, 47 insertions(+), 91 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index c632366..4dac096 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -213,27 +213,31 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return RET128(ret);
}
-/* 32-bit FP subtraction RR */
-uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP subtraction */
+uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
- env->fregs[f2].l.upper,
- &env->fpu_status);
- HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
- env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
-
- return set_cc_nz_f32(env->fregs[f1].l.upper);
+ float32 ret = float32_sub(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
-/* 64-bit FP subtraction RR */
-uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP subtraction */
+uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
- &env->fpu_status);
- HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
- __func__, env->fregs[f2].d, env->fregs[f1].d, f1);
+ float64 ret = float64_sub(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
- return set_cc_nz_f64(env->fregs[f1].d);
+/* 128-bit FP subtraction */
+uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint64_t bh, uint64_t bl)
+{
+ float128 ret = float128_sub(make_float128(ah, al),
+ make_float128(bh, bl),
+ &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
}
/* 32-bit FP division RR */
@@ -447,27 +451,6 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return float_comp_to_cc(env, cmp);
}
-/* 32-bit FP subtraction RM */
-void HELPER(seb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
- float32 v1 = env->fregs[f1].l.upper;
- CPU_FloatU v2;
-
- v2.l = val;
- env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
-}
-
-/* 64-bit FP subtraction RM */
-uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
- float64 v1 = env->fregs[f1].d;
- CPU_DoubleU v2;
-
- v2.ll = cpu_ldq_data(env, a2);
- env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
- return set_cc_nz_f64(v1);
-}
-
/* 64-bit FP multiplication RM */
void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
{
@@ -621,23 +604,6 @@ void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
env->fregs[f1 + 1].ll = x.ll.lower;
}
-/* 128-bit FP subtraction RR */
-uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- CPU_QuadU v1;
- CPU_QuadU v2;
- CPU_QuadU res;
-
- v1.ll.upper = env->fregs[f1].ll;
- v1.ll.lower = env->fregs[f1 + 2].ll;
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
- env->fregs[f1].ll = res.ll.upper;
- env->fregs[f1 + 2].ll = res.ll.lower;
- return set_cc_nz_f128(res.q);
-}
-
/* 32-bit FP multiplication RR */
void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 244c6ca..b3f5a40 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -50,8 +50,9 @@ DEF_HELPER_3(cxgbr, void, env, i32, s64)
DEF_HELPER_3(aeb, i64, env, i64, i64)
DEF_HELPER_3(adb, i64, env, i64, i64)
DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(sebr, i32, env, i32, i32)
-DEF_HELPER_3(sdbr, i32, env, i32, i32)
+DEF_HELPER_3(seb, i64, env, i64, i64)
+DEF_HELPER_3(sdb, i64, env, i64, i64)
+DEF_HELPER_5(sxb, i64, env, i64, i64, i64, i64)
DEF_HELPER_3(debr, void, env, i32, i32)
DEF_HELPER_3(dxbr, void, env, i32, i32)
DEF_HELPER_3(mdbr, void, env, i32, i32)
@@ -70,8 +71,6 @@ DEF_HELPER_3(lcdbr, i32, env, i32, i32)
DEF_HELPER_3(lcxbr, i32, env, i32, i32)
DEF_HELPER_3(deb, void, env, i32, i32)
DEF_HELPER_3(meeb, void, env, i32, i32)
-DEF_HELPER_3(seb, void, env, i32, i32)
-DEF_HELPER_3(sdb, i32, env, i32, i64)
DEF_HELPER_3(mdb, void, env, i32, i64)
DEF_HELPER_3(ddb, void, env, i32, i64)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_PURE, i32, env, i64, i64)
@@ -86,7 +85,6 @@ DEF_HELPER_2(lzxr, void, env, i32)
DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_3(sxbr, i32, env, i32, i32)
DEF_HELPER_3(meebr, void, env, i32, i32)
DEF_HELPER_3(ddbr, void, env, i32, i32)
DEF_HELPER_4(madb, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 1709cbf..9b02904 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -476,6 +476,11 @@
C(0xb9e9, SGRK, RRF_a, DO, r2, r3, r1, 0, sub, subs64)
C(0xe309, SG, RXY_a, Z, r1, m2_64, r1, 0, sub, subs64)
C(0xe319, SGF, RXY_a, Z, r1, m2_32s, r1, 0, sub, subs64)
+ C(0xb30b, SEBR, RRE, Z, e1, e2, new, e1, seb, f32)
+ C(0xb31b, SDBR, RRE, Z, f1_o, f2_o, f1, 0, sdb, f64)
+ C(0xb34b, SXBR, RRE, Z, 0, x2_o, x1, 0, sxb, f128)
+ C(0xed0b, SEB, RXE, Z, e1, m2_32u, new, e1, seb, f32)
+ C(0xed1b, SDB, RXE, Z, f1_o, m2_64, f1, 0, sdb, f64)
/* SUBTRACT HALFWORD */
C(0x4b00, SH, RX_a, Z, r1, m2_16s, new, r1_32, sub, subs32)
C(0xe37b, SHY, RXY_a, LD, r1, m2_16s, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3d5668d..2ed8b2c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -554,11 +554,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
}
-static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
-{
- gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
-}
-
/* CC value is in env->cc_op */
static inline void set_cc_static(DisasContext *s)
{
@@ -998,19 +993,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
addr = get_address(s, x2, b2, d2);
tmp_r1 = tcg_const_i32(r1);
switch (op) {
- case 0xb: /* SEB R1,D2(X2,B2) [RXE] */
- tmp = tcg_temp_new_i64();
- tmp32 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32, tmp);
- gen_helper_seb(cpu_env, tmp_r1, tmp32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32);
-
- tmp32 = load_freg32(r1);
- gen_set_cc_nz_f32(s, tmp32);
- tcg_temp_free_i32(tmp32);
- break;
case 0xd: /* DEB R1,D2(X2,B2) [RXE] */
tmp = tcg_temp_new_i64();
tmp32 = tcg_temp_new_i32();
@@ -1044,11 +1026,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32);
break;
- case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
- set_cc_static(s);
- break;
case 0x1c: /* MDB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_mdb(cpu_env, tmp_r1, addr);
@@ -1475,9 +1452,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x3: /* LCEBR R1,R2 [RRE] */
FP_HELPER_CC(lcebr);
break;
- case 0xb: /* SEBR R1,R2 [RRE] */
- FP_HELPER_CC(sebr);
- break;
case 0xd: /* DEBR R1,R2 [RRE] */
FP_HELPER(debr);
break;
@@ -1493,9 +1467,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x17: /* MEEBR R1,R2 [RRE] */
FP_HELPER(meebr);
break;
- case 0x1b: /* SDBR R1,R2 [RRE] */
- FP_HELPER_CC(sdbr);
- break;
case 0x1c: /* MDBR R1,R2 [RRE] */
FP_HELPER(mdbr);
break;
@@ -1532,9 +1503,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x43: /* LCXBR R1,R2 [RRE] */
FP_HELPER_CC(lcxbr);
break;
- case 0x4b: /* SXBR R1,R2 [RRE] */
- FP_HELPER_CC(sxbr);
- break;
case 0x4c: /* MXBR R1,R2 [RRE] */
FP_HELPER(mxbr);
break;
@@ -2892,6 +2860,25 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_seb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 071/126] target-s390: Convert FP DIVIDE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (69 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 070/126] target-s390: Convert FP SUBTRACT Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 072/126] target-s390: Convert FP MULTIPLY Richard Henderson
` (30 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 68 ++++++++++++++--------------------------------
target-s390x/helper.h | 8 ++----
target-s390x/insn-data.def | 5 ++++
target-s390x/translate.c | 41 +++++++++++++---------------
4 files changed, 47 insertions(+), 75 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 4dac096..aca3b77 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -240,28 +240,31 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return RET128(ret);
}
-/* 32-bit FP division RR */
-void HELPER(debr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP division */
+uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
- env->fregs[f2].l.upper,
- &env->fpu_status);
+ float32 ret = float32_div(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
-/* 128-bit FP division RR */
-void HELPER(dxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP division */
+uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- CPU_QuadU v1;
- CPU_QuadU v2;
- CPU_QuadU res;
+ float64 ret = float64_div(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
- v1.ll.upper = env->fregs[f1].ll;
- v1.ll.lower = env->fregs[f1 + 2].ll;
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- res.q = float128_div(v1.q, v2.q, &env->fpu_status);
- env->fregs[f1].ll = res.ll.upper;
- env->fregs[f1 + 2].ll = res.ll.lower;
+/* 128-bit FP division */
+uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint64_t bh, uint64_t bl)
+{
+ float128 ret = float128_div(make_float128(ah, al),
+ make_float128(bh, bl),
+ &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
}
/* 64-bit FP multiplication RR */
@@ -400,18 +403,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(x1.q);
}
-/* 32-bit FP division RM */
-void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
- float32 v1 = env->fregs[f1].l.upper;
- CPU_FloatU v2;
-
- v2.l = val;
- HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
- v1, f1, v2.f);
- env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
-}
-
/* 32-bit FP multiplication RM */
void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
{
@@ -463,18 +454,6 @@ void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
}
-/* 64-bit FP division RM */
-void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
- float64 v1 = env->fregs[f1].d;
- CPU_DoubleU v2;
-
- v2.ll = cpu_ldq_data(env, a2);
- HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
- v1, f1, v2.d);
- env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
-}
-
static void set_round_mode(CPUS390XState *env, int m3)
{
switch (m3) {
@@ -612,13 +591,6 @@ void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
&env->fpu_status);
}
-/* 64-bit FP division RR */
-void HELPER(ddbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
- &env->fpu_status);
-}
-
/* 64-bit FP multiply and add RM */
void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
{
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index b3f5a40..b0b4809 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -53,8 +53,9 @@ DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
DEF_HELPER_3(seb, i64, env, i64, i64)
DEF_HELPER_3(sdb, i64, env, i64, i64)
DEF_HELPER_5(sxb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(debr, void, env, i32, i32)
-DEF_HELPER_3(dxbr, void, env, i32, i32)
+DEF_HELPER_3(deb, i64, env, i64, i64)
+DEF_HELPER_3(ddb, i64, env, i64, i64)
+DEF_HELPER_5(dxb, i64, env, i64, i64, i64, i64)
DEF_HELPER_3(mdbr, void, env, i32, i32)
DEF_HELPER_3(mxbr, void, env, i32, i32)
DEF_HELPER_2(ldeb, i64, env, i64)
@@ -69,10 +70,8 @@ DEF_HELPER_3(lpxbr, i32, env, i32, i32)
DEF_HELPER_3(lcebr, i32, env, i32, i32)
DEF_HELPER_3(lcdbr, i32, env, i32, i32)
DEF_HELPER_3(lcxbr, i32, env, i32, i32)
-DEF_HELPER_3(deb, void, env, i32, i32)
DEF_HELPER_3(meeb, void, env, i32, i32)
DEF_HELPER_3(mdb, void, env, i32, i64)
-DEF_HELPER_3(ddb, void, env, i32, i64)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_PURE, i32, env, i64, i64, i64, i64)
@@ -86,7 +85,6 @@ DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
DEF_HELPER_3(meebr, void, env, i32, i32)
-DEF_HELPER_3(ddbr, void, env, i32, i32)
DEF_HELPER_4(madb, void, env, i32, i64, i32)
DEF_HELPER_4(maebr, void, env, i32, i32, i32)
DEF_HELPER_4(madbr, void, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9b02904..d6e0a6e 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -167,6 +167,11 @@
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_P32, r2_32s, new_P, r1_P32, divs32, 0)
C(0x5d00, D, RX_a, Z, r1_P32, m2_32s, new_P, r1_P32, divs32, 0)
+ C(0xb30d, DEBR, RRE, Z, e1, e2, new, e1, deb, 0)
+ C(0xb31d, DDBR, RRE, Z, f1_o, f2_o, f1, 0, ddb, 0)
+ C(0xb34d, DXBR, RRE, Z, 0, x2_o, x1, 0, dxb, 0)
+ C(0xed0d, DEB, RXE, Z, e1, m2_32u, new, e1, deb, 0)
+ C(0xed1d, DDB, RXE, Z, f1_o, m2_64, f1, 0, ddb, 0)
/* DIVIDE LOGICAL */
C(0xb997, DLR, RRE, Z, r1_P32, r2_32u, new_P, r1_P32, divu32, 0)
C(0xe397, DL, RXY_a, Z, r1_P32, m2_32u, new_P, r1_P32, divu32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2ed8b2c..7f02261 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -993,15 +993,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
addr = get_address(s, x2, b2, d2);
tmp_r1 = tcg_const_i32(r1);
switch (op) {
- case 0xd: /* DEB R1,D2(X2,B2) [RXE] */
- tmp = tcg_temp_new_i64();
- tmp32 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32, tmp);
- gen_helper_deb(cpu_env, tmp_r1, tmp32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32);
- break;
case 0x10: /* TCEB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
@@ -1030,10 +1021,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
potential_page_fault(s);
gen_helper_mdb(cpu_env, tmp_r1, addr);
break;
- case 0x1d: /* DDB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_ddb(cpu_env, tmp_r1, addr);
- break;
case 0x1e: /* MADB R1,R3,D2(X2,B2) [RXF] */
/* for RXF insns, r1 is R3 and r1b is R1 */
tmp32 = tcg_const_i32(r1b);
@@ -1452,9 +1439,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x3: /* LCEBR R1,R2 [RRE] */
FP_HELPER_CC(lcebr);
break;
- case 0xd: /* DEBR R1,R2 [RRE] */
- FP_HELPER(debr);
- break;
case 0x10: /* LPDBR R1,R2 [RRE] */
FP_HELPER_CC(lpdbr);
break;
@@ -1470,9 +1454,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x1c: /* MDBR R1,R2 [RRE] */
FP_HELPER(mdbr);
break;
- case 0x1d: /* DDBR R1,R2 [RRE] */
- FP_HELPER(ddbr);
- break;
case 0xe: /* MAEBR R1,R3,R2 [RRF] */
case 0x1e: /* MADBR R1,R3,R2 [RRF] */
case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
@@ -1506,9 +1487,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x4c: /* MXBR R1,R2 [RRE] */
FP_HELPER(mxbr);
break;
- case 0x4d: /* DXBR R1,R2 [RRE] */
- FP_HELPER(dxbr);
- break;
case 0x65: /* LXR R1,R2 [RRE] */
tmp = load_freg(r2);
store_freg(r1, tmp);
@@ -2379,6 +2357,25 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_deb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_deb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_ddb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_ddb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
{
tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 072/126] target-s390: Convert FP MULTIPLY
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (70 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 071/126] target-s390: Convert FP DIVIDE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 073/126] target-s390: Convert MULTIPLY AND ADD, SUBTRACT Richard Henderson
` (29 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 87 +++++++++++++++++++++-------------------------
target-s390x/helper.h | 10 +++---
target-s390x/insn-data.def | 9 +++++
target-s390x/translate.c | 56 +++++++++++++++++------------
4 files changed, 86 insertions(+), 76 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index aca3b77..edc326b 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -267,27 +267,50 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return RET128(ret);
}
-/* 64-bit FP multiplication RR */
-void HELPER(mdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP multiplication */
+uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
- &env->fpu_status);
+ float32 ret = float32_mul(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
-/* 128-bit FP multiplication RR */
-void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP multiplication */
+uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- CPU_QuadU v1;
- CPU_QuadU v2;
- CPU_QuadU res;
+ float64 ret = float64_mul(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
- v1.ll.upper = env->fregs[f1].ll;
- v1.ll.lower = env->fregs[f1 + 2].ll;
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
- env->fregs[f1].ll = res.ll.upper;
- env->fregs[f1 + 2].ll = res.ll.lower;
+/* 64/32-bit FP multiplication */
+uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
+{
+ float64 ret = float32_to_float64(f2, &env->fpu_status);
+ ret = float64_mul(f1, ret, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
+/* 128-bit FP multiplication */
+uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint64_t bh, uint64_t bl)
+{
+ float128 ret = float128_mul(make_float128(ah, al),
+ make_float128(bh, bl),
+ &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
+}
+
+/* 128/64-bit FP multiplication */
+uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+ uint64_t f2)
+{
+ float128 ret = float64_to_float128(f2, &env->fpu_status);
+ ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
}
/* convert 32-bit float to 64-bit float */
@@ -403,18 +426,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(x1.q);
}
-/* 32-bit FP multiplication RM */
-void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
- float32 v1 = env->fregs[f1].l.upper;
- CPU_FloatU v2;
-
- v2.l = val;
- HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
- v1, f1, v2.f);
- env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
-}
-
/* 32-bit FP compare */
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
@@ -442,18 +453,6 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return float_comp_to_cc(env, cmp);
}
-/* 64-bit FP multiplication RM */
-void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
- float64 v1 = env->fregs[f1].d;
- CPU_DoubleU v2;
-
- v2.ll = cpu_ldq_data(env, a2);
- HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
- v1, f1, v2.d);
- env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
-}
-
static void set_round_mode(CPUS390XState *env, int m3)
{
switch (m3) {
@@ -583,14 +582,6 @@ void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
env->fregs[f1 + 1].ll = x.ll.lower;
}
-/* 32-bit FP multiplication RR */
-void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
- env->fregs[f2].l.upper,
- &env->fpu_status);
-}
-
/* 64-bit FP multiply and add RM */
void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
{
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index b0b4809..8f16c36 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -56,8 +56,11 @@ DEF_HELPER_5(sxb, i64, env, i64, i64, i64, i64)
DEF_HELPER_3(deb, i64, env, i64, i64)
DEF_HELPER_3(ddb, i64, env, i64, i64)
DEF_HELPER_5(dxb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(mdbr, void, env, i32, i32)
-DEF_HELPER_3(mxbr, void, env, i32, i32)
+DEF_HELPER_3(meeb, i64, env, i64, i64)
+DEF_HELPER_3(mdeb, i64, env, i64, i64)
+DEF_HELPER_3(mdb, i64, env, i64, i64)
+DEF_HELPER_5(mxb, i64, env, i64, i64, i64, i64)
+DEF_HELPER_4(mxdb, i64, env, i64, i64, i64)
DEF_HELPER_2(ldeb, i64, env, i64)
DEF_HELPER_3(ldxb, i64, env, i64, i64)
DEF_HELPER_2(lxdb, i64, env, i64)
@@ -70,8 +73,6 @@ DEF_HELPER_3(lpxbr, i32, env, i32, i32)
DEF_HELPER_3(lcebr, i32, env, i32, i32)
DEF_HELPER_3(lcdbr, i32, env, i32, i32)
DEF_HELPER_3(lcxbr, i32, env, i32, i32)
-DEF_HELPER_3(meeb, void, env, i32, i32)
-DEF_HELPER_3(mdb, void, env, i32, i64)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_PURE, i32, env, i64, i64, i64, i64)
@@ -84,7 +85,6 @@ DEF_HELPER_2(lzxr, void, env, i32)
DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_3(meebr, void, env, i32, i32)
DEF_HELPER_4(madb, void, env, i32, i64, i32)
DEF_HELPER_4(maebr, void, env, i32, i32, i32)
DEF_HELPER_4(madbr, void, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index d6e0a6e..7bc337c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -359,6 +359,15 @@
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
C(0x5c00, M, RX_a, Z, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
C(0xe35c, MFY, RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
+ C(0xb317, MEEBR, RRE, Z, e1, e2, new, e1, meeb, 0)
+ C(0xb31c, MDBR, RRE, Z, f1_o, f2_o, f1, 0, mdb, 0)
+ C(0xb34c, MXBR, RRE, Z, 0, x2_o, x1, 0, mxb, 0)
+ C(0xb30c, MDEBR, RRE, Z, f1_o, e2, f1, 0, mdeb, 0)
+ C(0xb307, MXDBR, RRE, Z, 0, f2_o, x1, 0, mxdb, 0)
+ C(0xed17, MEEB, RXE, Z, e1, m2_32u, new, e1, meeb, 0)
+ C(0xed1c, MDB, RXE, Z, f1_o, m2_64, f1, 0, mdb, 0)
+ C(0xed0c, MDEB, RXE, Z, f1_o, m2_32u, f1, 0, mdeb, 0)
+ C(0xed07, MXDB, RXE, Z, 0, m2_64, x1, 0, mxdb, 0)
/* MULTIPLY HALFWORD */
C(0x4c00, MH, RX_a, Z, r1, m2_16s, new, r1_32, mul, 0)
C(0xe37c, MHY, RXY_a, GIE, r1, m2_16s, new, r1_32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 7f02261..513abe9 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -989,7 +989,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
int r1b)
{
TCGv_i32 tmp_r1, tmp32;
- TCGv_i64 addr, tmp;
+ TCGv_i64 addr;
addr = get_address(s, x2, b2, d2);
tmp_r1 = tcg_const_i32(r1);
switch (op) {
@@ -1008,19 +1008,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
set_cc_static(s);
break;
- case 0x17: /* MEEB R1,D2(X2,B2) [RXE] */
- tmp = tcg_temp_new_i64();
- tmp32 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32, tmp);
- gen_helper_meeb(cpu_env, tmp_r1, tmp32);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32);
- break;
- case 0x1c: /* MDB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_mdb(cpu_env, tmp_r1, addr);
- break;
case 0x1e: /* MADB R1,R3,D2(X2,B2) [RXF] */
/* for RXF insns, r1 is R3 and r1b is R1 */
tmp32 = tcg_const_i32(r1b);
@@ -1448,12 +1435,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x15: /* SQBDR R1,R2 [RRE] */
FP_HELPER(sqdbr);
break;
- case 0x17: /* MEEBR R1,R2 [RRE] */
- FP_HELPER(meebr);
- break;
- case 0x1c: /* MDBR R1,R2 [RRE] */
- FP_HELPER(mdbr);
- break;
case 0xe: /* MAEBR R1,R3,R2 [RRF] */
case 0x1e: /* MADBR R1,R3,R2 [RRF] */
case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
@@ -1484,9 +1465,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x43: /* LCXBR R1,R2 [RRE] */
FP_HELPER_CC(lcxbr);
break;
- case 0x4c: /* MXBR R1,R2 [RRE] */
- FP_HELPER(mxbr);
- break;
case 0x65: /* LXR R1,R2 [RRE] */
tmp = load_freg(r2);
store_freg(r1, tmp);
@@ -2764,6 +2742,38 @@ static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
{
gen_helper_nabs_i64(o->out, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 073/126] target-s390: Convert MULTIPLY AND ADD, SUBTRACT
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (71 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 072/126] target-s390: Convert FP MULTIPLY Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 074/126] target-s390: Convert TEST DATA CLASS Richard Henderson
` (28 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Use the new float*_muladd interface to softfloat.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 57 +++++++++++++++++++----------------------
target-s390x/helper.h | 8 +++---
target-s390x/insn-data.def | 11 ++++++++
target-s390x/translate.c | 63 +++++++++++++++++++++++-----------------------
4 files changed, 72 insertions(+), 67 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index edc326b..408e42b 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -582,47 +582,42 @@ void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
env->fregs[f1 + 1].ll = x.ll.lower;
}
-/* 64-bit FP multiply and add RM */
-void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
+/* 32-bit FP multiply and add */
+uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
+ uint64_t f2, uint64_t f3)
{
- CPU_DoubleU v2;
-
- HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
- v2.ll = cpu_ldq_data(env, a2);
- env->fregs[f1].d = float64_add(env->fregs[f1].d,
- float64_mul(v2.d, env->fregs[f3].d,
- &env->fpu_status),
- &env->fpu_status);
+ float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
-/* 64-bit FP multiply and add RR */
-void HELPER(madbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
+/* 64-bit FP multiply and add */
+uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
+ uint64_t f2, uint64_t f3)
{
- HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
- env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
- env->fregs[f3].d,
- &env->fpu_status),
- env->fregs[f1].d, &env->fpu_status);
+ float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
-/* 64-bit FP multiply and subtract RR */
-void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
+/* 32-bit FP multiply and subtract */
+uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
+ uint64_t f2, uint64_t f3)
{
- HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
- env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
- env->fregs[f3].d,
- &env->fpu_status),
- env->fregs[f1].d, &env->fpu_status);
+ float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
+ &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
-/* 32-bit FP multiply and add RR */
-void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
+/* 64-bit FP multiply and subtract */
+uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
+ uint64_t f2, uint64_t f3)
{
- env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
- float32_mul(env->fregs[f2].l.upper,
- env->fregs[f3].l.upper,
- &env->fpu_status),
- &env->fpu_status);
+ float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
+ &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* test data class 32-bit */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 8f16c36..5f31d96 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -85,10 +85,10 @@ DEF_HELPER_2(lzxr, void, env, i32)
DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(madb, void, env, i32, i64, i32)
-DEF_HELPER_4(maebr, void, env, i32, i32, i32)
-DEF_HELPER_4(madbr, void, env, i32, i32, i32)
-DEF_HELPER_4(msdbr, void, env, i32, i32, i32)
+DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
+DEF_HELPER_4(madb, i64, env, i64, i64, i64)
+DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
+DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7bc337c..6cecf27 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -391,6 +391,17 @@
C(0xc201, MSFI, RIL_a, GIE, r1, i2, new, r1_32, mul, 0)
C(0xc200, MSGFI, RIL_a, GIE, r1, i2, r1, 0, mul, 0)
+/* MULTIPLY AND ADD */
+ C(0xb30e, MAEBR, RRD, Z, e1, e2, new, e1, maeb, 0)
+ C(0xb31e, MADBR, RRD, Z, f1_o, f2_o, f1, 0, madb, 0)
+ C(0xed0e, MAEB, RXF, Z, e1, m2_32u, new, e1, maeb, 0)
+ C(0xed1e, MADB, RXF, Z, f1_o, m2_64, f1, 0, madb, 0)
+/* MULTIPLY AND SUBTRACT */
+ C(0xb30f, MSEBR, RRD, Z, e1, e2, new, e1, mseb, 0)
+ C(0xb31f, MSDBR, RRD, Z, f1_o, f2_o, f1, 0, msdb, 0)
+ C(0xed0f, MSEB, RXF, Z, e1, m2_32u, new, e1, mseb, 0)
+ C(0xed1f, MSDB, RXF, Z, f1_o, m2_64, f1, 0, msdb, 0)
+
/* OR */
C(0x1600, OR, RR_a, Z, r1, r2, new, r1_32, or, nz32)
C(0xb9f6, ORK, RRF_a, DO, r2, r3, new, r1_32, or, nz32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 513abe9..75f1ec8 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -988,7 +988,7 @@ static void free_compare(DisasCompare *c)
static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
int r1b)
{
- TCGv_i32 tmp_r1, tmp32;
+ TCGv_i32 tmp_r1;
TCGv_i64 addr;
addr = get_address(s, x2, b2, d2);
tmp_r1 = tcg_const_i32(r1);
@@ -1008,13 +1008,6 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
set_cc_static(s);
break;
- case 0x1e: /* MADB R1,R3,D2(X2,B2) [RXF] */
- /* for RXF insns, r1 is R3 and r1b is R1 */
- tmp32 = tcg_const_i32(r1b);
- potential_page_fault(s);
- gen_helper_madb(cpu_env, tmp32, addr, tmp_r1);
- tcg_temp_free_i32(tmp32);
- break;
default:
LOG_DISAS("illegal ed operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -1435,30 +1428,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
case 0x15: /* SQBDR R1,R2 [RRE] */
FP_HELPER(sqdbr);
break;
- case 0xe: /* MAEBR R1,R3,R2 [RRF] */
- case 0x1e: /* MADBR R1,R3,R2 [RRF] */
- case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
- /* for RRF insns, m3 is R1, r1 is R3, and r2 is R2 */
- tmp32_1 = tcg_const_i32(m3);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(r1);
- switch (op) {
- case 0xe:
- gen_helper_maebr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
- break;
- case 0x1e:
- gen_helper_madbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
- break;
- case 0x1f:
- gen_helper_msdbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0x40: /* LPXBR R1,R2 [RRE] */
FP_HELPER_CC(lpxbr);
break;
@@ -2774,6 +2743,36 @@ static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
+ gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
+ tcg_temp_free_i64(r3);
+ return NO_EXIT;
+}
+
+static ExitStatus op_madb(DisasContext *s, DisasOps *o)
+{
+ int r3 = get_field(s->fields, r3);
+ gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+ return NO_EXIT;
+}
+
+static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
+ gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
+ tcg_temp_free_i64(r3);
+ return NO_EXIT;
+}
+
+static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
+{
+ int r3 = get_field(s->fields, r3);
+ gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+ return NO_EXIT;
+}
+
static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
{
gen_helper_nabs_i64(o->out, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 074/126] target-s390: Convert TEST DATA CLASS
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (72 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 073/126] target-s390: Convert MULTIPLY AND ADD, SUBTRACT Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 075/126] target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE Richard Henderson
` (27 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 28 +++++++-------------
target-s390x/helper.h | 6 ++---
target-s390x/insn-data.def | 5 ++++
target-s390x/translate.c | 66 ++++++++++++++++------------------------------
4 files changed, 40 insertions(+), 65 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 408e42b..2c77fc6 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -621,13 +621,12 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
}
/* test data class 32-bit */
-uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2)
{
- float32 v1 = env->fregs[f1].l.upper;
+ float32 v1 = f1;
int neg = float32_is_neg(v1);
uint32_t cc = 0;
- HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
(float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
(float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -637,19 +636,16 @@ uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
/* assume normalized number */
cc = 1;
}
-
/* FIXME: denormalized? */
return cc;
}
/* test data class 64-bit */
-uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2)
{
- float64 v1 = env->fregs[f1].d;
int neg = float64_is_neg(v1);
uint32_t cc = 0;
- HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
(float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
(float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -664,20 +660,16 @@ uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
}
/* test data class 128-bit */
-uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
{
- CPU_QuadU v1;
+ float128 v1 = make_float128(ah, al);
+ int neg = float128_is_neg(v1);
uint32_t cc = 0;
- int neg;
-
- v1.ll.upper = env->fregs[f1].ll;
- v1.ll.lower = env->fregs[f1 + 2].ll;
- neg = float128_is_neg(v1.q);
- if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
- (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
- (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
- (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
+ if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
+ (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
+ (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
+ (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
cc = 1;
} else if (m2 & (1 << (9-neg))) {
/* assume normalized number */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 5f31d96..739ad1f 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -89,9 +89,9 @@ DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
DEF_HELPER_4(madb, i64, env, i64, i64, i64)
DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
+DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
+DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64, i64)
DEF_HELPER_3(flogr, i32, env, i32, i64)
DEF_HELPER_3(sqdbr, void, env, i32, i32)
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6cecf27..8fba8c7 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -531,6 +531,11 @@
/* SUPERVISOR CALL */
C(0x0a00, SVC, I, Z, 0, 0, 0, 0, svc, 0)
+/* TEST DATA CLASS */
+ C(0xed10, TCEB, RXE, Z, e1, a2, 0, 0, tceb, 0)
+ C(0xed11, TCDB, RXE, Z, f1_o, a2, 0, 0, tcdb, 0)
+ C(0xed12, TCXB, RXE, Z, x1_o, a2, 0, 0, tcxb, 0)
+
/* TEST UNDER MASK */
C(0x9100, TM, SI, Z, m1_8u, i2_8u, 0, 0, 0, tm32)
C(0xeb51, TMY, SIY, LD, m1_8u, i2_8u, 0, 0, 0, tm32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 75f1ec8..7a329ca 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -985,38 +985,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
- int r1b)
-{
- TCGv_i32 tmp_r1;
- TCGv_i64 addr;
- addr = get_address(s, x2, b2, d2);
- tmp_r1 = tcg_const_i32(r1);
- switch (op) {
- case 0x10: /* TCEB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
- set_cc_static(s);
- break;
- case 0x11: /* TCDB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_tcdb(cc_op, cpu_env, tmp_r1, addr);
- set_cc_static(s);
- break;
- case 0x12: /* TCXB R1,D2(X2,B2) [RXE] */
- potential_page_fault(s);
- gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
- set_cc_static(s);
- break;
- default:
- LOG_DISAS("illegal ed operation 0x%x\n", op);
- gen_illegal_opcode(s);
- return;
- }
- tcg_temp_free_i32(tmp_r1);
- tcg_temp_free_i64(addr);
-}
-
static void disas_b2(DisasContext *s, int op, uint32_t insn)
{
TCGv_i64 tmp, tmp2, tmp3;
@@ -1597,7 +1565,7 @@ static void disas_s390_insn(DisasContext *s)
{
unsigned char opc;
uint64_t insn;
- int op, r1, r2, r3, d2, x2, b2, r1b;
+ int op, r1, r2, r3;
opc = cpu_ldub_code(cpu_single_env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -1623,17 +1591,6 @@ static void disas_s390_insn(DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(s, op, r1, r2);
break;
- case 0xed:
- insn = ld_code6(s->pc);
- debug_insn(insn);
- op = insn & 0xff;
- r1 = (insn >> 36) & 0xf;
- x2 = (insn >> 32) & 0xf;
- b2 = (insn >> 28) & 0xf;
- d2 = (short)((insn >> 16) & 0xfff);
- r1b = (insn >> 12) & 0xf;
- disas_ed(s, op, r1, x2, b2, d2, r1b);
- break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
gen_illegal_opcode(s);
@@ -3146,6 +3103,27 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
return EXIT_NORETURN;
}
+static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_tceb(cc_op, o->in1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_tcdb(cc_op, o->in1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
+static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 075/126] target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (73 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 074/126] target-s390: Convert TEST DATA CLASS Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 076/126] target-s390: Convert FP SQUARE ROOT Richard Henderson
` (26 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 65 ------------------------------------
target-s390x/helper.h | 6 ----
target-s390x/insn-data.def | 9 +++++
target-s390x/translate.c | 83 +++++++++++++++++++++++++++++++---------------
4 files changed, 66 insertions(+), 97 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 2c77fc6..df70b1a 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -361,71 +361,6 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
return ret;
}
-/* absolute value of 32-bit float */
-uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- float32 v1;
- float32 v2 = env->fregs[f2].d;
-
- v1 = float32_abs(v2);
- env->fregs[f1].d = v1;
- return set_cc_nz_f32(v1);
-}
-
-/* absolute value of 64-bit float */
-uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- float64 v1;
- float64 v2 = env->fregs[f2].d;
-
- v1 = float64_abs(v2);
- env->fregs[f1].d = v1;
- return set_cc_nz_f64(v1);
-}
-
-/* absolute value of 128-bit float */
-uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- CPU_QuadU v1;
- CPU_QuadU v2;
-
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- v1.q = float128_abs(v2.q);
- env->fregs[f1].ll = v1.ll.upper;
- env->fregs[f1 + 2].ll = v1.ll.lower;
- return set_cc_nz_f128(v1.q);
-}
-
-/* load complement of 32-bit float */
-uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
-
- return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* load complement of 64-bit float */
-uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- env->fregs[f1].d = float64_chs(env->fregs[f2].d);
-
- return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* load complement of 128-bit float */
-uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
- CPU_QuadU x1, x2;
-
- x2.ll.upper = env->fregs[f2].ll;
- x2.ll.lower = env->fregs[f2 + 2].ll;
- x1.q = float128_chs(x2.q);
- env->fregs[f1].ll = x1.ll.upper;
- env->fregs[f1 + 2].ll = x1.ll.lower;
- return set_cc_nz_f128(x1.q);
-}
-
/* 32-bit FP compare */
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 739ad1f..59ebe36 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -67,12 +67,6 @@ DEF_HELPER_2(lxdb, i64, env, i64)
DEF_HELPER_2(lxeb, i64, env, i64)
DEF_HELPER_2(ledb, i64, env, i64)
DEF_HELPER_3(lexb, i64, env, i64, i64)
-DEF_HELPER_3(lpebr, i32, env, i32, i32)
-DEF_HELPER_3(lpdbr, i32, env, i32, i32)
-DEF_HELPER_3(lpxbr, i32, env, i32, i32)
-DEF_HELPER_3(lcebr, i32, env, i32, i32)
-DEF_HELPER_3(lcdbr, i32, env, i32, i32)
-DEF_HELPER_3(lcxbr, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_PURE, i32, env, i64, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8fba8c7..9c555d7 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -266,6 +266,9 @@
C(0x1300, LCR, RR_a, Z, 0, r2, new, r1_32, neg, neg32)
C(0xb903, LCGR, RRE, Z, 0, r2, r1, 0, neg, neg64)
C(0xb913, LCGFR, RRE, Z, 0, r2_32s, r1, 0, neg, neg64)
+ C(0xb303, LCEBR, RRE, Z, 0, e2, new, e1, negf32, f32)
+ C(0xb313, LCDBR, RRE, Z, 0, f2_o, f1, 0, negf64, f64)
+ C(0xb343, LCXBR, RRE, Z, 0, x2_o, x1, 0, negf128, f128)
/* LOAD HALFWORD */
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
@@ -310,10 +313,16 @@
C(0x1100, LNR, RR_a, Z, 0, r2_32s, new, r1_32, nabs, nabs32)
C(0xb901, LNGR, RRE, Z, 0, r2, r1, 0, nabs, nabs64)
C(0xb911, LNGFR, RRE, Z, 0, r2_32s, r1, 0, nabs, nabs64)
+ C(0xb301, LNEBR, RRE, Z, 0, e2, new, e1, nabsf32, f32)
+ C(0xb311, LNDBR, RRE, Z, 0, f2_o, f1, 0, nabsf64, f64)
+ C(0xb341, LNXBR, RRE, Z, 0, x2_o, x1, 0, nabsf128, f128)
/* LOAD POSITIVE */
C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32)
C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
+ C(0xb300, LPEBR, RRE, Z, 0, e2, new, e1, absf32, f32)
+ C(0xb310, LPDBR, RRE, Z, 0, f2_o, f1, 0, absf64, f64)
+ C(0xb340, LPXBR, RRE, Z, 0, x2_o, x1, 0, absf128, f128)
/* LOAD REVERSED */
C(0xb91f, LRVR, RRE, Z, 0, r2_32u, new, r1_32, rev32, 0)
C(0xb90f, LRVGR, RRE, Z, 0, r2_o, r1, 0, rev64, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 7a329ca..c9029ed 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1381,35 +1381,9 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
tcg_temp_free_i32(tmp32_2);
switch (op) {
- case 0x0: /* LPEBR R1,R2 [RRE] */
- FP_HELPER_CC(lpebr);
- break;
- case 0x3: /* LCEBR R1,R2 [RRE] */
- FP_HELPER_CC(lcebr);
- break;
- case 0x10: /* LPDBR R1,R2 [RRE] */
- FP_HELPER_CC(lpdbr);
- break;
- case 0x13: /* LCDBR R1,R2 [RRE] */
- FP_HELPER_CC(lcdbr);
- break;
case 0x15: /* SQBDR R1,R2 [RRE] */
FP_HELPER(sqdbr);
break;
- case 0x40: /* LPXBR R1,R2 [RRE] */
- FP_HELPER_CC(lpxbr);
- break;
- case 0x43: /* LCXBR R1,R2 [RRE] */
- FP_HELPER_CC(lcxbr);
- break;
- case 0x65: /* LXR R1,R2 [RRE] */
- tmp = load_freg(r2);
- store_freg(r1, tmp);
- tcg_temp_free_i64(tmp);
- tmp = load_freg(r2 + 2);
- store_freg(r1 + 2, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0x74: /* LZER R1 [RRE] */
tmp32_1 = tcg_const_i32(r1);
gen_helper_lzer(cpu_env, tmp32_1);
@@ -1948,6 +1922,25 @@ static ExitStatus op_abs(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_absf32(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull);
+ return NO_EXIT;
+}
+
+static ExitStatus op_absf64(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
+ return NO_EXIT;
+}
+
+static ExitStatus op_absf128(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull);
+ tcg_gen_mov_i64(o->out2, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_add(DisasContext *s, DisasOps *o)
{
tcg_gen_add_i64(o->out, o->in1, o->in2);
@@ -2736,6 +2729,25 @@ static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
+ return NO_EXIT;
+}
+
+static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
+ return NO_EXIT;
+}
+
+static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
+ tcg_gen_mov_i64(o->out2, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_nc(DisasContext *s, DisasOps *o)
{
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
@@ -2752,6 +2764,25 @@ static ExitStatus op_neg(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
+ return NO_EXIT;
+}
+
+static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
+ return NO_EXIT;
+}
+
+static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
+{
+ tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
+ tcg_gen_mov_i64(o->out2, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_oc(DisasContext *s, DisasOps *o)
{
TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 076/126] target-s390: Convert FP SQUARE ROOT
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (74 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 075/126] target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 077/126] target-s390: Convert LOAD ZERO Richard Henderson
` (25 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 24 +++++++++++++++++++++---
target-s390x/helper.h | 4 +++-
target-s390x/insn-data.def | 7 +++++++
target-s390x/translate.c | 22 +++++++++++++++++++---
4 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index df70b1a..7d08aae 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -614,8 +614,26 @@ uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
return cc;
}
-/* square root 64-bit RR */
-void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* square root 32-bit */
+uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
{
- env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
+ float32 ret = float32_sqrt(f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
+/* square root 64-bit */
+uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
+{
+ float64 ret = float64_sqrt(f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
+/* square root 128-bit */
+uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+{
+ float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
}
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 59ebe36..a7dcee9 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -87,7 +87,9 @@ DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64, i64)
DEF_HELPER_3(flogr, i32, env, i32, i64)
-DEF_HELPER_3(sqdbr, void, env, i32, i32)
+DEF_HELPER_2(sqeb, i64, env, i64)
+DEF_HELPER_2(sqdb, i64, env, i64)
+DEF_HELPER_3(sqxb, i64, env, i64, i64)
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
DEF_HELPER_4(unpk, void, env, i32, i64, i64)
DEF_HELPER_4(tr, void, env, i32, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9c555d7..97c38f2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -459,6 +459,13 @@
/* SHIFT RIGHT DOUBLE LOGICAL */
C(0x8c00, SRDL, RS_a, Z, r1_P32, sh64, new, r1_P32, srl, 0)
+/* SQUARE ROOT */
+ C(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0)
+ C(0xb315, SQDBR, RRE, Z, 0, f2_o, f1, 0, sqdb, 0)
+ C(0xb316, SQXBR, RRE, Z, 0, x2_o, x1, 0, sqxb, 0)
+ C(0xed14, SQEB, RXE, Z, 0, m2_32u, new, e1, sqeb, 0)
+ C(0xed15, SQDB, RXE, Z, 0, m2_64, f1, 0, sqdb, 0)
+
/* STORE */
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0)
C(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c9029ed..86b222a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1381,9 +1381,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
tcg_temp_free_i32(tmp32_2);
switch (op) {
- case 0x15: /* SQBDR R1,R2 [RRE] */
- FP_HELPER(sqdbr);
- break;
case 0x74: /* LZER R1 [RRE] */
tmp32_1 = tcg_const_i32(r1);
gen_helper_lzer(cpu_env, tmp32_1);
@@ -2873,6 +2870,25 @@ static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_sqeb(o->out, cpu_env, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_sqdb(o->out, cpu_env, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
+{
+ gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 077/126] target-s390: Convert LOAD ZERO
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (75 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 076/126] target-s390: Convert FP SQUARE ROOT Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 078/126] target-s390: Convert CONVERT TO FIXED Richard Henderson
` (24 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 22 ----------------------
target-s390x/helper.h | 3 ---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 29 ++++++++++++++---------------
4 files changed, 18 insertions(+), 40 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 7d08aae..4844f1e 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -495,28 +495,6 @@ uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
return set_cc_nz_f128(v2.q);
}
-/* load 32-bit FP zero */
-void HELPER(lzer)(CPUS390XState *env, uint32_t f1)
-{
- env->fregs[f1].l.upper = float32_zero;
-}
-
-/* load 64-bit FP zero */
-void HELPER(lzdr)(CPUS390XState *env, uint32_t f1)
-{
- env->fregs[f1].d = float64_zero;
-}
-
-/* load 128-bit FP zero */
-void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
-{
- CPU_QuadU x;
-
- x.q = float64_to_float128(float64_zero, &env->fpu_status);
- env->fregs[f1].ll = x.ll.upper;
- env->fregs[f1 + 1].ll = x.ll.lower;
-}
-
/* 32-bit FP multiply and add */
uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
uint64_t f2, uint64_t f3)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index a7dcee9..348f4cd 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -73,9 +73,6 @@ DEF_HELPER_FLAGS_5(cxb, TCG_CALL_PURE, i32, env, i64, i64, i64, i64)
DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
-DEF_HELPER_2(lzer, void, env, i32)
-DEF_HELPER_2(lzdr, void, env, i32)
-DEF_HELPER_2(lzxr, void, env, i32)
DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 97c38f2..912c1fa 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -329,6 +329,10 @@
C(0xe31f, LRVH, RXY_a, Z, 0, m2_16u, new, r1_16, rev16, 0)
C(0xe31e, LRV, RXY_a, Z, 0, m2_32u, new, r1_32, rev32, 0)
C(0xe30f, LRVG, RXY_a, Z, 0, m2_64, r1, 0, rev64, 0)
+/* LOAD ZERO */
+ C(0xb374, LZER, RRE, Z, 0, 0, 0, e1, zero, 0)
+ C(0xb375, LZDR, RRE, Z, 0, 0, 0, f1, zero, 0)
+ C(0xb376, LZXR, RRE, Z, 0, 0, 0, x1, zero2, 0)
/* LOAD LENGTHENED */
C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 86b222a..3c69079 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1381,21 +1381,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
tcg_temp_free_i32(tmp32_2);
switch (op) {
- case 0x74: /* LZER R1 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- gen_helper_lzer(cpu_env, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x75: /* LZDR R1 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- gen_helper_lzdr(cpu_env, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x76: /* LZXR R1 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- gen_helper_lzxr(cpu_env, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x84: /* SFPC R1 [RRE] */
tmp32_1 = load_reg32(r1);
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
@@ -3232,6 +3217,20 @@ static ExitStatus op_xori(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_zero(DisasContext *s, DisasOps *o)
+{
+ o->out = tcg_const_i64(0);
+ return NO_EXIT;
+}
+
+static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
+{
+ o->out = tcg_const_i64(0);
+ o->out2 = o->out;
+ o->g_out2 = true;
+ return NO_EXIT;
+}
+
/* ====================================================================== */
/* The "Cc OUTput" generators. Given the generated output (and in some cases
the original inputs), update the various cc data structures in order to
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 078/126] target-s390: Convert CONVERT TO FIXED
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (76 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 077/126] target-s390: Convert LOAD ZERO Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 079/126] target-s390: Convert CONVERT FROM FIXED Richard Henderson
` (23 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 98 +++++++++++++++--------------------
target-s390x/helper.h | 12 ++---
target-s390x/insn-data.def | 7 +++
target-s390x/translate.c | 125 +++++++++++++++++++++++++--------------------
4 files changed, 124 insertions(+), 118 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 4844f1e..3f9005f 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -388,8 +388,9 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return float_comp_to_cc(env, cmp);
}
-static void set_round_mode(CPUS390XState *env, int m3)
+static int swap_round_mode(CPUS390XState *env, int m3)
{
+ int ret = env->fpu_status.float_rounding_mode;
switch (m3) {
case 0:
/* current mode */
@@ -413,86 +414,69 @@ static void set_round_mode(CPUS390XState *env, int m3)
set_float_rounding_mode(float_round_down, &env->fpu_status);
break;
}
+ return ret;
}
/* convert 32-bit float to 64-bit int */
-uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float32 v2 = env->fregs[f2].l.upper;
-
- set_round_mode(env, m3);
- env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
- return set_cc_nz_f32(v2);
+ int hold = swap_round_mode(env, m3);
+ int64_t ret = float32_to_int64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 64-bit float to 64-bit int */
-uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float64 v2 = env->fregs[f2].d;
-
- set_round_mode(env, m3);
- env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
- return set_cc_nz_f64(v2);
+ int hold = swap_round_mode(env, m3);
+ int64_t ret = float64_to_int64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 128-bit float to 64-bit int */
-uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- CPU_QuadU v2;
-
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- set_round_mode(env, m3);
- env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
- if (float128_is_any_nan(v2.q)) {
- return 3;
- } else if (float128_is_zero(v2.q)) {
- return 0;
- } else if (float128_is_neg(v2.q)) {
- return 1;
- } else {
- return 2;
- }
+ int hold = swap_round_mode(env, m3);
+ float128 v2 = make_float128(h, l);
+ int64_t ret = float128_to_int64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 32-bit float to 32-bit int */
-uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float32 v2 = env->fregs[f2].l.upper;
-
- set_round_mode(env, m3);
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- float32_to_int32(v2, &env->fpu_status);
- return set_cc_nz_f32(v2);
+ int hold = swap_round_mode(env, m3);
+ int32_t ret = float32_to_int32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 64-bit float to 32-bit int */
-uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float64 v2 = env->fregs[f2].d;
-
- set_round_mode(env, m3);
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- float64_to_int32(v2, &env->fpu_status);
- return set_cc_nz_f64(v2);
+ int hold = swap_round_mode(env, m3);
+ int32_t ret = float64_to_int32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 128-bit float to 32-bit int */
-uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- CPU_QuadU v2;
-
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- float128_to_int32(v2.q, &env->fpu_status);
- return set_cc_nz_f128(v2.q);
+ int hold = swap_round_mode(env, m3);
+ float128 v2 = make_float128(h, l);
+ int32_t ret = float128_to_int32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* 32-bit FP multiply and add */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 348f4cd..155e34c 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -70,12 +70,12 @@ DEF_HELPER_3(lexb, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_PURE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_PURE, i32, env, i64, i64, i64, i64)
-DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
+DEF_HELPER_3(cgeb, i64, env, i64, i32)
+DEF_HELPER_3(cgdb, i64, env, i64, i32)
+DEF_HELPER_4(cgxb, i64, env, i64, i64, i32)
+DEF_HELPER_3(cfeb, i64, env, i64, i32)
+DEF_HELPER_3(cfdb, i64, env, i64, i32)
+DEF_HELPER_4(cfxb, i64, env, i64, i64, i32)
DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
DEF_HELPER_4(madb, i64, env, i64, i64, i64)
DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 912c1fa..551011b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -163,6 +163,13 @@
/* CONVERT TO DECIMAL */
C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
+/* CONVERT TO FIXED */
+ C(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0)
+ C(0xb399, CFDBR, RRF_e, Z, 0, f2_o, new, r1_32, cfdb, 0)
+ C(0xb39a, CFXBR, RRF_e, Z, 0, x2_o, new, r1_32, cfxb, 0)
+ C(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0)
+ C(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0)
+ C(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0)
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_P32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3c69079..f62a5b5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -483,6 +483,21 @@ static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_NZ, val);
}
+static inline void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
+}
+
+static inline void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
+}
+
+static inline void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
+{
+ gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
+}
+
static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
enum cc_op cond)
{
@@ -1363,7 +1378,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
{
TCGv_i64 tmp;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+ TCGv_i32 tmp32_1, tmp32_2;
LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
#define FP_HELPER(i) \
tmp32_1 = tcg_const_i32(r1); \
@@ -1407,30 +1422,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x98: /* CFEBR R1,R2 [RRE] */
- case 0x99: /* CFDBR R1,R2 [RRE] */
- case 0x9a: /* CFXBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- switch (op) {
- case 0x98:
- gen_helper_cfebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x99:
- gen_helper_cfdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x9a:
- gen_helper_cfxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- break;
- default:
- tcg_abort();
- }
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0xa4: /* CEGBR R1,R2 [RRE] */
case 0xa5: /* CDGBR R1,R2 [RRE] */
tmp32_1 = tcg_const_i32(r1);
@@ -1455,36 +1446,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
break;
- case 0xa8: /* CGEBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- gen_helper_cgebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0xa9: /* CGDBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- gen_helper_cgdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0xaa: /* CGXBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- gen_helper_cgxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
default:
LOG_DISAS("illegal b3 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2080,6 +2041,60 @@ static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_cfeb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f32(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cfdb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f64(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cfxb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f128(s, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cgeb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f32(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cgdb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f64(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f128(s, o->in1, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
{
int l = get_field(s->fields, l1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 079/126] target-s390: Convert CONVERT FROM FIXED
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (77 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 078/126] target-s390: Convert CONVERT TO FIXED Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 080/126] target-s390: Convert FLOGR Richard Henderson
` (22 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 81 +++++++++++++++++-----------------------------
target-s390x/helper.h | 9 ++----
target-s390x/insn-data.def | 7 ++++
target-s390x/translate.c | 73 +++++++++++++++--------------------------
4 files changed, 66 insertions(+), 104 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 3f9005f..b6cc45b 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -135,57 +135,6 @@ uint32_t set_cc_nz_f128(float128 v)
}
}
-/* convert 32-bit int to 64-bit float */
-void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
-{
- HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
- env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
-}
-
-/* convert 32-bit int to 128-bit float */
-void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
-{
- CPU_QuadU v1;
-
- v1.q = int32_to_float128(v2, &env->fpu_status);
- env->fregs[f1].ll = v1.ll.upper;
- env->fregs[f1 + 2].ll = v1.ll.lower;
-}
-
-/* convert 64-bit int to 32-bit float */
-void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
-{
- HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
- env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
-}
-
-/* convert 64-bit int to 64-bit float */
-void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
-{
- HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
- env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
-}
-
-/* convert 64-bit int to 128-bit float */
-void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
-{
- CPU_QuadU x1;
-
- x1.q = int64_to_float128(v2, &env->fpu_status);
- HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
- x1.ll.upper, x1.ll.lower);
- env->fregs[f1].ll = x1.ll.upper;
- env->fregs[f1 + 2].ll = x1.ll.lower;
-}
-
-/* convert 32-bit int to 32-bit float */
-void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
-{
- env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
- HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
- env->fregs[f1].l.upper, f1);
-}
-
/* 32-bit FP addition */
uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
@@ -417,6 +366,36 @@ static int swap_round_mode(CPUS390XState *env, int m3)
return ret;
}
+/* convert 64-bit int to 32-bit float */
+uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ float32 ret = int64_to_float32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
+/* convert 64-bit int to 64-bit float */
+uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ float64 ret = int64_to_float64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
+/* convert 64-bit int to 128-bit float */
+uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ float128 ret = int64_to_float128(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return RET128(ret);
+}
+
/* convert 32-bit float to 64-bit int */
uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 155e34c..7d8efec 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -41,12 +41,9 @@ DEF_HELPER_4(stam, void, env, i32, i64, i32)
DEF_HELPER_4(lam, void, env, i32, i64, i32)
DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
-DEF_HELPER_3(cefbr, void, env, i32, s32)
-DEF_HELPER_3(cdfbr, void, env, i32, s32)
-DEF_HELPER_3(cxfbr, void, env, i32, s32)
-DEF_HELPER_3(cegbr, void, env, i32, s64)
-DEF_HELPER_3(cdgbr, void, env, i32, s64)
-DEF_HELPER_3(cxgbr, void, env, i32, s64)
+DEF_HELPER_3(cegb, i64, env, s64, i32)
+DEF_HELPER_3(cdgb, i64, env, s64, i32)
+DEF_HELPER_3(cxgb, i64, env, s64, i32)
DEF_HELPER_3(aeb, i64, env, i64, i64)
DEF_HELPER_3(adb, i64, env, i64, i64)
DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 551011b..e3ca83c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -170,6 +170,13 @@
C(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0)
C(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0)
C(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0)
+/* CONVERT FROM FIXED */
+ C(0xb394, CEFBR, RRF_e, Z, 0, r2_32s, new, e1, cegb, 0)
+ C(0xb395, CDFBR, RRF_e, Z, 0, r2_32s, f1, 0, cdgb, 0)
+ C(0xb396, CXFBR, RRF_e, Z, 0, r2_32s, x1, 0, cxgb, 0)
+ C(0xb3a4, CEGBR, RRF_e, Z, 0, r2_o, new, e1, cegb, 0)
+ C(0xb3a5, CDGBR, RRF_e, Z, 0, r2_o, f1, 0, cdgb, 0)
+ C(0xb3a6, CXGBR, RRF_e, Z, 0, r2_o, x1, 0, cxgb, 0)
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_P32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f62a5b5..2326387 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1377,8 +1377,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
{
- TCGv_i64 tmp;
- TCGv_i32 tmp32_1, tmp32_2;
+ TCGv_i32 tmp32_1;
LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
#define FP_HELPER(i) \
tmp32_1 = tcg_const_i32(r1); \
@@ -1401,51 +1400,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
tcg_temp_free_i32(tmp32_1);
break;
- case 0x94: /* CEFBR R1,R2 [RRE] */
- case 0x95: /* CDFBR R1,R2 [RRE] */
- case 0x96: /* CXFBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = load_reg32(r2);
- switch (op) {
- case 0x94:
- gen_helper_cefbr(cpu_env, tmp32_1, tmp32_2);
- break;
- case 0x95:
- gen_helper_cdfbr(cpu_env, tmp32_1, tmp32_2);
- break;
- case 0x96:
- gen_helper_cxfbr(cpu_env, tmp32_1, tmp32_2);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- break;
- case 0xa4: /* CEGBR R1,R2 [RRE] */
- case 0xa5: /* CDGBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp = load_reg(r2);
- switch (op) {
- case 0xa4:
- gen_helper_cegbr(cpu_env, tmp32_1, tmp);
- break;
- case 0xa5:
- gen_helper_cdgbr(cpu_env, tmp32_1, tmp);
- break;
- default:
- tcg_abort();
- }
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
- case 0xa6: /* CXGBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp = load_reg(r2);
- gen_helper_cxgbr(cpu_env, tmp32_1, tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
default:
LOG_DISAS("illegal b3 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2095,6 +2049,31 @@ static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_cegb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cegb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cdgb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
{
int l = get_field(s->fields, l1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 080/126] target-s390: Convert FLOGR
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (78 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 079/126] target-s390: Convert CONVERT FROM FIXED Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 081/126] target-s390: Convert LFPC, SFPC Richard Henderson
` (21 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 8 ++++++
target-s390x/cpu.h | 2 ++
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 3 +++
target-s390x/int_helper.c | 22 +++-------------
target-s390x/translate.c | 65 +++++++++++++++++++++++++---------------------
6 files changed, 53 insertions(+), 49 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 27aac03..46c6d84 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -399,6 +399,11 @@ static uint32_t cc_calc_sla_64(uint64_t src, int shift)
return 2;
}
+static uint32_t cc_calc_flogr(uint64_t dst)
+{
+ return dst ? 2 : 0;
+}
+
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
{
@@ -504,6 +509,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_SLA_64:
r = cc_calc_sla_64(src, dst);
break;
+ case CC_OP_FLOGR:
+ r = cc_calc_flogr(dst);
+ break;
case CC_OP_NZ_F32:
r = set_cc_nz_f32(dst);
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 37a91d3..e7d37f3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -472,6 +472,7 @@ enum cc_op {
CC_OP_ICM, /* insert characters under mask */
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
+ CC_OP_FLOGR, /* find leftmost one */
CC_OP_MAX
};
@@ -515,6 +516,7 @@ static const char *cc_names[] = {
[CC_OP_ICM] = "CC_OP_ICM",
[CC_OP_SLA_32] = "CC_OP_SLA_32",
[CC_OP_SLA_64] = "CC_OP_SLA_64",
+ [CC_OP_FLOGR] = "CC_OP_FLOGR",
};
static inline const char *cc_name(int cc_op)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 7d8efec..0ba0342 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -80,7 +80,7 @@ DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64, i64)
-DEF_HELPER_3(flogr, i32, env, i32, i64)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_PURE | TCG_CALL_CONST, i64, i64)
DEF_HELPER_2(sqeb, i64, env, i64)
DEF_HELPER_2(sqdb, i64, env, i64)
DEF_HELPER_3(sqxb, i64, env, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index e3ca83c..f08a37e 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -220,6 +220,9 @@
/* EXTRACT FPC */
C(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0)
+/* FIND LEFTMOST ONE */
+ C(0xb983, FLOGR, RRE, EI, 0, r2_o, r1_P, 0, flogr, 0)
+
/* INSERT CHARACTER */
C(0x4300, IC, RX_a, Z, 0, m2_8u, 0, r1_8, mov2, 0)
C(0xe373, ICY, RXY_a, LD, 0, m2_8u, 0, r1_8, mov2, 0)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index f2f420c..00f764c 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -165,26 +165,10 @@ int64_t HELPER(nabs_i64)(int64_t val)
}
}
-/* find leftmost one */
-uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2)
+/* count leading zeros, for find leftmost one */
+uint64_t HELPER(clz)(uint64_t v)
{
- uint64_t res = 0;
- uint64_t ov2 = v2;
-
- while (!(v2 & 0x8000000000000000ULL) && v2) {
- v2 <<= 1;
- res++;
- }
-
- if (!v2) {
- env->regs[r1] = 64;
- env->regs[r1 + 1] = 0;
- return 0;
- } else {
- env->regs[r1] = res;
- env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
- return 2;
- }
+ return clz64(v);
}
uint64_t HELPER(cvd)(int32_t bin)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2326387..f07bed1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -618,6 +618,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_COMP_64:
case CC_OP_NZ_F32:
case CC_OP_NZ_F64:
+ case CC_OP_FLOGR:
/* 1 argument */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
break;
@@ -850,6 +851,20 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
account_inline_branch(s, old_cc_op);
break;
+ case CC_OP_FLOGR:
+ switch (mask & 0xa) {
+ case 8: /* src == 0 -> no one bit found */
+ cond = TCG_COND_EQ;
+ break;
+ case 2: /* src != 0 -> one bit found */
+ cond = TCG_COND_NE;
+ break;
+ default:
+ goto do_dynamic;
+ }
+ account_inline_branch(s, old_cc_op);
+ break;
+
default:
do_dynamic:
/* Calculate cc value. */
@@ -886,6 +901,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
case CC_OP_LTGT0_64:
case CC_OP_NZ:
+ case CC_OP_FLOGR:
c->u.s64.a = cc_dst;
c->u.s64.b = tcg_const_i64(0);
c->g1 = true;
@@ -1410,28 +1426,6 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
#undef FP_HELPER
}
-static void disas_b9(DisasContext *s, int op, int r1, int r2)
-{
- TCGv_i64 tmp;
- TCGv_i32 tmp32_1;
-
- LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
- switch (op) {
- case 0x83: /* FLOGR R1,R2 [RRE] */
- tmp = load_reg(r2);
- tmp32_1 = tcg_const_i32(r1);
- gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i32(tmp32_1);
- break;
- default:
- LOG_DISAS("illegal b9 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- break;
- }
-}
-
static void disas_s390_insn(DisasContext *s)
{
unsigned char opc;
@@ -1455,13 +1449,6 @@ static void disas_s390_insn(DisasContext *s)
r2 = insn & 0xf;
disas_b3(s, op, r3, r1, r2);
break;
- case 0xb9:
- insn = ld_code4(s->pc);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- op = (insn >> 16) & 0xff;
- disas_b9(s, op, r1, r2);
- break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
gen_illegal_opcode(s);
@@ -2281,6 +2268,26 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
+{
+ /* We'll use the original input for cc computation, since we get to
+ compare that against 0, which ought to be better than comparing
+ the real output against 64. It also lets cc_dst be a convenient
+ temporary during our computation. */
+ gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
+
+ /* R1 = IN ? CLZ(IN) : 64. */
+ gen_helper_clz(o->out, o->in2);
+
+ /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
+ value by 64, which is undefined. But since the shift is 64 iff the
+ input is zero, we still get the correct result after and'ing. */
+ tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
+ tcg_gen_shr_i64(o->out2, o->out2, o->out);
+ tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_icm(DisasContext *s, DisasOps *o)
{
int m3 = get_field(s->fields, m3);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 081/126] target-s390: Convert LFPC, SFPC
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (79 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 080/126] target-s390: Convert FLOGR Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 082/126] target-s390: Convert IPM Richard Henderson
` (20 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Note that we were failing to set the rounding mode in fpu_status.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 17 +++++++++++++
target-s390x/helper.h | 1 +
target-s390x/insn-data.def | 6 +++++
target-s390x/translate.c | 63 ++++++----------------------------------------
4 files changed, 31 insertions(+), 56 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index b6cc45b..4f5a29f 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -578,3 +578,20 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
handle_exceptions(env, GETPC());
return RET128(ret);
}
+
+/* set fpc */
+void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
+{
+ static const int rnd[4] = {
+ float_round_nearest_even,
+ float_round_to_zero,
+ float_round_up,
+ float_round_down
+ };
+
+ /* Install everything in the main FPC. */
+ env->fpc = fpc;
+
+ /* Install the rounding mode in the shadow fpu_status. */
+ set_float_rounding_mode(rnd[fpc & 3], &env->fpu_status);
+}
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 0ba0342..29f1565 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -120,6 +120,7 @@ DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env)
DEF_HELPER_2(lra, i64, env, i64)
DEF_HELPER_3(stura, void, env, i64, i32)
DEF_HELPER_3(cksm, void, env, i32, i32)
+DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
i32, env, i32, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f08a37e..652c7ad 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -351,6 +351,9 @@
C(0xb375, LZDR, RRE, Z, 0, 0, 0, f1, zero, 0)
C(0xb376, LZXR, RRE, Z, 0, 0, 0, x1, zero2, 0)
+/* LOAD FPC */
+ C(0xb29d, LFPC, S, Z, 0, m2_32u, 0, 0, sfpc, 0)
+
/* LOAD LENGTHENED */
C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0)
C(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0)
@@ -455,6 +458,9 @@
C(0xeb1d, RLL, RSY_a, Z, r3_o, sh32, new, r1_32, rll32, 0)
C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh64, r1, 0, rll64, 0)
+/* SET FPC */
+ C(0xb384, SFPC, RRE, Z, 0, r1_o, 0, 0, sfpc, 0)
+
/* SHIFT LEFT SINGLE */
D(0x8b00, SLA, RS_a, Z, r1, sh32, new, r1_32, sla, 0, 31)
D(0xebdd, SLAK, RSY_a, DO, r3, sh32, new, r1_32, sla, 0, 31)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f07bed1..4fbade5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1334,18 +1334,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x9d: /* LFPC D2(B2) [S] */
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
- tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
- tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0xb1: /* STFL D2(B2) [S] */
/* Store Facility List (CPU features) at 200 */
check_privileged(s);
@@ -1391,46 +1379,11 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
}
}
-static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
-{
- TCGv_i32 tmp32_1;
- LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
-#define FP_HELPER(i) \
- tmp32_1 = tcg_const_i32(r1); \
- tmp32_2 = tcg_const_i32(r2); \
- gen_helper_ ## i(cpu_env, tmp32_1, tmp32_2); \
- tcg_temp_free_i32(tmp32_1); \
- tcg_temp_free_i32(tmp32_2);
-
-#define FP_HELPER_CC(i) \
- tmp32_1 = tcg_const_i32(r1); \
- tmp32_2 = tcg_const_i32(r2); \
- gen_helper_ ## i(cc_op, cpu_env, tmp32_1, tmp32_2); \
- set_cc_static(s); \
- tcg_temp_free_i32(tmp32_1); \
- tcg_temp_free_i32(tmp32_2);
-
- switch (op) {
- case 0x84: /* SFPC R1 [RRE] */
- tmp32_1 = load_reg32(r1);
- tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
- tcg_temp_free_i32(tmp32_1);
- break;
- default:
- LOG_DISAS("illegal b3 operation 0x%x\n", op);
- gen_illegal_opcode(s);
- break;
- }
-
-#undef FP_HELPER_CC
-#undef FP_HELPER
-}
-
static void disas_s390_insn(DisasContext *s)
{
unsigned char opc;
uint64_t insn;
- int op, r1, r2, r3;
+ int op;
opc = cpu_ldub_code(cpu_single_env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -1441,14 +1394,6 @@ static void disas_s390_insn(DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b2(s, op, insn);
break;
- case 0xb3:
- insn = ld_code4(s->pc);
- op = (insn >> 16) & 0xff;
- r3 = (insn >> 12) & 0xf; /* aka m3 */
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- disas_b3(s, op, r3, r1, r2);
- break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
gen_illegal_opcode(s);
@@ -2919,6 +2864,12 @@ static ExitStatus op_srl(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
+{
+ gen_helper_sfpc(cpu_env, o->in2);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 082/126] target-s390: Convert IPM
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (80 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 081/126] target-s390: Convert LFPC, SFPC Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 083/126] target-s390: Convert CKSM Richard Henderson
` (19 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Note that the previous placement of the PM field was incorrect.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cc_helper.c | 12 ------------
target-s390x/helper.h | 1 -
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 25 +++++++++++++++++++------
4 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 46c6d84..78c0cb2 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -544,18 +544,6 @@ uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
return do_calc_cc(env, cc_op, src, dst, vr);
}
-/* insert psw mask and condition code into r1 */
-void HELPER(ipm)(CPUS390XState *env, uint32_t cc, uint32_t r1)
-{
- uint64_t r = env->regs[r1];
-
- r &= 0xffffffff00ffffffULL;
- r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf);
- env->regs[r1] = r;
- HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__,
- cc, env->psw.mask, r);
-}
-
#ifndef CONFIG_USER_ONLY
void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
{
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 29f1565..bb1f740 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -36,7 +36,6 @@ DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32)
DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
-DEF_HELPER_3(ipm, void, env, i32, i32)
DEF_HELPER_4(stam, void, env, i32, i64, i32)
DEF_HELPER_4(lam, void, env, i32, i64, i32)
DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 652c7ad..2eb248f 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -237,6 +237,8 @@
D(0xa501, IIHL, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1020)
D(0xa502, IILH, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1010)
D(0xa503, IILL, RI_a, Z, r1_o, i2_16u, r1, 0, insi, 0, 0x1000)
+/* INSERT PROGRAM MASK */
+ C(0xb222, IPM, RRE, Z, 0, 0, r1, 0, ipm, 0)
/* LOAD */
C(0x1800, LR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4fbade5..34615cb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1031,12 +1031,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x22: /* IPM R1 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- gen_op_calc_cc(s);
- gen_helper_ipm(cpu_env, cc_op, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x41: /* CKSM R1,R2 [RRE] */
tmp32_1 = tcg_const_i32(r1);
tmp32_2 = tcg_const_i32(r2);
@@ -2301,6 +2295,25 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 t1;
+
+ gen_op_calc_cc(s);
+ tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
+
+ t1 = tcg_temp_new_i64();
+ tcg_gen_shli_i64(t1, psw_mask, 20);
+ tcg_gen_shri_i64(t1, t1, 36);
+ tcg_gen_or_i64(o->out, o->out, t1);
+
+ tcg_gen_extu_i32_i64(t1, cc_op);
+ tcg_gen_shli_i64(t1, t1, 28);
+ tcg_gen_or_i64(o->out, o->out, t1);
+ tcg_temp_free_i64(t1);
+ return NO_EXIT;
+}
+
static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
{
gen_helper_ldeb(o->out, cpu_env, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 083/126] target-s390: Convert CKSM
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (81 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 082/126] target-s390: Convert IPM Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 084/126] target-s390: Convert EAR, SAR Richard Henderson
` (18 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 3 +++
target-s390x/mem_helper.c | 40 ++++++++++++++++++++++------------------
target-s390x/translate.c | 31 ++++++++++++++++++++++---------
4 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index bb1f740..2bd4105 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -118,7 +118,7 @@ DEF_HELPER_FLAGS_3(ipte, TCG_CALL_CONST, void, env, i64, i64)
DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env)
DEF_HELPER_2(lra, i64, env, i64)
DEF_HELPER_3(stura, void, env, i64, i32)
-DEF_HELPER_3(cksm, void, env, i32, i32)
+DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2eb248f..eec99fe 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -91,6 +91,9 @@
C(0xa706, BRCT, RI_b, Z, 0, 0, 0, 0, bct32, 0)
C(0xa707, BRCTG, RI_b, Z, 0, 0, 0, 0, bct64, 0)
+/* CHECKSUM */
+ C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
+
/* COMPARE */
C(0x1900, CR, RR_a, Z, r1_o, r2_o, 0, 0, 0, cmps32)
C(0x5900, C, RX_a, Z, r1_o, m2_32s, 0, 0, 0, cmps32)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index dfdb2c7..5f70aad 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -753,23 +753,22 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
}
/* checksum */
-void HELPER(cksm)(CPUS390XState *env, uint32_t r1, uint32_t r2)
+uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1,
+ uint64_t src, uint64_t src_len)
{
- uint64_t src = get_address_31fix(env, r2);
- uint64_t src_len = env->regs[(r2 + 1) & 15];
- uint64_t cksm = (uint32_t)env->regs[r1];
+ uint64_t max_len, len;
+ uint64_t cksm = (uint32_t)r1;
- while (src_len >= 4) {
- cksm += cpu_ldl_data(env, src);
+ /* Lest we fail to service interrupts in a timely manner, limit the
+ amount of work we're willing to do. For now, lets cap at 8k. */
+ max_len = (src_len > 0x2000 ? 0x2000 : src_len);
- /* move to next word */
- src_len -= 4;
- src += 4;
+ /* Process full words as available. */
+ for (len = 0; len + 4 <= max_len; len += 4, src += 4) {
+ cksm += (uint32_t)cpu_ldl_data(env, src);
}
- switch (src_len) {
- case 0:
- break;
+ switch (max_len - len) {
case 1:
cksm += cpu_ldub_data(env, src) << 24;
break;
@@ -782,13 +781,18 @@ void HELPER(cksm)(CPUS390XState *env, uint32_t r1, uint32_t r2)
break;
}
- /* indicate we've processed everything */
- env->regs[r2] = src + src_len;
- env->regs[(r2 + 1) & 15] = 0;
+ /* Fold the carry from the checksum. Note that we can see carry-out
+ during folding more than once (but probably not more than twice). */
+ while (cksm > 0xffffffffull) {
+ cksm = (uint32_t)cksm + (cksm >> 32);
+ }
+
+ /* Indicate whether or not we've processed everything. */
+ env->cc_op = (len == src_len ? 0 : 3);
- /* store result */
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- ((uint32_t)cksm + (cksm >> 32));
+ /* Return both cksm and processed length. */
+ env->retxl = cksm;
+ return len;
}
void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 34615cb..16eabba 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1031,15 +1031,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x41: /* CKSM R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- potential_page_fault(s);
- gen_helper_cksm(cpu_env, tmp32_1, tmp32_2);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- gen_op_movi_cc(s, 0);
- break;
case 0x4e: /* SAR R1,R2 [RRE] */
tmp32_1 = load_reg32(r2);
tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
@@ -2000,6 +1991,23 @@ static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
+{
+ int r2 = get_field(s->fields, r2);
+ TCGv_i64 len = tcg_temp_new_i64();
+
+ potential_page_fault(s);
+ gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
+ set_cc_static(s);
+ return_low128(o->out);
+
+ tcg_gen_add_i64(regs[r2], regs[r2], len);
+ tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
+ tcg_temp_free_i64(len);
+
+ return NO_EXIT;
+}
+
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
{
int l = get_field(s->fields, l1);
@@ -3771,6 +3779,11 @@ static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_in1 = o->g_in2 = true;
}
+static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in2 = get_address(s, 0, get_field(f, r2), 0);
+}
+
static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
{
int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 084/126] target-s390: Convert EAR, SAR
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (82 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 083/126] target-s390: Convert CKSM Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 085/126] target-s390: Convert MVPG Richard Henderson
` (17 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 25 ++++++++++++++-----------
2 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index eec99fe..f282e99 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -220,6 +220,8 @@
/* EXECUTE RELATIVE LONG */
C(0xc600, EXRL, RIL_b, EE, r1_o, ri2, 0, 0, ex, 0)
+/* EXTRACT ACCESS */
+ C(0xb24f, EAR, RRE, Z, 0, 0, new, r1_32, ear, 0)
/* EXTRACT FPC */
C(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0)
@@ -463,6 +465,8 @@
C(0xeb1d, RLL, RSY_a, Z, r3_o, sh32, new, r1_32, rll32, 0)
C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh64, r1, 0, rll64, 0)
+/* SET ACCESS */
+ C(0xb24e, SAR, RRE, Z, 0, r2_o, 0, 0, sar, 0)
/* SET FPC */
C(0xb384, SFPC, RRE, Z, 0, r1_o, 0, 0, sfpc, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 16eabba..08a3e77 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1031,17 +1031,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x4e: /* SAR R1,R2 [RRE] */
- tmp32_1 = load_reg32(r2);
- tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
- tcg_temp_free_i32(tmp32_1);
- break;
- case 0x4f: /* EAR R1,R2 [RRE] */
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r2]));
- store_reg32(r1, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x54: /* MVPG R1,R2 [RRE] */
tmp = load_reg(0);
tmp2 = load_reg(r1);
@@ -2183,6 +2172,13 @@ static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ear(DisasContext *s, DisasOps *o)
+{
+ int r2 = get_field(s->fields, r2);
+ tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2]));
+ return NO_EXIT;
+}
+
static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
{
tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
@@ -2803,6 +2799,13 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_sar(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
+ return NO_EXIT;
+}
+
static ExitStatus op_seb(DisasContext *s, DisasOps *o)
{
gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 085/126] target-s390: Convert MVPG
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (83 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 084/126] target-s390: Convert EAR, SAR Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST Richard Henderson
` (16 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/mem_helper.c | 7 ++-----
target-s390x/translate.c | 20 ++++++++------------
3 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f282e99..4b30dd5 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -394,6 +394,8 @@
C(0x0e00, MVCL, RR_a, Z, 0, 0, 0, 0, mvcl, 0)
/* MOVE LONG EXTENDED */
C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0)
+/* MOVE PAGE */
+ C(0xb254, MVPG, RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0)
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 5f70aad..e9cacf9 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -404,12 +404,9 @@ uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
{
/* XXX missing r0 handling */
+ env->cc_op = 0;
#ifdef CONFIG_USER_ONLY
- int i;
-
- for (i = 0; i < TARGET_PAGE_SIZE; i++) {
- cpu_stb_data(env, r1 + i, cpu_ldub_data(env, r2 + i));
- }
+ memmove(g2h(r1), g2h(r2), TARGET_PAGE_SIZE);
#else
mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
#endif
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 08a3e77..a49475b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1031,18 +1031,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x54: /* MVPG R1,R2 [RRE] */
- tmp = load_reg(0);
- tmp2 = load_reg(r1);
- tmp3 = load_reg(r2);
- potential_page_fault(s);
- gen_helper_mvpg(cpu_env, tmp, tmp2, tmp3);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- /* XXX check CCO bit and set CC accordingly */
- gen_op_movi_cc(s, 0);
- break;
case 0x55: /* MVST R1,R2 [RRE] */
tmp32_1 = load_reg32(0);
tmp32_2 = tcg_const_i32(r1);
@@ -2593,6 +2581,14 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
}
#endif
+static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
+{
+ potential_page_fault(s);
+ gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
{
tcg_gen_mul_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (84 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 085/126] target-s390: Convert MVPG Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-11 19:11 ` Blue Swirl
2012-09-09 21:05 ` [Qemu-devel] [PATCH 087/126] target-s390: Convert SRST Richard Henderson
` (15 subsequent siblings)
101 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 4 +-
target-s390x/insn-data.def | 4 ++
target-s390x/mem_helper.c | 119 ++++++++++++++++++++++-----------------------
target-s390x/translate.c | 42 ++++++++--------
4 files changed, 83 insertions(+), 86 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 2bd4105..473e776 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -25,9 +25,9 @@ DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i
DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
DEF_HELPER_4(srst, i32, env, i32, i32, i32)
-DEF_HELPER_4(clst, i32, env, i32, i32, i32)
+DEF_HELPER_4(clst, i64, env, i64, i64, i64)
DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
-DEF_HELPER_4(mvst, void, env, i32, i32, i32)
+DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
DEF_HELPER_4(csg, i64, env, i64, i64, i64)
DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
DEF_HELPER_4(cs, i64, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4b30dd5..501d02e 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -153,6 +153,8 @@
C(0xbd00, CLM, RS_b, Z, r1_o, a2, 0, 0, clm, 0)
C(0xeb21, CLMY, RSY_b, LD, r1_o, a2, 0, 0, clm, 0)
C(0xeb20, CLMH, RSY_b, Z, r1_sr32, a2, 0, 0, clm, 0)
+/* COMPARE LOGICAL STRING */
+ C(0xb25d, CLST, RRE, Z, r1_o, r2_o, 0, 0, clst, 0)
/* COMPARE AND SWAP */
C(0xba00, CS, RS_a, Z, r1_o, a2, new, r1_32, cs, 0)
@@ -396,6 +398,8 @@
C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0)
/* MOVE PAGE */
C(0xb254, MVPG, RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0)
+/* MOVE STRING */
+ C(0xb255, MVST, RRE, Z, r1_o, r2_o, 0, 0, mvst, 0)
/* MULTIPLY */
C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index e9cacf9..8cc4625 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -310,36 +310,30 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
return cc;
}
+static inline uint64_t fix_address(CPUS390XState *env, uint64_t a)
+{
+ /* 31-Bit mode */
+ if (!(env->psw.mask & PSW_MASK_64)) {
+ a &= 0x7fffffff;
+ }
+ return a;
+}
+
static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2)
{
uint64_t r = d2;
-
if (x2) {
r += env->regs[x2];
}
-
if (b2) {
r += env->regs[b2];
}
-
- /* 31-Bit mode */
- if (!(env->psw.mask & PSW_MASK_64)) {
- r &= 0x7fffffff;
- }
-
- return r;
+ return fix_address(env, r);
}
static inline uint64_t get_address_31fix(CPUS390XState *env, int reg)
{
- uint64_t r = env->regs[reg];
-
- /* 31-Bit mode */
- if (!(env->psw.mask & PSW_MASK_64)) {
- r &= 0x7fffffff;
- }
-
- return r;
+ return fix_address(env, env->regs[reg]);
}
/* search string (c is byte to search, r2 is string, r1 end of string) */
@@ -365,39 +359,40 @@ uint32_t HELPER(srst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
}
/* unsigned string compare (c is string terminator) */
-uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2)
{
- uint64_t s1 = get_address_31fix(env, r1);
- uint64_t s2 = get_address_31fix(env, r2);
- uint8_t v1, v2;
- uint32_t cc;
+ uint32_t len;
c = c & 0xff;
-#ifdef CONFIG_USER_ONLY
- if (!c) {
- HELPER_LOG("%s: comparing '%s' and '%s'\n",
- __func__, (char *)g2h(s1), (char *)g2h(s2));
- }
-#endif
- for (;;) {
- v1 = cpu_ldub_data(env, s1);
- v2 = cpu_ldub_data(env, s2);
- if ((v1 == c || v2 == c) || (v1 != v2)) {
- break;
+ s1 = fix_address(env, s1);
+ s2 = fix_address(env, s2);
+
+ /* Lest we fail to service interrupts in a timely manner, limit the
+ amount of work we're willing to do. For now, lets cap at 8k. */
+ for (len = 0; len < 0x2000; ++len) {
+ uint8_t v1 = cpu_ldub_data(env, s1 + len);
+ uint8_t v2 = cpu_ldub_data(env, s2 + len);
+ if (v1 == v2) {
+ if (v1 == c) {
+ /* Equal. CC=0, and don't advance the registers. */
+ env->cc_op = 0;
+ env->retxl = s2;
+ return s1;
+ }
+ } else {
+ /* Unequal. CC={1,2}, and advance the registers. Note that
+ the terminator need not be zero, but the string that contains
+ the terminator is by definition "low". */
+ env->cc_op = (v1 == c ? 1 : v2 == c ? 2 : v1 < v2 ? 1 : 2);
+ env->retxl = s2 + len;
+ return s1 + len;
}
- s1++;
- s2++;
}
- if (v1 == v2) {
- cc = 0;
- } else {
- cc = (v1 < v2) ? 1 : 2;
- /* FIXME: 31-bit mode! */
- env->regs[r1] = s1;
- env->regs[r2] = s2;
- }
- return cc;
+ /* CPU-determined bytes equal; advance the registers. */
+ env->cc_op = 3;
+ env->retxl = s2 + len;
+ return s1 + len;
}
/* move page */
@@ -413,29 +408,31 @@ void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
}
/* string copy (c is string terminator) */
-void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
{
- uint64_t dest = get_address_31fix(env, r1);
- uint64_t src = get_address_31fix(env, r2);
- uint8_t v;
+ uint32_t len;
c = c & 0xff;
-#ifdef CONFIG_USER_ONLY
- if (!c) {
- HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src),
- dest);
- }
-#endif
- for (;;) {
- v = cpu_ldub_data(env, src);
- cpu_stb_data(env, dest, v);
+ d = fix_address(env, d);
+ s = fix_address(env, s);
+
+ /* Lest we fail to service interrupts in a timely manner, limit the
+ amount of work we're willing to do. For now, lets cap at 8k. */
+ for (len = 0; len < 0x2000; ++len) {
+ uint8_t v = cpu_ldub_data(env, s + len);
+ cpu_stb_data(env, d + len, v);
if (v == c) {
- break;
+ /* Complete. Set CC=1 and advance R1. */
+ env->cc_op = 1;
+ env->retxl = s;
+ return d + len;
}
- src++;
- dest++;
}
- env->regs[r1] = dest; /* FIXME: 31-bit mode! */
+
+ /* Incomplete. Set CC=3 and signal to advance R1 and R2. */
+ env->cc_op = 3;
+ env->retxl = s + len;
+ return d + len;
}
/* compare and swap 64-bit */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a49475b..49f419a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -425,7 +425,7 @@ static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
return tmp;
}
-static void gen_op_movi_cc(DisasContext *s, uint32_t val)
+static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
{
s->cc_op = CC_OP_CONST0 + val;
}
@@ -1031,28 +1031,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x55: /* MVST R1,R2 [RRE] */
- tmp32_1 = load_reg32(0);
- tmp32_2 = tcg_const_i32(r1);
- tmp32_3 = tcg_const_i32(r2);
- potential_page_fault(s);
- gen_helper_mvst(cpu_env, tmp32_1, tmp32_2, tmp32_3);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- gen_op_movi_cc(s, 1);
- break;
- case 0x5d: /* CLST R1,R2 [RRE] */
- tmp32_1 = load_reg32(0);
- tmp32_2 = tcg_const_i32(r1);
- tmp32_3 = tcg_const_i32(r2);
- potential_page_fault(s);
- gen_helper_clst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0x5e: /* SRST R1,R2 [RRE] */
tmp32_1 = load_reg32(0);
tmp32_2 = tcg_const_i32(r1);
@@ -2044,6 +2022,15 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_clst(DisasContext *s, DisasOps *o)
+{
+ potential_page_fault(s);
+ gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+ set_cc_static(s);
+ return_low128(o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_cs(DisasContext *s, DisasOps *o)
{
int r3 = get_field(s->fields, r3);
@@ -2589,6 +2576,15 @@ static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
+{
+ potential_page_fault(s);
+ gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+ set_cc_static(s);
+ return_low128(o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_mul(DisasContext *s, DisasOps *o)
{
tcg_gen_mul_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 087/126] target-s390: Convert SRST
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (85 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 088/126] target-s390: Convert STIDP Richard Henderson
` (14 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 3 +++
target-s390x/mem_helper.c | 38 +++++++++++++++++++++++++-------------
target-s390x/translate.c | 31 ++++++++++++++-----------------
4 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 473e776..281ec42 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -24,7 +24,7 @@ DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s6
DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_4(srst, i32, env, i32, i32, i32)
+DEF_HELPER_4(srst, i64, env, i64, i64, i64)
DEF_HELPER_4(clst, i64, env, i64, i64, i64)
DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 501d02e..06cb96e 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -471,6 +471,9 @@
C(0xeb1d, RLL, RSY_a, Z, r3_o, sh32, new, r1_32, rll32, 0)
C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh64, r1, 0, rll64, 0)
+/* SEARCH STRING */
+ C(0xb25e, SRST, RRE, Z, r1_o, r2_o, 0, 0, srst, 0)
+
/* SET ACCESS */
C(0xb24e, SAR, RRE, Z, 0, r2_o, 0, 0, sar, 0)
/* SET FPC */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 8cc4625..a700bb0 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -337,25 +337,37 @@ static inline uint64_t get_address_31fix(CPUS390XState *env, int reg)
}
/* search string (c is byte to search, r2 is string, r1 end of string) */
-uint32_t HELPER(srst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+uint64_t HELPER(srst)(CPUS390XState *env, uint64_t c, uint64_t end,
+ uint64_t str)
{
- uint64_t i;
- uint32_t cc = 2;
- uint64_t str = get_address_31fix(env, r2);
- uint64_t end = get_address_31fix(env, r1);
+ uint32_t len;
- HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__,
- c, env->regs[r1], env->regs[r2]);
+ c = c & 0xff;
+ str = fix_address(env, str);
+ end = fix_address(env, end);
- for (i = str; i != end; i++) {
- if (cpu_ldub_data(env, i) == c) {
- env->regs[r1] = i;
- cc = 1;
- break;
+ /* Assume for now that R2 is unmodified. */
+ env->retxl = str;
+
+ /* Lest we fail to service interrupts in a timely manner, limit the
+ amount of work we're willing to do. For now, lets cap at 8k. */
+ for (len = 0; len < 0x2000; ++len) {
+ uint8_t v = cpu_ldub_data(env, str + len);
+ if (v == c) {
+ /* Character found. Set R1 to the found location. */
+ env->cc_op = 1;
+ return str + len;
+ } else if (str + len == end) {
+ /* Character not found. R1 is unmodified. */
+ env->cc_op = 2;
+ return end;
}
}
- return cc;
+ /* CPU-determined bytes processed. Advance R2 to next byte to process. */
+ env->retxl = str + len;
+ env->cc_op = 3;
+ return end;
}
/* unsigned string compare (c is string terminator) */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 49f419a..018ddfc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1018,12 +1018,11 @@ static void free_compare(DisasCompare *c)
static void disas_b2(DisasContext *s, int op, uint32_t insn)
{
+#ifndef CONFIG_USER_ONLY
TCGv_i64 tmp, tmp2, tmp3;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+ TCGv_i32 tmp32_1, tmp32_2;
int r1, r2;
-#ifndef CONFIG_USER_ONLY
int r3, d2, b2;
-#endif
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
@@ -1031,19 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x5e: /* SRST R1,R2 [RRE] */
- tmp32_1 = load_reg32(0);
- tmp32_2 = tcg_const_i32(r1);
- tmp32_3 = tcg_const_i32(r2);
- potential_page_fault(s);
- gen_helper_srst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
-
-#ifndef CONFIG_USER_ONLY
case 0x02: /* STIDP D2(B2) [S] */
/* Store CPU ID */
check_privileged(s);
@@ -1311,12 +1297,14 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
break;
-#endif
default:
+#endif
LOG_DISAS("illegal b2 operation 0x%x\n", op);
gen_illegal_opcode(s);
+#ifndef CONFIG_USER_ONLY
break;
}
+#endif
}
static void disas_s390_insn(DisasContext *s)
@@ -3060,6 +3048,15 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_srst(DisasContext *s, DisasOps *o)
+{
+ potential_page_fault(s);
+ gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+ set_cc_static(s);
+ return_low128(o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_sub(DisasContext *s, DisasOps *o)
{
tcg_gen_sub_i64(o->out, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 088/126] target-s390: Convert STIDP
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (86 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 087/126] target-s390: Convert SRST Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 089/126] target-s390: Convert SCK Richard Henderson
` (13 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 1 -
target-s390x/insn-data.def | 2 ++
target-s390x/misc_helper.c | 6 ------
target-s390x/translate.c | 16 +++++++---------
4 files changed, 9 insertions(+), 16 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 281ec42..36d3539 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -91,7 +91,6 @@ DEF_HELPER_3(servc, i32, env, i32, i64)
DEF_HELPER_4(diag, i64, env, i32, i64, i64)
DEF_HELPER_3(load_psw, void, env, i64, i64)
DEF_HELPER_1(program_interrupt, void, i32)
-DEF_HELPER_FLAGS_2(stidp, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64)
DEF_HELPER_2(stck, i32, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 06cb96e..dfac564 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -640,6 +640,8 @@
/* STORE CONTROL */
C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0)
C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0)
+/* STORE CPU ID */
+ C(0xb202, STIDP, S, Z, la2, 0, new, m1_64, stidp, 0)
/* STORE THEN AND SYSTEM MASK */
C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 32b75f2..6e9978c 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -730,12 +730,6 @@ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
return r;
}
-/* Store CPU ID */
-void HELPER(stidp)(CPUS390XState *env, uint64_t a1)
-{
- cpu_stq_data(env, a1, env->cpu_num);
-}
-
/* Set Prefix */
void HELPER(spx)(CPUS390XState *env, uint64_t a1)
{
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 018ddfc..796da9d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,15 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x02: /* STIDP D2(B2) [S] */
- /* Store CPU ID */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_stidp(cpu_env, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0x04: /* SCK D2(B2) [S] */
/* Set Clock */
check_privileged(s);
@@ -2906,6 +2897,13 @@ static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
+ return NO_EXIT;
+}
+
static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 089/126] target-s390: Convert SCK
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (87 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 088/126] target-s390: Convert STIDP Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 090/126] target-s390: Convert STCK Richard Henderson
` (12 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 1 -
target-s390x/insn-data.def | 3 +++
target-s390x/misc_helper.c | 8 --------
target-s390x/translate.c | 10 ----------
4 files changed, 3 insertions(+), 19 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 36d3539..33af097 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -92,7 +92,6 @@ DEF_HELPER_4(diag, i64, env, i32, i64, i64)
DEF_HELPER_3(load_psw, void, env, i64, i64)
DEF_HELPER_1(program_interrupt, void, i32)
DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64)
-DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64)
DEF_HELPER_2(stck, i32, env, i64)
DEF_HELPER_2(stcke, i32, env, i64)
DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index dfac564..f5129bd 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -633,6 +633,9 @@
/* We only do 64-bit, so accept this as a no-op.
Let SAM24 and SAM31 signal illegal instruction. */
C(0x010e, SAM64, E, Z, 0, 0, 0, 0, 0, 0)
+/* SET CLOCK */
+ /* ??? Not implemented - is it necessary? */
+ C(0xb204, SCK, S, Z, 0, 0, 0, 0, 0, 0)
/* SET SYSTEM MASK */
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
/* SIGNAL PROCESSOR */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 6e9978c..1a22f12 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -742,14 +742,6 @@ void HELPER(spx)(CPUS390XState *env, uint64_t a1)
tlb_flush_page(env, TARGET_PAGE_SIZE);
}
-/* Set Clock */
-uint32_t HELPER(sck)(uint64_t a1)
-{
- /* XXX not implemented - is it necessary? */
-
- return 0;
-}
-
static inline uint64_t clock_value(CPUS390XState *env)
{
uint64_t time;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 796da9d..7221b22 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,16 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x04: /* SCK D2(B2) [S] */
- /* Set Clock */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_sck(cc_op, tmp);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- break;
case 0x05: /* STCK D2(B2) [S] */
/* Store Clock */
decode_rs(s, insn, &r1, &r3, &b2, &d2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 090/126] target-s390: Convert STCK
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (88 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 089/126] target-s390: Convert SCK Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 091/126] target-s390: Convert SCKC, STCKC Richard Henderson
` (11 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 3 +++
target-s390x/misc_helper.c | 6 ++----
target-s390x/translate.c | 17 ++++++++---------
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 33af097..00608c8 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -92,7 +92,7 @@ DEF_HELPER_4(diag, i64, env, i32, i64, i64)
DEF_HELPER_3(load_psw, void, env, i64, i64)
DEF_HELPER_1(program_interrupt, void, i32)
DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64)
-DEF_HELPER_2(stck, i32, env, i64)
+DEF_HELPER_FLAGS_1(stck, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
DEF_HELPER_2(stcke, i32, env, i64)
DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f5129bd..abff0cf 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -640,6 +640,9 @@
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
/* SIGNAL PROCESSOR */
C(0xae00, SIGP, RS_a, Z, r3_o, a2, 0, 0, sigp, 0)
+/* STORE CLOCK */
+ C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0)
+ C(0xb27c, STCKF, S, Z, la2, 0, new, m1_64, stck, 0)
/* STORE CONTROL */
C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0)
C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0)
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 1a22f12..8bff132 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -753,11 +753,9 @@ static inline uint64_t clock_value(CPUS390XState *env)
}
/* Store Clock */
-uint32_t HELPER(stck)(CPUS390XState *env, uint64_t a1)
+uint64_t HELPER(stck)(CPUS390XState *env)
{
- cpu_stq_data(env, a1, clock_value(env));
-
- return 0;
+ return clock_value(env);
}
/* Store Clock Extended */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 7221b22..dcb0c01 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,15 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x05: /* STCK D2(B2) [S] */
- /* Store Clock */
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_stck(cc_op, cpu_env, tmp);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- break;
case 0x06: /* SCKC D2(B2) [S] */
/* Set Clock Comparator */
check_privileged(s);
@@ -2894,6 +2885,14 @@ static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stck(DisasContext *s, DisasOps *o)
+{
+ gen_helper_stck(o->out, cpu_env);
+ /* ??? We don't implement clock states. */
+ gen_op_movi_cc(s, 0);
+ return NO_EXIT;
+}
+
static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 091/126] target-s390: Convert SCKC, STCKC
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (89 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 090/126] target-s390: Convert STCK Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 092/126] target-s390: Convert SPT, STPT Richard Henderson
` (10 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 4 ++++
target-s390x/misc_helper.c | 8 +++-----
target-s390x/translate.c | 32 ++++++++++++++------------------
4 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 00608c8..011e64e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -95,7 +95,7 @@ DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_1(stck, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
DEF_HELPER_2(stcke, i32, env, i64)
DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64)
-DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_1(stckc, TCG_CALL_CONST, i64, env)
DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index abff0cf..a2b4c73 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -636,6 +636,8 @@
/* SET CLOCK */
/* ??? Not implemented - is it necessary? */
C(0xb204, SCK, S, Z, 0, 0, 0, 0, 0, 0)
+/* SET CLOCK COMPARATOR */
+ C(0xb206, SCKC, S, Z, 0, m2_64, 0, 0, sckc, 0)
/* SET SYSTEM MASK */
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
/* SIGNAL PROCESSOR */
@@ -643,6 +645,8 @@
/* STORE CLOCK */
C(0xb205, STCK, S, Z, la2, 0, new, m1_64, stck, 0)
C(0xb27c, STCKF, S, Z, la2, 0, new, m1_64, stck, 0)
+/* STORE CLOCK COMPARATOR */
+ C(0xb207, STCKC, S, Z, la2, 0, new, m1_64, stckc, 0)
/* STORE CONTROL */
C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0)
C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0)
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 8bff132..bdf3f09 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -773,10 +773,8 @@ uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1)
}
/* Set Clock Comparator */
-void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
+void HELPER(sckc)(CPUS390XState *env, uint64_t time)
{
- uint64_t time = cpu_ldq_data(env, a1);
-
if (time == -1ULL) {
return;
}
@@ -790,10 +788,10 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
}
/* Store Clock Comparator */
-void HELPER(stckc)(CPUS390XState *env, uint64_t a1)
+uint64_t HELPER(stckc)(CPUS390XState *env)
{
/* XXX implement */
- cpu_stq_data(env, a1, 0);
+ return 0;
}
/* Set CPU Timer */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index dcb0c01..bcf0809 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,24 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x06: /* SCKC D2(B2) [S] */
- /* Set Clock Comparator */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_sckc(cpu_env, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0x07: /* STCKC D2(B2) [S] */
- /* Store Clock Comparator */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_stckc(cpu_env, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0x08: /* SPT D2(B2) [S] */
/* Set CPU Timer */
check_privileged(s);
@@ -2893,6 +2875,20 @@ static ExitStatus op_stck(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_sckc(cpu_env, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_stckc(o->out, cpu_env);
+ return NO_EXIT;
+}
+
static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 092/126] target-s390: Convert SPT, STPT
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (90 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 091/126] target-s390: Convert SCKC, STCKC Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 093/126] target-s390: Convert SPKA Richard Henderson
` (9 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 4 ++++
target-s390x/misc_helper.c | 8 +++-----
target-s390x/translate.c | 32 ++++++++++++++------------------
4 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 011e64e..13ceeec 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -97,7 +97,7 @@ DEF_HELPER_2(stcke, i32, env, i64)
DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_1(stckc, TCG_CALL_CONST, i64, env)
DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64)
-DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_1(stpt, TCG_CALL_CONST, i64, env)
DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
DEF_HELPER_4(lctl, void, env, i32, i64, i32)
DEF_HELPER_4(lctlg, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a2b4c73..29b3eb2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -638,6 +638,8 @@
C(0xb204, SCK, S, Z, 0, 0, 0, 0, 0, 0)
/* SET CLOCK COMPARATOR */
C(0xb206, SCKC, S, Z, 0, m2_64, 0, 0, sckc, 0)
+/* SET CPU TIMER */
+ C(0xb208, SPT, S, Z, 0, m2_64, 0, 0, spt, 0)
/* SET SYSTEM MASK */
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
/* SIGNAL PROCESSOR */
@@ -652,6 +654,8 @@
C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0)
/* STORE CPU ID */
C(0xb202, STIDP, S, Z, la2, 0, new, m1_64, stidp, 0)
+/* STORE CPU TIMER */
+ C(0xb209, STPT, S, Z, la2, 0, new, m1_64, stpt, 0)
/* STORE THEN AND SYSTEM MASK */
C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index bdf3f09..d205259 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -795,10 +795,8 @@ uint64_t HELPER(stckc)(CPUS390XState *env)
}
/* Set CPU Timer */
-void HELPER(spt)(CPUS390XState *env, uint64_t a1)
+void HELPER(spt)(CPUS390XState *env, uint64_t time)
{
- uint64_t time = cpu_ldq_data(env, a1);
-
if (time == -1ULL) {
return;
}
@@ -810,10 +808,10 @@ void HELPER(spt)(CPUS390XState *env, uint64_t a1)
}
/* Store CPU Timer */
-void HELPER(stpt)(CPUS390XState *env, uint64_t a1)
+uint64_t HELPER(stpt)(CPUS390XState *env)
{
/* XXX implement */
- cpu_stq_data(env, a1, 0);
+ return 0;
}
/* Store System Information */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index bcf0809..2043d6c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,24 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x08: /* SPT D2(B2) [S] */
- /* Set CPU Timer */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_spt(cpu_env, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0x09: /* STPT D2(B2) [S] */
- /* Store CPU Timer */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_stpt(cpu_env, tmp);
- tcg_temp_free_i64(tmp);
- break;
case 0x0a: /* SPKA D2(B2) [S] */
/* Set PSW Key from Address */
check_privileged(s);
@@ -2889,6 +2871,20 @@ static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_spt(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_spt(cpu_env, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_stpt(o->out, cpu_env);
+ return NO_EXIT;
+}
+
static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 093/126] target-s390: Convert SPKA
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (91 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 092/126] target-s390: Convert SPT, STPT Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 094/126] target-s390: Convert PTLB Richard Henderson
` (8 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 20 ++++++++------------
2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 29b3eb2..79ed499 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -640,6 +640,8 @@
C(0xb206, SCKC, S, Z, 0, m2_64, 0, 0, sckc, 0)
/* SET CPU TIMER */
C(0xb208, SPT, S, Z, 0, m2_64, 0, 0, spt, 0)
+/* SET PSW KEY FROM ADDRESS */
+ C(0xb20a, SPKA, S, Z, 0, a2, 0, 0, spka, 0)
/* SET SYSTEM MASK */
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
/* SIGNAL PROCESSOR */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2043d6c..09901bc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,18 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x0a: /* SPKA D2(B2) [S] */
- /* Set PSW Key from Address */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_andi_i64(tmp2, psw_mask, ~PSW_MASK_KEY);
- tcg_gen_shli_i64(tmp, tmp, PSW_SHIFT_KEY - 4);
- tcg_gen_or_i64(psw_mask, tmp2, tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp);
- break;
case 0x0d: /* PTLB [S] */
/* Purge TLB */
check_privileged(s);
@@ -2811,6 +2799,14 @@ static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
}
#ifndef CONFIG_USER_ONLY
+static ExitStatus op_spka(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ tcg_gen_shri_i64(o->in2, o->in2, 4);
+ tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY - 4, 4);
+ return NO_EXIT;
+}
+
static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
{
check_privileged(s);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 094/126] target-s390: Convert PTLB
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (92 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 093/126] target-s390: Convert SPKA Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 095/126] target-s390: Convert SPX, STPX Richard Henderson
` (7 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 14 +++++++++-----
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 79ed499..58f2b41 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -629,6 +629,8 @@
C(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0)
/* MOVE TO SECONDARY */
C(0xdb00, MVCS, SS_d, Z, la1, a2, 0, 0, mvcs, 0)
+/* PURGE TLB */
+ C(0xb20d, PTLB, S, Z, 0, 0, 0, 0, ptlb, 0)
/* SET ADDRESSING MODE */
/* We only do 64-bit, so accept this as a no-op.
Let SAM24 and SAM31 signal illegal instruction. */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 09901bc..f3108f3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,11 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x0d: /* PTLB [S] */
- /* Purge TLB */
- check_privileged(s);
- gen_helper_ptlb(cpu_env);
- break;
case 0x10: /* SPX D2(B2) [S] */
/* Set Prefix Register */
check_privileged(s);
@@ -2664,6 +2659,15 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_ptlb(cpu_env);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
{
tcg_gen_bswap16_i64(o->out, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 095/126] target-s390: Convert SPX, STPX
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (93 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 094/126] target-s390: Convert PTLB Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 096/126] target-s390: Convert STAP Richard Henderson
` (6 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
target-s390x/misc_helper.c | 6 ++----
target-s390x/translate.c | 35 +++++++++++++++--------------------
3 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 58f2b41..63da5ab 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -642,6 +642,8 @@
C(0xb206, SCKC, S, Z, 0, m2_64, 0, 0, sckc, 0)
/* SET CPU TIMER */
C(0xb208, SPT, S, Z, 0, m2_64, 0, 0, spt, 0)
+/* SET PREFIX */
+ C(0xb210, SPX, S, Z, 0, m2_32u, 0, 0, spx, 0)
/* SET PSW KEY FROM ADDRESS */
C(0xb20a, SPKA, S, Z, 0, a2, 0, 0, spka, 0)
/* SET SYSTEM MASK */
@@ -660,6 +662,8 @@
C(0xb202, STIDP, S, Z, la2, 0, new, m1_64, stidp, 0)
/* STORE CPU TIMER */
C(0xb209, STPT, S, Z, la2, 0, new, m1_64, stpt, 0)
+/* STORE PREFIX */
+ C(0xb211, STPX, S, Z, la2, 0, new, m1_32, stpx, 0)
/* STORE THEN AND SYSTEM MASK */
C(0xac00, STNSM, SI, Z, la1, 0, new, m1_8, stnsm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index d205259..e604613 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -733,10 +733,8 @@ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
/* Set Prefix */
void HELPER(spx)(CPUS390XState *env, uint64_t a1)
{
- uint32_t prefix;
-
- prefix = cpu_ldl_data(env, a1);
- env->psa = prefix & 0xfffff000;
+ uint32_t prefix = a1 & 0x7fffe000;
+ env->psa = prefix;
qemu_log("prefix: %#x\n", prefix);
tlb_flush_page(env, 0);
tlb_flush_page(env, TARGET_PAGE_SIZE);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f3108f3..6b60de1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,26 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x10: /* SPX D2(B2) [S] */
- /* Set Prefix Register */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_spx(cpu_env, tmp);
- tcg_temp_free_i64(tmp);
- break;
- case 0x11: /* STPX D2(B2) [S] */
- /* Store Prefix */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tcg_gen_ld_i64(tmp2, cpu_env, offsetof(CPUS390XState, psa));
- tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x12: /* STAP D2(B2) [S] */
/* Store CPU Address */
check_privileged(s);
@@ -2885,6 +2865,21 @@ static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_spx(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_spx(cpu_env, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
+ tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
+ return NO_EXIT;
+}
+
static ExitStatus op_stnsm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 096/126] target-s390: Convert STAP
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (94 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 095/126] target-s390: Convert SPX, STPX Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 097/126] target-s390: Convert IPTE Richard Henderson
` (5 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 24 ++++++++++--------------
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 63da5ab..6638453 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -658,6 +658,8 @@
/* STORE CONTROL */
C(0xb600, STCTL, RS_a, Z, 0, a2, 0, 0, stctl, 0)
C(0xeb25, STCTG, RSY_a, Z, 0, a2, 0, 0, stctg, 0)
+/* STORE CPU ADDRESS */
+ C(0xb212, STAP, S, Z, la2, 0, new, m1_16, stap, 0)
/* STORE CPU ID */
C(0xb202, STIDP, S, Z, la2, 0, new, m1_64, stidp, 0)
/* STORE CPU TIMER */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6b60de1..873e08c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,20 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x12: /* STAP D2(B2) [S] */
- /* Store CPU Address */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp2 = tcg_temp_new_i64();
- tmp32_1 = tcg_temp_new_i32();
- tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, cpu_num));
- tcg_gen_extu_i32_i64(tmp2, tmp32_1);
- tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i32(tmp32_1);
- break;
case 0x21: /* IPTE R1,R2 [RRE] */
/* Invalidate PTE */
check_privileged(s);
@@ -2798,6 +2784,16 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stap(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ /* ??? Surely cpu address != cpu number. In any case the previous
+ version of this stored more than the required half-word, so it
+ is unlikely this has ever been tested. */
+ tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
+ return NO_EXIT;
+}
+
static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
{
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 097/126] target-s390: Convert IPTE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (95 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 096/126] target-s390: Convert STAP Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 098/126] target-s390: Convert ISKE Richard Henderson
` (4 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 20 +++++++++-----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6638453..ba7b876 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -616,6 +616,8 @@
#ifndef CONFIG_USER_ONLY
/* DIAGNOSE (KVM hypercall) */
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
+/* INVALIDATE PAGE TABLE ENTRY */
+ C(0xb221, IPTE, RRF_a, Z, r1_o, r2_o, 0, 0, ipte, 0)
/* LOAD CONTROL */
C(0xb700, LCTL, RS_a, Z, 0, a2, 0, 0, lctl, 0)
C(0xeb2f, LCTLG, RSY_a, Z, 0, a2, 0, 0, lctlg, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 873e08c..a677ded 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,17 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x21: /* IPTE R1,R2 [RRE] */
- /* Invalidate PTE */
- check_privileged(s);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- tmp = load_reg(r1);
- tmp2 = load_reg(r2);
- gen_helper_ipte(cpu_env, tmp, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x29: /* ISKE R1,R2 [RRE] */
/* Insert Storage Key Extended */
check_privileged(s);
@@ -2166,6 +2155,15 @@ static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_ipte(cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
{
gen_helper_ldeb(o->out, cpu_env, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 098/126] target-s390: Convert ISKE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (96 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 097/126] target-s390: Convert IPTE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 099/126] target-s390: Convert SSKE Richard Henderson
` (3 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 ++
target-s390x/translate.c | 19 +++++++------------
2 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ba7b876..3af659a 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -616,6 +616,8 @@
#ifndef CONFIG_USER_ONLY
/* DIAGNOSE (KVM hypercall) */
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
+/* INSERT STORAGE KEY EXTENDED */
+ C(0xb229, ISKE, RRE, Z, 0, r2_o, new, r1_8, iske, 0)
/* INVALIDATE PAGE TABLE ENTRY */
C(0xb221, IPTE, RRF_a, Z, r1_o, r2_o, 0, 0, ipte, 0)
/* LOAD CONTROL */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a677ded..b39ecc8 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,18 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x29: /* ISKE R1,R2 [RRE] */
- /* Insert Storage Key Extended */
- check_privileged(s);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- tmp = load_reg(r2);
- tmp2 = tcg_temp_new_i64();
- gen_helper_iske(tmp2, cpu_env, tmp);
- store_reg(r1, tmp2);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- break;
case 0x2a: /* RRBE R1,R2 [RRE] */
/* Set Storage Key Extended */
check_privileged(s);
@@ -2162,6 +2150,13 @@ static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
gen_helper_ipte(cpu_env, o->in1, o->in2);
return NO_EXIT;
}
+
+static ExitStatus op_iske(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_iske(o->out, cpu_env, o->in2);
+ return NO_EXIT;
+}
#endif
static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 099/126] target-s390: Convert SSKE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (97 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 098/126] target-s390: Convert ISKE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 100/126] target-s390: Convert RRBE Richard Henderson
` (2 subsequent siblings)
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 2 ++
target-s390x/mem_helper.c | 2 +-
target-s390x/translate.c | 18 +++++++-----------
4 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 13ceeec..aca4158 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -105,7 +105,7 @@ DEF_HELPER_4(stctl, void, env, i32, i64, i32)
DEF_HELPER_4(stctg, void, env, i32, i64, i32)
DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64)
DEF_HELPER_FLAGS_2(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64)
-DEF_HELPER_FLAGS_3(sske, TCG_CALL_CONST, void, env, i32, i64)
+DEF_HELPER_FLAGS_3(sske, TCG_CALL_CONST, void, env, i64, i64)
DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_CONST, i32, env, i32, i64)
DEF_HELPER_3(csp, i32, env, i32, i32)
DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 3af659a..4f944e2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -650,6 +650,8 @@
C(0xb210, SPX, S, Z, 0, m2_32u, 0, 0, spx, 0)
/* SET PSW KEY FROM ADDRESS */
C(0xb20a, SPKA, S, Z, 0, a2, 0, 0, spka, 0)
+/* SET STORAGE KEY EXTENDED */
+ C(0xb22b, SSKE, RRF_c, Z, r1_o, r2_o, 0, 0, sske, 0)
/* SET SYSTEM MASK */
C(0x8000, SSM, S, Z, 0, m2_8u, 0, 0, ssm, 0)
/* SIGNAL PROCESSOR */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index a700bb0..4c19deb 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -948,7 +948,7 @@ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
}
/* set storage key extended */
-void HELPER(sske)(CPUS390XState *env, uint32_t r1, uint64_t r2)
+void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
{
uint64_t addr = get_address(env, 0, 0, r2);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b39ecc8..9e047eb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1042,17 +1042,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
break;
- case 0x2b: /* SSKE R1,R2 [RRE] */
- /* Set Storage Key Extended */
- check_privileged(s);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- tmp32_1 = load_reg32(r1);
- tmp = load_reg(r2);
- gen_helper_sske(cpu_env, tmp32_1, tmp);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
case 0x34: /* STCH ? */
/* Store Subchannel */
check_privileged(s);
@@ -2770,6 +2759,13 @@ static ExitStatus op_spka(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_sske(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_sske(cpu_env, o->in1, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
{
check_privileged(s);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 100/126] target-s390: Convert RRBE
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (98 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 099/126] target-s390: Convert SSKE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 101/126] target-s390: Convert subchannel instructions Richard Henderson
2012-09-18 21:08 ` [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Alexander Graf
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 2 ++
target-s390x/mem_helper.c | 2 +-
target-s390x/translate.c | 22 ++++++++++------------
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index aca4158..52ce5ad 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -106,7 +106,7 @@ DEF_HELPER_4(stctg, void, env, i32, i64, i32)
DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64)
DEF_HELPER_FLAGS_2(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64)
DEF_HELPER_FLAGS_3(sske, TCG_CALL_CONST, void, env, i64, i64)
-DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_CONST, i32, env, i32, i64)
+DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, env, i64)
DEF_HELPER_3(csp, i32, env, i32, i32)
DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4f944e2..5a38750 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -635,6 +635,8 @@
C(0xdb00, MVCS, SS_d, Z, la1, a2, 0, 0, mvcs, 0)
/* PURGE TLB */
C(0xb20d, PTLB, S, Z, 0, 0, 0, 0, ptlb, 0)
+/* RESET REFERENCE BIT EXTENDED */
+ C(0xb22a, RRBE, RRE, Z, 0, r2_o, 0, 0, rrbe, 0)
/* SET ADDRESSING MODE */
/* We only do 64-bit, so accept this as a no-op.
Let SAM24 and SAM31 signal illegal instruction. */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 4c19deb..1e24d29 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -960,7 +960,7 @@ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
}
/* reset reference bit extended */
-uint32_t HELPER(rrbe)(CPUS390XState *env, uint32_t r1, uint64_t r2)
+uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
{
uint8_t re;
uint8_t key;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9e047eb..b4c8633 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,18 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x2a: /* RRBE R1,R2 [RRE] */
- /* Set Storage Key Extended */
- check_privileged(s);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- tmp32_1 = load_reg32(r1);
- tmp = load_reg(r2);
- gen_helper_rrbe(cc_op, cpu_env, tmp32_1, tmp);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
case 0x34: /* STCH ? */
/* Store Subchannel */
check_privileged(s);
@@ -2655,6 +2643,16 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_rrbe(cc_op, cpu_env, o->in2);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_sar(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s->fields, r1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* [Qemu-devel] [PATCH 101/126] target-s390: Convert subchannel instructions
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (99 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 100/126] target-s390: Convert RRBE Richard Henderson
@ 2012-09-09 21:05 ` Richard Henderson
2012-09-18 21:08 ` [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Alexander Graf
101 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-09 21:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Note that 0xb25f is not listed in PoO -08 as a valid insn. I believe
the "CHSC" listed in the old code must be a typo for the "CSCH" insn
at 0xb230. Because I'm not 100% certain what the errant entry was
supposed to be, I've listed all of the chapter 14 subchannel insns.
Which is easy since all merely need indicate non-operation.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 11 +++++++++++
target-s390x/translate.c | 18 ++++++++----------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 5a38750..6b5f934 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -680,4 +680,15 @@
C(0xad00, STOSM, SI, Z, la1, 0, new, m1_8, stosm, 0)
/* TEST PROTECTION */
C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0)
+
+/* I/O Instructions. For each we simply indicate non-operation. */
+ C(0xb276, XSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb230, CSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb231, HSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb232, MSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb23b, RCHP, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb238, RSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb233, SSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb234, STSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
+ C(0xb235, TSCH, S, Z, 0, 0, 0, 0, subchannel, 0)
#endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b4c8633..d714308 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1030,11 +1030,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x34: /* STCH ? */
- /* Store Subchannel */
- check_privileged(s);
- gen_op_movi_cc(s, 3);
- break;
case 0x46: /* STURA R1,R2 [RRE] */
/* Store Using Real Address */
check_privileged(s);
@@ -1059,11 +1054,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x5f: /* CHSC ? */
- /* Channel Subsystem Call */
- check_privileged(s);
- gen_op_movi_cc(s, 3);
- break;
case 0x78: /* STCKE D2(B2) [S] */
/* Store Clock Extended */
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2855,6 +2845,14 @@ static ExitStatus op_spx(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_subchannel(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ /* Not operational. */
+ gen_op_movi_cc(s, 3);
+ return NO_EXIT;
+}
+
static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
{
check_privileged(s);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 001/126] tcg: Add TCGV_IS_UNUSED_*
2012-09-09 21:04 ` [Qemu-devel] [PATCH 001/126] tcg: Add TCGV_IS_UNUSED_* Richard Henderson
@ 2012-09-10 14:16 ` Aurelien Jarno
0 siblings, 0 replies; 129+ messages in thread
From: Aurelien Jarno @ 2012-09-10 14:16 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Alexander Graf
On Sun, Sep 09, 2012 at 02:04:19PM -0700, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> tcg/tcg.h | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index d710694..a9367fe 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -251,6 +251,9 @@ typedef int TCGv_i64;
> #define TCGV_UNUSED_I32(x) x = MAKE_TCGV_I32(-1)
> #define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1)
>
> +#define TCGV_IS_UNUSED_I32(x) (GET_TCGV_I32(x) == -1)
> +#define TCGV_IS_UNUSED_I64(x) (GET_TCGV_I64(x) == -1)
> +
> /* call flags */
> /* A pure function only reads its arguments and TCG global variables
> and cannot raise exceptions. Hence a call to a pure function can be
Looks fine.
Reviewed: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 002/126] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS
2012-09-09 21:04 ` [Qemu-devel] [PATCH 002/126] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS Richard Henderson
@ 2012-09-10 14:17 ` Aurelien Jarno
0 siblings, 0 replies; 129+ messages in thread
From: Aurelien Jarno @ 2012-09-10 14:17 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Alexander Graf
On Sun, Sep 09, 2012 at 02:04:20PM -0700, Richard Henderson wrote:
> There are several cases that can be handled easier inside both
> translators and code generators if we have out-of-band values
> for conditions. It's easy enough to handle ALWAYS and NEVER in
> the natural way inside the tcg middle-end.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> tcg/arm/tcg-target.c | 2 +-
> tcg/hppa/tcg-target.c | 2 +-
> tcg/i386/tcg-target.c | 2 +-
> tcg/ppc/tcg-target.c | 2 +-
> tcg/ppc64/tcg-target.c | 2 +-
> tcg/s390/tcg-target.c | 6 ++--
> tcg/sparc/tcg-target.c | 2 +-
> tcg/tcg-op.h | 82 ++++++++++++++++++++++++++++++++++++++------------
> tcg/tcg.c | 2 ++
> tcg/tcg.h | 40 ++++++++++++++++--------
> 10 files changed, 101 insertions(+), 41 deletions(-)
>
> diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
> index cf0ca3d..bb9516c 100644
> --- a/tcg/arm/tcg-target.c
> +++ b/tcg/arm/tcg-target.c
> @@ -342,7 +342,7 @@ enum arm_cond_code_e {
> COND_AL = 0xe,
> };
>
> -static const uint8_t tcg_cond_to_arm_cond[10] = {
> +static const uint8_t tcg_cond_to_arm_cond[] = {
> [TCG_COND_EQ] = COND_EQ,
> [TCG_COND_NE] = COND_NE,
> [TCG_COND_LT] = COND_LT,
> diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
> index 2885212..9cd97d5 100644
> --- a/tcg/hppa/tcg-target.c
> +++ b/tcg/hppa/tcg-target.c
> @@ -738,7 +738,7 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul)
> }
> }
>
> -static const uint8_t tcg_cond_to_cmp_cond[10] =
> +static const uint8_t tcg_cond_to_cmp_cond[] =
> {
> [TCG_COND_EQ] = COND_EQ,
> [TCG_COND_NE] = COND_EQ | COND_FALSE,
> diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
> index da17bba..5dfa113 100644
> --- a/tcg/i386/tcg-target.c
> +++ b/tcg/i386/tcg-target.c
> @@ -338,7 +338,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
> #define JCC_JLE 0xe
> #define JCC_JG 0xf
>
> -static const uint8_t tcg_cond_to_jcc[10] = {
> +static const uint8_t tcg_cond_to_jcc[] = {
> [TCG_COND_EQ] = JCC_JE,
> [TCG_COND_NE] = JCC_JNE,
> [TCG_COND_LT] = JCC_JL,
> diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
> index 0cff181..4c70fba 100644
> --- a/tcg/ppc/tcg-target.c
> +++ b/tcg/ppc/tcg-target.c
> @@ -456,7 +456,7 @@ enum {
> CR_SO
> };
>
> -static const uint32_t tcg_to_bc[10] = {
> +static const uint32_t tcg_to_bc[] = {
> [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
> [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
> [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
> diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
> index 27a0ae8..62dff6a 100644
> --- a/tcg/ppc64/tcg-target.c
> +++ b/tcg/ppc64/tcg-target.c
> @@ -428,7 +428,7 @@ enum {
> CR_SO
> };
>
> -static const uint32_t tcg_to_bc[10] = {
> +static const uint32_t tcg_to_bc[] = {
> [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
> [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
> [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
> diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
> index 04662c1..2bffdb2 100644
> --- a/tcg/s390/tcg-target.c
> +++ b/tcg/s390/tcg-target.c
> @@ -268,7 +268,7 @@ static const int tcg_target_call_oarg_regs[] = {
> #define S390_CC_ALWAYS 15
>
> /* Condition codes that result from a COMPARE and COMPARE LOGICAL. */
> -static const uint8_t tcg_cond_to_s390_cond[10] = {
> +static const uint8_t tcg_cond_to_s390_cond[] = {
> [TCG_COND_EQ] = S390_CC_EQ,
> [TCG_COND_NE] = S390_CC_NE,
> [TCG_COND_LT] = S390_CC_LT,
> @@ -284,7 +284,7 @@ static const uint8_t tcg_cond_to_s390_cond[10] = {
> /* Condition codes that result from a LOAD AND TEST. Here, we have no
> unsigned instruction variation, however since the test is vs zero we
> can re-map the outcomes appropriately. */
> -static const uint8_t tcg_cond_to_ltr_cond[10] = {
> +static const uint8_t tcg_cond_to_ltr_cond[] = {
> [TCG_COND_EQ] = S390_CC_EQ,
> [TCG_COND_NE] = S390_CC_NE,
> [TCG_COND_LT] = S390_CC_LT,
> @@ -1138,7 +1138,7 @@ static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val)
> static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
> TCGArg c2, int c2const)
> {
> - bool is_unsigned = (c > TCG_COND_GT);
> + bool is_unsigned = is_unsigned_cond(c);
> if (c2const) {
> if (c2 == 0) {
> if (type == TCG_TYPE_I32) {
> diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
> index 247a278..0a25065 100644
> --- a/tcg/sparc/tcg-target.c
> +++ b/tcg/sparc/tcg-target.c
> @@ -510,7 +510,7 @@ static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
> }
> #endif
>
> -static const uint8_t tcg_cond_to_bcond[10] = {
> +static const uint8_t tcg_cond_to_bcond[] = {
> [TCG_COND_EQ] = COND_E,
> [TCG_COND_NE] = COND_NE,
> [TCG_COND_LT] = COND_L,
> diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
> index 169d3b2..96a30de 100644
> --- a/tcg/tcg-op.h
> +++ b/tcg/tcg-op.h
> @@ -627,29 +627,49 @@ static inline void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
> static inline void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1,
> TCGv_i32 arg2, int label_index)
> {
> - tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_br(label_index);
> + } else if (cond != TCG_COND_NEVER) {
> + tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
> + }
> }
>
> static inline void tcg_gen_brcondi_i32(TCGCond cond, TCGv_i32 arg1,
> int32_t arg2, int label_index)
> {
> - TCGv_i32 t0 = tcg_const_i32(arg2);
> - tcg_gen_brcond_i32(cond, arg1, t0, label_index);
> - tcg_temp_free_i32(t0);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_br(label_index);
> + } else if (cond != TCG_COND_NEVER) {
> + TCGv_i32 t0 = tcg_const_i32(arg2);
> + tcg_gen_brcond_i32(cond, arg1, t0, label_index);
> + tcg_temp_free_i32(t0);
> + }
> }
>
> static inline void tcg_gen_setcond_i32(TCGCond cond, TCGv_i32 ret,
> TCGv_i32 arg1, TCGv_i32 arg2)
> {
> - tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_movi_i32(ret, 1);
> + } else if (cond == TCG_COND_NEVER) {
> + tcg_gen_movi_i32(ret, 0);
> + } else {
> + tcg_gen_op4i_i32(INDEX_op_setcond_i32, ret, arg1, arg2, cond);
> + }
> }
>
> static inline void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret,
> TCGv_i32 arg1, int32_t arg2)
> {
> - TCGv_i32 t0 = tcg_const_i32(arg2);
> - tcg_gen_setcond_i32(cond, ret, arg1, t0);
> - tcg_temp_free_i32(t0);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_movi_i32(ret, 1);
> + } else if (cond == TCG_COND_NEVER) {
> + tcg_gen_movi_i32(ret, 0);
> + } else {
> + TCGv_i32 t0 = tcg_const_i32(arg2);
> + tcg_gen_setcond_i32(cond, ret, arg1, t0);
> + tcg_temp_free_i32(t0);
> + }
> }
>
> static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
> @@ -945,17 +965,27 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
> static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
> TCGv_i64 arg2, int label_index)
> {
> - tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
> - TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
> - TCGV_HIGH(arg2), cond, label_index);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_br(label_index);
> + } else if (cond != TCG_COND_NEVER) {
> + tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
> + TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
> + TCGV_HIGH(arg2), cond, label_index);
> + }
> }
>
> static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
> TCGv_i64 arg1, TCGv_i64 arg2)
> {
> - tcg_gen_op6i_i32(INDEX_op_setcond2_i32, TCGV_LOW(ret),
> - TCGV_LOW(arg1), TCGV_HIGH(arg1),
> - TCGV_LOW(arg2), TCGV_HIGH(arg2), cond);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_movi_i32(TCGV_LOW(ret), 1);
> + } else if (cond == TCG_COND_NEVER) {
> + tcg_gen_movi_i32(TCGV_LOW(ret), 0);
> + } else {
> + 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_movi_i32(TCGV_HIGH(ret), 0);
> }
>
> @@ -1210,13 +1240,23 @@ static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
> static inline void tcg_gen_brcond_i64(TCGCond cond, TCGv_i64 arg1,
> TCGv_i64 arg2, int label_index)
> {
> - tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_br(label_index);
> + } else if (cond != TCG_COND_NEVER) {
> + tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
> + }
> }
>
> static inline void tcg_gen_setcond_i64(TCGCond cond, TCGv_i64 ret,
> TCGv_i64 arg1, TCGv_i64 arg2)
> {
> - tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_movi_i64(ret, 1);
> + } else if (cond == TCG_COND_NEVER) {
> + tcg_gen_movi_i64(ret, 0);
> + } else {
> + tcg_gen_op4i_i64(INDEX_op_setcond_i64, ret, arg1, arg2, cond);
> + }
> }
>
> static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
> @@ -1334,9 +1374,13 @@ static inline void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
> static inline void tcg_gen_brcondi_i64(TCGCond cond, TCGv_i64 arg1,
> int64_t arg2, int label_index)
> {
> - TCGv_i64 t0 = tcg_const_i64(arg2);
> - tcg_gen_brcond_i64(cond, arg1, t0, label_index);
> - tcg_temp_free_i64(t0);
> + if (cond == TCG_COND_ALWAYS) {
> + tcg_gen_br(label_index);
> + } else if (cond != TCG_COND_NEVER) {
> + TCGv_i64 t0 = tcg_const_i64(arg2);
> + tcg_gen_brcond_i64(cond, arg1, t0, label_index);
> + tcg_temp_free_i64(t0);
> + }
> }
>
> static inline void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret,
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index 8386b70..42c3b40 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -861,6 +861,8 @@ static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
>
> static const char * const cond_name[] =
> {
> + [TCG_COND_NEVER] = "never",
> + [TCG_COND_ALWAYS] = "always",
> [TCG_COND_EQ] = "eq",
> [TCG_COND_NE] = "ne",
> [TCG_COND_LT] = "lt",
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index a9367fe..6c37f15 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -268,18 +268,28 @@ typedef int TCGv_i64;
> #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
> #define TCG_CALL_DUMMY_ARG ((TCGArg)(-1))
>
> +/* Conditions. Note that these are layed out for easy manipulation by
> + the the functions below:
> + bit 0 is used for inverting;
> + bit 1 is signed,
> + bit 2 is unsigned,
> + bit 3 is used with bit 0 for swapping signed/unsigned. */
> typedef enum {
> - TCG_COND_EQ,
> - TCG_COND_NE,
> - TCG_COND_LT,
> - TCG_COND_GE,
> - TCG_COND_LE,
> - TCG_COND_GT,
> + /* non-signed */
> + TCG_COND_NEVER = 0 | 0 | 0 | 0,
> + TCG_COND_ALWAYS = 0 | 0 | 0 | 1,
> + TCG_COND_EQ = 8 | 0 | 0 | 0,
> + TCG_COND_NE = 8 | 0 | 0 | 1,
> + /* signed */
> + TCG_COND_LT = 0 | 0 | 2 | 0,
> + TCG_COND_GE = 0 | 0 | 2 | 1,
> + TCG_COND_LE = 8 | 0 | 2 | 0,
> + TCG_COND_GT = 8 | 0 | 2 | 1,
> /* unsigned */
> - TCG_COND_LTU,
> - TCG_COND_GEU,
> - TCG_COND_LEU,
> - TCG_COND_GTU,
> + TCG_COND_LTU = 0 | 4 | 0 | 0,
> + TCG_COND_GEU = 0 | 4 | 0 | 1,
> + TCG_COND_LEU = 8 | 4 | 0 | 0,
> + TCG_COND_GTU = 8 | 4 | 0 | 1,
> } TCGCond;
>
> /* Invert the sense of the comparison. */
> @@ -291,13 +301,17 @@ static inline TCGCond tcg_invert_cond(TCGCond c)
> /* Swap the operands in a comparison. */
> static inline TCGCond tcg_swap_cond(TCGCond c)
> {
> - int mask = (c < TCG_COND_LT ? 0 : c < TCG_COND_LTU ? 7 : 15);
> - return (TCGCond)(c ^ mask);
> + return c & 6 ? (TCGCond)(c ^ 9) : c;
> }
>
> static inline TCGCond tcg_unsigned_cond(TCGCond c)
> {
> - return (c >= TCG_COND_LT && c <= TCG_COND_GT ? c + 4 : c);
> + return c & 2 ? (TCGCond)(c ^ 6) : c;
> +}
> +
> +static inline bool is_unsigned_cond(TCGCond c)
> +{
> + return (c & 4) != 0;
> }
>
> #define TEMP_VAL_DEAD 0
Technically looks fine, but I still don't really fully see the point of
doing that. So I guess:
Reviewed: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR
2012-09-09 21:04 ` [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR Richard Henderson
@ 2012-09-10 14:34 ` Aurelien Jarno
2012-09-10 14:45 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Aurelien Jarno @ 2012-09-10 14:34 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Alexander Graf
On Sun, Sep 09, 2012 at 02:04:25PM -0700, Richard Henderson wrote:
> At the same time, tidy other usages of tcg_gen_deposit_i64.
> In some cases we can "type cast" rather than extend, and in
> others we can allow tcg_gen_deposit_i64 itself to optimize
> the HOST_LONG_BITS==32 case.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-s390x/translate.c | 68 ++++++++++++++++++++++++++++--------------------
> 1 file changed, 40 insertions(+), 28 deletions(-)
>
> diff --git a/target-s390x/translate.c b/target-s390x/translate.c
> index 3080cef..bf35a65 100644
> --- a/target-s390x/translate.c
> +++ b/target-s390x/translate.c
> @@ -89,7 +89,7 @@ void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf,
> }
>
> for (i = 0; i < 16; i++) {
> - cpu_fprintf(f, "F%02d=%016" PRIx64, i, *(uint64_t *)&env->fregs[i]);
> + cpu_fprintf(f, "F%02d=%016" PRIx64, i, env->fregs[i].ll);
> if ((i % 4) == 3) {
> cpu_fprintf(f, "\n");
> } else {
> @@ -136,21 +136,22 @@ static TCGv_i64 cc_src;
> static TCGv_i64 cc_dst;
> static TCGv_i64 cc_vr;
>
> -static char cpu_reg_names[10*3 + 6*4];
> +static char cpu_reg_names[32][4];
> static TCGv_i64 regs[16];
> +static TCGv_i64 fregs[16];
>
> static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
>
> void s390x_translate_init(void)
> {
> int i;
> - size_t cpu_reg_names_size = sizeof(cpu_reg_names);
> - char *p;
>
> cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
> - psw_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.addr),
> + psw_addr = tcg_global_mem_new_i64(TCG_AREG0,
> + offsetof(CPUS390XState, psw.addr),
> "psw_addr");
> - psw_mask = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.mask),
> + psw_mask = tcg_global_mem_new_i64(TCG_AREG0,
> + offsetof(CPUS390XState, psw.mask),
> "psw_mask");
>
> cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
> @@ -162,13 +163,18 @@ void s390x_translate_init(void)
> cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
> "cc_vr");
>
> - p = cpu_reg_names;
> for (i = 0; i < 16; i++) {
> - snprintf(p, cpu_reg_names_size, "r%d", i);
> + snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i);
> regs[i] = tcg_global_mem_new(TCG_AREG0,
> - offsetof(CPUS390XState, regs[i]), p);
> - p += (i < 10) ? 3 : 4;
> - cpu_reg_names_size -= (i < 10) ? 3 : 4;
> + offsetof(CPUS390XState, regs[i]),
> + cpu_reg_names[i]);
> + }
> +
> + for (i = 0; i < 16; i++) {
> + snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
> + fregs[i] = tcg_global_mem_new(TCG_AREG0,
> + offsetof(CPUS390XState, fregs[i].d),
> + cpu_reg_names[i + 16]);
> }
> }
>
> @@ -182,14 +188,18 @@ static inline TCGv_i64 load_reg(int reg)
> static inline TCGv_i64 load_freg(int reg)
> {
> TCGv_i64 r = tcg_temp_new_i64();
> - tcg_gen_ld_i64(r, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
> + tcg_gen_mov_i64(r, fregs[reg]);
> return r;
> }
>
> static inline TCGv_i32 load_freg32(int reg)
> {
> TCGv_i32 r = tcg_temp_new_i32();
> - tcg_gen_ld_i32(r, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
> +#if HOST_LONG_BITS == 32
> + tcg_gen_mov_i32(r, TCGV_HIGH(fregs[reg]));
> +#else
> + tcg_gen_shri_i64(MAKE_TCGV_I64(GET_TCGV_I32(r)), fregs[reg], 32);
> +#endif
> return r;
> }
>
> @@ -214,39 +224,35 @@ static inline void store_reg(int reg, TCGv_i64 v)
>
> static inline void store_freg(int reg, TCGv_i64 v)
> {
> - tcg_gen_st_i64(v, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
> + tcg_gen_mov_i64(fregs[reg], v);
> }
>
> static inline void store_reg32(int reg, TCGv_i32 v)
> {
> + /* 32 bit register writes keep the upper half */
> #if HOST_LONG_BITS == 32
> tcg_gen_mov_i32(TCGV_LOW(regs[reg]), v);
> #else
> - TCGv_i64 tmp = tcg_temp_new_i64();
> - tcg_gen_extu_i32_i64(tmp, v);
> - /* 32 bit register writes keep the upper half */
> - tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 32);
> - tcg_temp_free_i64(tmp);
> + tcg_gen_deposit_i64(regs[reg], regs[reg],
> + MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 32);
> #endif
> }
>
> static inline void store_reg32_i64(int reg, TCGv_i64 v)
> {
> /* 32 bit register writes keep the upper half */
> -#if HOST_LONG_BITS == 32
> - tcg_gen_mov_i32(TCGV_LOW(regs[reg]), TCGV_LOW(v));
> -#else
> tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
> -#endif
> }
>
> static inline void store_reg16(int reg, TCGv_i32 v)
> {
> - TCGv_i64 tmp = tcg_temp_new_i64();
> - tcg_gen_extu_i32_i64(tmp, v);
> /* 16 bit register writes keep the upper bytes */
> - tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 16);
> - tcg_temp_free_i64(tmp);
> +#if HOST_LONG_BITS == 32
> + tcg_gen_deposit_i32(TCGV_LOW(regs[reg]), TCGV_LOW(regs[reg]), v, 0, 16);
> +#else
> + tcg_gen_deposit_i64(regs[reg], regs[reg],
> + MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 16);
> +#endif
> }
>
> static inline void store_reg8(int reg, TCGv_i64 v)
> @@ -257,7 +263,13 @@ static inline void store_reg8(int reg, TCGv_i64 v)
>
> static inline void store_freg32(int reg, TCGv_i32 v)
> {
> - tcg_gen_st_i32(v, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
> + /* 32 bit register writes keep the lower half */
> +#if HOST_LONG_BITS == 32
> + tcg_gen_mov_i32(TCGV_HIGH(fregs[reg]), v);
> +#else
> + tcg_gen_deposit_i64(fregs[reg], fregs[reg],
> + MAKE_TCGV_I64(GET_TCGV_I32(v)), 32, 32);
> +#endif
> }
>
I am not sure we want to start mixing different layers, and especially
having some assumptions about the host inside the target. That's why I
don't think we should have things like HOST_LONG_BITS in target-*/ and
even less MAKE_TCGV_I64() and GET_TCGV_I32().
Your code take the assumption that it's possible to do moves between 32
and 64-bit registers, which might not be guaranteed on some hosts. It's
fine taking such assumptions (as long as there is also a comment) in the
TCG code.
To handle conversion between 32- and 64-bit registers we have functions
like:
- concat_i32_i64
- extu_i32_i64
- ext_i32_i64
- trunc_i64_i32
These functions work on both 32- and 64-bit hosts, accessing directly
the high and low part on 32-bit hosts.
If it is not possible to implement your FPR code using these functions,
we might want to add some more, but I really thing it's a bad idea to
have this code in the targets.
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR
2012-09-10 14:34 ` Aurelien Jarno
@ 2012-09-10 14:45 ` Richard Henderson
2012-09-10 14:52 ` Aurelien Jarno
0 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-10 14:45 UTC (permalink / raw)
To: Aurelien Jarno; +Cc: qemu-devel, Alexander Graf
On 09/10/2012 07:34 AM, Aurelien Jarno wrote:
> If it is not possible to implement your FPR code using these functions,
> we might want to add some more, but I really thing it's a bad idea to
> have this code in the targets.
I thought I got rid of all this in the various rebasing. Certainly it's
all gone by the end of the patch series.
In particular, the optimization that I was looking for is handled inside
tcg_gen_deposit_i64, so there's no point in doing this in target code too.
I'll make sure this is gone from the next revision.
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR
2012-09-10 14:45 ` Richard Henderson
@ 2012-09-10 14:52 ` Aurelien Jarno
0 siblings, 0 replies; 129+ messages in thread
From: Aurelien Jarno @ 2012-09-10 14:52 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Alexander Graf
On Mon, Sep 10, 2012 at 07:45:04AM -0700, Richard Henderson wrote:
> On 09/10/2012 07:34 AM, Aurelien Jarno wrote:
> > If it is not possible to implement your FPR code using these functions,
> > we might want to add some more, but I really thing it's a bad idea to
> > have this code in the targets.
>
> I thought I got rid of all this in the various rebasing. Certainly it's
> all gone by the end of the patch series.
>
> In particular, the optimization that I was looking for is handled inside
> tcg_gen_deposit_i64, so there's no point in doing this in target code too.
>
> I'll make sure this is gone from the next revision.
Ok, I have to say the series being quite long, I haven't looked at it in
details. If they are gone at the end, it's pretty fine for me.
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST
2012-09-09 21:05 ` [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST Richard Henderson
@ 2012-09-11 19:11 ` Blue Swirl
2012-09-11 21:09 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Blue Swirl @ 2012-09-11 19:11 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Alexander Graf
On Sun, Sep 9, 2012 at 9:05 PM, Richard Henderson <rth@twiddle.net> wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-s390x/helper.h | 4 +-
> target-s390x/insn-data.def | 4 ++
> target-s390x/mem_helper.c | 119 ++++++++++++++++++++++-----------------------
> target-s390x/translate.c | 42 ++++++++--------
> 4 files changed, 83 insertions(+), 86 deletions(-)
>
> diff --git a/target-s390x/helper.h b/target-s390x/helper.h
> index 2bd4105..473e776 100644
> --- a/target-s390x/helper.h
> +++ b/target-s390x/helper.h
> @@ -25,9 +25,9 @@ DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i
> DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
> DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
> DEF_HELPER_4(srst, i32, env, i32, i32, i32)
> -DEF_HELPER_4(clst, i32, env, i32, i32, i32)
> +DEF_HELPER_4(clst, i64, env, i64, i64, i64)
> DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
> -DEF_HELPER_4(mvst, void, env, i32, i32, i32)
> +DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
> DEF_HELPER_4(csg, i64, env, i64, i64, i64)
> DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
> DEF_HELPER_4(cs, i64, env, i64, i64, i64)
> diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
> index 4b30dd5..501d02e 100644
> --- a/target-s390x/insn-data.def
> +++ b/target-s390x/insn-data.def
> @@ -153,6 +153,8 @@
> C(0xbd00, CLM, RS_b, Z, r1_o, a2, 0, 0, clm, 0)
> C(0xeb21, CLMY, RSY_b, LD, r1_o, a2, 0, 0, clm, 0)
> C(0xeb20, CLMH, RSY_b, Z, r1_sr32, a2, 0, 0, clm, 0)
> +/* COMPARE LOGICAL STRING */
> + C(0xb25d, CLST, RRE, Z, r1_o, r2_o, 0, 0, clst, 0)
>
> /* COMPARE AND SWAP */
> C(0xba00, CS, RS_a, Z, r1_o, a2, new, r1_32, cs, 0)
> @@ -396,6 +398,8 @@
> C(0xa800, MVCLE, RS_a, Z, 0, a2, 0, 0, mvcle, 0)
> /* MOVE PAGE */
> C(0xb254, MVPG, RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0)
> +/* MOVE STRING */
> + C(0xb255, MVST, RRE, Z, r1_o, r2_o, 0, 0, mvst, 0)
>
> /* MULTIPLY */
> C(0x1c00, MR, RR_a, Z, r1p1_32s, r2_32s, new, r1_D32, mul, 0)
> diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
> index e9cacf9..8cc4625 100644
> --- a/target-s390x/mem_helper.c
> +++ b/target-s390x/mem_helper.c
> @@ -310,36 +310,30 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
> return cc;
> }
>
> +static inline uint64_t fix_address(CPUS390XState *env, uint64_t a)
> +{
> + /* 31-Bit mode */
> + if (!(env->psw.mask & PSW_MASK_64)) {
PSW_MASK_64 bit could be added to TB flags and that could be checked
during translation, then the mask needs to be applied only when the
mode is active. Whether that actually improves performance depends on
how often the bit is changed. Also all PSW writes need to be handled,
possibly causing a TB flush.
Masking could be done with TCG ops too.
> + a &= 0x7fffffff;
> + }
> + return a;
> +}
> +
> static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2)
> {
> uint64_t r = d2;
> -
> if (x2) {
> r += env->regs[x2];
> }
> -
> if (b2) {
> r += env->regs[b2];
> }
> -
> - /* 31-Bit mode */
> - if (!(env->psw.mask & PSW_MASK_64)) {
> - r &= 0x7fffffff;
> - }
> -
> - return r;
> + return fix_address(env, r);
> }
>
> static inline uint64_t get_address_31fix(CPUS390XState *env, int reg)
> {
> - uint64_t r = env->regs[reg];
> -
> - /* 31-Bit mode */
> - if (!(env->psw.mask & PSW_MASK_64)) {
> - r &= 0x7fffffff;
> - }
> -
> - return r;
> + return fix_address(env, env->regs[reg]);
> }
>
> /* search string (c is byte to search, r2 is string, r1 end of string) */
> @@ -365,39 +359,40 @@ uint32_t HELPER(srst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
> }
>
> /* unsigned string compare (c is string terminator) */
> -uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
> +uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2)
> {
> - uint64_t s1 = get_address_31fix(env, r1);
> - uint64_t s2 = get_address_31fix(env, r2);
> - uint8_t v1, v2;
> - uint32_t cc;
> + uint32_t len;
>
> c = c & 0xff;
> -#ifdef CONFIG_USER_ONLY
> - if (!c) {
> - HELPER_LOG("%s: comparing '%s' and '%s'\n",
> - __func__, (char *)g2h(s1), (char *)g2h(s2));
> - }
> -#endif
> - for (;;) {
> - v1 = cpu_ldub_data(env, s1);
> - v2 = cpu_ldub_data(env, s2);
> - if ((v1 == c || v2 == c) || (v1 != v2)) {
> - break;
> + s1 = fix_address(env, s1);
> + s2 = fix_address(env, s2);
> +
> + /* Lest we fail to service interrupts in a timely manner, limit the
> + amount of work we're willing to do. For now, lets cap at 8k. */
> + for (len = 0; len < 0x2000; ++len) {
> + uint8_t v1 = cpu_ldub_data(env, s1 + len);
> + uint8_t v2 = cpu_ldub_data(env, s2 + len);
> + if (v1 == v2) {
> + if (v1 == c) {
> + /* Equal. CC=0, and don't advance the registers. */
> + env->cc_op = 0;
> + env->retxl = s2;
> + return s1;
> + }
> + } else {
> + /* Unequal. CC={1,2}, and advance the registers. Note that
> + the terminator need not be zero, but the string that contains
> + the terminator is by definition "low". */
> + env->cc_op = (v1 == c ? 1 : v2 == c ? 2 : v1 < v2 ? 1 : 2);
> + env->retxl = s2 + len;
> + return s1 + len;
> }
> - s1++;
> - s2++;
> }
>
> - if (v1 == v2) {
> - cc = 0;
> - } else {
> - cc = (v1 < v2) ? 1 : 2;
> - /* FIXME: 31-bit mode! */
> - env->regs[r1] = s1;
> - env->regs[r2] = s2;
> - }
> - return cc;
> + /* CPU-determined bytes equal; advance the registers. */
> + env->cc_op = 3;
> + env->retxl = s2 + len;
> + return s1 + len;
> }
>
> /* move page */
> @@ -413,29 +408,31 @@ void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
> }
>
> /* string copy (c is string terminator) */
> -void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
> +uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
> {
> - uint64_t dest = get_address_31fix(env, r1);
> - uint64_t src = get_address_31fix(env, r2);
> - uint8_t v;
> + uint32_t len;
>
> c = c & 0xff;
> -#ifdef CONFIG_USER_ONLY
> - if (!c) {
> - HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src),
> - dest);
> - }
> -#endif
> - for (;;) {
> - v = cpu_ldub_data(env, src);
> - cpu_stb_data(env, dest, v);
> + d = fix_address(env, d);
> + s = fix_address(env, s);
> +
> + /* Lest we fail to service interrupts in a timely manner, limit the
> + amount of work we're willing to do. For now, lets cap at 8k. */
> + for (len = 0; len < 0x2000; ++len) {
> + uint8_t v = cpu_ldub_data(env, s + len);
> + cpu_stb_data(env, d + len, v);
> if (v == c) {
> - break;
> + /* Complete. Set CC=1 and advance R1. */
> + env->cc_op = 1;
> + env->retxl = s;
> + return d + len;
> }
> - src++;
> - dest++;
> }
> - env->regs[r1] = dest; /* FIXME: 31-bit mode! */
> +
> + /* Incomplete. Set CC=3 and signal to advance R1 and R2. */
> + env->cc_op = 3;
> + env->retxl = s + len;
> + return d + len;
> }
>
> /* compare and swap 64-bit */
> diff --git a/target-s390x/translate.c b/target-s390x/translate.c
> index a49475b..49f419a 100644
> --- a/target-s390x/translate.c
> +++ b/target-s390x/translate.c
> @@ -425,7 +425,7 @@ static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
> return tmp;
> }
>
> -static void gen_op_movi_cc(DisasContext *s, uint32_t val)
> +static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
> {
> s->cc_op = CC_OP_CONST0 + val;
> }
> @@ -1031,28 +1031,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
> LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
>
> switch (op) {
> - case 0x55: /* MVST R1,R2 [RRE] */
> - tmp32_1 = load_reg32(0);
> - tmp32_2 = tcg_const_i32(r1);
> - tmp32_3 = tcg_const_i32(r2);
> - potential_page_fault(s);
> - gen_helper_mvst(cpu_env, tmp32_1, tmp32_2, tmp32_3);
> - tcg_temp_free_i32(tmp32_1);
> - tcg_temp_free_i32(tmp32_2);
> - tcg_temp_free_i32(tmp32_3);
> - gen_op_movi_cc(s, 1);
> - break;
> - case 0x5d: /* CLST R1,R2 [RRE] */
> - tmp32_1 = load_reg32(0);
> - tmp32_2 = tcg_const_i32(r1);
> - tmp32_3 = tcg_const_i32(r2);
> - potential_page_fault(s);
> - gen_helper_clst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
> - set_cc_static(s);
> - tcg_temp_free_i32(tmp32_1);
> - tcg_temp_free_i32(tmp32_2);
> - tcg_temp_free_i32(tmp32_3);
> - break;
> case 0x5e: /* SRST R1,R2 [RRE] */
> tmp32_1 = load_reg32(0);
> tmp32_2 = tcg_const_i32(r1);
> @@ -2044,6 +2022,15 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o)
> return NO_EXIT;
> }
>
> +static ExitStatus op_clst(DisasContext *s, DisasOps *o)
> +{
> + potential_page_fault(s);
> + gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2);
> + set_cc_static(s);
> + return_low128(o->in2);
> + return NO_EXIT;
> +}
> +
> static ExitStatus op_cs(DisasContext *s, DisasOps *o)
> {
> int r3 = get_field(s->fields, r3);
> @@ -2589,6 +2576,15 @@ static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
> return NO_EXIT;
> }
>
> +static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
> +{
> + potential_page_fault(s);
> + gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
> + set_cc_static(s);
> + return_low128(o->in2);
> + return NO_EXIT;
> +}
> +
> static ExitStatus op_mul(DisasContext *s, DisasOps *o)
> {
> tcg_gen_mul_i64(o->out, o->in1, o->in2);
> --
> 1.7.11.4
>
>
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST
2012-09-11 19:11 ` Blue Swirl
@ 2012-09-11 21:09 ` Richard Henderson
2012-09-18 21:04 ` Alexander Graf
0 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-11 21:09 UTC (permalink / raw)
To: Blue Swirl; +Cc: qemu-devel, Alexander Graf
On 09/11/2012 12:11 PM, Blue Swirl wrote:
> PSW_MASK_64 bit could be added to TB flags and that could be checked
> during translation, then the mask needs to be applied only when the
> mode is active. Whether that actually improves performance depends on
> how often the bit is changed. Also all PSW writes need to be handled,
> possibly causing a TB flush.
Actually I'm not sure why we check this at all, given that we only
actually handle 64-bit mode -- at least as documented by the code
implementing the SET ADDRESS MODE instruction.
That said, we do encode the bit in TB flags, and we do perform this
masking for qemu loads performed within the TB. No TB flushes are
required because we simply don't match TBs with different flags.
As for clst, mvst, srst, I thought about performing the masking in
the TB, but didn't figure it was worth it. Do you have an opinion, Alex?
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub
2012-09-09 21:04 ` [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub Richard Henderson
@ 2012-09-12 13:25 ` Alexander Graf
2012-09-12 15:11 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-12 13:25 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 09/09/2012 11:04 PM, Richard Henderson wrote:
> The real gdb protocol doesn't split out pc or cc as real registers.
> Those are pseudos that are extracted as needed from the PSW. Don't
> modify env->cc_op during read -- that way lies heisenbugs.
>
> Fill in the XXX for the fp registers.
>
> Remove duplicated defines in cpu.h.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> gdbstub.c | 78 +++++++++++++++++++++++++++++++++---------------------
> target-s390x/cpu.h | 73 --------------------------------------------------
> 2 files changed, 48 insertions(+), 103 deletions(-)
>
> diff --git a/gdbstub.c b/gdbstub.c
> index 5d37dd9..6aed0b4 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -1499,27 +1499,35 @@ static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
> }
> #elif defined (TARGET_S390X)
>
> -#define NUM_CORE_REGS S390_NUM_TOTAL_REGS
> +#define NUM_CORE_REGS S390_NUM_REGS
>
> static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
> {
> + uint64_t val;
> + int cc_op;
> +
> switch (n) {
> - case S390_PSWM_REGNUM: GET_REGL(env->psw.mask); break;
> - case S390_PSWA_REGNUM: GET_REGL(env->psw.addr); break;
> - case S390_R0_REGNUM ... S390_R15_REGNUM:
> - GET_REGL(env->regs[n-S390_R0_REGNUM]); break;
> - case S390_A0_REGNUM ... S390_A15_REGNUM:
> - GET_REG32(env->aregs[n-S390_A0_REGNUM]); break;
> - case S390_FPC_REGNUM: GET_REG32(env->fpc); break;
> - case S390_F0_REGNUM ... S390_F15_REGNUM:
> - /* XXX */
> - break;
> - case S390_PC_REGNUM: GET_REGL(env->psw.addr); break;
> - case S390_CC_REGNUM:
> - env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
> - env->cc_vr);
> - GET_REG32(env->cc_op);
> - break;
> + case S390_PSWM_REGNUM:
> + val = env->psw.mask & ~(3ull << 13);
> + cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
> + val |= cc_op << 13;
> + GET_REGL(val);
> + break;
> + case S390_PSWA_REGNUM:
> + GET_REGL(env->psw.addr);
> + break;
> + case S390_R0_REGNUM ... S390_R15_REGNUM:
> + GET_REGL(env->regs[n-S390_R0_REGNUM]);
> + break;
> + case S390_A0_REGNUM ... S390_A15_REGNUM:
> + GET_REG32(env->aregs[n-S390_A0_REGNUM]);
> + break;
> + case S390_FPC_REGNUM:
> + GET_REG32(env->fpc);
> + break;
> + case S390_F0_REGNUM ... S390_F15_REGNUM:
> + GET_REG64(env->fregs[n-S390_F0_REGNUM].ll);
> + break;
> }
>
> return 0;
> @@ -1534,20 +1542,30 @@ static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n)
> tmp32 = ldl_p(mem_buf);
>
> switch (n) {
> - case S390_PSWM_REGNUM: env->psw.mask = tmpl; break;
> - case S390_PSWA_REGNUM: env->psw.addr = tmpl; break;
> - case S390_R0_REGNUM ... S390_R15_REGNUM:
> - env->regs[n-S390_R0_REGNUM] = tmpl; break;
> - case S390_A0_REGNUM ... S390_A15_REGNUM:
> - env->aregs[n-S390_A0_REGNUM] = tmp32; r=4; break;
> - case S390_FPC_REGNUM: env->fpc = tmp32; r=4; break;
> - case S390_F0_REGNUM ... S390_F15_REGNUM:
> - /* XXX */
> - break;
> - case S390_PC_REGNUM: env->psw.addr = tmpl; break;
> - case S390_CC_REGNUM: env->cc_op = tmp32; r=4; break;
> + case S390_PSWM_REGNUM:
> + env->psw.mask = tmpl;
> + env->cc_op = (tmpl >> 13) & 3;
Are you sure this is correct? I thought gdbstub would just ignore the cc
bits.
Alex
> + break;
> + case S390_PSWA_REGNUM:
> + env->psw.addr = tmpl;
> + break;
> + case S390_R0_REGNUM ... S390_R15_REGNUM:
> + env->regs[n-S390_R0_REGNUM] = tmpl;
> + break;
> + case S390_A0_REGNUM ... S390_A15_REGNUM:
> + env->aregs[n-S390_A0_REGNUM] = tmp32;
> + r = 4;
> + break;
> + case S390_FPC_REGNUM:
> + env->fpc = tmp32;
> + r = 4;
> + break;
> + case S390_F0_REGNUM ... S390_F15_REGNUM:
> + env->fregs[n-S390_F0_REGNUM].ll = tmpl;
> + break;
> + default:
> + return 0;
> }
> -
> return r;
> }
> #elif defined (TARGET_LM32)
> diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
> index ed81af3..471fb91 100644
> --- a/target-s390x/cpu.h
> +++ b/target-s390x/cpu.h
> @@ -430,79 +430,6 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
> /* Total. */
> #define S390_NUM_REGS 51
>
> -/* Pseudo registers -- PC and condition code. */
> -#define S390_PC_REGNUM S390_NUM_REGS
> -#define S390_CC_REGNUM (S390_NUM_REGS+1)
> -#define S390_NUM_PSEUDO_REGS 2
> -#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
> -
> -
> -
> -/* Program Status Word. */
> -#define S390_PSWM_REGNUM 0
> -#define S390_PSWA_REGNUM 1
> -/* General Purpose Registers. */
> -#define S390_R0_REGNUM 2
> -#define S390_R1_REGNUM 3
> -#define S390_R2_REGNUM 4
> -#define S390_R3_REGNUM 5
> -#define S390_R4_REGNUM 6
> -#define S390_R5_REGNUM 7
> -#define S390_R6_REGNUM 8
> -#define S390_R7_REGNUM 9
> -#define S390_R8_REGNUM 10
> -#define S390_R9_REGNUM 11
> -#define S390_R10_REGNUM 12
> -#define S390_R11_REGNUM 13
> -#define S390_R12_REGNUM 14
> -#define S390_R13_REGNUM 15
> -#define S390_R14_REGNUM 16
> -#define S390_R15_REGNUM 17
> -/* Access Registers. */
> -#define S390_A0_REGNUM 18
> -#define S390_A1_REGNUM 19
> -#define S390_A2_REGNUM 20
> -#define S390_A3_REGNUM 21
> -#define S390_A4_REGNUM 22
> -#define S390_A5_REGNUM 23
> -#define S390_A6_REGNUM 24
> -#define S390_A7_REGNUM 25
> -#define S390_A8_REGNUM 26
> -#define S390_A9_REGNUM 27
> -#define S390_A10_REGNUM 28
> -#define S390_A11_REGNUM 29
> -#define S390_A12_REGNUM 30
> -#define S390_A13_REGNUM 31
> -#define S390_A14_REGNUM 32
> -#define S390_A15_REGNUM 33
> -/* Floating Point Control Word. */
> -#define S390_FPC_REGNUM 34
> -/* Floating Point Registers. */
> -#define S390_F0_REGNUM 35
> -#define S390_F1_REGNUM 36
> -#define S390_F2_REGNUM 37
> -#define S390_F3_REGNUM 38
> -#define S390_F4_REGNUM 39
> -#define S390_F5_REGNUM 40
> -#define S390_F6_REGNUM 41
> -#define S390_F7_REGNUM 42
> -#define S390_F8_REGNUM 43
> -#define S390_F9_REGNUM 44
> -#define S390_F10_REGNUM 45
> -#define S390_F11_REGNUM 46
> -#define S390_F12_REGNUM 47
> -#define S390_F13_REGNUM 48
> -#define S390_F14_REGNUM 49
> -#define S390_F15_REGNUM 50
> -/* Total. */
> -#define S390_NUM_REGS 51
> -
> -/* Pseudo registers -- PC and condition code. */
> -#define S390_PC_REGNUM S390_NUM_REGS
> -#define S390_CC_REGNUM (S390_NUM_REGS+1)
> -#define S390_NUM_PSEUDO_REGS 2
> -#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
> -
Hrm. Mind to quickly explain why it's ok to remove these? Where to they
come from now? Or were they defined twice in cpu.h?
Alex
> /* CC optimization */
>
> enum cc_op {
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub
2012-09-12 13:25 ` Alexander Graf
@ 2012-09-12 15:11 ` Richard Henderson
2012-09-12 15:54 ` Alexander Graf
0 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-12 15:11 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
On 09/12/2012 06:25 AM, Alexander Graf wrote:
>> + case S390_PSWM_REGNUM:
>> + env->psw.mask = tmpl;
>> + env->cc_op = (tmpl >> 13) & 3;
>
> Are you sure this is correct? I thought gdbstub would just ignore the cc bits.
Well... no it won't ignore the cc bits. But it would appear that I've got
them at the wrong location. From gdb/s390-tdep.c:
if (regnum == tdep->cc_regnum)
{
enum register_status status;
status = regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
if (status == REG_VALID)
{
if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
val = (val >> 12) & 3;
else
val = (val >> 44) & 3;
store_unsigned_integer (buf, regsize, byte_order, val);
}
return status;
}
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub
2012-09-12 15:11 ` Richard Henderson
@ 2012-09-12 15:54 ` Alexander Graf
2012-09-12 16:15 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-12 15:54 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 09/12/2012 05:11 PM, Richard Henderson wrote:
> On 09/12/2012 06:25 AM, Alexander Graf wrote:
>>> + case S390_PSWM_REGNUM:
>>> + env->psw.mask = tmpl;
>>> + env->cc_op = (tmpl >> 13) & 3;
>> Are you sure this is correct? I thought gdbstub would just ignore the cc bits.
> Well... no it won't ignore the cc bits.
So the CC pseudo-register is never written to?
> But it would appear that I've got
> them at the wrong location. From gdb/s390-tdep.c:
>
> if (regnum == tdep->cc_regnum)
> {
> enum register_status status;
>
> status = regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
> if (status == REG_VALID)
> {
> if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
> val = (val >> 12) & 3;
Oops :)
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub
2012-09-12 15:54 ` Alexander Graf
@ 2012-09-12 16:15 ` Richard Henderson
0 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-12 16:15 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
On 09/12/2012 08:54 AM, Alexander Graf wrote:
> So the CC pseudo-register is never written to?
They do handle a write to cc_regnum in s390_pseudo_register_write.
They modify psw.mask as one would expect.
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-09 21:04 ` [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling Richard Henderson
@ 2012-09-18 20:18 ` Alexander Graf
2012-09-19 0:14 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-18 20:18 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 09/09/2012 11:04 PM, Richard Henderson wrote:
> Make the user path more like the system path. Prepare for more kinds
> of runtime exceptions. Compute ILC from S->NEXT_PC, rather than
> passing it around.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> linux-user/main.c | 133 +++++++++++++++++----------
> target-s390x/cpu.h | 11 ---
> target-s390x/misc_helper.c | 10 ++-
> target-s390x/translate.c | 220 +++++++++++++++++----------------------------
> 4 files changed, 174 insertions(+), 200 deletions(-)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 1a1c661..8f6f39b 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2935,71 +2935,108 @@ void cpu_loop(CPUAlphaState *env)
> #ifdef TARGET_S390X
> void cpu_loop(CPUS390XState *env)
> {
> - int trapnr;
> + int trapnr, n, sig;
> target_siginfo_t info;
> + target_ulong addr;
>
> while (1) {
> - trapnr = cpu_s390x_exec (env);
> -
> + trapnr = cpu_s390x_exec(env);
> switch (trapnr) {
> case EXCP_INTERRUPT:
> - /* just indicate that signals should be handled asap */
> + /* Just indicate that signals should be handled asap. */
> break;
> - case EXCP_DEBUG:
> - {
> - int sig;
>
> - sig = gdb_handlesig (env, TARGET_SIGTRAP);
> - if (sig) {
> - info.si_signo = sig;
> - info.si_errno = 0;
> - info.si_code = TARGET_TRAP_BRKPT;
> - queue_signal(env, info.si_signo, &info);
> - }
> + case EXCP_SVC:
> + n = env->int_svc_code;
> + if (!n) {
> + /* syscalls > 255 */
> + n = env->regs[1];
> }
> + env->psw.addr += env->int_svc_ilc;
> + env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
> + env->regs[4], env->regs[5],
> + env->regs[6], env->regs[7], 0, 0);
> break;
> - case EXCP_SVC:
> - {
> - int n = env->int_svc_code;
> - if (!n) {
> - /* syscalls > 255 */
> - n = env->regs[1];
> - }
> - env->psw.addr += env->int_svc_ilc;
> - env->regs[2] = do_syscall(env, n,
> - env->regs[2],
> - env->regs[3],
> - env->regs[4],
> - env->regs[5],
> - env->regs[6],
> - env->regs[7],
> - 0, 0);
> +
> + case EXCP_DEBUG:
> + sig = gdb_handlesig(env, TARGET_SIGTRAP);
> + if (sig) {
> + n = TARGET_TRAP_BRKPT;
> + goto do_signal_pc;
> }
> break;
> - case EXCP_ADDR:
> - {
> - info.si_signo = SIGSEGV;
> - info.si_errno = 0;
> + case EXCP_PGM:
> + n = env->int_pgm_code;
> + switch (n) {
> + case PGM_OPERATION:
> + case PGM_PRIVILEGED:
> + sig = SIGILL;
> + n = TARGET_ILL_ILLOPC;
> + goto do_signal_pc;
> + case PGM_PROTECTION:
> + case PGM_ADDRESSING:
> + sig = SIGSEGV;
> /* XXX: check env->error_code */
> - info.si_code = TARGET_SEGV_MAPERR;
> - info._sifields._sigfault._addr = env->__excp_addr;
> - queue_signal(env, info.si_signo, &info);
> + n = TARGET_SEGV_MAPERR;
> + addr = env->__excp_addr;
> + goto do_signal;
> + case PGM_EXECUTE:
> + case PGM_SPECIFICATION:
> + case PGM_DATA:
> + case PGM_SPECIAL_OP:
> + case PGM_OPERAND:
> + sig = SIGILL;
> + n = TARGET_ILL_ILLOPN;
> + goto do_signal_pc;
> + case PGM_FIXPT_OVERFLOW:
> + sig = SIGFPE;
> + n = TARGET_FPE_INTOVF;
> + goto do_signal_pc;
> + case PGM_FIXPT_DIVIDE:
> + sig = SIGFPE;
> + n = TARGET_FPE_INTDIV;
> + goto do_signal_pc;
> + case PGM_HFP_EXP_OVERFLOW:
> + sig = SIGFPE;
> + n = TARGET_FPE_FLTOVF;
> + goto do_signal_pc;
> + case PGM_HFP_EXP_UNDERFLOW:
> + sig = SIGFPE;
> + n = TARGET_FPE_FLTUND;
> + goto do_signal_pc;
> + case PGM_HFP_SIGNIFICANCE:
> + sig = SIGFPE;
> + n = TARGET_FPE_FLTRES;
> + goto do_signal_pc;
> + case PGM_HFP_DIVIDE:
> + sig = SIGFPE;
> + n = TARGET_FPE_FLTDIV;
> + goto do_signal_pc;
> + case PGM_HFP_SQRT:
> + sig = SIGFPE;
> + n = TARGET_FPE_FLTINV;
> + goto do_signal_pc;
> + default:
> + fprintf(stderr, "Unhandled program exception: %#x\n", n);
> + cpu_dump_state(env, stderr, fprintf, 0);
> + exit(1);
> }
> break;
> - case EXCP_SPEC:
> - {
> - fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4));
> - info.si_signo = SIGILL;
> - info.si_errno = 0;
> - info.si_code = TARGET_ILL_ILLOPC;
> - info._sifields._sigfault._addr = env->__excp_addr;
> - queue_signal(env, info.si_signo, &info);
> - }
> +
> + do_signal_pc:
> + addr = env->psw.addr;
> + do_signal:
> + info.si_signo = sig;
> + info.si_errno = 0;
> + info.si_code = n;
> + info._sifields._sigfault._addr = addr;
> + queue_signal(env, info.si_signo, &info);
> break;
> +
> default:
> - printf ("Unhandled trap: 0x%x\n", trapnr);
> + fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
> cpu_dump_state(env, stderr, fprintf, 0);
> - exit (1);
> + exit(1);
> }
> process_pending_signals (env);
> }
> diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
> index 471fb91..17829b5 100644
> --- a/target-s390x/cpu.h
> +++ b/target-s390x/cpu.h
> @@ -352,21 +352,10 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
>
> #include "exec-all.h"
>
> -#ifdef CONFIG_USER_ONLY
> -
> -#define EXCP_OPEX 1 /* operation exception (sigill) */
> -#define EXCP_SVC 2 /* supervisor call (syscall) */
> -#define EXCP_ADDR 5 /* addressing exception */
> -#define EXCP_SPEC 6 /* specification exception */
> -
> -#else
> -
> #define EXCP_EXT 1 /* external interrupt */
> #define EXCP_SVC 2 /* supervisor call (syscall) */
> #define EXCP_PGM 3 /* program interruption */
>
> -#endif /* CONFIG_USER_ONLY */
> -
> #define INTERRUPT_EXT (1 << 0)
> #define INTERRUPT_TOD (1 << 1)
> #define INTERRUPT_CPUTIMER (1 << 2)
> diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
> index f405b97..1502f15 100644
> --- a/target-s390x/misc_helper.c
> +++ b/target-s390x/misc_helper.c
> @@ -86,10 +86,12 @@ void do_interrupt(CPUS390XState *env)
> int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address,
> int rw, int mmu_idx)
> {
> - /* fprintf(stderr, "%s: address 0x%lx rw %d mmu_idx %d\n",
> - __func__, address, rw, mmu_idx); */
> - env->exception_index = EXCP_ADDR;
> - /* FIXME: find out how this works on a real machine */
> + env->exception_index = EXCP_PGM;
> + env->int_pgm_code = PGM_PROTECTION;
> + /* A real machine puts the address in LowCore, which the kernel
> + helpfully interprets for us. Since we've nothing similar
> + within the userland address space, invent something for use
> + within cpu_loop. */
> env->__excp_addr = address;
> return 1;
> }
> diff --git a/target-s390x/translate.c b/target-s390x/translate.c
> index 996d786..70e5d87 100644
> --- a/target-s390x/translate.c
> +++ b/target-s390x/translate.c
> @@ -18,7 +18,6 @@
> * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> */
>
> -/* #define DEBUG_ILLEGAL_INSTRUCTIONS */
> /* #define DEBUG_INLINE_BRANCHES */
> #define S390X_DEBUG_DISAS
> /* #define S390X_DEBUG_DISAS_VERBOSE */
> @@ -336,103 +335,52 @@ static inline int get_mem_index(DisasContext *s)
> }
> }
>
> -static inline void gen_debug(DisasContext *s)
> +static void gen_exception(int excp)
> {
> - TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
> - update_psw_addr(s);
> - gen_op_calc_cc(s);
> - gen_helper_exception(cpu_env, tmp);
> - tcg_temp_free_i32(tmp);
> - s->is_jmp = DISAS_EXCP;
> -}
> -
> -#ifdef CONFIG_USER_ONLY
> -
> -static void gen_illegal_opcode(DisasContext *s, int ilc)
> -{
> - TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC);
> - update_psw_addr(s);
> - gen_op_calc_cc(s);
> + TCGv_i32 tmp = tcg_const_i32(excp);
> gen_helper_exception(cpu_env, tmp);
> tcg_temp_free_i32(tmp);
> - s->is_jmp = DISAS_EXCP;
> }
>
> -#else /* CONFIG_USER_ONLY */
> -
> -static void debug_print_inst(DisasContext *s, int ilc)
> -{
> -#ifdef DEBUG_ILLEGAL_INSTRUCTIONS
> - uint64_t inst = 0;
> -
> - switch (ilc & 3) {
> - case 1:
> - inst = ld_code2(s->pc);
> - break;
> - case 2:
> - inst = ld_code4(s->pc);
> - break;
> - case 3:
> - inst = ld_code6(s->pc);
> - break;
> - }
> -
> - fprintf(stderr, "Illegal instruction [%d at %016" PRIx64 "]: 0x%016"
> - PRIx64 "\n", ilc, s->pc, inst);
> -#endif
> -}
> -
> -static void gen_program_exception(DisasContext *s, int ilc, int code)
> +static void gen_program_exception(DisasContext *s, int code)
> {
> TCGv_i32 tmp;
>
> - debug_print_inst(s, ilc);
> -
> - /* remember what pgm exeption this was */
> + /* Remember what pgm exeption this was. */
> tmp = tcg_const_i32(code);
> tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
> tcg_temp_free_i32(tmp);
>
> - tmp = tcg_const_i32(ilc);
> + tmp = tcg_const_i32(s->next_pc - s->pc);
Mind to explain this one?
> tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc));
> tcg_temp_free_i32(tmp);
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 047/126] target-s390: Convert LOAD, STORE MULTIPLE
2012-09-09 21:05 ` [Qemu-devel] [PATCH 047/126] target-s390: Convert LOAD, STORE MULTIPLE Richard Henderson
@ 2012-09-18 20:49 ` Alexander Graf
2012-09-19 0:15 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-18 20:49 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 09/09/2012 11:05 PM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> target-s390x/insn-data.def | 14 ++++
> target-s390x/translate.c | 191 ++++++++++++++++++++++++---------------------
> 2 files changed, 116 insertions(+), 89 deletions(-)
>
> diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
> index 103c1d2..b1f0448 100644
> --- a/target-s390x/insn-data.def
> +++ b/target-s390x/insn-data.def
> @@ -269,6 +269,13 @@
> C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
> C(0xb910, LPGFR, RRE, Z, 0, r2_32s, r1, 0, abs, abs64)
>
> +/* LOAD MULTIPLE */
> + C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
> + C(0xeb98, LMY, RSY_a, LD, 0, a2, 0, 0, lm32, 0)
> + C(0xeb04, LMG, RSY_a, Z, 0, a2, 0, 0, lm64, 0)
> +/* LOAD MULTIPLE HIGH */
> + C(0xeb96, LMH, RSY_a, Z, 0, a2, 0, 0, lmh, 0)
> +
> /* MOVE LONG */
> C(0x0e00, MVCL, RR_a, Z, 0, 0, 0, 0, mvcl, 0)
>
> @@ -364,6 +371,13 @@
> /* STORE HALFWORD RELATIVE LONG */
> C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
>
> +/* STORE MULTIPLE */
> + D(0x9000, STM, RS_a, Z, 0, a2, 0, 0, stm, 0, 4)
> + D(0xeb90, STMY, RSY_a, LD, 0, a2, 0, 0, stm, 0, 4)
> + D(0xeb24, STMG, RSY_a, Z, 0, a2, 0, 0, stm, 0, 8)
> +/* STORE MULTIPLE HIGH */
> + C(0xeb26, STMH, RSY_a, Z, 0, a2, 0, 0, stmh, 0)
> +
> /* SUBTRACT */
> C(0x1b00, SR, RR_a, Z, r1, r2, new, r1_32, sub, subs32)
> C(0xb9f9, SRK, RRF_a, DO, r2, r3, new, r1_32, sub, subs32)
> diff --git a/target-s390x/translate.c b/target-s390x/translate.c
> index e78e4bb..4c5540d 100644
> --- a/target-s390x/translate.c
> +++ b/target-s390x/translate.c
> @@ -271,6 +271,11 @@ static inline void store_reg32_i64(int reg, TCGv_i64 v)
> tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
> }
>
> +static inline void store_reg32h_i64(int reg, TCGv_i64 v)
> +{
> + tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
> +}
> +
> static inline void store_reg16(int reg, TCGv_i32 v)
> {
> /* 16 bit register writes keep the upper bytes */
> @@ -1320,65 +1325,12 @@ static void disas_e5(DisasContext* s, uint64_t insn)
>
> static void disas_eb(DisasContext *s, int op, int r1, int r3, int b2, int d2)
> {
> - TCGv_i64 tmp, tmp2, tmp3, tmp4;
> + TCGv_i64 tmp, tmp2;
> TCGv_i32 tmp32_1, tmp32_2;
> - int i, stm_len;
>
> LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
> op, r1, r3, b2, d2);
> switch (op) {
> - case 0x4: /* LMG R1,R3,D2(B2) [RSE] */
> - case 0x24: /* STMG R1,R3,D2(B2) [RSE] */
> - stm_len = 8;
> - goto do_mh;
> - case 0x26: /* STMH R1,R3,D2(B2) [RSE] */
> - case 0x96: /* LMH R1,R3,D2(B2) [RSE] */
> - stm_len = 4;
> -do_mh:
> - /* Apparently, unrolling lmg/stmg of any size gains performance -
> - even for very long ones... */
> - tmp = get_address(s, 0, b2, d2);
> - tmp3 = tcg_const_i64(stm_len);
> - tmp4 = tcg_const_i64(op == 0x26 ? 32 : 4);
> - for (i = r1;; i = (i + 1) % 16) {
> - switch (op) {
> - case 0x4:
> - tcg_gen_qemu_ld64(regs[i], tmp, get_mem_index(s));
> - break;
> - case 0x96:
> - tmp2 = tcg_temp_new_i64();
> -#if HOST_LONG_BITS == 32
> - tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
> - tcg_gen_trunc_i64_i32(TCGV_HIGH(regs[i]), tmp2);
> -#else
> - tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
> - tcg_gen_shl_i64(tmp2, tmp2, tmp4);
> - tcg_gen_ext32u_i64(regs[i], regs[i]);
> - tcg_gen_or_i64(regs[i], regs[i], tmp2);
> -#endif
> - tcg_temp_free_i64(tmp2);
> - break;
> - case 0x24:
> - tcg_gen_qemu_st64(regs[i], tmp, get_mem_index(s));
> - break;
> - case 0x26:
> - tmp2 = tcg_temp_new_i64();
> - tcg_gen_shr_i64(tmp2, regs[i], tmp4);
> - tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
> - tcg_temp_free_i64(tmp2);
> - break;
> - default:
> - tcg_abort();
> - }
> - if (i == r3) {
> - break;
> - }
> - tcg_gen_add_i64(tmp, tmp, tmp3);
> - }
> - tcg_temp_free_i64(tmp);
> - tcg_temp_free_i64(tmp3);
> - tcg_temp_free_i64(tmp4);
> - break;
> case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
> tmp = get_address(s, 0, b2, d2);
> tmp32_1 = tcg_const_i32(r1);
> @@ -2270,44 +2222,17 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
>
> static void disas_s390_insn(DisasContext *s)
> {
> - TCGv_i64 tmp, tmp2, tmp3, tmp4;
> + TCGv_i64 tmp, tmp2;
> TCGv_i32 tmp32_1, tmp32_2;
> unsigned char opc;
> uint64_t insn;
> - int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
> + int op, r1, r2, r3, d1, d2, x2, b1, b2, i2, r1b;
> TCGv_i32 vl;
>
> opc = cpu_ldub_code(cpu_single_env, s->pc);
> LOG_DISAS("opc 0x%x\n", opc);
>
> switch (opc) {
> - case 0x98: /* LM R1,R3,D2(B2) [RS] */
> - case 0x90: /* STM R1,R3,D2(B2) [RS] */
> - insn = ld_code4(s->pc);
> - decode_rs(s, insn, &r1, &r3, &b2, &d2);
> -
> - tmp = get_address(s, 0, b2, d2);
> - tmp2 = tcg_temp_new_i64();
> - tmp3 = tcg_const_i64(4);
> - tmp4 = tcg_const_i64(0xffffffff00000000ULL);
> - for (i = r1;; i = (i + 1) % 16) {
> - if (opc == 0x98) {
> - tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
> - tcg_gen_and_i64(regs[i], regs[i], tmp4);
> - tcg_gen_or_i64(regs[i], regs[i], tmp2);
> - } else {
> - tcg_gen_qemu_st32(regs[i], tmp, get_mem_index(s));
> - }
> - if (i == r3) {
> - break;
> - }
> - tcg_gen_add_i64(tmp, tmp, tmp3);
> - }
> - tcg_temp_free_i64(tmp);
> - tcg_temp_free_i64(tmp2);
> - tcg_temp_free_i64(tmp3);
> - tcg_temp_free_i64(tmp4);
> - break;
> case 0x92: /* MVI D1(B1),I2 [SI] */
> insn = ld_code4(s->pc);
> tmp = decode_si(s, insn, &i2, &b1, &d1);
> @@ -2604,19 +2529,17 @@ static void disas_s390_insn(DisasContext *s)
> d1 = (insn >> 16) & 0xfff;
> b2 = (insn >> 12) & 0xf;
> d2 = insn & 0xfff;
> - tmp = load_reg(r1);
> /* XXX key in r3 */
> - tmp2 = get_address(s, 0, b1, d1);
> - tmp3 = get_address(s, 0, b2, d2);
> + tmp = get_address(s, 0, b1, d1);
> + tmp2 = get_address(s, 0, b2, d2);
> if (opc == 0xda) {
> - gen_helper_mvcp(cc_op, cpu_env, tmp, tmp2, tmp3);
> + gen_helper_mvcp(cc_op, cpu_env, regs[r1], tmp, tmp2);
> } else {
> - gen_helper_mvcs(cc_op, cpu_env, tmp, tmp2, tmp3);
> + gen_helper_mvcs(cc_op, cpu_env, regs[r1], tmp, tmp2);
> }
> set_cc_static(s);
> tcg_temp_free_i64(tmp);
> tcg_temp_free_i64(tmp2);
> - tcg_temp_free_i64(tmp3);
> break;
> #endif
> case 0xe3:
> @@ -3346,6 +3269,57 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
> }
> #endif
>
> +static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
> +{
> + int r1 = get_field(s->fields, r1);
> + int r3 = get_field(s->fields, r3);
> + TCGv_i64 t = tcg_temp_new_i64();
> +
> + while (1) {
> + tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
> + store_reg32_i64(r1, t);
> + if (r1 == r3) {
> + break;
> + }
> + tcg_gen_addi_i64(o->in2, o->in2, 4);
> + r1 = (r1 + 1) & 15;
> + }
> + return NO_EXIT;
> +}
> +
> +static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
> +{
> + int r1 = get_field(s->fields, r1);
> + int r3 = get_field(s->fields, r3);
> + TCGv_i64 t = tcg_temp_new_i64();
> +
> + while (1) {
> + tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
> + store_reg32h_i64(r1, t);
> + if (r1 == r3) {
> + break;
> + }
> + tcg_gen_addi_i64(o->in2, o->in2, 4);
I don't have a good answer here, but how do we guarantee that we're not
overrunning the tcg inst buffer?
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 053/126] target-s390: Convert MVC
2012-09-09 21:05 ` [Qemu-devel] [PATCH 053/126] target-s390: Convert MVC Richard Henderson
@ 2012-09-18 20:52 ` Alexander Graf
0 siblings, 0 replies; 129+ messages in thread
From: Alexander Graf @ 2012-09-18 20:52 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 09/09/2012 11:05 PM, Richard Henderson wrote:
> The code that was in gen_op_mvc was a bit confused wrt what lengths
> it wanted to handle. I also disbelieve that the inline memset is
> worthwhile.
I measured it back when I inlined it and I'm fairly sure I remember
significant speedups from it. Compiling qemu with gprof enabled should
be able to tell you :).
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST
2012-09-11 21:09 ` Richard Henderson
@ 2012-09-18 21:04 ` Alexander Graf
0 siblings, 0 replies; 129+ messages in thread
From: Alexander Graf @ 2012-09-18 21:04 UTC (permalink / raw)
To: Richard Henderson; +Cc: Blue Swirl, qemu-devel
On 09/11/2012 11:09 PM, Richard Henderson wrote:
> On 09/11/2012 12:11 PM, Blue Swirl wrote:
>> PSW_MASK_64 bit could be added to TB flags and that could be checked
>> during translation, then the mask needs to be applied only when the
>> mode is active. Whether that actually improves performance depends on
>> how often the bit is changed. Also all PSW writes need to be handled,
>> possibly causing a TB flush.
> Actually I'm not sure why we check this at all, given that we only
> actually handle 64-bit mode -- at least as documented by the code
> implementing the SET ADDRESS MODE instruction.
For kernel code, we only support 64 bit mode, yes. But for user space
code, we need to support 31-bit mode to enable Debian to work. They
still run all user space in 31-bit mode.
> That said, we do encode the bit in TB flags, and we do perform this
> masking for qemu loads performed within the TB. No TB flushes are
> required because we simply don't match TBs with different flags.
>
> As for clst, mvst, srst, I thought about performing the masking in
> the TB, but didn't figure it was worth it. Do you have an opinion, Alex?
I don't know if it's worth it either. When calling anything with address
parameters we already need to save off all registers to env, since we
could take a page fault any time. So moving code into TCG context
shouldn't improve anything performance wise.
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 000/126] Rewrite s390x translator
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
` (100 preceding siblings ...)
2012-09-09 21:05 ` [Qemu-devel] [PATCH 101/126] target-s390: Convert subchannel instructions Richard Henderson
@ 2012-09-18 21:08 ` Alexander Graf
2012-09-18 21:09 ` Alexander Graf
101 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-18 21:08 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 09/09/2012 11:04 PM, Richard Henderson wrote:
> As promised the other week. I've cleaned up the patch set and
> re-based it on Blueswirl's areg0 patch set. For reference, the
> entire patch set is available at
>
> git://repo.or.cz/qemu/rth.git rth/s390-reorg-3
>
> Testing has mostly been on the gcc testsuite, where the execute
> test failures are reduced to
>
> FAIL: gcc.dg/attr-ifunc-1.c execution test
> FAIL: gcc.dg/attr-ifunc-3.c execution test
> FAIL: gcc.dg/attr-ifunc-4.c execution test
> FAIL: gcc.dg/attr-ifunc-5.c execution test
> FAIL: gcc.dg/cdce1.c execution test
> FAIL: gcc.dg/cleanup-11.c execution test
> FAIL: gcc.dg/cleanup-9.c execution test
> FAIL: gcc.dg/torture/pr41094.c -O0 execution test
> FAIL: gcc.dg/torture/tls/tls-test.c * execution test
>
> I'll probably start trying out the glibc testsuite next, as
> that's quite likely to flush out remaining problems with the
> fp support (both cdce1 and pr41094 are both failures in pow).
>
> I've also done some testing with -march={z10,z196}, but I
> don't have those results handy atm.
So I've had a look at the patch set. Overall it looks ok. I have to
admit that I found the old code a lot easier to understand and read. But
if you want to keep maintaining it the new way, I'm definitely ok with
that as well :).
There's one thing I would really like to see first though: Performance
numbers. Could you please try and compare the old code with your new
code performance wise? How do small linux-user programs compare? How
does a full Linux boot compare?
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 000/126] Rewrite s390x translator
2012-09-18 21:08 ` [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Alexander Graf
@ 2012-09-18 21:09 ` Alexander Graf
2012-09-19 0:32 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-18 21:09 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 09/18/2012 11:08 PM, Alexander Graf wrote:
> On 09/09/2012 11:04 PM, Richard Henderson wrote:
>> As promised the other week. I've cleaned up the patch set and
>> re-based it on Blueswirl's areg0 patch set. For reference, the
>> entire patch set is available at
>>
>> git://repo.or.cz/qemu/rth.git rth/s390-reorg-3
>>
>> Testing has mostly been on the gcc testsuite, where the execute
>> test failures are reduced to
>>
>> FAIL: gcc.dg/attr-ifunc-1.c execution test
>> FAIL: gcc.dg/attr-ifunc-3.c execution test
>> FAIL: gcc.dg/attr-ifunc-4.c execution test
>> FAIL: gcc.dg/attr-ifunc-5.c execution test
>> FAIL: gcc.dg/cdce1.c execution test
>> FAIL: gcc.dg/cleanup-11.c execution test
>> FAIL: gcc.dg/cleanup-9.c execution test
>> FAIL: gcc.dg/torture/pr41094.c -O0 execution test
>> FAIL: gcc.dg/torture/tls/tls-test.c * execution test
>>
>> I'll probably start trying out the glibc testsuite next, as
>> that's quite likely to flush out remaining problems with the
>> fp support (both cdce1 and pr41094 are both failures in pow).
>>
>> I've also done some testing with -march={z10,z196}, but I
>> don't have those results handy atm.
>
> So I've had a look at the patch set. Overall it looks ok. I have to
> admit that I found the old code a lot easier to understand and read.
> But if you want to keep maintaining it the new way, I'm definitely ok
> with that as well :).
Also, 102-126 are missing for me :).
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-18 20:18 ` Alexander Graf
@ 2012-09-19 0:14 ` Richard Henderson
2012-09-19 11:07 ` Alexander Graf
2012-09-19 11:29 ` Peter Maydell
0 siblings, 2 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-19 0:14 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
On 09/18/2012 01:18 PM, Alexander Graf wrote:
>> - /* remember what pgm exeption this was */
>> + /* Remember what pgm exeption this was. */
>> tmp = tcg_const_i32(code);
>> tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
>> tcg_temp_free_i32(tmp);
>> - tmp = tcg_const_i32(ilc);
>> + tmp = tcg_const_i32(s->next_pc - s->pc);
>
> Mind to explain this one?
ILC = the size of the insn. Rather than passing ILC around into
gen_program_exception, get it back from the s->next_pc value that
we stored into DisasContext.
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 047/126] target-s390: Convert LOAD, STORE MULTIPLE
2012-09-18 20:49 ` Alexander Graf
@ 2012-09-19 0:15 ` Richard Henderson
0 siblings, 0 replies; 129+ messages in thread
From: Richard Henderson @ 2012-09-19 0:15 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
On 09/18/2012 01:49 PM, Alexander Graf wrote:
> I don't have a good answer here, but how do we guarantee that we're
> not overrunning the tcg inst buffer?
Dunno. Not a new problem though, since the old code does the same thing.
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 000/126] Rewrite s390x translator
2012-09-18 21:09 ` Alexander Graf
@ 2012-09-19 0:32 ` Richard Henderson
2012-09-19 11:04 ` Alexander Graf
0 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-19 0:32 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
On 09/18/2012 02:09 PM, Alexander Graf wrote:
> Also, 102-126 are missing for me :).
Yeah, they never made it to the list. I guess next time I shouldn't
try to send to many at the same time. I should stagger them into
hunks of 25 at a time or so.
I've fixed some bugs since the v1, and I believe I've incorporated
all of the comments to date. Is it helpful for you if I re-send, or
would it simply be easier to examine the branch?
git://repo.or.cz/qemu/rth.git rth/s390-reorg-3
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 000/126] Rewrite s390x translator
2012-09-19 0:32 ` Richard Henderson
@ 2012-09-19 11:04 ` Alexander Graf
0 siblings, 0 replies; 129+ messages in thread
From: Alexander Graf @ 2012-09-19 11:04 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 19.09.2012, at 02:32, Richard Henderson wrote:
> On 09/18/2012 02:09 PM, Alexander Graf wrote:
>> Also, 102-126 are missing for me :).
>
> Yeah, they never made it to the list. I guess next time I shouldn't
> try to send to many at the same time. I should stagger them into
> hunks of 25 at a time or so.
>
> I've fixed some bugs since the v1, and I believe I've incorporated
> all of the comments to date. Is it helpful for you if I re-send, or
> would it simply be easier to examine the branch?
I find email easier to read usually :). Please make sure to test a full Debian guest as well as something s390x based (RHEL/SLES).
Alex
>
> git://repo.or.cz/qemu/rth.git rth/s390-reorg-3
>
>
> r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-19 0:14 ` Richard Henderson
@ 2012-09-19 11:07 ` Alexander Graf
2012-09-19 11:29 ` Peter Maydell
1 sibling, 0 replies; 129+ messages in thread
From: Alexander Graf @ 2012-09-19 11:07 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On 19.09.2012, at 02:14, Richard Henderson wrote:
> On 09/18/2012 01:18 PM, Alexander Graf wrote:
>>> - /* remember what pgm exeption this was */
>>> + /* Remember what pgm exeption this was. */
>>> tmp = tcg_const_i32(code);
>>> tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
>>> tcg_temp_free_i32(tmp);
>>> - tmp = tcg_const_i32(ilc);
>>> + tmp = tcg_const_i32(s->next_pc - s->pc);
>>
>> Mind to explain this one?
>
> ILC = the size of the insn. Rather than passing ILC around into
> gen_program_exception, get it back from the s->next_pc value that
> we stored into DisasContext.
Ah, makes sense. Maybe create a small helper that makes it more obvious:
static int current_ilc(DisasContext *s)
{
/* Next pc - current pc = current instruction length. */
return s->next_pc - s->pc;
}
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-19 0:14 ` Richard Henderson
2012-09-19 11:07 ` Alexander Graf
@ 2012-09-19 11:29 ` Peter Maydell
2012-09-19 11:34 ` Alexander Graf
1 sibling, 1 reply; 129+ messages in thread
From: Peter Maydell @ 2012-09-19 11:29 UTC (permalink / raw)
To: Richard Henderson; +Cc: Alexander Graf, qemu-devel
On 19 September 2012 01:14, Richard Henderson <rth@twiddle.net> wrote:
> On 09/18/2012 01:18 PM, Alexander Graf wrote:
>>> - /* remember what pgm exeption this was */
>>> + /* Remember what pgm exeption this was. */
...if you're changing this comment then at least fix the typo
("exception")...
>>> tmp = tcg_const_i32(code);
>>> tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
>>> tcg_temp_free_i32(tmp);
>>> - tmp = tcg_const_i32(ilc);
>>> + tmp = tcg_const_i32(s->next_pc - s->pc);
>>
>> Mind to explain this one?
>
> ILC = the size of the insn. Rather than passing ILC around into
> gen_program_exception, get it back from the s->next_pc value that
> we stored into DisasContext.
...but isn't (s-next_pc - s->pc) ilc*2, not ilc? Compare this hunk
from elsewhere in the patch:
- tmp32_2 = tcg_const_i32(ilc * 2);
- tmp32_3 = tcg_const_i32(EXCP_SVC);
+ tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
-- PMM
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-19 11:29 ` Peter Maydell
@ 2012-09-19 11:34 ` Alexander Graf
2012-09-19 13:02 ` Alexander Graf
0 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-19 11:34 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel, Richard Henderson
On 19.09.2012, at 13:29, Peter Maydell wrote:
> On 19 September 2012 01:14, Richard Henderson <rth@twiddle.net> wrote:
>> On 09/18/2012 01:18 PM, Alexander Graf wrote:
>>>> - /* remember what pgm exeption this was */
>>>> + /* Remember what pgm exeption this was. */
>
> ...if you're changing this comment then at least fix the typo
> ("exception")...
>
>>>> tmp = tcg_const_i32(code);
>>>> tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
>>>> tcg_temp_free_i32(tmp);
>>>> - tmp = tcg_const_i32(ilc);
>>>> + tmp = tcg_const_i32(s->next_pc - s->pc);
>>>
>>> Mind to explain this one?
>>
>> ILC = the size of the insn. Rather than passing ILC around into
>> gen_program_exception, get it back from the s->next_pc value that
>> we stored into DisasContext.
>
> ...but isn't (s-next_pc - s->pc) ilc*2, not ilc? Compare this hunk
> from elsewhere in the patch:
>
> - tmp32_2 = tcg_const_i32(ilc * 2);
> - tmp32_3 = tcg_const_i32(EXCP_SVC);
> + tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
Yes, it is, and hence it's correct. The exception field encodes the real instruction length, not the ILC bits in the opcode. Maybe the naming is unfortunate...
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-19 11:34 ` Alexander Graf
@ 2012-09-19 13:02 ` Alexander Graf
2012-09-19 14:34 ` Richard Henderson
0 siblings, 1 reply; 129+ messages in thread
From: Alexander Graf @ 2012-09-19 13:02 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel, Richard Henderson
On 19.09.2012, at 13:34, Alexander Graf wrote:
>
> On 19.09.2012, at 13:29, Peter Maydell wrote:
>
>> On 19 September 2012 01:14, Richard Henderson <rth@twiddle.net> wrote:
>>> On 09/18/2012 01:18 PM, Alexander Graf wrote:
>>>>> - /* remember what pgm exeption this was */
>>>>> + /* Remember what pgm exeption this was. */
>>
>> ...if you're changing this comment then at least fix the typo
>> ("exception")...
>>
>>>>> tmp = tcg_const_i32(code);
>>>>> tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
>>>>> tcg_temp_free_i32(tmp);
>>>>> - tmp = tcg_const_i32(ilc);
>>>>> + tmp = tcg_const_i32(s->next_pc - s->pc);
>>>>
>>>> Mind to explain this one?
>>>
>>> ILC = the size of the insn. Rather than passing ILC around into
>>> gen_program_exception, get it back from the s->next_pc value that
>>> we stored into DisasContext.
>>
>> ...but isn't (s-next_pc - s->pc) ilc*2, not ilc? Compare this hunk
>> from elsewhere in the patch:
>>
>> - tmp32_2 = tcg_const_i32(ilc * 2);
>> - tmp32_3 = tcg_const_i32(EXCP_SVC);
>> + tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
>
> Yes, it is, and hence it's correct. The exception field encodes the real instruction length, not the ILC bits in the opcode. Maybe the naming is unfortunate...
Or maybe not. For SVC we seem to pass in the full instruction length, while PGM only gets ILC. So the above hunk is wrong.
Richard, please double-check all the ilc passing again with the spec.
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-19 13:02 ` Alexander Graf
@ 2012-09-19 14:34 ` Richard Henderson
2012-09-19 14:40 ` Alexander Graf
0 siblings, 1 reply; 129+ messages in thread
From: Richard Henderson @ 2012-09-19 14:34 UTC (permalink / raw)
To: Alexander Graf; +Cc: Peter Maydell, qemu-devel
On 09/19/2012 06:02 AM, Alexander Graf wrote:
> Richard, please double-check all the ilc passing again with the spec.
I'll look again.
But I do recall that the spec is consistent in placing a 3-bit field (values 1-3)
shifted one bit left into the larger 32-bit field, so that in essence the value
is always the real instruction length.
However, qemu was not consistent in performing that multiplication. So there
will be some place that gets changed because of this. Frankly I think it would
be least confusing to always manipulate the full instruction length and never
explicitly perform the multiply.
r~
^ permalink raw reply [flat|nested] 129+ messages in thread
* Re: [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling
2012-09-19 14:34 ` Richard Henderson
@ 2012-09-19 14:40 ` Alexander Graf
0 siblings, 0 replies; 129+ messages in thread
From: Alexander Graf @ 2012-09-19 14:40 UTC (permalink / raw)
To: Richard Henderson; +Cc: Peter Maydell, qemu-devel
On 19.09.2012, at 16:34, Richard Henderson wrote:
> On 09/19/2012 06:02 AM, Alexander Graf wrote:
>> Richard, please double-check all the ilc passing again with the spec.
>
> I'll look again.
>
> But I do recall that the spec is consistent in placing a 3-bit field (values 1-3)
> shifted one bit left into the larger 32-bit field, so that in essence the value
> is always the real instruction length.
>
> However, qemu was not consistent in performing that multiplication. So there
> will be some place that gets changed because of this. Frankly I think it would
> be least confusing to always manipulate the full instruction length and never
> explicitly perform the multiply.
I agree. How about we rename the whole thing to inst_len and then just modify it accordingly when we move it into the exception area?
Alex
^ permalink raw reply [flat|nested] 129+ messages in thread
end of thread, other threads:[~2012-09-19 14:40 UTC | newest]
Thread overview: 129+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-09 21:04 [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 001/126] tcg: Add TCGV_IS_UNUSED_* Richard Henderson
2012-09-10 14:16 ` Aurelien Jarno
2012-09-09 21:04 ` [Qemu-devel] [PATCH 002/126] tcg: Add TCG_COND_NEVER, TCG_COND_ALWAYS Richard Henderson
2012-09-10 14:17 ` Aurelien Jarno
2012-09-09 21:04 ` [Qemu-devel] [PATCH 003/126] target-s390: Disassemble more z10 and z196 opcodes Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 004/126] target-s390: Fix disassembly of cpsdr Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 005/126] target-s390: Fix gdbstub Richard Henderson
2012-09-12 13:25 ` Alexander Graf
2012-09-12 15:11 ` Richard Henderson
2012-09-12 15:54 ` Alexander Graf
2012-09-12 16:15 ` Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 006/126] target-s390: Add missing temp_free in gen_op_calc_cc Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 007/126] target-s390: Use TCG registers for FPR Richard Henderson
2012-09-10 14:34 ` Aurelien Jarno
2012-09-10 14:45 ` Richard Henderson
2012-09-10 14:52 ` Aurelien Jarno
2012-09-09 21:04 ` [Qemu-devel] [PATCH 008/126] target-s390: Add format based disassassmbly infrastructure Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 009/126] target-s390: Split out disas_jcc Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 010/126] target-s390: Reorg exception handling Richard Henderson
2012-09-18 20:18 ` Alexander Graf
2012-09-19 0:14 ` Richard Henderson
2012-09-19 11:07 ` Alexander Graf
2012-09-19 11:29 ` Peter Maydell
2012-09-19 11:34 ` Alexander Graf
2012-09-19 13:02 ` Alexander Graf
2012-09-19 14:34 ` Richard Henderson
2012-09-19 14:40 ` Alexander Graf
2012-09-09 21:04 ` [Qemu-devel] [PATCH 011/126] target-s390: Convert ADD HALFWORD Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 012/126] target-s390: Implement SUBTRACT HALFWORD Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 013/126] target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 014/126] target-s390: Convert MULTIPLY Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 015/126] target-s390: Convert AND, OR, XOR Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 016/126] target-s390: Convert COMPARE, COMPARE LOGICAL Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 017/126] target-s390: Convert LOAD, LOAD LOGICAL Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 018/126] target-s390: Convert LOAD ADDRESS Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 019/126] target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 020/126] target-s390: Convert LOAD AND TEST Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 021/126] target-s390: Convert LOAD LOGICAL IMMEDIATE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 022/126] target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 023/126] target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 024/126] target-s390: Convert STORE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 025/126] target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 026/126] target-s390: Convert BRANCH AND SAVE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 027/126] target-s390: Convert BRANCH ON CONDITION Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 028/126] target-s390: Convert BRANCH ON COUNT Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 029/126] target-s390: Convert DIVIDE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 030/126] target-s390: Send signals for divide Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 031/126] target-s390: Convert TEST UNDER MASK Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 032/126] target-s390: Convert SET ADDRESSING MODE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 033/126] target-s390: Convert SUPERVISOR CALL Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 034/126] target-s390: Convert MOVE LONG Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 035/126] target-s390: Convert FP LOAD Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 036/126] target-s390: Convert INSERT CHARACTER Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 037/126] target-s390: Cleanup cc computation helpers Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 038/126] target-s390: Convert INSERT CHARACTERS UNDER MASK Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 039/126] target-s390: Convert EXECUTE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 040/126] target-s390: Convert FP STORE Richard Henderson
2012-09-09 21:04 ` [Qemu-devel] [PATCH 041/126] target-s390: Convert CONVERT TO DECIMAL Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 042/126] target-s390: Convert SET SYSTEM MASK Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 043/126] target-s390: Convert LOAD PSW Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 044/126] target-s390: Convert DIAGNOSE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 045/126] target-s390: Convert SHIFT, ROTATE SINGLE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 046/126] target-s390: Convert SHIFT DOUBLE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 047/126] target-s390: Convert LOAD, STORE MULTIPLE Richard Henderson
2012-09-18 20:49 ` Alexander Graf
2012-09-19 0:15 ` Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 048/126] target-s390: Convert MOVE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 049/126] target-s390: Convert NI, XI, OI Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 050/126] target-s390: Convert STNSM, STOSM Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 051/126] target-s390: Convert LAM, STAM Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 052/126] target-s390: Convert CLCLE, MVCLE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 053/126] target-s390: Convert MVC Richard Henderson
2012-09-18 20:52 ` Alexander Graf
2012-09-09 21:05 ` [Qemu-devel] [PATCH 054/126] target-s390: Convert NC, XC, OC, TR, UNPK Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 055/126] target-s390: Convert CLC Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 056/126] target-s390: Convert MVCP, MVCS Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 057/126] target-s390: Convert LRA Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 058/126] target-s390: Convert SIGP Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 059/126] target-s390: Convert EFPC, STFPC Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 060/126] target-s390: Convert LCTL, STCTL Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 061/126] target-s390: Convert COMPARE AND SWAP Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 062/126] target-s390: Convert CLM Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 063/126] target-s390: Convert STCM Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 064/126] target-s390: Convert TPROT Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 065/126] target-s390: Convert LOAD CONTROL, part 2 Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 066/126] target-s390: Convert LOAD REVERSED Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 067/126] target-s390: Convert STORE REVERSED Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 068/126] target-s390: Convert LLGT Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 069/126] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 070/126] target-s390: Convert FP SUBTRACT Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 071/126] target-s390: Convert FP DIVIDE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 072/126] target-s390: Convert FP MULTIPLY Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 073/126] target-s390: Convert MULTIPLY AND ADD, SUBTRACT Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 074/126] target-s390: Convert TEST DATA CLASS Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 075/126] target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 076/126] target-s390: Convert FP SQUARE ROOT Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 077/126] target-s390: Convert LOAD ZERO Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 078/126] target-s390: Convert CONVERT TO FIXED Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 079/126] target-s390: Convert CONVERT FROM FIXED Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 080/126] target-s390: Convert FLOGR Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 081/126] target-s390: Convert LFPC, SFPC Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 082/126] target-s390: Convert IPM Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 083/126] target-s390: Convert CKSM Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 084/126] target-s390: Convert EAR, SAR Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 085/126] target-s390: Convert MVPG Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 086/126] target-s390: Convert CLST, MVST Richard Henderson
2012-09-11 19:11 ` Blue Swirl
2012-09-11 21:09 ` Richard Henderson
2012-09-18 21:04 ` Alexander Graf
2012-09-09 21:05 ` [Qemu-devel] [PATCH 087/126] target-s390: Convert SRST Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 088/126] target-s390: Convert STIDP Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 089/126] target-s390: Convert SCK Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 090/126] target-s390: Convert STCK Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 091/126] target-s390: Convert SCKC, STCKC Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 092/126] target-s390: Convert SPT, STPT Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 093/126] target-s390: Convert SPKA Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 094/126] target-s390: Convert PTLB Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 095/126] target-s390: Convert SPX, STPX Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 096/126] target-s390: Convert STAP Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 097/126] target-s390: Convert IPTE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 098/126] target-s390: Convert ISKE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 099/126] target-s390: Convert SSKE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 100/126] target-s390: Convert RRBE Richard Henderson
2012-09-09 21:05 ` [Qemu-devel] [PATCH 101/126] target-s390: Convert subchannel instructions Richard Henderson
2012-09-18 21:08 ` [Qemu-devel] [PATCH 000/126] Rewrite s390x translator Alexander Graf
2012-09-18 21:09 ` Alexander Graf
2012-09-19 0:32 ` Richard Henderson
2012-09-19 11:04 ` Alexander Graf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).